[automerger skipped] Convert android.car to Soong.
am: 683e37e879 -s ours
Change-Id: Ica2935186bac383861ff2eee116d029d69d518cd
diff --git a/Android.mk b/Android.mk
index b33eecc..04f8004 100644
--- a/Android.mk
+++ b/Android.mk
@@ -17,7 +17,6 @@
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
-CAR_CURRENT_SDK_VERSION := 23
CAR_API_CHECK := $(LOCAL_PATH)/apicheck.mk
api_check_current_msg_file := $(LOCAL_PATH)/apicheck_msg_current.txt
api_check_last_msg_file := $(LOCAL_PATH)/apicheck_msg_last.txt
@@ -28,7 +27,6 @@
include $(call all-makefiles-under,$(LOCAL_PATH))
# Clear out variables
-CAR_CURRENT_SDK_VERSION :=
CAR_API_CHECK :=
api_check_current_msg_file :=
api_check_last_msg_file :=
diff --git a/CleanSpec.mk b/CleanSpec.mk
index d828faa..67d5bef 100644
--- a/CleanSpec.mk
+++ b/CleanSpec.mk
@@ -57,6 +57,9 @@
$(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/JAVA_LIBRARIES/android.car_intermediates/src/android/car/hardware/ICarDiagnostic*.java)
$(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/JAVA_LIBRARIES/android.car7_intermediates/src/android/car/hardware/ICarDiagnostic*.java)
+$(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/JAVA_LIBRARIES/android.car7_intermediates/)
+$(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/JAVA_LIBRARIES/android.car_intermediates/)
+
# ************************************************
# NEWER CLEAN STEPS MUST BE AT THE END OF THE LIST
# ************************************************
diff --git a/PREUPLOAD.cfg b/PREUPLOAD.cfg
new file mode 100644
index 0000000..38f9800
--- /dev/null
+++ b/PREUPLOAD.cfg
@@ -0,0 +1,7 @@
+[Hook Scripts]
+checkstyle_hook = ${REPO_ROOT}/prebuilts/checkstyle/checkstyle.py --sha ${PREUPLOAD_COMMIT}
+ktlint_hook = ${REPO_ROOT}/prebuilts/ktlint/ktlint.py -f ${PREUPLOAD_FILES}
+
+[Builtin Hooks]
+commit_msg_changeid_field = true
+commit_msg_test_field = true
diff --git a/TrustAgent/Android.mk b/TrustAgent/Android.mk
index 4308a1d..5d9ff98 100644
--- a/TrustAgent/Android.mk
+++ b/TrustAgent/Android.mk
@@ -18,7 +18,9 @@
LOCAL_PATH:= $(call my-dir)
include $(CLEAR_VARS)
+LOCAL_JAVA_LIBRARIES += android.car
LOCAL_USE_AAPT2 := true
+LOCAL_RESOURCE_DIR := $(LOCAL_PATH)/res
LOCAL_SRC_FILES := $(call all-java-files-under, src)
@@ -36,8 +38,6 @@
LOCAL_DEX_PREOPT := false
-LOCAL_STATIC_JAVA_LIBRARIES := android-support-v4
-
include $(BUILD_PACKAGE)
endif
diff --git a/TrustAgent/AndroidManifest.xml b/TrustAgent/AndroidManifest.xml
index 1f5e6e6..69e501c 100644
--- a/TrustAgent/AndroidManifest.xml
+++ b/TrustAgent/AndroidManifest.xml
@@ -19,7 +19,7 @@
<uses-sdk android:minSdkVersion="23" android:targetSdkVersion="23"/>
<!-- Need Bluetooth LE -->
- <uses-feature android:name="android.hardware.bluetooth_le" android:required="true" />
+ <uses-feature android:name="android.hardware.bluetooth_le" android:required="true" />
<uses-permission android:name="android.permission.BLUETOOTH" />
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />
@@ -28,6 +28,8 @@
<!-- Needed to unlock user -->
<uses-permission android:name="android.permission.INTERACT_ACROSS_USERS_FULL" />
+ <!-- TODO(b/77717079) INTERACT_ACROSS_USERS_FULL should have granted INTERACT_ACROSS_USERS -->
+ <uses-permission android:name="android.permission.INTERACT_ACROSS_USERS" />
<uses-permission android:name="android.permission.MANAGE_USERS" />
<uses-permission android:name="android.permission.CONTROL_KEYGUARD" />
<uses-permission android:name="android.permission.PROVIDE_TRUST_AGENT" />
@@ -36,10 +38,10 @@
<application android:label="@string/app_name">
<service
android:name=".CarBleTrustAgent"
- android:label="@string/app_name"
android:permission="android.permission.BIND_TRUST_AGENT"
android:directBootAware="true"
- android:exported="true">
+ android:exported="true"
+ android:singleUser="true">
<intent-filter>
<action android:name="android.service.trust.TrustAgentService" />
<category android:name="android.intent.category.DEFAULT" />
@@ -51,10 +53,12 @@
android:resource="@xml/car_sample_trust_agent"/>
</service>
- <!-- CarUnlockService needs to be direct boot aware, since the trust agent
+ <!-- CarTrustAgentBleService needs to be direct boot aware, since the trust agent
binds to it during direct boot.-->
- <service android:name=".CarUnlockService"
- android:directBootAware="true">
+ <service
+ android:name=".CarTrustAgentBleService"
+ android:directBootAware="true"
+ android:singleUser="true">
<!-- Warning: the meta data must be included if the service is direct boot aware.
If not included, the device will crash before boot completes. Rendering the device
unusable. -->
@@ -62,10 +66,8 @@
android:resource="@xml/car_sample_trust_agent"/>
</service>
- <service android:name=".CarEnrolmentService"/>
-
<activity
- android:name=".MainActivity"
+ android:name=".CarEnrolmentActivity"
android:label="@string/app_name"
android:exported="true"
android:launchMode="singleInstance">
@@ -75,13 +77,5 @@
</intent-filter>
</activity>
- <activity android:name=".CarEnrolmentActivity"
- android:exported="false" />
-
- <activity android:name=".PhoneEnrolmentActivity"
- android:exported="false" />
-
- <activity android:name=".PhoneUnlockActivity"
- android:exported="false" />
</application>
</manifest>
diff --git a/TrustAgent/res/layout/car_client.xml b/TrustAgent/res/layout/car_enrolment_activity.xml
similarity index 100%
rename from TrustAgent/res/layout/car_client.xml
rename to TrustAgent/res/layout/car_enrolment_activity.xml
diff --git a/TrustAgent/res/layout/main_app.xml b/TrustAgent/res/layout/main_app.xml
deleted file mode 100644
index 5153ca8..0000000
--- a/TrustAgent/res/layout/main_app.xml
+++ /dev/null
@@ -1,37 +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="match_parent"
- android:weightSum="1">
-
- <Button android:id="@+id/car_button"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:layout_weight="0.20"
- android:text="@string/car"/>
- <Button android:id="@+id/phone_enrolment_button"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:layout_weight="0.20"
- android:text="@string/enrollment_client"/>
- <Button android:id="@+id/phone_unlock_button"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:layout_weight="0.20"
- android:text="@string/unlock_client"/>
-</LinearLayout>
diff --git a/TrustAgent/res/layout/phone_client.xml b/TrustAgent/res/layout/phone_client.xml
deleted file mode 100644
index 41ead63..0000000
--- a/TrustAgent/res/layout/phone_client.xml
+++ /dev/null
@@ -1,45 +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="match_parent"
- android:weightSum="1">
- <ScrollView
- android:id="@+id/scroll"
- android:layout_width="fill_parent"
- android:layout_height="wrap_content"
- android:scrollbars="vertical"
- android:layout_weight="0.60"
- android:fillViewport="true">
-
- <TextView
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:id="@+id/output"/>
- </ScrollView>
- <Button
- android:id="@+id/ble_scan_btn"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:text="@string/start_scanning"
- android:layout_weight="0.20"/>
- <Button
- android:id="@+id/action_button"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:layout_weight="0.20"/>
-</LinearLayout>
diff --git a/TrustAgent/res/values/strings.xml b/TrustAgent/res/values/strings.xml
index d23a4b3..d077262 100644
--- a/TrustAgent/res/values/strings.xml
+++ b/TrustAgent/res/values/strings.xml
@@ -14,7 +14,7 @@
limitations under the License.
-->
<resources>
- <string name="app_name">CarBleTrustAgent</string>
+ <string name="app_name">CarTrustAgentService</string>
<string name="trust_granted_explanation">Unlock via escrow token, now granting trust</string>
<!-- service/characteristics uuid for unlocking a device -->
@@ -36,8 +36,4 @@
<string name="start_advertising">Start Advertising</string>
<string name="revoke_trust">Revoke Trust</string>
- <string name="car">Car</string>
- <string name="enrollment_client">Phone Enrolment Client</string>
- <string name="unlock_client">Phone Unlock Client</string>
- <string name="start_scanning">Start Scanning</string>
</resources>
diff --git a/TrustAgent/src/com/android/car/trust/CarBleTrustAgent.java b/TrustAgent/src/com/android/car/trust/CarBleTrustAgent.java
index 997f028..227ea89 100644
--- a/TrustAgent/src/com/android/car/trust/CarBleTrustAgent.java
+++ b/TrustAgent/src/com/android/car/trust/CarBleTrustAgent.java
@@ -20,25 +20,25 @@
import android.bluetooth.BluetoothGattServer;
import android.bluetooth.BluetoothGattServerCallback;
import android.bluetooth.BluetoothManager;
-import android.content.BroadcastReceiver;
+import android.car.trust.ICarTrustAgentBleService;
+import android.car.trust.ICarTrustAgentTokenRequestDelegate;
+import android.car.trust.ICarTrustAgentUnlockCallback;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
-import android.content.IntentFilter;
import android.content.ServiceConnection;
import android.os.Handler;
import android.os.IBinder;
+import android.os.RemoteException;
import android.os.UserHandle;
import android.os.UserManager;
import android.service.trust.TrustAgentService;
-import android.support.v4.content.LocalBroadcastManager;
import android.util.Log;
-import com.android.car.trust.comms.SimpleBleServer;
import java.util.concurrent.TimeUnit;
/**
- * A sample trust agent that demonstrates how to use the escrow token unlock APIs. </p>
+ * A BluetoothLE (BLE) based {@link TrustAgentService} that uses the escrow token unlock APIs. </p>
*
* This trust agent runs during direct boot and binds to a BLE service that listens for remote
* devices to trigger an unlock. <p/>
@@ -46,86 +46,108 @@
* The permissions for this agent must be enabled as priv-app permissions for it to start.
*/
public class CarBleTrustAgent extends TrustAgentService {
- public static final String ACTION_REVOKE_TRUST = "revoke-trust-action";
- public static final String ACTION_ADD_TOKEN = "add-token-action";
- public static final String ACTION_IS_TOKEN_ACTIVE = "is-token-active-action";
- public static final String ACTION_REMOVE_TOKEN = "remove-token-action";
- public static final String ACTION_UNLOCK_DEVICE = "unlock-device-action";
- public static final String ACTION_TOKEN_STATUS_RESULT = "token-status-result-action";
- public static final String ACTION_ADD_TOKEN_RESULT = "add-token-result-action";
-
- public static final String INTENT_EXTRA_ESCROW_TOKEN = "extra-escrow-token";
- public static final String INTENT_EXTRA_TOKEN_HANDLE = "extra-token-handle";
- public static final String INTENT_EXTRA_TOKEN_STATUS = "extra-token-status";
-
-
- private static final String TAG = "CarBleTrustAgent";
+ private static final String TAG = CarBleTrustAgent.class.getSimpleName();
private static final long TRUST_DURATION_MS = TimeUnit.MINUTES.toMicros(5);
private static final long BLE_RETRY_MS = TimeUnit.SECONDS.toMillis(1);
- private CarUnlockService mCarUnlockService;
- private LocalBroadcastManager mLocalBroadcastManager;
+ private Handler mHandler;
+ private BluetoothManager mBluetoothManager;
+ private ICarTrustAgentBleService mCarTrustAgentBleService;
+ private boolean mCarTrustAgentBleServiceBound;
- private boolean mBleServiceBound;
-
- // We cannot directly bind to TrustAgentService since the onBind method is final.
- // As a result, we communicate with the various UI components using a LocalBroadcastManager.
- private final BroadcastReceiver mTrustEventReceiver = new BroadcastReceiver() {
+ private final ICarTrustAgentUnlockCallback mUnlockCallback =
+ new ICarTrustAgentUnlockCallback.Stub() {
@Override
- public void onReceive(Context context, Intent intent) {
- String action = intent.getAction();
- if (Log.isLoggable(TAG, Log.DEBUG)) {
- Log.d(TAG, "Received broadcast: " + action);
+ public void onUnlockDataReceived(byte[] token, long handle) {
+ UserManager um = (UserManager) getSystemService(Context.USER_SERVICE);
+ // TODO(b/77854782): get the actual user to unlock by token
+ UserHandle userHandle = getForegroundUserHandle();
+
+ Log.d(TAG, "About to unlock user. Handle: " + handle
+ + " Time: " + System.currentTimeMillis());
+ unlockUserWithToken(handle, token, userHandle);
+
+ Log.d(TAG, "Attempted to unlock user, is user unlocked: "
+ + um.isUserUnlocked(userHandle)
+ + " Time: " + System.currentTimeMillis());
+ setManagingTrust(true);
+
+ if (um.isUserUnlocked(userHandle)) {
+ Log.d(TAG, getString(R.string.trust_granted_explanation));
+ grantTrust("Granting trust from escrow token",
+ TRUST_DURATION_MS, FLAG_GRANT_TRUST_DISMISS_KEYGUARD);
}
- if (ACTION_REVOKE_TRUST.equals(action)) {
- revokeTrust();
- } else if (ACTION_ADD_TOKEN.equals(action)) {
- byte[] token = intent.getByteArrayExtra(INTENT_EXTRA_ESCROW_TOKEN);
- addEscrowToken(token, getCurrentUserHandle());
- } else if (ACTION_IS_TOKEN_ACTIVE.equals(action)) {
- long handle = intent.getLongExtra(INTENT_EXTRA_TOKEN_HANDLE, -1);
- isEscrowTokenActive(handle, getCurrentUserHandle());
- } else if (ACTION_REMOVE_TOKEN.equals(action)) {
- long handle = intent.getLongExtra(INTENT_EXTRA_TOKEN_HANDLE, -1);
- removeEscrowToken(handle, getCurrentUserHandle());
+ }
+ };
+
+ private final ICarTrustAgentTokenRequestDelegate mTokenRequestDelegate =
+ new ICarTrustAgentTokenRequestDelegate.Stub() {
+ @Override
+ public void revokeTrust() {
+ CarBleTrustAgent.this.revokeTrust();
+ }
+
+ @Override
+ public void addEscrowToken(byte[] token, int uid) {
+ CarBleTrustAgent.this.addEscrowToken(token, UserHandle.of(uid));
+ }
+
+ @Override
+ public void removeEscrowToken(long handle, int uid) {
+ CarBleTrustAgent.this.removeEscrowToken(handle, UserHandle.of(uid));
+ }
+
+ @Override
+ public void isEscrowTokenActive(long handle, int uid) {
+ CarBleTrustAgent.this.isEscrowTokenActive(handle, UserHandle.of(uid));
+ }
+ };
+
+ private final ServiceConnection mServiceConnection = new ServiceConnection() {
+ @Override
+ public void onServiceConnected(ComponentName name, IBinder service) {
+ Log.d(TAG, "CarTrustAgentBleService connected");
+ mCarTrustAgentBleServiceBound = true;
+ mCarTrustAgentBleService = ICarTrustAgentBleService.Stub.asInterface(service);
+ try {
+ mCarTrustAgentBleService.registerUnlockCallback(mUnlockCallback);
+ mCarTrustAgentBleService.setTokenRequestDelegate(mTokenRequestDelegate);
+ maybeStartBleUnlockService();
+ } catch (RemoteException e) {
+ Log.e(TAG, "Error registerUnlockCallback", e);
+ }
+ }
+
+ @Override
+ public void onServiceDisconnected(ComponentName name) {
+ if (mCarTrustAgentBleService != null) {
+ try {
+ mCarTrustAgentBleService.unregisterUnlockCallback(mUnlockCallback);
+ mCarTrustAgentBleService.setTokenRequestDelegate(null);
+ } catch (RemoteException e) {
+ Log.e(TAG, "Error unregisterUnlockCallback", e);
+ }
+ mCarTrustAgentBleService = null;
+ mCarTrustAgentBleServiceBound = false;
}
}
};
@Override
- public void onTrustTimeout() {
- super.onTrustTimeout();
- if (Log.isLoggable(TAG, Log.DEBUG)) {
- Log.d(TAG, "onTrustTimeout(): timeout expired");
- }
- }
-
- @Override
public void onCreate() {
super.onCreate();
- if (Log.isLoggable(TAG, Log.DEBUG)) {
- Log.d(TAG, "Bluetooth trust agent starting up");
- }
- IntentFilter filter = new IntentFilter();
- filter.addAction(ACTION_REVOKE_TRUST);
- filter.addAction(ACTION_ADD_TOKEN);
- filter.addAction(ACTION_IS_TOKEN_ACTIVE);
- filter.addAction(ACTION_REMOVE_TOKEN);
-
- mLocalBroadcastManager = LocalBroadcastManager.getInstance(this /* context */);
- mLocalBroadcastManager.registerReceiver(mTrustEventReceiver, filter);
+ Log.d(TAG, "Bluetooth trust agent starting up");
+ mHandler = new Handler();
+ mBluetoothManager = (BluetoothManager) getSystemService(BLUETOOTH_SERVICE);
// If the user is already unlocked, don't bother starting the BLE service.
UserManager um = (UserManager) getSystemService(Context.USER_SERVICE);
- if (!um.isUserUnlocked()) {
- if (Log.isLoggable(TAG, Log.DEBUG)) {
- Log.d(TAG, "User locked, will now bind CarUnlockService");
- }
- Intent intent = new Intent(this, CarUnlockService.class);
-
+ if (!um.isUserUnlocked(getForegroundUserHandle())) {
+ Log.d(TAG, "User locked, will now bind CarTrustAgentBleService");
+ Intent intent = new Intent(this, CarTrustAgentBleService.class);
bindService(intent, mServiceConnection, Context.BIND_AUTO_CREATE);
} else {
setManagingTrust(true);
@@ -134,81 +156,48 @@
@Override
public void onDestroy() {
- if (Log.isLoggable(TAG, Log.DEBUG)) {
- Log.d(TAG, "Car Trust agent shutting down");
- }
- mLocalBroadcastManager.unregisterReceiver(mTrustEventReceiver);
+ Log.d(TAG, "Car Trust agent shutting down");
+ mHandler.removeCallbacks(null);
// Unbind the service to avoid leaks from BLE stack.
- if (mBleServiceBound) {
+ if (mCarTrustAgentBleServiceBound) {
unbindService(mServiceConnection);
}
super.onDestroy();
}
- private SimpleBleServer.ConnectionListener mConnectionListener
- = new SimpleBleServer.ConnectionListener() {
- @Override
- public void onServerStarted() {
- if (Log.isLoggable(TAG, Log.DEBUG)) {
- Log.d(TAG, "BLE server started");
+ @Override
+ public void onDeviceLocked() {
+ super.onDeviceLocked();
+ if (mCarTrustAgentBleServiceBound) {
+ try {
+ // Only one BLE advertising is allowed, ensure enrolment advertising is stopped
+ // before start unlock advertising.
+ mCarTrustAgentBleService.stopEnrolmentAdvertising();
+ mCarTrustAgentBleService.startUnlockAdvertising();
+ } catch (RemoteException e) {
+ Log.e(TAG, "Error startUnlockAdvertising", e);
}
}
+ }
- @Override
- public void onServerStartFailed(int errorCode) {
- Log.w(TAG, "BLE server failed to start. Error Code: " + errorCode);
- }
-
- @Override
- public void onDeviceConnected(BluetoothDevice device) {
- if (Log.isLoggable(TAG, Log.DEBUG)) {
- Log.d(TAG, "BLE device connected. Name: " + device.getName()
- + " Address: " + device.getAddress());
+ @Override
+ public void onDeviceUnlocked() {
+ super.onDeviceUnlocked();
+ if (mCarTrustAgentBleServiceBound) {
+ try {
+ // Only one BLE advertising is allowed, ensure unlock advertising is stopped.
+ mCarTrustAgentBleService.stopUnlockAdvertising();
+ } catch (RemoteException e) {
+ Log.e(TAG, "Error stopUnlockAdvertising", e);
}
}
- };
-
- private CarUnlockService.UnlockServiceCallback mUnlockCallback
- = new CarUnlockService.UnlockServiceCallback() {
- @Override
- public void unlockDevice(byte[] token, long handle) {
- unlock(token, handle);
- }
- };
-
- private ServiceConnection mServiceConnection = new ServiceConnection() {
-
- public void onServiceConnected(ComponentName className, IBinder service) {
- if (Log.isLoggable(TAG, Log.DEBUG)) {
- Log.d(TAG, "CarUnlockService connected");
- }
-
- mBleServiceBound = true;
- CarUnlockService.UnlockServiceBinder binder
- = (CarUnlockService.UnlockServiceBinder) service;
- mCarUnlockService = binder.getService();
- mCarUnlockService.addUnlockServiceCallback(mUnlockCallback);
- mCarUnlockService.addConnectionListener(mConnectionListener);
- maybeStartBleUnlockService();
- }
-
- public void onServiceDisconnected(ComponentName arg0) {
- mCarUnlockService = null;
- mBleServiceBound = false;
- }
-
- };
+ }
private void maybeStartBleUnlockService() {
- if (Log.isLoggable(TAG, Log.DEBUG)) {
- Log.d(TAG, "Trying to open a Ble GATT server");
- }
-
- BluetoothManager btManager =
- (BluetoothManager) getSystemService(Context.BLUETOOTH_SERVICE);
- BluetoothGattServer mGattServer
- = btManager.openGattServer(this, new BluetoothGattServerCallback() {
+ Log.d(TAG, "Trying to open a Ble GATT server");
+ BluetoothGattServer gattServer = mBluetoothManager.openGattServer(
+ this, new BluetoothGattServerCallback() {
@Override
public void onConnectionStateChange(BluetoothDevice device, int status, int newState) {
super.onConnectionStateChange(device, status, newState);
@@ -218,87 +207,64 @@
// The BLE stack is started up before the trust agent service, however Gatt capabilities
// might not be ready just yet. Keep trying until a GattServer can open up before proceeding
// to start the rest of the BLE services.
- if (mGattServer == null) {
+ if (gattServer == null) {
Log.e(TAG, "Gatt not available, will try again...in " + BLE_RETRY_MS + "ms");
-
- Handler handler = new Handler();
- handler.postDelayed(new Runnable() {
- @Override
- public void run() {
- maybeStartBleUnlockService();
- }
- }, BLE_RETRY_MS);
+ mHandler.postDelayed(this::maybeStartBleUnlockService, BLE_RETRY_MS);
} else {
- mGattServer.close();
- if (Log.isLoggable(TAG, Log.DEBUG)) {
- Log.d(TAG, "GATT available, starting up UnlockService");
+ mHandler.removeCallbacks(null);
+ gattServer.close();
+ Log.d(TAG, "GATT available, starting up UnlockService");
+ try {
+ mCarTrustAgentBleService.startUnlockAdvertising();
+ } catch (RemoteException e) {
+ Log.e(TAG, "Error startUnlockAdvertising", e);
}
- mCarUnlockService.start();
- }
- }
-
- private void unlock(byte[] token, long handle) {
- UserManager um = (UserManager) getSystemService(Context.USER_SERVICE);
-
- if (Log.isLoggable(TAG, Log.DEBUG)) {
- Log.d(TAG, "About to unlock user. Current handle: " + handle
- + " Time: " + System.currentTimeMillis());
- }
- unlockUserWithToken(handle, token, getCurrentUserHandle());
-
- if (Log.isLoggable(TAG, Log.DEBUG)) {
- Log.d(TAG, "Attempted to unlock user, is user unlocked? " + um.isUserUnlocked()
- + " Time: " + System.currentTimeMillis());
- }
- setManagingTrust(true);
-
- if (um.isUserUnlocked()) {
- if (Log.isLoggable(TAG, Log.DEBUG)) {
- Log.d(TAG, getString(R.string.trust_granted_explanation));
- }
- grantTrust("Granting trust from escrow token",
- TRUST_DURATION_MS, FLAG_GRANT_TRUST_DISMISS_KEYGUARD);
- // Trust has been granted, disable the BLE server. This trust agent service does
- // not need to receive additional BLE data.
- unbindService(mServiceConnection);
}
}
@Override
public void onEscrowTokenRemoved(long handle, boolean successful) {
- if (Log.isLoggable(TAG, Log.DEBUG)) {
- Log.d(TAG, "onEscrowTokenRemoved. Handle: " + handle + " successful? " + successful);
+ if (mCarTrustAgentBleServiceBound) {
+ try {
+ mCarTrustAgentBleService.onEscrowTokenRemoved(handle, successful);
+ Log.v(TAG, "Callback onEscrowTokenRemoved");
+ } catch (RemoteException e) {
+ Log.e(TAG, "Error callback onEscrowTokenRemoved", e);
+ }
}
}
@Override
public void onEscrowTokenStateReceived(long handle, int tokenState) {
boolean isActive = tokenState == TOKEN_STATE_ACTIVE;
- if (Log.isLoggable(TAG, Log.DEBUG)) {
- Log.d(TAG, "Token handle: " + handle + " isActive: " + isActive);
+ if (mCarTrustAgentBleServiceBound) {
+ try {
+ mCarTrustAgentBleService.onEscrowTokenActiveStateChanged(handle, isActive);
+ Log.v(TAG, "Callback onEscrowTokenActiveStateChanged");
+ } catch (RemoteException e) {
+ Log.e(TAG, "Error callback onEscrowTokenActiveStateChanged", e);
+ }
}
-
- Intent intent = new Intent();
- intent.setAction(ACTION_TOKEN_STATUS_RESULT);
- intent.putExtra(INTENT_EXTRA_TOKEN_STATUS, isActive);
-
- mLocalBroadcastManager.sendBroadcast(intent);
}
@Override
public void onEscrowTokenAdded(byte[] token, long handle, UserHandle user) {
- if (Log.isLoggable(TAG, Log.DEBUG)) {
- Log.d(TAG, "onEscrowTokenAdded, handle: " + handle);
+ if (mCarTrustAgentBleServiceBound) {
+ try {
+ mCarTrustAgentBleService.onEscrowTokenAdded(token, handle, user.getIdentifier());
+ Log.v(TAG, "Callback onEscrowTokenAdded");
+ } catch (RemoteException e) {
+ Log.e(TAG, "Error callback onEscrowTokenAdded", e);
+ }
}
-
- Intent intent = new Intent();
- intent.setAction(ACTION_ADD_TOKEN_RESULT);
- intent.putExtra(INTENT_EXTRA_TOKEN_HANDLE, handle);
-
- mLocalBroadcastManager.sendBroadcast(intent);
}
- private UserHandle getCurrentUserHandle() {
+ /**
+ * TODO(b/77854782): return the {@link UserHandle} of foreground user.
+ * CarBleTrustAgent itself runs as user-0
+ */
+ private UserHandle getForegroundUserHandle() {
+ Log.d(TAG, "getForegroundUserHandle for " + UserHandle.myUserId());
return UserHandle.of(UserHandle.myUserId());
}
}
diff --git a/TrustAgent/src/com/android/car/trust/CarEnrolmentActivity.java b/TrustAgent/src/com/android/car/trust/CarEnrolmentActivity.java
index 89e68fe..d7160e3 100644
--- a/TrustAgent/src/com/android/car/trust/CarEnrolmentActivity.java
+++ b/TrustAgent/src/com/android/car/trust/CarEnrolmentActivity.java
@@ -15,232 +15,226 @@
*/
package com.android.car.trust;
+import android.Manifest;
import android.app.Activity;
import android.bluetooth.BluetoothDevice;
-import android.content.BroadcastReceiver;
+import android.car.trust.ICarTrustAgentBleCallback;
+import android.car.trust.ICarTrustAgentBleService;
+import android.car.trust.ICarTrustAgentEnrolmentCallback;
+import android.car.trust.ICarTrustAgentTokenResponseCallback;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
-import android.content.IntentFilter;
import android.content.ServiceConnection;
import android.content.SharedPreferences;
+import android.content.pm.PackageManager;
import android.os.Bundle;
import android.os.IBinder;
import android.os.RemoteException;
+import android.os.UserHandle;
import android.preference.PreferenceManager;
-import android.support.v4.content.LocalBroadcastManager;
import android.util.Log;
-import android.view.View;
-import android.widget.Button;
import android.widget.TextView;
-import com.android.car.trust.CarEnrolmentService.EnrolmentCallback;
-import com.android.car.trust.comms.SimpleBleServer.ConnectionListener;
-
-import static com.android.car.trust.CarBleTrustAgent.ACTION_ADD_TOKEN_RESULT;
-import static com.android.car.trust.CarBleTrustAgent.ACTION_TOKEN_STATUS_RESULT;
-import static com.android.car.trust.CarBleTrustAgent.INTENT_EXTRA_TOKEN_HANDLE;
-import static com.android.car.trust.CarBleTrustAgent.INTENT_EXTRA_TOKEN_STATUS;
/**
- * Setup activity that binds {@link CarEnrolmentService} and starts the enrolment process.
+ * Setup activity that binds {@link CarTrustAgentBleService} and starts the enrolment process.
*/
public class CarEnrolmentActivity extends Activity {
- private static String TAG = "CarEnrolment";
- private static String SP_HANDLE_KEY = "sp-test";
- private TextView mOutputText;
- private TextView mStartButton;
+ private static final String TAG = CarEnrolmentActivity.class.getSimpleName();
- private long mHandle;
+ private static final String SP_HANDLE_KEY = "sp-test";
+ private static final int FINE_LOCATION_REQUEST_CODE = 42;
- private CarEnrolmentService mEnrolmentService;
-
- private BluetoothDevice mDevice;
-
- private boolean mServiceBound;
-
- private LocalBroadcastManager mLocalBroadcastManager;
-
- private SharedPreferences mPrefs;
-
- private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
+ private final ICarTrustAgentTokenResponseCallback mCarTrustAgentTokenResponseCallback =
+ new ICarTrustAgentTokenResponseCallback.Stub() {
@Override
- public void onReceive(Context context, Intent intent) {
- intent.getPackage();
+ public void onEscrowTokenAdded(byte[] token, long handle, int uid) {
+ runOnUiThread(() -> {
+ mPrefs.edit().putLong(SP_HANDLE_KEY, handle).apply();
+ Log.d(TAG, "stored new handle");
+ });
- String action = intent.getAction();
- if (Log.isLoggable(TAG, Log.DEBUG)) {
- Log.d(TAG, "Received broadcast: " + action);
+ if (mBluetoothDevice == null) {
+ Log.e(TAG, "No active bluetooth found to add escrow token");
+ return;
}
- if (ACTION_TOKEN_STATUS_RESULT.equals(action)) {
- boolean tokenActive = intent.getBooleanExtra(INTENT_EXTRA_TOKEN_STATUS, false);
- appendOutputText("Is token active? " + tokenActive + " handle: " + mHandle);
- } else if (ACTION_ADD_TOKEN_RESULT.equals(action)) {
- final long handle = intent.getLongExtra(INTENT_EXTRA_TOKEN_HANDLE, -1);
+ try {
+ // Notify the enrolment client that escrow token has been added
+ mCarTrustAgentBleService.sendEnrolmentHandle(mBluetoothDevice, handle);
+ appendOutputText("Escrow Token Added. Handle: " + handle);
+ appendOutputText("Lock and unlock the device to activate token");
+ } catch (RemoteException e) {
+ Log.e(TAG, "Error sendEnrolmentHandle", e);
+ }
+ }
- runOnUiThread(new Runnable() {
- @Override
- public void run() {
- mPrefs.edit().putLong(SP_HANDLE_KEY, handle).apply();
- if (Log.isLoggable(TAG, Log.DEBUG)) {
- Log.d(TAG, "stored new handle");
- }
- }
- });
+ @Override
+ public void onEscrowTokenRemoved(long handle, boolean successful) {
+ appendOutputText("Escrow token Removed. Handle: " + handle);
+ }
- mEnrolmentService.sendHandle(handle, mDevice);
- appendOutputText("Escrow Token Added. Handle: " + handle
- + "\nLock and unlock the device to activate token");
+ @Override
+ public void onEscrowTokenActiveStateChanged(long handle, boolean active) {
+ appendOutputText("Is token active? " + active + " handle: " + handle);
+ }
+ };
+
+ private final ICarTrustAgentBleCallback mBleConnectionCallback =
+ new ICarTrustAgentBleCallback.Stub() {
+ @Override
+ public void onBleServerStartSuccess() {
+ appendOutputText("Server started");
+ }
+
+ @Override
+ public void onBleServerStartFailure(int errorCode) {
+ appendOutputText("Server failed to start, error code: " + errorCode);
+ }
+
+ @Override
+ public void onBleDeviceConnected(BluetoothDevice device) {
+ mBluetoothDevice = device;
+ appendOutputText("Device connected: " + device.getName()
+ + " address: " + device.getAddress());
+ }
+
+ @Override
+ public void onBleDeviceDisconnected(BluetoothDevice device) {
+ mBluetoothDevice = null;
+ appendOutputText("Device disconnected: " + device.getName()
+ + " address: " + device.getAddress());
+ }
+ };
+
+ private final ICarTrustAgentEnrolmentCallback mEnrolmentCallback =
+ new ICarTrustAgentEnrolmentCallback.Stub() {
+ @Override
+ public void onEnrolmentDataReceived(byte[] token) {
+ appendOutputText("Enrolment data received ");
+ try {
+ addEscrowToken(token);
+ } catch (RemoteException e) {
+ Log.e(TAG, "Error addEscrowToken", e);
}
}
};
+ private final ServiceConnection mServiceConnection = new ServiceConnection() {
+ @Override
+ public void onServiceConnected(ComponentName name, IBinder service) {
+ mCarTrustAgentBleServiceBound = true;
+ mCarTrustAgentBleService = ICarTrustAgentBleService.Stub.asInterface(service);
+ try {
+ mCarTrustAgentBleService.registerBleCallback(mBleConnectionCallback);
+ mCarTrustAgentBleService.registerEnrolmentCallback(mEnrolmentCallback);
+ mCarTrustAgentBleService.setTokenResponseCallback(
+ mCarTrustAgentTokenResponseCallback);
+ mCarTrustAgentBleService.startEnrolmentAdvertising();
+ } catch (RemoteException e) {
+ Log.e(TAG, "Error startEnrolmentAdvertising", e);
+ }
+ }
+
+ @Override
+ public void onServiceDisconnected(ComponentName name) {
+ if (mCarTrustAgentBleService != null) {
+ try {
+ mCarTrustAgentBleService.unregisterBleCallback(mBleConnectionCallback);
+ mCarTrustAgentBleService.unregisterEnrolmentCallback(mEnrolmentCallback);
+ mCarTrustAgentBleService.setTokenResponseCallback(null);
+ mCarTrustAgentBleService.stopEnrolmentAdvertising();
+ } catch (RemoteException e) {
+ Log.e(TAG, "Error unregister callbacks", e);
+ }
+ mCarTrustAgentBleService = null;
+ }
+ mCarTrustAgentBleServiceBound = false;
+ }
+ };
+
+ private TextView mOutputText;
+ private BluetoothDevice mBluetoothDevice;
+ private ICarTrustAgentBleService mCarTrustAgentBleService;
+ private boolean mCarTrustAgentBleServiceBound;
+ private SharedPreferences mPrefs;
+
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
- setContentView(R.layout.car_client);
- mOutputText = (TextView) findViewById(R.id.textfield);
-
- final Intent intent = new Intent(this, CarEnrolmentService.class);
-
+ setContentView(R.layout.car_enrolment_activity);
+ mOutputText = findViewById(R.id.textfield);
mPrefs = PreferenceManager.getDefaultSharedPreferences(this /* context */);
- IntentFilter filter = new IntentFilter();
- filter.addAction(ACTION_TOKEN_STATUS_RESULT);
- filter.addAction(ACTION_ADD_TOKEN_RESULT);
-
- mLocalBroadcastManager = LocalBroadcastManager.getInstance(this /* context */);
- mLocalBroadcastManager.registerReceiver(mReceiver, filter);
-
- mStartButton = (Button) findViewById(R.id.start_button);
- mStartButton.setOnClickListener(new View.OnClickListener() {
- @Override
- public void onClick(View v) {
- // binding the service will start it if not started.
- bindService(intent, mServiceConnection, Context.BIND_AUTO_CREATE);
- }
+ findViewById(R.id.start_button).setOnClickListener((view) -> {
+ Intent bindIntent = new Intent(this, CarTrustAgentBleService.class);
+ bindService(bindIntent, mServiceConnection, Context.BIND_AUTO_CREATE);
});
- Button revokeButton = (Button) findViewById(R.id.revoke_trust_button);
- revokeButton.setOnClickListener(new View.OnClickListener() {
- @Override
- public void onClick(View v) {
- Intent intent = new Intent(CarBleTrustAgent.ACTION_REVOKE_TRUST);
- intent.setPackage(getPackageName());
- sendBroadcast(intent);
+ findViewById(R.id.revoke_trust_button).setOnClickListener((view) -> {
+ if (mCarTrustAgentBleServiceBound) {
+ try {
+ mCarTrustAgentBleService.revokeTrust();
+ } catch (RemoteException e) {
+ Log.e(TAG, "Error revokeTrust", e);
+ }
}
});
}
- private ServiceConnection mServiceConnection = new ServiceConnection() {
- public void onServiceConnected(ComponentName className,
- IBinder service) {
- mServiceBound = true;
- CarEnrolmentService.EnrolmentServiceBinder binder
- = (CarEnrolmentService.EnrolmentServiceBinder) service;
- mEnrolmentService = binder.getService();
- mEnrolmentService.addEnrolmentCallback(mEnrolmentCallback);
- mEnrolmentService.addConnectionListener(mConnectionListener);
- mEnrolmentService.start();
- }
-
- public void onServiceDisconnected(ComponentName arg0) {
- mEnrolmentService = null;
- mServiceBound = false;
- }
- };
-
@Override
- public void onResume() {
+ protected void onResume() {
super.onResume();
- if (!mPrefs.contains(SP_HANDLE_KEY)) {
- appendOutputText("No handles found.");
- return;
- }
-
- try {
- mHandle = mPrefs.getLong(SP_HANDLE_KEY, -1);
- if (Log.isLoggable(TAG, Log.DEBUG)) {
- Log.d(TAG, "onResume, checking handle active: " + mHandle);
+ if (checkSelfPermission(Manifest.permission.ACCESS_FINE_LOCATION) !=
+ PackageManager.PERMISSION_GRANTED) {
+ requestPermissions(
+ new String[] { android.Manifest.permission.ACCESS_FINE_LOCATION },
+ FINE_LOCATION_REQUEST_CODE);
+ } else {
+ long tokenHandle = getTokenHandle();
+ if (tokenHandle != -1) {
+ Log.d(TAG, "onResume, checking handle active: " + tokenHandle);
+ if (mCarTrustAgentBleServiceBound) {
+ try {
+ // Due to the asynchronous nature of isEscrowTokenActive in
+ // TrustAgentService, query result will be delivered via
+ // {@link #mCarTrustAgentTokenResponseCallback}
+ mCarTrustAgentBleService.isEscrowTokenActive(tokenHandle,
+ UserHandle.myUserId());
+ } catch (RemoteException e) {
+ Log.e(TAG, "Error isEscrowTokenActive", e);
+ }
+ }
+ } else {
+ appendOutputText("No handles found");
}
- isTokenActive(mHandle);
- } catch (RemoteException e) {
- Log.e(TAG, "Error checking if token is valid");
- appendOutputText("Error checking if token is valid");
}
}
@Override
- public void onDestroy() {
- if (mServiceBound) {
+ protected void onDestroy() {
+ if (mCarTrustAgentBleServiceBound) {
unbindService(mServiceConnection);
}
super.onDestroy();
}
private void appendOutputText(final String text) {
- runOnUiThread(new Runnable() {
- @Override
- public void run() {
- mOutputText.append("\n" + text);
- }
- });
+ runOnUiThread(() -> mOutputText.append("\n" + text));
}
- private ConnectionListener mConnectionListener = new ConnectionListener() {
- @Override
- public void onServerStarted() {
- appendOutputText("Server started");
+ private void addEscrowToken(byte[] token) throws RemoteException {
+ if (!mCarTrustAgentBleServiceBound) {
+ Log.e(TAG, "No CarTrustAgentBleService bounded");
+ return;
}
-
- @Override
- public void onServerStartFailed(int errorCode) {
- appendOutputText("Server failed to start, error code: " + errorCode);
- }
-
- @Override
- public void onDeviceConnected(BluetoothDevice device) {
- mDevice = device;
- appendOutputText("Device connected: " + device.getName()
- + " addr: " + device.getAddress());
- }
- };
-
- private EnrolmentCallback mEnrolmentCallback = new EnrolmentCallback() {
- @Override
- public void onEnrolmentDataReceived(byte[] token) {
- appendOutputText("Enrolment data received ");
- addEscrowToken(token);
- }
- };
-
- private void isTokenActive(long handle) throws RemoteException {
- Intent intent = new Intent();
- intent.setAction(CarBleTrustAgent.ACTION_IS_TOKEN_ACTIVE);
- intent.putExtra(CarBleTrustAgent.INTENT_EXTRA_TOKEN_HANDLE, handle);
-
- mLocalBroadcastManager.sendBroadcast(intent);
+ mCarTrustAgentBleService.addEscrowToken(token, UserHandle.myUserId());
}
- private void addEscrowToken(byte[] token) {
- long handle;
-
- if (mPrefs.contains(SP_HANDLE_KEY)) {
- handle = mPrefs.getLong(SP_HANDLE_KEY, -1);
- appendOutputText("Removing old token, handle value: " + handle);
- Intent intent = new Intent();
- intent.setAction(CarBleTrustAgent.ACTION_REMOVE_TOKEN);
- intent.putExtra(CarBleTrustAgent.INTENT_EXTRA_TOKEN_HANDLE, handle);
- mLocalBroadcastManager.sendBroadcast(intent);
- }
-
- Intent intent = new Intent();
- intent.setAction(CarBleTrustAgent.ACTION_ADD_TOKEN);
- intent.putExtra(CarBleTrustAgent.INTENT_EXTRA_ESCROW_TOKEN, token);
-
- mLocalBroadcastManager.sendBroadcast(intent);
+ private long getTokenHandle() {
+ return mPrefs.getLong(SP_HANDLE_KEY, -1);
}
}
diff --git a/TrustAgent/src/com/android/car/trust/CarEnrolmentService.java b/TrustAgent/src/com/android/car/trust/CarEnrolmentService.java
deleted file mode 100644
index e6bbee2..0000000
--- a/TrustAgent/src/com/android/car/trust/CarEnrolmentService.java
+++ /dev/null
@@ -1,129 +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.android.car.trust;
-
-import android.bluetooth.BluetoothDevice;
-import android.bluetooth.BluetoothGattCharacteristic;
-import android.bluetooth.BluetoothGattService;
-import android.content.Intent;
-import android.os.Binder;
-import android.os.IBinder;
-import android.os.ParcelUuid;
-import android.util.Log;
-import com.android.car.trust.comms.SimpleBleServer;
-
-import java.util.HashSet;
-import java.util.UUID;
-
-/**
- * A service that receives escrow token enrollment requests from remote devices.
- */
-public class CarEnrolmentService extends SimpleBleServer {
- private static final String TAG = "CarEnrolmentService";
-
- public interface EnrolmentCallback {
- void onEnrolmentDataReceived(byte[] token);
- }
-
- private BluetoothGattService mEnrolmentService;
- private BluetoothGattCharacteristic mEnrolmentEscrowToken;
- private BluetoothGattCharacteristic mEnrolmentTokenHandle;
-
- private HashSet<EnrolmentCallback> mCallbacks;
-
- private final IBinder mBinder = new EnrolmentServiceBinder();
-
- @Override
- public void onCreate() {
- super.onCreate();
- mCallbacks = new HashSet<>();
- setupEnrolmentService();
- }
-
- public void start() {
- ParcelUuid uuid = new ParcelUuid(
- UUID.fromString(getString(R.string.enrollment_service_uuid)));
- start(uuid, mEnrolmentService);
- }
-
- @Override
- public IBinder onBind(Intent intent) {
- return mBinder;
- }
-
- @Override
- public void onCharacteristicWrite(BluetoothDevice device,
- int requestId, BluetoothGattCharacteristic characteristic,
- boolean preparedWrite, boolean responseNeeded, int offset, byte[] value) {
- if (characteristic.getUuid().equals(mEnrolmentEscrowToken.getUuid())) {
- if (Log.isLoggable(TAG, Log.DEBUG)) {
- Log.d(TAG, "Enrolment token received, value: " + Utils.getLong(value));
- }
-
- for (EnrolmentCallback callback : mCallbacks) {
- callback.onEnrolmentDataReceived(value);
- }
- }
- }
-
- @Override
- public void onCharacteristicRead(BluetoothDevice device,
- int requestId, int offset, BluetoothGattCharacteristic characteristic) {
- //Enrolment service should not have any read requests.
- }
-
- public void addEnrolmentCallback(EnrolmentCallback callback) {
- mCallbacks.add(callback);
- }
-
- public void sendHandle(long handle, BluetoothDevice device) {
- mEnrolmentTokenHandle.setValue(Utils.getBytes(handle));
-
- if (Log.isLoggable(TAG, Log.DEBUG)) {
- Log.d(TAG, "Sending notification for EscrowToken Handle");
- }
- mGattServer.notifyCharacteristicChanged(device,
- mEnrolmentTokenHandle, false /* confirm */);
- }
-
- public class EnrolmentServiceBinder extends Binder {
- public CarEnrolmentService getService() {
- return CarEnrolmentService.this;
- }
- }
-
- // Create services and characteristics for enrolling new unlocking escrow tokens
- private void setupEnrolmentService() {
- mEnrolmentService = new BluetoothGattService(
- UUID.fromString(getString(R.string.enrollment_service_uuid)),
- BluetoothGattService.SERVICE_TYPE_PRIMARY);
-
- // Characteristic to describe the escrow token being used for unlock
- mEnrolmentEscrowToken = new BluetoothGattCharacteristic(
- UUID.fromString(getString(R.string.enrollment_token_uuid)),
- BluetoothGattCharacteristic.PROPERTY_WRITE,
- BluetoothGattCharacteristic.PERMISSION_WRITE);
-
- // Characteristic to describe the handle being used for this escrow token
- mEnrolmentTokenHandle = new BluetoothGattCharacteristic(
- UUID.fromString(getString(R.string.enrollment_handle_uuid)),
- BluetoothGattCharacteristic.PROPERTY_NOTIFY,
- BluetoothGattCharacteristic.PERMISSION_READ);
-
- mEnrolmentService.addCharacteristic(mEnrolmentEscrowToken);
- mEnrolmentService.addCharacteristic(mEnrolmentTokenHandle);
- }
-}
diff --git a/TrustAgent/src/com/android/car/trust/CarTrustAgentBleService.java b/TrustAgent/src/com/android/car/trust/CarTrustAgentBleService.java
new file mode 100644
index 0000000..f8ba90f
--- /dev/null
+++ b/TrustAgent/src/com/android/car/trust/CarTrustAgentBleService.java
@@ -0,0 +1,377 @@
+/*
+ * 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.trust;
+
+import android.bluetooth.BluetoothDevice;
+import android.bluetooth.BluetoothGattCharacteristic;
+import android.bluetooth.BluetoothGattService;
+import android.car.trust.ICarTrustAgentBleCallback;
+import android.car.trust.ICarTrustAgentBleService;
+import android.car.trust.ICarTrustAgentEnrolmentCallback;
+import android.car.trust.ICarTrustAgentTokenRequestDelegate;
+import android.car.trust.ICarTrustAgentTokenResponseCallback;
+import android.car.trust.ICarTrustAgentUnlockCallback;
+import android.content.Intent;
+import android.os.IBinder;
+import android.os.ParcelUuid;
+import android.os.RemoteCallbackList;
+import android.os.RemoteException;
+import android.util.Log;
+
+import java.nio.ByteBuffer;
+import java.util.UUID;
+
+/**
+ * Abstracts enrolment and unlock token exchange via BluetoothLE (BLE).
+ * {@link CarBleTrustAgent} and any enrolment client should bind to
+ * {@link ICarTrustAgentBleService}.
+ */
+public class CarTrustAgentBleService extends SimpleBleServer {
+
+ private static final String TAG = CarTrustAgentBleService.class.getSimpleName();
+
+ private RemoteCallbackList<ICarTrustAgentBleCallback> mBleCallbacks;
+ private RemoteCallbackList<ICarTrustAgentEnrolmentCallback> mEnrolmentCallbacks;
+ private RemoteCallbackList<ICarTrustAgentUnlockCallback> mUnlockCallbacks;
+ private ICarTrustAgentTokenRequestDelegate mTokenRequestDelegate;
+ private ICarTrustAgentTokenResponseCallback mTokenResponseCallback;
+ private CarTrustAgentBleWrapper mCarTrustBleService;
+
+ private ParcelUuid mEnrolmentUuid;
+ private BluetoothGattCharacteristic mEnrolmentEscrowToken;
+ private BluetoothGattCharacteristic mEnrolmentTokenHandle;
+ private BluetoothGattService mEnrolmentGattServer;
+
+ private ParcelUuid mUnlockUuid;
+ private BluetoothGattCharacteristic mUnlockEscrowToken;
+ private BluetoothGattCharacteristic mUnlockTokenHandle;
+ private BluetoothGattService mUnlockGattServer;
+ private byte[] mCurrentUnlockToken;
+ private Long mCurrentUnlockHandle;
+
+ @Override
+ public void onCreate() {
+ super.onCreate();
+ mBleCallbacks = new RemoteCallbackList<>();
+ mEnrolmentCallbacks = new RemoteCallbackList<>();
+ mUnlockCallbacks = new RemoteCallbackList<>();
+ mCarTrustBleService = new CarTrustAgentBleWrapper();
+
+ setupEnrolmentBleServer();
+ setupUnlockBleServer();
+ }
+
+ @Override
+ public IBinder onBind(Intent intent) {
+ return mCarTrustBleService;
+ }
+
+ @Override
+ public int onStartCommand(Intent intent, int flags, int startId) {
+ // keep it alive.
+ return START_STICKY;
+ }
+
+ @Override
+ public void onCharacteristicWrite(final BluetoothDevice device, int requestId,
+ BluetoothGattCharacteristic characteristic, boolean preparedWrite, boolean
+ responseNeeded, int offset, byte[] value) {
+ UUID uuid = characteristic.getUuid();
+ Log.d(TAG, "onCharacteristicWrite received uuid: " + uuid);
+ if (uuid.equals(mEnrolmentEscrowToken.getUuid())) {
+ final int callbackCount = mEnrolmentCallbacks.beginBroadcast();
+ for (int i = 0; i < callbackCount; i++) {
+ try {
+ mEnrolmentCallbacks.getBroadcastItem(i).onEnrolmentDataReceived(value);
+ } catch (RemoteException e) {
+ Log.e(TAG, "Error callback onEnrolmentDataReceived", e);
+ }
+ }
+ mEnrolmentCallbacks.finishBroadcast();
+ } else if (uuid.equals(mUnlockEscrowToken.getUuid())) {
+ mCurrentUnlockToken = value;
+ maybeSendUnlockToken();
+ } else if (uuid.equals(mUnlockTokenHandle.getUuid())) {
+ mCurrentUnlockHandle = getLong(value);
+ maybeSendUnlockToken();
+ }
+ }
+
+ @Override
+ public void onCharacteristicRead(BluetoothDevice device,
+ int requestId, int offset, final BluetoothGattCharacteristic characteristic) {
+ // Ignored read requests.
+ }
+
+ @Override
+ protected void onAdvertiseStartSuccess() {
+ final int callbackCount = mBleCallbacks.beginBroadcast();
+ for (int i = 0; i < callbackCount; i++) {
+ try {
+ mBleCallbacks.getBroadcastItem(i).onBleServerStartSuccess();
+ } catch (RemoteException e) {
+ Log.e(TAG, "Error callback onBleServerStartSuccess", e);
+ }
+ }
+ mBleCallbacks.finishBroadcast();
+ }
+
+ @Override
+ protected void onAdvertiseStartFailure(int errorCode) {
+ final int callbackCount = mBleCallbacks.beginBroadcast();
+ for (int i = 0; i < callbackCount; i++) {
+ try {
+ mBleCallbacks.getBroadcastItem(i).onBleServerStartFailure(errorCode);
+ } catch (RemoteException e) {
+ Log.e(TAG, "Error callback onBleServerStartFailure", e);
+ }
+ }
+ mBleCallbacks.finishBroadcast();
+ }
+
+ @Override
+ protected void onAdvertiseDeviceConnected(BluetoothDevice device) {
+ final int callbackCount = mBleCallbacks.beginBroadcast();
+ for (int i = 0; i < callbackCount; i++) {
+ try {
+ mBleCallbacks.getBroadcastItem(i).onBleDeviceConnected(device);
+ } catch (RemoteException e) {
+ Log.e(TAG, "Error callback onBleDeviceConnected", e);
+ }
+ }
+ mBleCallbacks.finishBroadcast();
+ }
+
+ @Override
+ protected void onAdvertiseDeviceDisconnected(BluetoothDevice device) {
+ final int callbackCount = mBleCallbacks.beginBroadcast();
+ for (int i = 0; i < callbackCount; i++) {
+ try {
+ mBleCallbacks.getBroadcastItem(i).onBleDeviceDisconnected(device);
+ } catch (RemoteException e) {
+ Log.e(TAG, "Error callback onBleDeviceDisconnected", e);
+ }
+ }
+ mBleCallbacks.finishBroadcast();
+ }
+
+ private void setupEnrolmentBleServer() {
+ mEnrolmentUuid = new ParcelUuid(
+ UUID.fromString(getString(R.string.enrollment_service_uuid)));
+ mEnrolmentGattServer = new BluetoothGattService(
+ UUID.fromString(getString(R.string.enrollment_service_uuid)),
+ BluetoothGattService.SERVICE_TYPE_PRIMARY);
+
+ // Characteristic to describe the escrow token being used for unlock
+ mEnrolmentEscrowToken = new BluetoothGattCharacteristic(
+ UUID.fromString(getString(R.string.enrollment_token_uuid)),
+ BluetoothGattCharacteristic.PROPERTY_WRITE,
+ BluetoothGattCharacteristic.PERMISSION_WRITE);
+
+ // Characteristic to describe the handle being used for this escrow token
+ mEnrolmentTokenHandle = new BluetoothGattCharacteristic(
+ UUID.fromString(getString(R.string.enrollment_handle_uuid)),
+ BluetoothGattCharacteristic.PROPERTY_NOTIFY,
+ BluetoothGattCharacteristic.PERMISSION_READ);
+
+ mEnrolmentGattServer.addCharacteristic(mEnrolmentEscrowToken);
+ mEnrolmentGattServer.addCharacteristic(mEnrolmentTokenHandle);
+ }
+
+ private void setupUnlockBleServer() {
+ mUnlockUuid = new ParcelUuid(
+ UUID.fromString(getString(R.string.unlock_service_uuid)));
+ mUnlockGattServer = new BluetoothGattService(
+ UUID.fromString(getString(R.string.unlock_service_uuid)),
+ BluetoothGattService.SERVICE_TYPE_PRIMARY);
+
+ // Characteristic to describe the escrow token being used for unlock
+ mUnlockEscrowToken = new BluetoothGattCharacteristic(
+ UUID.fromString(getString(R.string.unlock_escrow_token_uiid)),
+ BluetoothGattCharacteristic.PROPERTY_WRITE,
+ BluetoothGattCharacteristic.PERMISSION_WRITE);
+
+ // Characteristic to describe the handle being used for this escrow token
+ mUnlockTokenHandle = new BluetoothGattCharacteristic(
+ UUID.fromString(getString(R.string.unlock_handle_uiid)),
+ BluetoothGattCharacteristic.PROPERTY_WRITE,
+ BluetoothGattCharacteristic.PERMISSION_WRITE);
+
+ mUnlockGattServer.addCharacteristic(mUnlockEscrowToken);
+ mUnlockGattServer.addCharacteristic(mUnlockTokenHandle);
+ }
+
+ private synchronized void maybeSendUnlockToken() {
+ if (mCurrentUnlockToken == null || mCurrentUnlockHandle == null) {
+ return;
+ }
+ Log.d(TAG, "Handle and token both received, requesting unlock. Time: "
+ + System.currentTimeMillis());
+ final int callbackCount = mUnlockCallbacks.beginBroadcast();
+ for (int i = 0; i < callbackCount; i++) {
+ try {
+ mUnlockCallbacks.getBroadcastItem(i).onUnlockDataReceived(
+ mCurrentUnlockToken, mCurrentUnlockHandle);
+ } catch (RemoteException e) {
+ Log.e(TAG, "Error callback onUnlockDataReceived", e);
+ }
+ }
+ mUnlockCallbacks.finishBroadcast();
+ mCurrentUnlockHandle = null;
+ mCurrentUnlockToken = null;
+ }
+
+ private static byte[] getBytes(long primitive) {
+ ByteBuffer buffer = ByteBuffer.allocate(Long.SIZE / Byte.SIZE);
+ buffer.putLong(0, primitive);
+ return buffer.array();
+ }
+
+ private static long getLong(byte[] bytes) {
+ ByteBuffer buffer = ByteBuffer.allocate(Long.SIZE / Byte.SIZE);
+ buffer.put(bytes);
+ buffer.flip();
+ return buffer.getLong();
+ }
+
+ private final class CarTrustAgentBleWrapper extends ICarTrustAgentBleService.Stub {
+ @Override
+ public void registerBleCallback(ICarTrustAgentBleCallback callback) {
+ mBleCallbacks.register(callback);
+ }
+
+ @Override
+ public void unregisterBleCallback(ICarTrustAgentBleCallback callback) {
+ mBleCallbacks.unregister(callback);
+ }
+
+ @Override
+ public void startEnrolmentAdvertising() {
+ Log.d(TAG, "startEnrolmentAdvertising");
+ stopUnlockAdvertising();
+ startAdvertising(mEnrolmentUuid, mEnrolmentGattServer);
+ }
+
+ @Override
+ public void stopEnrolmentAdvertising() {
+ Log.d(TAG, "stopEnrolmentAdvertising");
+ stopAdvertising();
+ }
+
+ @Override
+ public void sendEnrolmentHandle(BluetoothDevice device, long handle) {
+ Log.d(TAG, "sendEnrolmentHandle: " + handle);
+ mEnrolmentTokenHandle.setValue(getBytes(handle));
+ notifyCharacteristicChanged(device, mEnrolmentTokenHandle, false);
+ }
+
+ @Override
+ public void registerEnrolmentCallback(ICarTrustAgentEnrolmentCallback callback) {
+ mEnrolmentCallbacks.register(callback);
+ }
+
+ @Override
+ public void unregisterEnrolmentCallback(ICarTrustAgentEnrolmentCallback callback) {
+ mEnrolmentCallbacks.unregister(callback);
+ }
+
+ @Override
+ public void startUnlockAdvertising() {
+ Log.d(TAG, "startUnlockAdvertising");
+ stopEnrolmentAdvertising();
+ startAdvertising(mUnlockUuid, mUnlockGattServer);
+ }
+
+ @Override
+ public void stopUnlockAdvertising() {
+ Log.d(TAG, "stopUnlockAdvertising");
+ stopAdvertising();
+ }
+
+ @Override
+ public void registerUnlockCallback(ICarTrustAgentUnlockCallback callback) {
+ mUnlockCallbacks.register(callback);
+ }
+
+ @Override
+ public void unregisterUnlockCallback(ICarTrustAgentUnlockCallback callback) {
+ mUnlockCallbacks.unregister(callback);
+ }
+
+ @Override
+ public void setTokenRequestDelegate(ICarTrustAgentTokenRequestDelegate delegate) {
+ mTokenRequestDelegate = delegate;
+ }
+
+ @Override
+ public void revokeTrust() throws RemoteException {
+ if (mTokenRequestDelegate != null) {
+ mTokenRequestDelegate.revokeTrust();
+ }
+ }
+
+ @Override
+ public void addEscrowToken(byte[] token, int uid) throws RemoteException {
+ if (mTokenRequestDelegate != null) {
+ mTokenRequestDelegate.addEscrowToken(token, uid);
+ }
+ }
+
+ @Override
+ public void removeEscrowToken(long handle, int uid) throws RemoteException {
+ if (mTokenRequestDelegate != null) {
+ mTokenRequestDelegate.removeEscrowToken(handle, uid);
+ }
+ }
+
+ @Override
+ public void isEscrowTokenActive(long handle, int uid) throws RemoteException {
+ if (mTokenRequestDelegate != null) {
+ mTokenRequestDelegate.isEscrowTokenActive(handle, uid);
+ }
+ }
+
+ @Override
+ public void setTokenResponseCallback(ICarTrustAgentTokenResponseCallback callback) {
+ mTokenResponseCallback = callback;
+ }
+
+ @Override
+ public void onEscrowTokenAdded(byte[] token, long handle, int uid)
+ throws RemoteException {
+ Log.d(TAG, "onEscrowTokenAdded handle:" + handle + " uid:" + uid);
+ if (mTokenResponseCallback != null) {
+ mTokenResponseCallback.onEscrowTokenAdded(token, handle, uid);
+ }
+ }
+
+ @Override
+ public void onEscrowTokenRemoved(long handle, boolean successful) throws RemoteException {
+ Log.d(TAG, "onEscrowTokenRemoved handle:" + handle);
+ if (mTokenResponseCallback != null) {
+ mTokenResponseCallback.onEscrowTokenRemoved(handle, successful);
+ }
+ }
+
+ @Override
+ public void onEscrowTokenActiveStateChanged(long handle, boolean active)
+ throws RemoteException {
+ if (mTokenResponseCallback != null) {
+ mTokenResponseCallback.onEscrowTokenActiveStateChanged(handle, active);
+ }
+ }
+ }
+}
diff --git a/TrustAgent/src/com/android/car/trust/CarUnlockService.java b/TrustAgent/src/com/android/car/trust/CarUnlockService.java
deleted file mode 100644
index 0c1bc89..0000000
--- a/TrustAgent/src/com/android/car/trust/CarUnlockService.java
+++ /dev/null
@@ -1,157 +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.android.car.trust;
-
-import android.bluetooth.BluetoothDevice;
-import android.bluetooth.BluetoothGattCharacteristic;
-import android.bluetooth.BluetoothGattService;
-import android.content.Intent;
-import android.os.Binder;
-import android.os.IBinder;
-import android.os.ParcelUuid;
-import android.util.Log;
-import com.android.car.trust.comms.SimpleBleServer;
-
-import java.util.UUID;
-
-/**
- * A service that receives unlock requests from remote devices.
- */
-public class CarUnlockService extends SimpleBleServer {
- /**
- * A callback to receives callback
- */
- public interface UnlockServiceCallback {
- void unlockDevice(byte[] token, long handle);
- }
-
- private static final String TAG = "CarUnlockService";
-
- private BluetoothGattService mUnlockService;
- private BluetoothGattCharacteristic mUnlockEscrowToken;
- private BluetoothGattCharacteristic mUnlockTokenHandle;
-
- private UnlockServiceCallback mCallback;
-
- private byte[] mCurrentToken;
- private Long mCurrentHandle;
-
- private final IBinder mBinder = new UnlockServiceBinder();
-
- public class UnlockServiceBinder extends Binder {
- public CarUnlockService getService() {
- return CarUnlockService.this;
- }
- }
-
- @Override
- public void onCreate() {
- super.onCreate();
- if (Log.isLoggable(TAG, Log.DEBUG)) {
- Log.d(TAG, "CarUnlockService starting up, creating BLE service");
- }
- setupUnlockService();
- }
-
- /**
- * Start advertising the BLE unlock service
- */
- public void start() {
- ParcelUuid uuid = new ParcelUuid(
- UUID.fromString(getString(R.string.unlock_service_uuid)));
- start(uuid, mUnlockService);
- }
-
- public void addUnlockServiceCallback(UnlockServiceCallback callback) {
- mCallback = callback;
- }
-
- @Override
- public IBinder onBind(Intent intent) {
- return mBinder;
- }
-
- @Override
- public void onCharacteristicWrite(BluetoothDevice device,
- int requestId, BluetoothGattCharacteristic characteristic,
- boolean preparedWrite, boolean responseNeeded, int offset, byte[] value) {
- UUID uuid = characteristic.getUuid();
-
- if (uuid.equals(mUnlockTokenHandle.getUuid())) {
- if (Log.isLoggable(TAG, Log.DEBUG)) {
- Log.d(TAG, "Unlock handle received, value: " + Utils.getLong(value));
- }
- mCurrentHandle = Utils.getLong(value);
- unlockDataReceived();
- } else if (uuid.equals(mUnlockEscrowToken.getUuid())) {
- if (Log.isLoggable(TAG, Log.DEBUG)) {
- Log.d(TAG, "Unlock escrow token received, value: " + Utils.getLong(value));
- }
- mCurrentToken = value;
- unlockDataReceived();
- }
- }
-
- @Override
- public void onCharacteristicRead(BluetoothDevice device,
- int requestId, int offset, BluetoothGattCharacteristic characteristic) {
- // The BLE unlock service should not receive any read requests.
- }
-
- private synchronized void unlockDataReceived() {
- // If any piece of the unlocking data is not received, then do not unlock.
- if (mCurrentHandle == null || mCurrentToken == null) {
- return;
- }
-
- if (Log.isLoggable(TAG, Log.DEBUG)) {
- Log.d(TAG, "Handle and token both received, requesting unlock. Time: "
- + System.currentTimeMillis());
- }
- // Both the handle and token has been received, try to unlock the device.
-
-
- mCallback.unlockDevice(mCurrentToken, mCurrentHandle);
-
- // Once we've notified the client of the unlocking data, clear it out.
- mCurrentToken = null;
- mCurrentHandle = null;
- }
-
-
- // Create services and characteristics to receive tokens and handles for unlocking the device.
- private void setupUnlockService() {
- mUnlockService = new BluetoothGattService(
- UUID.fromString(getString(R.string.unlock_service_uuid)),
- BluetoothGattService.SERVICE_TYPE_PRIMARY);
-
- // Characteristic to describe the escrow token being used for unlock
- mUnlockEscrowToken = new BluetoothGattCharacteristic(
- UUID.fromString(getString(R.string.unlock_escrow_token_uiid)),
- BluetoothGattCharacteristic.PROPERTY_WRITE,
- BluetoothGattCharacteristic.PERMISSION_WRITE);
-
- // Characteristic to describe the handle being used for this escrow token
- mUnlockTokenHandle = new BluetoothGattCharacteristic(
- UUID.fromString(getString(R.string.unlock_handle_uiid)),
- BluetoothGattCharacteristic.PROPERTY_WRITE,
- BluetoothGattCharacteristic.PERMISSION_WRITE);
-
- mUnlockService.addCharacteristic(mUnlockEscrowToken);
- mUnlockService.addCharacteristic(mUnlockTokenHandle);
- }
-
-}
diff --git a/TrustAgent/src/com/android/car/trust/MainActivity.java b/TrustAgent/src/com/android/car/trust/MainActivity.java
deleted file mode 100644
index 8c1348b..0000000
--- a/TrustAgent/src/com/android/car/trust/MainActivity.java
+++ /dev/null
@@ -1,94 +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.android.car.trust;
-
-import android.app.Activity;
-import android.content.Intent;
-import android.content.pm.PackageManager;
-import android.os.Bundle;
-import android.view.View;
-import android.widget.Button;
-
-/**
- * Selects whether the device is started as the car or remote device.
- */
-public class MainActivity extends Activity {
- private static final int FINE_LOCATION_REQUEST_CODE = 13;
-
- private Button mCarEnrolmentButton;
- private Button mPhoneEnrolmentButton;
- private Button mPhoneUnlockButton;
-
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.main_app);
- mCarEnrolmentButton = (Button) findViewById(R.id.car_button);
- mPhoneEnrolmentButton = (Button) findViewById(R.id.phone_enrolment_button);
- mPhoneUnlockButton = (Button) findViewById(R.id.phone_unlock_button);
-
- mCarEnrolmentButton.setOnClickListener(new View.OnClickListener() {
- @Override
- public void onClick(View v) {
- Intent intent = new Intent(MainActivity.this /* context */,
- CarEnrolmentActivity.class);
- startActivity(intent);
- }
- });
-
- mPhoneEnrolmentButton.setOnClickListener(new View.OnClickListener() {
- @Override
- public void onClick(View v) {
- Intent intent = new Intent(MainActivity.this /* context */,
- PhoneEnrolmentActivity.class);
- startActivity(intent);
- }
- });
-
- mPhoneUnlockButton.setOnClickListener(new View.OnClickListener() {
- @Override
- public void onClick(View v) {
- Intent intent = new Intent(MainActivity.this /* context */,
- PhoneUnlockActivity.class);
- startActivity(intent);
- }
- });
-
- if (!checkPermissionGranted()) {
- requestPermissions(new String[]{android.Manifest.permission.ACCESS_FINE_LOCATION},
- FINE_LOCATION_REQUEST_CODE);
- // If location access isn't granted, BLE scanning will fail.
- mCarEnrolmentButton.setEnabled(false);
- mPhoneEnrolmentButton.setEnabled(false);
- mPhoneUnlockButton.setEnabled(false);
- }
- }
-
- @Override
- public void onRequestPermissionsResult(int requestCode,
- String permissions[], int[] grantResults) {
- if (requestCode == FINE_LOCATION_REQUEST_CODE && checkPermissionGranted()) {
- mCarEnrolmentButton.setEnabled(true);
- mPhoneEnrolmentButton.setEnabled(true);
- mPhoneUnlockButton.setEnabled(true);
- }
- }
-
- private boolean checkPermissionGranted() {
- return checkSelfPermission(android.Manifest.permission.ACCESS_FINE_LOCATION)
- == PackageManager.PERMISSION_GRANTED;
- }
-}
\ No newline at end of file
diff --git a/TrustAgent/src/com/android/car/trust/PhoneEnrolmentActivity.java b/TrustAgent/src/com/android/car/trust/PhoneEnrolmentActivity.java
deleted file mode 100644
index 6e187e2..0000000
--- a/TrustAgent/src/com/android/car/trust/PhoneEnrolmentActivity.java
+++ /dev/null
@@ -1,52 +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.android.car.trust;
-
-import android.app.Activity;
-import android.os.Bundle;
-import android.widget.Button;
-import android.widget.TextView;
-
-/**
- * Activity to allow the user to add an escrow token to a remote device. <p/>
- *
- * For this to work properly, the correct permissions must be set in the system config. In AOSP,
- * this config is in frameworks/base/core/res/res/values/config.xml <p/>
- *
- * The config must set config_allowEscrowTokenForTrustAgent to true. For the desired car
- * experience, the config should also set config_strongAuthRequiredOnBoot to false.
- */
-public class PhoneEnrolmentActivity extends Activity {
- private Button mScanButton;
- private Button mEnrollButton;
-
- private TextView mTextOutput;
-
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.phone_client);
-
- mScanButton = (Button) findViewById(R.id.ble_scan_btn);
- mEnrollButton = (Button) findViewById(R.id.action_button);
- mEnrollButton.setText(getString(R.string.enroll_button));
-
- mTextOutput = (TextView) findViewById(R.id.output);
-
- PhoneEnrolmentController controller = new PhoneEnrolmentController(this /* context */);
- controller.bind(mTextOutput, mScanButton, mEnrollButton);
- }
-}
diff --git a/TrustAgent/src/com/android/car/trust/PhoneEnrolmentController.java b/TrustAgent/src/com/android/car/trust/PhoneEnrolmentController.java
deleted file mode 100644
index b887dc4..0000000
--- a/TrustAgent/src/com/android/car/trust/PhoneEnrolmentController.java
+++ /dev/null
@@ -1,209 +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.android.car.trust;
-
-import android.bluetooth.BluetoothDevice;
-import android.bluetooth.BluetoothGatt;
-import android.bluetooth.BluetoothGattCharacteristic;
-import android.bluetooth.BluetoothGattService;
-import android.content.Context;
-import android.content.SharedPreferences;
-import android.os.Handler;
-import android.os.ParcelUuid;
-import android.preference.PreferenceManager;
-import android.util.Base64;
-import android.util.Log;
-import android.view.View;
-import android.widget.Button;
-import android.widget.TextView;
-import com.android.car.trust.comms.SimpleBleClient;
-
-import java.nio.ByteBuffer;
-import java.util.Random;
-import java.util.UUID;
-
-/**
- * A controller that sets up a {@link SimpleBleClient} to connect to the BLE enrollment service.
- * It also binds the UI components to control the enrollment process.
- */
-public class PhoneEnrolmentController {
- private static final String TAG = "PhoneEnrolmentCtlr";
- private String mTokenHandleKey;
- private String mEscrowTokenKey;
-
- // BLE characteristics associated with the enrollment/add escrow token service.
- private BluetoothGattCharacteristic mEnrolmentTokenHandle;
- private BluetoothGattCharacteristic mEnrolmentEscrowToken;
-
- private ParcelUuid mEnrolmentServiceUuid;
-
- private SimpleBleClient mClient;
- private Context mContext;
-
- private TextView mTextView;
- private Handler mHandler;
-
- private Button mScanButton;
- private Button mEnrolButton;
-
- public PhoneEnrolmentController(Context context) {
- mContext = context;
-
- mTokenHandleKey = context.getString(R.string.pref_key_token_handle);
- mEscrowTokenKey = context.getString(R.string.pref_key_escrow_token);
-
- mClient = new SimpleBleClient(context);
- mEnrolmentServiceUuid = new ParcelUuid(
- UUID.fromString(mContext.getString(R.string.enrollment_service_uuid)));
- mClient.addCallback(mCallback /* callback */);
-
- mHandler = new Handler(mContext.getMainLooper());
- }
-
- /**
- * Binds the views to the actions that can be performed by this controller.
- *
- * @param textView A text view used to display results from various BLE actions
- * @param scanButton Button used to start scanning for available BLE devices.
- * @param enrolButton Button used to send new escrow token to remote device.
- */
- public void bind(TextView textView, Button scanButton, Button enrolButton) {
- mTextView = textView;
- mScanButton = scanButton;
- mEnrolButton = enrolButton;
-
- mScanButton.setOnClickListener(new View.OnClickListener() {
- @Override
- public void onClick(View v) {
- mClient.start(mEnrolmentServiceUuid);
- }
- });
-
- mEnrolButton.setEnabled(false);
- mEnrolButton.setAlpha(0.3f);
- mEnrolButton.setOnClickListener(new View.OnClickListener() {
- @Override
- public void onClick(View v) {
- appendOutputText("Sending new escrow token to remote device");
-
- byte[] token = generateEscrowToken();
- sendEnrolmentRequest(token);
-
- // WARNING: Store the token so it can be used later for unlocking. This token
- // should NEVER be stored on the device that is being unlocked. It should
- // always be securely stored on a remote device that will trigger the unlock.
- storeToken(token);
- }
- });
- }
-
- /**
- * @return A random byte array that is used as the escrow token for remote device unlock.
- */
- private byte[] generateEscrowToken() {
- Random random = new Random();
- ByteBuffer buffer = ByteBuffer.allocate(Long.SIZE / Byte.SIZE);
- buffer.putLong(0, random.nextLong());
- return buffer.array();
- }
-
- private void sendEnrolmentRequest(byte[] token) {
- mEnrolmentEscrowToken.setValue(token);
- mClient.writeCharacteristic(mEnrolmentEscrowToken);
- storeToken(token);
- }
-
- private SimpleBleClient.ClientCallback mCallback = new SimpleBleClient.ClientCallback() {
- @Override
- public void onDeviceConnected(BluetoothDevice device) {
- appendOutputText("Device connected: " + device.getName()
- + " addr: " + device.getAddress());
- }
-
- @Override
- public void onDeviceDisconnected() {
- appendOutputText("Device disconnected");
- }
-
- @Override
- public void onCharacteristicChanged(BluetoothGatt gatt,
- BluetoothGattCharacteristic characteristic) {
-
- if (Log.isLoggable(TAG, Log.DEBUG)) {
- Log.d(TAG, "onCharacteristicChanged: " + Utils.getLong(characteristic.getValue()));
- }
-
- if (characteristic.getUuid().equals(mEnrolmentTokenHandle.getUuid())) {
- // Store the new token handle that the BLE server is sending us. This required
- // to unlock the device.
- long handle = Utils.getLong(characteristic.getValue());
- storeHandle(handle);
- appendOutputText("Token handle received: " + handle);
- }
- }
-
- @Override
- public void onServiceDiscovered(BluetoothGattService service) {
- if (!service.getUuid().equals(mEnrolmentServiceUuid.getUuid())) {
- if (Log.isLoggable(TAG, Log.DEBUG)) {
- Log.d(TAG, "Service UUID: " + service.getUuid()
- + " does not match Enrolment UUID " + mEnrolmentServiceUuid.getUuid());
- }
- return;
- }
-
- if (Log.isLoggable(TAG, Log.DEBUG)) {
- Log.d(TAG, "Enrolment Service # characteristics: "
- + service.getCharacteristics().size());
- }
- mEnrolmentEscrowToken
- = Utils.getCharacteristic(R.string.enrollment_token_uuid, service, mContext);
- mEnrolmentTokenHandle
- = Utils.getCharacteristic(R.string.enrollment_handle_uuid, service, mContext);
- mClient.setCharacteristicNotification(mEnrolmentTokenHandle, true /* enable */);
- appendOutputText("Enrolment BLE client successfully connected");
-
- mHandler.post(new Runnable() {
- @Override
- public void run() {
- // Services are now set up, allow users to enrol new escrow tokens.
- mEnrolButton.setEnabled(true);
- mEnrolButton.setAlpha(1.0f);
- }
- });
- }
- };
-
- private void storeHandle(long handle) {
- SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(mContext);
- prefs.edit().putLong(mTokenHandleKey, handle).apply();
- }
-
- private void storeToken(byte[] token) {
- SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(mContext);
- String byteArray = Base64.encodeToString(token, Base64.DEFAULT);
- prefs.edit().putString(mEscrowTokenKey, byteArray).apply();
- }
-
- private void appendOutputText(final String text) {
- mHandler.post(new Runnable() {
- @Override
- public void run() {
- mTextView.append("\n" + text);
- }
- });
- }
-}
diff --git a/TrustAgent/src/com/android/car/trust/PhoneUnlockActivity.java b/TrustAgent/src/com/android/car/trust/PhoneUnlockActivity.java
deleted file mode 100644
index 767e1c5..0000000
--- a/TrustAgent/src/com/android/car/trust/PhoneUnlockActivity.java
+++ /dev/null
@@ -1,46 +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.android.car.trust;
-
-import android.app.Activity;
-import android.os.Bundle;
-import android.widget.Button;
-import android.widget.TextView;
-
-/**
- * Activity to allow the user to unlock a remote devices with the stored escrow token.
- */
-public class PhoneUnlockActivity extends Activity {
- private Button mScannButton;
- private Button mUnlockButton;
-
- private TextView mTextOutput;
-
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.phone_client);
-
- mScannButton = (Button) findViewById(R.id.ble_scan_btn);
- mUnlockButton = (Button) findViewById(R.id.action_button);
- mUnlockButton.setText(getString(R.string.unlock_button));
-
- mTextOutput = (TextView) findViewById(R.id.output);
-
- PhoneUnlockController controller = new PhoneUnlockController(this /* context */);
- controller.bind(mTextOutput, mScannButton, mUnlockButton);
- }
-}
diff --git a/TrustAgent/src/com/android/car/trust/PhoneUnlockController.java b/TrustAgent/src/com/android/car/trust/PhoneUnlockController.java
deleted file mode 100644
index c956333..0000000
--- a/TrustAgent/src/com/android/car/trust/PhoneUnlockController.java
+++ /dev/null
@@ -1,174 +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.android.car.trust;
-
-import android.bluetooth.BluetoothDevice;
-import android.bluetooth.BluetoothGatt;
-import android.bluetooth.BluetoothGattCharacteristic;
-import android.bluetooth.BluetoothGattService;
-import android.content.Context;
-import android.content.SharedPreferences;
-import android.os.Handler;
-import android.os.ParcelUuid;
-import android.preference.PreferenceManager;
-import android.util.Base64;
-import android.util.Log;
-import android.view.View;
-import android.widget.Button;
-import android.widget.TextView;
-import com.android.car.trust.comms.SimpleBleClient;
-
-import java.util.UUID;
-
-/**
- * A controller that sets up a {@link SimpleBleClient} to connect to the BLE unlock service.
- */
-public class PhoneUnlockController {
- private static final String TAG = "PhoneUnlockController";
-
- private String mTokenHandleKey;
- private String mEscrowTokenKey;
-
- // BLE characteristics associated with the enrolment/add escrow token service.
- private BluetoothGattCharacteristic mUnlockTokenHandle;
- private BluetoothGattCharacteristic mUnlockEscrowToken;
-
- private ParcelUuid mUnlockServiceUuid;
-
- private SimpleBleClient mClient;
- private Context mContext;
-
- private TextView mTextView;
- private Handler mHandler;
-
- private Button mScanButton;
- private Button mUnlockButton;
-
- public PhoneUnlockController(Context context) {
- mContext = context;
-
- mTokenHandleKey = context.getString(R.string.pref_key_token_handle);
- mEscrowTokenKey = context.getString(R.string.pref_key_escrow_token);
-
- mClient = new SimpleBleClient(context);
- mUnlockServiceUuid = new ParcelUuid(
- UUID.fromString(mContext.getString(R.string.unlock_service_uuid)));
- mClient.addCallback(mCallback /* callback */);
-
- mHandler = new Handler(mContext.getMainLooper());
- }
-
- /**
- * Binds the views to the actions that can be performed by this controller.
- *
- * @param textView A text view used to display results from various BLE actions
- * @param scanButton Button used to start scanning for available BLE devices.
- * @param enrolButton Button used to send new escrow token to remote device.
- */
- public void bind(TextView textView, Button scanButton, Button enrolButton) {
- mTextView = textView;
- mScanButton = scanButton;
- mUnlockButton = enrolButton;
-
- mScanButton.setOnClickListener(new View.OnClickListener() {
- @Override
- public void onClick(View v) {
- mClient.start(mUnlockServiceUuid);
- }
- });
-
- mUnlockButton.setEnabled(false);
- mUnlockButton.setAlpha(0.3f);
- mUnlockButton.setOnClickListener(new View.OnClickListener() {
- @Override
- public void onClick(View v) {
- appendOutputText("Sending unlock token and handle to remote device");
- sendUnlockRequest();
- }
- });
- }
-
- private void sendUnlockRequest() {
- // Retrieve stored token and handle and write to remote device.
- SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(mContext);
- long handle = prefs.getLong(mTokenHandleKey, -1);
- byte[] token = Base64.decode(prefs.getString(mEscrowTokenKey, null), Base64.DEFAULT);
-
- mUnlockEscrowToken.setValue(token);
- mUnlockTokenHandle.setValue(Utils.getBytes(handle));
-
- mClient.writeCharacteristic(mUnlockEscrowToken);
- mClient.writeCharacteristic(mUnlockTokenHandle);
- }
-
- private SimpleBleClient.ClientCallback mCallback = new SimpleBleClient.ClientCallback() {
- @Override
- public void onDeviceConnected(BluetoothDevice device) {
- appendOutputText("Device connected: " + device.getName()
- + " addr: " + device.getAddress());
- }
-
- @Override
- public void onDeviceDisconnected() {
- appendOutputText("Device disconnected");
- }
-
- @Override
- public void onCharacteristicChanged(BluetoothGatt gatt,
- BluetoothGattCharacteristic characteristic) {
- // Not expecting any characteristics changes for the unlocking client.
- }
-
- @Override
- public void onServiceDiscovered(BluetoothGattService service) {
- if (!service.getUuid().equals(mUnlockServiceUuid.getUuid())) {
- if (Log.isLoggable(TAG, Log.DEBUG)) {
- Log.d(TAG, "Service UUID: " + service.getUuid()
- + " does not match Enrolment UUID " + mUnlockServiceUuid.getUuid());
- }
- return;
- }
-
- if (Log.isLoggable(TAG, Log.DEBUG)) {
- Log.d(TAG, "Unlock Service # characteristics: "
- + service.getCharacteristics().size());
- }
- mUnlockEscrowToken
- = Utils.getCharacteristic(R.string.unlock_escrow_token_uiid, service, mContext);
- mUnlockTokenHandle
- = Utils.getCharacteristic(R.string.unlock_handle_uiid, service, mContext);
- appendOutputText("Unlock BLE client successfully connected");
-
- mHandler.post(new Runnable() {
- @Override
- public void run() {
- // Services are now set up, allow users to enrol new escrow tokens.
- mUnlockButton.setEnabled(true);
- mUnlockButton.setAlpha(1.0f);
- }
- });
- }
- };
-
- private void appendOutputText(final String text) {
- mHandler.post(new Runnable() {
- @Override
- public void run() {
- mTextView.append("\n" + text);
- }
- });
- }
-}
diff --git a/TrustAgent/src/com/android/car/trust/SimpleBleServer.java b/TrustAgent/src/com/android/car/trust/SimpleBleServer.java
new file mode 100644
index 0000000..7fbf2fe
--- /dev/null
+++ b/TrustAgent/src/com/android/car/trust/SimpleBleServer.java
@@ -0,0 +1,231 @@
+/*
+ * 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.android.car.trust;
+
+import static android.bluetooth.BluetoothProfile.GATT_SERVER;
+
+import android.app.Service;
+import android.bluetooth.BluetoothAdapter;
+import android.bluetooth.BluetoothDevice;
+import android.bluetooth.BluetoothGatt;
+import android.bluetooth.BluetoothGattCharacteristic;
+import android.bluetooth.BluetoothGattServer;
+import android.bluetooth.BluetoothGattServerCallback;
+import android.bluetooth.BluetoothGattService;
+import android.bluetooth.BluetoothManager;
+import android.bluetooth.BluetoothProfile;
+import android.bluetooth.le.AdvertiseCallback;
+import android.bluetooth.le.AdvertiseData;
+import android.bluetooth.le.AdvertiseSettings;
+import android.bluetooth.le.BluetoothLeAdvertiser;
+import android.content.Context;
+import android.content.pm.PackageManager;
+import android.os.Handler;
+import android.os.ParcelUuid;
+import android.util.Log;
+
+/**
+ * A generic service to start a BLE
+ */
+public abstract class SimpleBleServer extends Service {
+
+ private static final String TAG = SimpleBleServer.class.getSimpleName();
+
+ private static final int BLE_RETRY_LIMIT = 5;
+ private static final int BLE_RETRY_INTERVAL_MS = 1000;
+
+ private final AdvertiseCallback mAdvertisingCallback = new AdvertiseCallback() {
+ @Override
+ public void onStartSuccess(AdvertiseSettings settingsInEffect) {
+ super.onStartSuccess(settingsInEffect);
+ Log.d(TAG, "Successfully started advertising service");
+ onAdvertiseStartSuccess();
+ }
+
+ @Override
+ public void onStartFailure(int errorCode) {
+ super.onStartFailure(errorCode);
+ Log.e(TAG, "Failed to advertise, errorCode: " + errorCode);
+ onAdvertiseStartFailure(errorCode);
+ }
+ };
+
+ private final BluetoothGattServerCallback mGattServerCallback =
+ new BluetoothGattServerCallback() {
+ @Override
+ public void onConnectionStateChange(BluetoothDevice device,
+ final int status, final int newState) {
+ Log.d(TAG, "GattServer connection change status: " + status
+ + " newState: " + newState
+ + " device name: " + device.getName());
+ switch (newState) {
+ case BluetoothProfile.STATE_CONNECTED:
+ onAdvertiseDeviceConnected(device);
+ break;
+ case BluetoothProfile.STATE_DISCONNECTED:
+ onAdvertiseDeviceDisconnected(device);
+ break;
+ }
+ }
+
+ @Override
+ public void onServiceAdded(final int status, BluetoothGattService service) {
+ Log.d(TAG, "Service added status: " + status + " uuid: " + service.getUuid());
+ }
+
+ @Override
+ public void onCharacteristicReadRequest(BluetoothDevice device,
+ int requestId, int offset, final BluetoothGattCharacteristic characteristic) {
+ Log.d(TAG, "Read request for characteristic: " + characteristic.getUuid());
+ mGattServer.sendResponse(device, requestId,
+ BluetoothGatt.GATT_SUCCESS, offset, characteristic.getValue());
+ onCharacteristicRead(device, requestId, offset, characteristic);
+ }
+
+ @Override
+ public void onCharacteristicWriteRequest(final BluetoothDevice device, int requestId,
+ BluetoothGattCharacteristic characteristic, boolean preparedWrite, boolean
+ responseNeeded, int offset, byte[] value) {
+ Log.d(TAG, "Write request for characteristic: " + characteristic.getUuid());
+ mGattServer.sendResponse(device, requestId, BluetoothGatt.GATT_SUCCESS,
+ offset, value);
+ onCharacteristicWrite(device, requestId, characteristic,
+ preparedWrite, responseNeeded, offset, value);
+ }
+ };
+
+ private final Handler mHandler = new Handler();
+
+ private BluetoothManager mBluetoothManager;
+ private BluetoothLeAdvertiser mAdvertiser;
+ private BluetoothGattServer mGattServer;
+ private int mAdvertiserStartCount;
+
+ /**
+ * Starts the GATT server with the given {@link BluetoothGattService} and begins
+ * advertising with the {@link ParcelUuid}.
+ * <p>It is possible that BLE service is still in TURNING_ON state when this method is invoked.
+ * Therefore, several retries will be made to ensure advertising is started.
+ *
+ * @param advertiseUuid Service Uuid used in the {@link AdvertiseData}
+ * @param service {@link BluetoothGattService} that will be discovered by clients
+ */
+ protected void startAdvertising(ParcelUuid advertiseUuid, BluetoothGattService service) {
+ if (!getPackageManager().hasSystemFeature(PackageManager.FEATURE_BLUETOOTH_LE)) {
+ Log.e(TAG, "System does not support BLE");
+ return;
+ }
+
+ mBluetoothManager = (BluetoothManager) getSystemService(Context.BLUETOOTH_SERVICE);
+ mGattServer = mBluetoothManager.openGattServer(this, mGattServerCallback);
+ if (mGattServer == null) {
+ Log.e(TAG, "Gatt Server not created");
+ return;
+ }
+
+ // We only allow adding one service in this implementation. If multiple services need
+ // to be added, then they need to be queued up and added only after
+ // BluetoothGattServerCallback.onServiceAdded is called.
+ mGattServer.addService(service);
+
+ AdvertiseSettings settings = new AdvertiseSettings.Builder()
+ .setAdvertiseMode(AdvertiseSettings.ADVERTISE_MODE_LOW_LATENCY)
+ .setTxPowerLevel(AdvertiseSettings.ADVERTISE_TX_POWER_HIGH)
+ .setConnectable(true)
+ .build();
+
+ AdvertiseData data = new AdvertiseData.Builder()
+ .setIncludeDeviceName(true)
+ .addServiceUuid(advertiseUuid)
+ .build();
+
+ mAdvertiserStartCount = 0;
+ startAdvertisingInternally(settings, data);
+ }
+
+ private void startAdvertisingInternally(AdvertiseSettings settings, AdvertiseData data) {
+ mAdvertiserStartCount += 1;
+ mAdvertiser = BluetoothAdapter.getDefaultAdapter().getBluetoothLeAdvertiser();
+ if (mAdvertiser == null && mAdvertiserStartCount < BLE_RETRY_LIMIT) {
+ mHandler.postDelayed(() -> startAdvertisingInternally(settings, data),
+ BLE_RETRY_INTERVAL_MS);
+ } else {
+ mHandler.removeCallbacks(null);
+ mAdvertiser.startAdvertising(settings, data, mAdvertisingCallback);
+ mAdvertiserStartCount = 0;
+ }
+ }
+
+ protected void stopAdvertising() {
+ if (mAdvertiser != null) {
+ mAdvertiser.stopAdvertising(mAdvertisingCallback);
+ }
+ }
+
+ /**
+ * Notifies the characteristic change via {@link BluetoothGattServer}
+ */
+ protected void notifyCharacteristicChanged(BluetoothDevice device,
+ BluetoothGattCharacteristic characteristic, boolean confirm) {
+ if (mGattServer != null) {
+ mGattServer.notifyCharacteristicChanged(device, characteristic, confirm);
+ }
+ }
+
+ @Override
+ public void onDestroy() {
+ // Stops the advertiser and GATT server. This needs to be done to avoid leaks
+ if (mAdvertiser != null) {
+ mAdvertiser.stopAdvertising(mAdvertisingCallback);
+ mAdvertiser.cleanup();
+ }
+
+ if (mGattServer != null) {
+ mGattServer.clearServices();
+ try {
+ for (BluetoothDevice d : mBluetoothManager.getConnectedDevices(GATT_SERVER)) {
+ mGattServer.cancelConnection(d);
+ }
+ } catch (UnsupportedOperationException e) {
+ Log.e(TAG, "Error getting connected devices", e);
+ } finally {
+ mGattServer.close();
+ }
+ }
+ super.onDestroy();
+ }
+
+ // Delegate to subclass
+ protected void onAdvertiseStartSuccess() { }
+ protected void onAdvertiseStartFailure(int errorCode) { }
+ protected void onAdvertiseDeviceConnected(BluetoothDevice device) { }
+ protected void onAdvertiseDeviceDisconnected(BluetoothDevice device) { }
+
+ /**
+ * Triggered when this BleService receives a write request from a remote
+ * device. Sub-classes should implement how to handle requests.
+ */
+ protected abstract void onCharacteristicWrite(BluetoothDevice device, int requestId,
+ BluetoothGattCharacteristic characteristic, boolean preparedWrite, boolean
+ responseNeeded, int offset, byte[] value);
+
+ /**
+ * Triggered when this BleService receives a read request from a remote device.
+ */
+ protected abstract void onCharacteristicRead(BluetoothDevice device,
+ int requestId, int offset, final BluetoothGattCharacteristic characteristic);
+
+}
diff --git a/TrustAgent/src/com/android/car/trust/Utils.java b/TrustAgent/src/com/android/car/trust/Utils.java
deleted file mode 100644
index 3e9181f..0000000
--- a/TrustAgent/src/com/android/car/trust/Utils.java
+++ /dev/null
@@ -1,44 +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.android.car.trust;
-
-import android.bluetooth.BluetoothGattCharacteristic;
-import android.bluetooth.BluetoothGattService;
-import android.content.Context;
-
-import java.nio.ByteBuffer;
-import java.util.UUID;
-
-public class Utils {
-
- public static byte[] getBytes(long l) {
- ByteBuffer buffer = ByteBuffer.allocate(Long.SIZE / Byte.SIZE);
- buffer.putLong(0, l);
- return buffer.array();
- }
-
- public static long getLong(byte[] bytes) {
- ByteBuffer buffer = ByteBuffer.allocate(Long.SIZE / Byte.SIZE);
- buffer.put(bytes);
- buffer.flip();
- return buffer.getLong();
- }
-
- public static BluetoothGattCharacteristic getCharacteristic(int uuidRes,
- BluetoothGattService service, Context context) {
- return service.getCharacteristic(UUID.fromString(context.getString(uuidRes)));
- }
-}
diff --git a/TrustAgent/src/com/android/car/trust/comms/SimpleBleClient.java b/TrustAgent/src/com/android/car/trust/comms/SimpleBleClient.java
deleted file mode 100644
index 77bf2d3..0000000
--- a/TrustAgent/src/com/android/car/trust/comms/SimpleBleClient.java
+++ /dev/null
@@ -1,380 +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.android.car.trust.comms;
-
-import android.bluetooth.BluetoothDevice;
-import android.bluetooth.BluetoothGatt;
-import android.bluetooth.BluetoothGattCallback;
-import android.bluetooth.BluetoothGattCharacteristic;
-import android.bluetooth.BluetoothGattService;
-import android.bluetooth.BluetoothManager;
-import android.bluetooth.BluetoothProfile;
-import android.bluetooth.le.BluetoothLeScanner;
-import android.bluetooth.le.ScanCallback;
-import android.bluetooth.le.ScanFilter;
-import android.bluetooth.le.ScanResult;
-import android.bluetooth.le.ScanSettings;
-import android.content.Context;
-import android.os.Handler;
-import android.os.ParcelUuid;
-import android.support.annotation.NonNull;
-import android.util.Log;
-
-import java.util.ArrayList;
-import java.util.List;
-import java.util.Queue;
-import java.util.concurrent.ConcurrentLinkedQueue;
-
-/**
- * A simple client that supports the scanning and connecting to available BLE devices. Should be
- * used along with {@link SimpleBleServer}.
- */
-public class SimpleBleClient {
- public interface ClientCallback {
- /**
- * Called when a device that has a matching service UUID is found.
- **/
- void onDeviceConnected(BluetoothDevice device);
-
- void onDeviceDisconnected();
-
- void onCharacteristicChanged(BluetoothGatt gatt,
- BluetoothGattCharacteristic characteristic);
-
- /**
- * Called for each {@link BluetoothGattService} that is discovered on the
- * {@link BluetoothDevice} after a matching scan result and connection.
- *
- * @param service {@link BluetoothGattService} that has been discovered.
- */
- void onServiceDiscovered(BluetoothGattService service);
- }
-
- /**
- * Wrapper class to allow queuing of BLE actions. The BLE stack allows only one action to be
- * executed at a time.
- */
- public static class BleAction {
- public static final int ACTION_WRITE = 0;
- public static final int ACTION_READ = 1;
-
- private int mAction;
- private BluetoothGattCharacteristic mCharacteristic;
-
- public BleAction(BluetoothGattCharacteristic characteristic, int action) {
- mAction = action;
- mCharacteristic = characteristic;
- }
-
- public int getAction() {
- return mAction;
- }
-
- public BluetoothGattCharacteristic getCharacteristic() {
- return mCharacteristic;
- }
- }
-
- private static final String TAG = "SimpleBleClient";
- private static final long SCAN_TIME_MS = 10000;
-
- private Queue<BleAction> mBleActionQueue = new ConcurrentLinkedQueue<BleAction>();
-
- private BluetoothManager mBtManager;
- private BluetoothLeScanner mScanner;
-
- protected BluetoothGatt mBtGatt;
-
- private List<ClientCallback> mCallbacks;
- private ParcelUuid mServiceUuid;
- private Context mContext;
-
- public SimpleBleClient(@NonNull Context context) {
- mContext = context;
- mBtManager = (BluetoothManager) mContext.getSystemService(Context.BLUETOOTH_SERVICE);
- mScanner = mBtManager.getAdapter().getBluetoothLeScanner();
- mCallbacks = new ArrayList<>();
- }
-
- /**
- * Start scanning for a BLE devices with the specified service uuid.
- *
- * @param parcelUuid {@link ParcelUuid} used to identify the device that should be used for
- * this client. This uuid should be the same as the one that is set in the
- * {@link android.bluetooth.le.AdvertiseData.Builder} by the advertising
- * device.
- */
- public void start(ParcelUuid parcelUuid) {
- mServiceUuid = parcelUuid;
-
- // We only want to scan for devices that have the correct uuid set in its advertise data.
- List<ScanFilter> filters = new ArrayList<ScanFilter>();
- ScanFilter.Builder serviceFilter = new ScanFilter.Builder();
- serviceFilter.setServiceUuid(mServiceUuid);
- filters.add(serviceFilter.build());
-
- ScanSettings.Builder settings = new ScanSettings.Builder();
- settings.setScanMode(ScanSettings.SCAN_MODE_LOW_LATENCY);
-
- if (Log.isLoggable(TAG, Log.DEBUG)) {
- Log.d(TAG, "Start scanning for uuid: " + mServiceUuid.getUuid());
- }
- mScanner.startScan(filters, settings.build(), mScanCallback);
-
- Handler handler = new Handler();
- handler.postDelayed(new Runnable() {
- @Override
- public void run() {
- mScanner.stopScan(mScanCallback);
- if (Log.isLoggable(TAG, Log.DEBUG)) {
- Log.d(TAG, "Stopping Scanner");
- }
- }
- }, SCAN_TIME_MS);
- }
-
- private boolean hasServiceUuid(ScanResult result) {
- if (result.getScanRecord() == null
- || result.getScanRecord().getServiceUuids() == null
- || result.getScanRecord().getServiceUuids().size() == 0) {
- return false;
- }
- return true;
- }
-
- /**
- * Writes to a {@link BluetoothGattCharacteristic} if possible, or queues the action until
- * other actions are complete.
- *
- * @param characteristic {@link BluetoothGattCharacteristic} to be written
- */
- public void writeCharacteristic(BluetoothGattCharacteristic characteristic) {
- processAction(new BleAction(characteristic, BleAction.ACTION_WRITE));
- }
-
- /**
- * Reads a {@link BluetoothGattCharacteristic} if possible, or queues the read action until
- * other actions are complete.
- *
- * @param characteristic {@link BluetoothGattCharacteristic} to be read.
- */
- public void readCharacteristic(BluetoothGattCharacteristic characteristic) {
- processAction(new BleAction(characteristic, BleAction.ACTION_READ));
- }
-
- /**
- * Enable or disable notification for specified {@link BluetoothGattCharacteristic}.
- *
- * @param characteristic The {@link BluetoothGattCharacteristic} for which to enable
- * notifications.
- * @param enabled True if notifications should be enabled, false otherwise.
- */
- public void setCharacteristicNotification(BluetoothGattCharacteristic characteristic,
- boolean enabled) {
- mBtGatt.setCharacteristicNotification(characteristic, enabled);
- }
-
- /**
- * Add a {@link ClientCallback} to listen for updates from BLE components
- */
- public void addCallback(ClientCallback callback) {
- mCallbacks.add(callback);
- }
-
- public void removeCallback(ClientCallback callback) {
- mCallbacks.remove(callback);
- }
-
- private void processAction(BleAction action) {
- // Only execute actions if the queue is empty.
- if (mBleActionQueue.size() > 0) {
- mBleActionQueue.add(action);
- return;
- }
-
- mBleActionQueue.add(action);
- executeAction(mBleActionQueue.peek());
- }
-
- private void processNextAction() {
- mBleActionQueue.poll();
- executeAction(mBleActionQueue.peek());
- }
-
- private void executeAction(BleAction action) {
- if (action == null) {
- return;
- }
-
- if (Log.isLoggable(TAG, Log.DEBUG)) {
- Log.d(TAG, "Executing BLE Action type: " + action.getAction());
- }
-
- int actionType = action.getAction();
- switch (actionType) {
- case BleAction.ACTION_WRITE:
- mBtGatt.writeCharacteristic(action.getCharacteristic());
- break;
- case BleAction.ACTION_READ:
- mBtGatt.readCharacteristic(action.getCharacteristic());
- break;
- default:
- }
- }
-
- private String getStatus(int status) {
- switch (status) {
- case BluetoothGatt.GATT_FAILURE:
- return "Failure";
- case BluetoothGatt.GATT_SUCCESS:
- return "GATT_SUCCESS";
- case BluetoothGatt.GATT_READ_NOT_PERMITTED:
- return "GATT_READ_NOT_PERMITTED";
- case BluetoothGatt.GATT_WRITE_NOT_PERMITTED:
- return "GATT_WRITE_NOT_PERMITTED";
- case BluetoothGatt.GATT_INSUFFICIENT_AUTHENTICATION:
- return "GATT_INSUFFICIENT_AUTHENTICATION";
- case BluetoothGatt.GATT_REQUEST_NOT_SUPPORTED:
- return "GATT_REQUEST_NOT_SUPPORTED";
- case BluetoothGatt.GATT_INVALID_OFFSET:
- return "GATT_INVALID_OFFSET";
- case BluetoothGatt.GATT_INVALID_ATTRIBUTE_LENGTH:
- return "GATT_INVALID_ATTRIBUTE_LENGTH";
- case BluetoothGatt.GATT_CONNECTION_CONGESTED:
- return "GATT_CONNECTION_CONGESTED";
- default:
- return "unknown";
- }
- }
-
- private ScanCallback mScanCallback = new ScanCallback() {
- @Override
- public void onScanResult(int callbackType, ScanResult result) {
- BluetoothDevice device = result.getDevice();
- if (Log.isLoggable(TAG, Log.DEBUG)) {
- Log.d(TAG, "Scan result found: " + result.getScanRecord().getServiceUuids());
- }
-
- if (!hasServiceUuid(result)) {
- return;
- }
-
- for (ParcelUuid uuid : result.getScanRecord().getServiceUuids()) {
- if (Log.isLoggable(TAG, Log.DEBUG)) {
- Log.d(TAG, "Scan result UUID: " + uuid);
- }
- if (uuid.equals(mServiceUuid)) {
- // This client only supports connecting to one service.
- // Once we find one, stop scanning and open a GATT connection to the device.
- mScanner.stopScan(mScanCallback);
- mBtGatt = device.connectGatt(mContext, false /* autoConnect */, mGattCallback);
- return;
- }
- }
- }
-
- @Override
- public void onBatchScanResults(List<ScanResult> results) {
- for (ScanResult r : results) {
- if (Log.isLoggable(TAG, Log.DEBUG)) {
- Log.d(TAG, "Batch scanResult: " + r.getDevice().getName()
- + " " + r.getDevice().getAddress());
- }
- }
- }
-
- @Override
- public void onScanFailed(int errorCode) {
- Log.w(TAG, "Scan failed: " + errorCode);
- }
- };
-
- private BluetoothGattCallback mGattCallback = new BluetoothGattCallback() {
- @Override
- public void onConnectionStateChange(BluetoothGatt gatt, int status, int newState) {
- super.onConnectionStateChange(gatt, status, newState);
-
- String state = "";
-
- if (newState == BluetoothProfile.STATE_CONNECTED) {
- state = "Connected";
- mBtGatt.discoverServices();
- for (ClientCallback callback : mCallbacks) {
- callback.onDeviceConnected(gatt.getDevice());
- }
-
- } else if (newState == BluetoothProfile.STATE_DISCONNECTED) {
- state = "Disconnected";
- for (ClientCallback callback : mCallbacks) {
- callback.onDeviceDisconnected();
- }
- }
- if (Log.isLoggable(TAG, Log.DEBUG)) {
- Log.d(TAG, " Gatt connection status: " + getStatus(status) + " newState: " + state);
- }
- }
-
- @Override
- public void onServicesDiscovered(BluetoothGatt gatt, int status) {
- super.onServicesDiscovered(gatt, status);
- if (Log.isLoggable(TAG, Log.DEBUG)) {
- Log.d(TAG, "onServicesDiscovered: " + status);
- }
-
- List<BluetoothGattService> services = gatt.getServices();
- if (services == null || services.size() <= 0) {
- return;
- }
-
- // Notify clients of newly discovered services.
- for (BluetoothGattService service : mBtGatt.getServices()) {
- if (Log.isLoggable(TAG, Log.DEBUG)) {
- Log.d(TAG, "Found service: " + service.getUuid() + " notifying clients");
- }
- for (ClientCallback callback : mCallbacks) {
- callback.onServiceDiscovered(service);
- }
- }
- }
-
- @Override
- public void onCharacteristicWrite(BluetoothGatt gatt,
- BluetoothGattCharacteristic characteristic, int status) {
- if (Log.isLoggable(TAG, Log.DEBUG)) {
- Log.d(TAG, "onCharacteristicWrite: " + status);
- }
- processNextAction();
- }
-
- @Override
- public void onCharacteristicRead(BluetoothGatt gatt,
- BluetoothGattCharacteristic characteristic, int status) {
- if (Log.isLoggable(TAG, Log.DEBUG)) {
- Log.d(TAG, "onCharacteristicRead:" + new String(characteristic.getValue()));
- }
- processNextAction();
- }
-
- @Override
- public void onCharacteristicChanged(BluetoothGatt gatt,
- BluetoothGattCharacteristic characteristic) {
- for (ClientCallback callback : mCallbacks) {
- callback.onCharacteristicChanged(gatt, characteristic);
- }
- processNextAction();
- }
- };
-}
diff --git a/TrustAgent/src/com/android/car/trust/comms/SimpleBleServer.java b/TrustAgent/src/com/android/car/trust/comms/SimpleBleServer.java
deleted file mode 100644
index da3f7ac..0000000
--- a/TrustAgent/src/com/android/car/trust/comms/SimpleBleServer.java
+++ /dev/null
@@ -1,251 +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.android.car.trust.comms;
-
-import android.app.Service;
-import android.bluetooth.BluetoothAdapter;
-import android.bluetooth.BluetoothDevice;
-import android.bluetooth.BluetoothGatt;
-import android.bluetooth.BluetoothGattCharacteristic;
-import android.bluetooth.BluetoothGattServer;
-import android.bluetooth.BluetoothGattServerCallback;
-import android.bluetooth.BluetoothGattService;
-import android.bluetooth.BluetoothManager;
-import android.bluetooth.BluetoothProfile;
-import android.bluetooth.le.AdvertiseCallback;
-import android.bluetooth.le.AdvertiseData;
-import android.bluetooth.le.AdvertiseSettings;
-import android.bluetooth.le.BluetoothLeAdvertiser;
-import android.content.Context;
-import android.content.Intent;
-import android.content.pm.PackageManager;
-import android.os.IBinder;
-import android.os.ParcelUuid;
-import android.util.Log;
-
-import java.util.HashSet;
-
-/**
- * A generic service to start a BLE
- */
-public abstract class SimpleBleServer extends Service {
-
- /**
- * Listener that is notified when the status of the BLE server changes.
- */
- public interface ConnectionListener {
- /**
- * Called when the GATT server is started and BLE is successfully advertising.
- */
- void onServerStarted();
-
- /**
- * Called when the BLE advertisement fails to start.
- *
- * @param errorCode Error code (see {@link AdvertiseCallback}#ADVERTISE_FAILED_* constants)
- */
- void onServerStartFailed(int errorCode);
-
- /**
- * Called when a device is connected.
- * @param device
- */
- void onDeviceConnected(BluetoothDevice device);
- }
-
- private static final String TAG = "SimpleBleServer";
-
- private BluetoothLeAdvertiser mAdvertiser;
- protected BluetoothGattServer mGattServer;
-
- private HashSet<ConnectionListener> mListeners = new HashSet<>();
-
- @Override
- public IBinder onBind(Intent intent) {
- // Override in child classes.
- return null;
- }
-
- /**
- * Starts the GATT server with the given {@link BluetoothGattService} and begins
- * advertising with the {@link ParcelUuid}.
- * @param advertiseUuid Service Uuid used in the {@link AdvertiseData}
- * @param service {@link BluetoothGattService} that will be discovered by clients
- */
- protected void start(ParcelUuid advertiseUuid, BluetoothGattService service) {
- if (!getPackageManager().hasSystemFeature(PackageManager.FEATURE_BLUETOOTH_LE)) {
- Log.e(TAG, "System does not support BLE");
- return;
- }
-
- BluetoothManager btManager =
- (BluetoothManager) getSystemService(Context.BLUETOOTH_SERVICE);
-
- mGattServer = btManager.openGattServer(this, mGattServerCallback);
- if (mGattServer == null) {
- Log.e(TAG, "Gatt Server not created");
- return;
- }
-
- // We only allow adding one service in this implementation. If multiple services need
- // to be added, then they need to be queued up and added only after
- // BluetoothGattServerCallback.onServiceAdded is called.
- mGattServer.addService(service);
-
- AdvertiseSettings settings = new AdvertiseSettings.Builder()
- .setAdvertiseMode(AdvertiseSettings.ADVERTISE_MODE_LOW_LATENCY)
- .setTxPowerLevel(AdvertiseSettings.ADVERTISE_TX_POWER_HIGH)
- .setConnectable(true)
- .build();
-
- AdvertiseData data = new AdvertiseData.Builder()
- .setIncludeDeviceName(true)
- .addServiceUuid(advertiseUuid)
- .build();
-
- mAdvertiser
- = BluetoothAdapter.getDefaultAdapter().getBluetoothLeAdvertiser();
-
- mAdvertiser.startAdvertising(settings, data, mAdvertisingCallback);
- }
-
- /**
- * Stops the advertiser and GATT server. This needs to be done to avoid leaks
- */
- protected void stop() {
- if (mAdvertiser != null) {
- mAdvertiser.stopAdvertising(mAdvertisingCallback);
- mAdvertiser.cleanup();
- }
-
- if (mGattServer != null) {
- mGattServer.clearServices();
- try {
- for (BluetoothDevice d : mGattServer.getConnectedDevices()) {
- mGattServer.cancelConnection(d);
- }
- } catch (UnsupportedOperationException e) {
- Log.e(TAG, "Error getting connected devices", e);
- } finally {
- mGattServer.close();
- }
- }
-
- mListeners.clear();
- }
-
- @Override
- public void onDestroy() {
- stop();
- super.onDestroy();
- }
-
- public void addConnectionListener(ConnectionListener listener) {
- if (Log.isLoggable(TAG, Log.DEBUG)) {
- Log.d(TAG, "Adding connection listener");
- }
- mListeners.add(listener);
- }
-
- /**
- * Triggered when this BleService receives a write request from a remote
- * device. Sub-classes should implement how to handle requests.
- */
- public abstract void onCharacteristicWrite(final BluetoothDevice device, int requestId,
- BluetoothGattCharacteristic characteristic, boolean preparedWrite, boolean
- responseNeeded, int offset, byte[] value);
-
- /**
- * Triggered when this BleService receives a read request from a remote device.
- */
- public abstract void onCharacteristicRead(BluetoothDevice device,
- int requestId, int offset, final BluetoothGattCharacteristic characteristic);
-
- private AdvertiseCallback mAdvertisingCallback = new AdvertiseCallback() {
- @Override
- public void onStartSuccess(AdvertiseSettings settingsInEffect) {
- super.onStartSuccess(settingsInEffect);
- if (Log.isLoggable(TAG, Log.DEBUG)) {
- Log.d(TAG, "Successfully started advertising service");
- }
- for (ConnectionListener listener : mListeners) {
- listener.onServerStarted();
- }
- }
-
- @Override
- public void onStartFailure(int errorCode) {
- super.onStartFailure(errorCode);
- if (Log.isLoggable(TAG, Log.DEBUG)) {
- Log.d(TAG, "Failed to advertise, errorCode: " + errorCode);
- }
- for (ConnectionListener listener : mListeners) {
- listener.onServerStartFailed(errorCode);
- }
- }
- };
-
- private BluetoothGattServerCallback mGattServerCallback = new BluetoothGattServerCallback() {
- @Override
- public void onConnectionStateChange(BluetoothDevice device,
- final int status, final int newState) {
- if (Log.isLoggable(TAG, Log.DEBUG)) {
- Log.d(TAG, "GattServer connection change status: "
- + newState + " newState: "
- + newState + " device name: " + device.getName());
- }
- if (newState == BluetoothProfile.STATE_CONNECTED) {
- for (ConnectionListener listener : mListeners) {
- listener.onDeviceConnected(device);
- }
- }
- }
-
- @Override
- public void onServiceAdded(final int status, BluetoothGattService service) {
- if (Log.isLoggable(TAG, Log.DEBUG)) {
- Log.d(TAG, "Service added status: " + status + " uuid: " + service.getUuid());
- }
- }
-
- @Override
- public void onCharacteristicReadRequest(BluetoothDevice device,
- int requestId, int offset, final BluetoothGattCharacteristic characteristic) {
- if (Log.isLoggable(TAG, Log.DEBUG)) {
- Log.d(TAG, "Read request for characteristic: " + characteristic.getUuid());
- }
- mGattServer.sendResponse(device, requestId,
- BluetoothGatt.GATT_SUCCESS, offset, characteristic.getValue());
- SimpleBleServer.
- this.onCharacteristicRead(device, requestId, offset, characteristic);
- }
-
- @Override
- public void onCharacteristicWriteRequest(final BluetoothDevice device, int requestId,
- BluetoothGattCharacteristic characteristic, boolean preparedWrite, boolean
- responseNeeded, int offset, byte[] value) {
- if (Log.isLoggable(TAG, Log.DEBUG)) {
- Log.d(TAG, "Write request for characteristic: " + characteristic.getUuid());
- }
- mGattServer.sendResponse(device, requestId, BluetoothGatt.GATT_SUCCESS,
- offset, value);
-
- SimpleBleServer.
- this.onCharacteristicWrite(device, requestId, characteristic,
- preparedWrite, responseNeeded, offset, value);
- }
- };
-}
diff --git a/car-cluster-logging-renderer/src/android/car/cluster/loggingrenderer/LoggingClusterRenderingService.java b/car-cluster-logging-renderer/src/android/car/cluster/loggingrenderer/LoggingClusterRenderingService.java
index b6ed388..381b7ee 100644
--- a/car-cluster-logging-renderer/src/android/car/cluster/loggingrenderer/LoggingClusterRenderingService.java
+++ b/car-cluster-logging-renderer/src/android/car/cluster/loggingrenderer/LoggingClusterRenderingService.java
@@ -43,34 +43,6 @@
return config;
}
-
- @Override
- public void onStartNavigation() {
- Log.i(TAG, "onStartNavigation");
- }
-
- @Override
- public void onStopNavigation() {
- Log.i(TAG, "onStopNavigation");
- }
-
- @Override
- public void onNextTurnChanged(int event, CharSequence eventName, int turnAngle,
- int turnNumber, Bitmap image, int turnSide) {
- Log.i(TAG, "event: " + event + ", eventName: " + eventName +
- ", turnAngle: " + turnAngle + ", turnNumber: " + turnNumber +
- ", image: " + image + ", turnSide: " + turnSide);
- }
-
- @Override
- public void onNextTurnDistanceChanged(int distanceMeters, int timeSeconds,
- int displayDistanceMillis, int displayDistanceUnit) {
- Log.i(TAG, "onNextTurnDistanceChanged, distanceMeters: " + distanceMeters
- + ", timeSeconds: " + timeSeconds
- + ", displayDistanceMillis: " + displayDistanceMillis
- + ", displayDistanceUnit: " + displayDistanceUnit);
- }
-
@Override
public void onEvent(int eventType, Bundle bundle) {
Log.i(TAG, "onEvent, eventType: " + eventType + ", bundle: " + bundle);
diff --git a/car-lib/Android.bp b/car-lib/Android.bp
index 2ed9299..806121f 100644
--- a/car-lib/Android.bp
+++ b/car-lib/Android.bp
@@ -12,6 +12,41 @@
// See the License for the specific language governing permissions and
// limitations under the License.
+cc_library {
+ name: "libcarpowermanager",
+
+ aidl: {
+ export_aidl_headers: true,
+ local_include_dirs: [
+ "src",
+ ],
+ },
+
+ cflags: [
+ "-Wall",
+ "-Werror",
+ "-Wextra",
+ "-Wno-unused-parameter",
+ ],
+
+ include_dirs: [
+ "packages/services/Car/car-lib/native/include",
+ ],
+
+ shared_libs: [
+ "libbinder",
+ "liblog",
+ "libutils",
+ ],
+
+ srcs: [
+ "src/android/car/ICar.aidl",
+ "src/android/car/hardware/power/ICarPower.aidl",
+ "src/android/car/hardware/power/ICarPowerStateListener.aidl",
+ "native/CarPowerManager/CarPowerManager.cpp",
+ ],
+}
+
java_library {
name: "android.car",
srcs: [
@@ -24,6 +59,10 @@
"system/bt/binder",
],
},
+ exclude_srcs: [
+ "src/android/car/storagemonitoring/IoStats.aidl",
+ "src/android/car/storagemonitoring/IoStatsEntry.aidl",
+ ],
product_variables: {
pdk: {
enabled: false,
diff --git a/car-lib/Android.mk b/car-lib/Android.mk
index 4873ab9..e0fa482 100644
--- a/car-lib/Android.mk
+++ b/car-lib/Android.mk
@@ -23,8 +23,17 @@
car_lib_sources := $(call all-java-files-under, src)
car_lib_sources += $(call all-java-files-under, src_feature_future)
+
car_lib_sources += $(call all-Iaidl-files-under, src)
+# IoStats* are parcelable types (vs. interface types), but the build system uses an initial
+# I as a magic marker to mean "interface", and due to this ends up refusing to compile
+# these files as part of the build process.
+# A clean solution to this is actively being worked on by the build team, but is not yet
+# available, so for now we just filter the files out by hand.
+car_lib_sources := $(filter-out src/android/car/storagemonitoring/IoStats.aidl,$(car_lib_sources))
+car_lib_sources := $(filter-out src/android/car/storagemonitoring/IoStatsEntry.aidl,$(car_lib_sources))
+
ifeq ($(BOARD_IS_AUTOMOTIVE), true)
full_classes_jar := $(call intermediates-dir-for,JAVA_LIBRARIES,android.car,,COMMON)/classes.jar
$(call dist-for-goals,dist_files,$(full_classes_jar):android.car.jar)
@@ -40,18 +49,63 @@
car_module_java_packages := android.car*
include $(CAR_API_CHECK)
+# Build stubs jar for target android-support-car
+# ---------------------------------------------
include $(CLEAR_VARS)
-LOCAL_MODULE := android.car7
-LOCAL_SRC_FILES := $(car_lib_sources)
-LOCAL_JAVA_LANGUAGE_VERSION := 1.7
-LOCAL_AIDL_INCLUDES += system/bt/binder
+LOCAL_SRC_FILES := $(call all-java-files-under, src)
-ifeq ($(EMMA_INSTRUMENT_FRAMEWORK),true)
-LOCAL_EMMA_INSTRUMENT := true
-endif
+LOCAL_JAVA_LIBRARIES := android.car
-include $(BUILD_JAVA_LIBRARY)
-$(call dist-for-goals,dist_files,$(full_classes_jar):$(LOCAL_MODULE).jar)
+LOCAL_ADDITIONAL_JAVA_DIR := $(call intermediates-dir-for,JAVA_LIBRARIES,android.car,,COMMON)/src
+
+android_car_stub_packages := \
+ android.car*
+
+android_car_api := \
+ $(TARGET_OUT_COMMON_INTERMEDIATES)/PACKAGING/android.car_api.txt
+
+# Note: The make target is android.car-stub-docs
+LOCAL_MODULE := android.car-stub
+LOCAL_DROIDDOC_OPTIONS := \
+ -stubs $(call intermediates-dir-for,JAVA_LIBRARIES,android.car-stubs,,COMMON)/src \
+ -stubpackages $(subst $(space),:,$(android_car_stub_packages)) \
+ -api $(android_car_api) \
+ -nodocs
+
+LOCAL_DROIDDOC_SOURCE_PATH := $(LOCAL_PATH)/java/
+LOCAL_DROIDDOC_HTML_DIR :=
+
+LOCAL_MODULE_CLASS := JAVA_LIBRARIES
+
+LOCAL_UNINSTALLABLE_MODULE := true
+
+include $(BUILD_DROIDDOC)
+
+$(android_car_api): $(full_target)
+
+android.car-stubs_stamp := $(full_target)
+
+###############################################
+# Build the stubs java files into a jar. This build rule relies on the
+# stubs_stamp make variable being set from the droiddoc rule.
+
+include $(CLEAR_VARS)
+
+# CAR_API_CHECK uses the same name to generate a module, but BUILD_DROIDDOC
+# appends "-docs" to module name.
+LOCAL_MODULE := android.car-stubs
+LOCAL_SOURCE_FILES_ALL_GENERATED := true
+
+# Make sure to run droiddoc first to generate the stub source files.
+LOCAL_ADDITIONAL_DEPENDENCIES := $(android.car-stubs_stamp)
+
+include $(BUILD_STATIC_JAVA_LIBRARY)
+
+android.car-stubs_stamp :=
+android_car_stub_packages :=
+android_car_api :=
+
+include $(call all-makefiles-under,$(LOCAL_PATH))
endif #TARGET_BUILD_PDK
diff --git a/car-lib/api/current.txt b/car-lib/api/current.txt
index 242c337..9cd2e4c 100644
--- a/car-lib/api/current.txt
+++ b/car-lib/api/current.txt
@@ -11,16 +11,23 @@
method public boolean isConnecting();
field public static final java.lang.String APP_FOCUS_SERVICE = "app_focus";
field public static final java.lang.String AUDIO_SERVICE = "audio";
+ field public static final java.lang.String CAR_CONFIGURATION_SERVICE = "configuration";
field public static final java.lang.String CAR_EXTRA_MEDIA_PACKAGE = "android.car.intent.extra.MEDIA_PACKAGE";
field public static final java.lang.String CAR_INTENT_ACTION_MEDIA_TEMPLATE = "android.car.intent.action.MEDIA_TEMPLATE";
+ field public static final java.lang.String CAR_NAVIGATION_SERVICE = "car_navigation_service";
+ field public static final java.lang.String CAR_UX_RESTRICTION_SERVICE = "uxrestriction";
field public static final int CONNECTION_TYPE_EMBEDDED = 5; // 0x5
field public static final java.lang.String INFO_SERVICE = "info";
field public static final java.lang.String PACKAGE_SERVICE = "package";
field public static final java.lang.String PERMISSION_CAR_CONTROL_AUDIO_VOLUME = "android.car.permission.CAR_CONTROL_AUDIO_VOLUME";
- field public static final java.lang.String PERMISSION_FUEL = "android.car.permission.CAR_FUEL";
- field public static final java.lang.String PERMISSION_MILEAGE = "android.car.permission.CAR_MILEAGE";
+ field public static final java.lang.String PERMISSION_CAR_INFO = "android.car.permission.CAR_INFO";
+ field public static final java.lang.String PERMISSION_CAR_NAVIGATION_MANAGER = "android.car.permission.CAR_NAVIGATION_MANAGER";
+ field public static final java.lang.String PERMISSION_ENERGY = "android.car.permission.CAR_ENERGY";
+ field public static final java.lang.String PERMISSION_ENERGY_PORTS = "android.car.permission.CAR_ENERGY_PORTS";
+ field public static final java.lang.String PERMISSION_EXTERIOR_ENVIRONMENT = "android.car.permission.CAR_EXTERIOR_ENVIRONMENT";
+ field public static final java.lang.String PERMISSION_IDENTIFICATION = "android.car.permission.CAR_IDENTIFICATION";
+ field public static final java.lang.String PERMISSION_POWERTRAIN = "android.car.permission.CAR_POWERTRAIN";
field public static final java.lang.String PERMISSION_SPEED = "android.car.permission.CAR_SPEED";
- field public static final java.lang.String PERMISSION_VEHICLE_DYNAMICS_STATE = "android.car.permission.VEHICLE_DYNAMICS_STATE";
field public static final java.lang.String SENSOR_SERVICE = "sensor";
field public static final int VERSION = 3; // 0x3
}
@@ -49,6 +56,10 @@
}
public final class CarInfoManager {
+ method public float getEvBatteryCapacity() throws android.car.CarNotConnectedException;
+ method public int[] getEvConnectorTypes() throws android.car.CarNotConnectedException;
+ method public float getFuelCapacity() throws android.car.CarNotConnectedException;
+ method public int[] getFuelTypes() throws android.car.CarNotConnectedException;
method public java.lang.String getManufacturer() throws android.car.CarNotConnectedException;
method public java.lang.String getModel() throws android.car.CarNotConnectedException;
method public java.lang.String getModelYear() throws android.car.CarNotConnectedException;
@@ -172,8 +183,58 @@
package android.car.content.pm {
public final class CarPackageManager {
- method public boolean isActivityAllowedWhileDriving(java.lang.String, java.lang.String) throws android.car.CarNotConnectedException;
- method public boolean isServiceAllowedWhileDriving(java.lang.String, java.lang.String) throws android.car.CarNotConnectedException;
+ method public boolean isActivityDistractionOptimized(java.lang.String, java.lang.String) throws android.car.CarNotConnectedException;
+ method public boolean isServiceDistractionOptimized(java.lang.String, java.lang.String) throws android.car.CarNotConnectedException;
+ }
+
+}
+
+package android.car.drivingstate {
+
+ public class CarUxRestrictions implements android.os.Parcelable {
+ ctor public CarUxRestrictions(android.car.drivingstate.CarUxRestrictions);
+ method public int describeContents();
+ method public int getActiveRestrictions();
+ method public int getMaxContentDepth();
+ method public int getMaxCumulativeContentItems();
+ method public int getMaxRestrictedStringLength();
+ method public long getTimeStamp();
+ method public boolean isRequiresDistractionOptimization();
+ method public boolean isSameRestrictions(android.car.drivingstate.CarUxRestrictions);
+ method public void writeToParcel(android.os.Parcel, int);
+ field public static final android.os.Parcelable.Creator<android.car.drivingstate.CarUxRestrictions> CREATOR;
+ field public static final int UX_RESTRICTIONS_BASELINE = 0; // 0x0
+ field public static final int UX_RESTRICTIONS_FULLY_RESTRICTED = 511; // 0x1ff
+ field public static final int UX_RESTRICTIONS_LIMIT_CONTENT = 32; // 0x20
+ field public static final int UX_RESTRICTIONS_LIMIT_STRING_LENGTH = 4; // 0x4
+ field public static final int UX_RESTRICTIONS_NO_DIALPAD = 1; // 0x1
+ field public static final int UX_RESTRICTIONS_NO_FILTERING = 2; // 0x2
+ field public static final int UX_RESTRICTIONS_NO_KEYBOARD = 8; // 0x8
+ field public static final int UX_RESTRICTIONS_NO_SETUP = 64; // 0x40
+ field public static final int UX_RESTRICTIONS_NO_TEXT_MESSAGE = 128; // 0x80
+ field public static final int UX_RESTRICTIONS_NO_VIDEO = 16; // 0x10
+ field public static final int UX_RESTRICTIONS_NO_VOICE_TRANSCRIPTION = 256; // 0x100
+ }
+
+ public static class CarUxRestrictions.Builder {
+ ctor public CarUxRestrictions.Builder(boolean, int, long);
+ method public android.car.drivingstate.CarUxRestrictions build();
+ method public android.car.drivingstate.CarUxRestrictions.Builder setMaxContentDepth(int);
+ method public android.car.drivingstate.CarUxRestrictions.Builder setMaxCumulativeContentItems(int);
+ method public android.car.drivingstate.CarUxRestrictions.Builder setMaxStringLength(int);
+ }
+
+ public static abstract class CarUxRestrictions.CarUxRestrictionsInfo implements java.lang.annotation.Annotation {
+ }
+
+ public final class CarUxRestrictionsManager {
+ method public android.car.drivingstate.CarUxRestrictions getCurrentCarUxRestrictions() throws android.car.CarNotConnectedException;
+ method public synchronized void registerListener(android.car.drivingstate.CarUxRestrictionsManager.OnUxRestrictionsChangedListener) throws android.car.CarNotConnectedException, java.lang.IllegalArgumentException;
+ method public synchronized void unregisterListener() throws android.car.CarNotConnectedException;
+ }
+
+ public static abstract interface CarUxRestrictionsManager.OnUxRestrictionsChangedListener {
+ method public abstract void onUxRestrictionsChanged(android.car.drivingstate.CarUxRestrictions);
}
}
@@ -184,27 +245,20 @@
method public int describeContents();
method public void writeToParcel(android.os.Parcel, int);
field public static final android.os.Parcelable.Creator<android.car.hardware.CarSensorEvent> CREATOR;
- field public static final int DRIVE_STATUS_FULLY_RESTRICTED = 31; // 0x1f
- field public static final int DRIVE_STATUS_LIMIT_MESSAGE_LEN = 16; // 0x10
- field public static final int DRIVE_STATUS_NO_CONFIG = 8; // 0x8
- field public static final int DRIVE_STATUS_NO_KEYBOARD_INPUT = 2; // 0x2
- field public static final int DRIVE_STATUS_NO_VIDEO = 1; // 0x1
- field public static final int DRIVE_STATUS_NO_VOICE_INPUT = 4; // 0x4
- field public static final int DRIVE_STATUS_UNRESTRICTED = 0; // 0x0
- field public static final int GEAR_DRIVE = 100; // 0x64
- field public static final int GEAR_EIGHTH = 8; // 0x8
- field public static final int GEAR_FIFTH = 5; // 0x5
- field public static final int GEAR_FIRST = 1; // 0x1
- field public static final int GEAR_FOURTH = 4; // 0x4
- field public static final int GEAR_NEUTRAL = 0; // 0x0
- field public static final int GEAR_NINTH = 9; // 0x9
- field public static final int GEAR_PARK = 101; // 0x65
- field public static final int GEAR_REVERSE = 102; // 0x66
- field public static final int GEAR_SECOND = 2; // 0x2
- field public static final int GEAR_SEVENTH = 7; // 0x7
- field public static final int GEAR_SIXTH = 6; // 0x6
- field public static final int GEAR_TENTH = 10; // 0xa
- field public static final int GEAR_THIRD = 3; // 0x3
+ field public static final int GEAR_DRIVE = 8; // 0x8
+ field public static final int GEAR_EIGHTH = 2048; // 0x800
+ field public static final int GEAR_FIFTH = 256; // 0x100
+ field public static final int GEAR_FIRST = 16; // 0x10
+ field public static final int GEAR_FOURTH = 128; // 0x80
+ field public static final int GEAR_NEUTRAL = 1; // 0x1
+ field public static final int GEAR_NINTH = 4096; // 0x1000
+ field public static final int GEAR_PARK = 4; // 0x4
+ field public static final int GEAR_REVERSE = 2; // 0x2
+ field public static final int GEAR_SECOND = 32; // 0x20
+ field public static final int GEAR_SEVENTH = 1024; // 0x400
+ field public static final int GEAR_SIXTH = 512; // 0x200
+ field public static final int GEAR_TENTH = 8192; // 0x2000
+ field public static final int GEAR_THIRD = 64; // 0x40
field public static final int IGNITION_STATE_ACC = 3; // 0x3
field public static final int IGNITION_STATE_LOCK = 1; // 0x1
field public static final int IGNITION_STATE_OFF = 2; // 0x2
@@ -213,9 +267,6 @@
field public static final int IGNITION_STATE_UNDEFINED = 0; // 0x0
field public static final int INDEX_ENVIRONMENT_PRESSURE = 1; // 0x1
field public static final int INDEX_ENVIRONMENT_TEMPERATURE = 0; // 0x0
- field public static final int INDEX_FUEL_LEVEL_IN_DISTANCE = 1; // 0x1
- field public static final int INDEX_FUEL_LEVEL_IN_PERCENTILE = 0; // 0x0
- field public static final int INDEX_FUEL_LOW_WARNING = 0; // 0x0
field public static final int INDEX_WHEEL_DISTANCE_FRONT_LEFT = 1; // 0x1
field public static final int INDEX_WHEEL_DISTANCE_FRONT_RIGHT = 2; // 0x2
field public static final int INDEX_WHEEL_DISTANCE_REAR_LEFT = 4; // 0x4
@@ -236,30 +287,34 @@
public final class CarSensorManager {
method public android.car.hardware.CarSensorEvent getLatestSensorEvent(int) throws android.car.CarNotConnectedException;
+ method public java.util.List<android.car.hardware.CarPropertyConfig> getPropertyList() throws android.car.CarNotConnectedException;
method public int[] getSupportedSensors() throws android.car.CarNotConnectedException;
method public boolean isSensorSupported(int) throws android.car.CarNotConnectedException;
method public static boolean isSensorSupported(int[], int);
method public boolean registerListener(android.car.hardware.CarSensorManager.OnSensorChangedListener, int, int) throws android.car.CarNotConnectedException, java.lang.IllegalArgumentException;
method public void unregisterListener(android.car.hardware.CarSensorManager.OnSensorChangedListener);
method public void unregisterListener(android.car.hardware.CarSensorManager.OnSensorChangedListener, int);
- field public static final int SENSOR_RATE_FAST = 1; // 0x1
- field public static final int SENSOR_RATE_FASTEST = 0; // 0x0
- field public static final int SENSOR_RATE_NORMAL = 3; // 0x3
- field public static final int SENSOR_RATE_UI = 2; // 0x2
- field public static final int SENSOR_TYPE_ABS_ACTIVE = 24; // 0x18
- field public static final int SENSOR_TYPE_CAR_SPEED = 2; // 0x2
- field public static final int SENSOR_TYPE_DRIVING_STATUS = 11; // 0xb
+ field public static final int SENSOR_RATE_FAST = 10; // 0xa
+ field public static final int SENSOR_RATE_FASTEST = 100; // 0x64
+ field public static final int SENSOR_RATE_NORMAL = 1; // 0x1
+ field public static final int SENSOR_RATE_UI = 5; // 0x5
+ field public static final int SENSOR_TYPE_ABS_ACTIVE = 287310858; // 0x1120040a
+ field public static final int SENSOR_TYPE_CAR_SPEED = 291504647; // 0x11600207
field public static final int SENSOR_TYPE_ENVIRONMENT = 12; // 0xc
- field public static final int SENSOR_TYPE_FUEL_LEVEL = 5; // 0x5
- field public static final int SENSOR_TYPE_GEAR = 7; // 0x7
- field public static final int SENSOR_TYPE_IGNITION_STATE = 22; // 0x16
- field public static final int SENSOR_TYPE_NIGHT = 9; // 0x9
- field public static final int SENSOR_TYPE_ODOMETER = 4; // 0x4
- field public static final int SENSOR_TYPE_PARKING_BRAKE = 6; // 0x6
- field public static final int SENSOR_TYPE_RPM = 3; // 0x3
- field public static final int SENSOR_TYPE_TRACTION_CONTROL_ACTIVE = 25; // 0x19
- field public static final int SENSOR_TYPE_VENDOR_EXTENSION_END = 1879048191; // 0x6fffffff
- field public static final int SENSOR_TYPE_WHEEL_TICK_DISTANCE = 23; // 0x17
+ field public static final int SENSOR_TYPE_EV_BATTERY_CHARGE_RATE = 291504908; // 0x1160030c
+ field public static final int SENSOR_TYPE_EV_BATTERY_LEVEL = 291504905; // 0x11600309
+ field public static final int SENSOR_TYPE_EV_CHARGE_PORT_CONNECTED = 287310603; // 0x1120030b
+ field public static final int SENSOR_TYPE_EV_CHARGE_PORT_OPEN = 287310602; // 0x1120030a
+ field public static final int SENSOR_TYPE_FUEL_DOOR_OPEN = 287310600; // 0x11200308
+ field public static final int SENSOR_TYPE_FUEL_LEVEL = 291504903; // 0x11600307
+ field public static final int SENSOR_TYPE_GEAR = 289408000; // 0x11400400
+ field public static final int SENSOR_TYPE_IGNITION_STATE = 289408009; // 0x11400409
+ field public static final int SENSOR_TYPE_NIGHT = 287310855; // 0x11200407
+ field public static final int SENSOR_TYPE_ODOMETER = 291504644; // 0x11600204
+ field public static final int SENSOR_TYPE_PARKING_BRAKE = 287310850; // 0x11200402
+ field public static final int SENSOR_TYPE_RPM = 291504901; // 0x11600305
+ field public static final int SENSOR_TYPE_TRACTION_CONTROL_ACTIVE = 287310859; // 0x1120040b
+ field public static final int SENSOR_TYPE_WHEEL_TICK_DISTANCE = 290521862; // 0x11510306
}
public static abstract interface CarSensorManager.OnSensorChangedListener {
@@ -271,30 +326,49 @@
package android.car.media {
public final class CarAudioManager {
- method public void abandonAudioFocus(android.media.AudioManager.OnAudioFocusChangeListener, android.media.AudioAttributes);
- method public android.media.AudioAttributes getAudioAttributesForCarUsage(int) throws android.car.CarNotConnectedException;
- method public int getStreamMaxVolume(int) throws android.car.CarNotConnectedException;
- method public int getStreamMinVolume(int) throws android.car.CarNotConnectedException;
- method public int getStreamVolume(int) throws android.car.CarNotConnectedException;
- method public int requestAudioFocus(android.media.AudioManager.OnAudioFocusChangeListener, android.media.AudioAttributes, int, int) throws android.car.CarNotConnectedException, java.lang.IllegalArgumentException;
- method public void setStreamVolume(int, int, int) throws android.car.CarNotConnectedException;
- field public static final int CAR_AUDIO_USAGE_ALARM = 6; // 0x6
- field public static final int CAR_AUDIO_USAGE_DEFAULT = 0; // 0x0
- field public static final int CAR_AUDIO_USAGE_MUSIC = 1; // 0x1
- field public static final int CAR_AUDIO_USAGE_NAVIGATION_GUIDANCE = 3; // 0x3
- field public static final int CAR_AUDIO_USAGE_NOTIFICATION = 7; // 0x7
- field public static final int CAR_AUDIO_USAGE_RADIO = 2; // 0x2
- field public static final int CAR_AUDIO_USAGE_RINGTONE = 10; // 0xa
- field public static final int CAR_AUDIO_USAGE_SYSTEM_SAFETY_ALERT = 9; // 0x9
- field public static final int CAR_AUDIO_USAGE_SYSTEM_SOUND = 8; // 0x8
- field public static final int CAR_AUDIO_USAGE_VOICE_CALL = 4; // 0x4
- field public static final int CAR_AUDIO_USAGE_VOICE_COMMAND = 5; // 0x5
+ method public android.car.media.CarAudioPatchHandle createAudioPatch(java.lang.String, int, int) throws android.car.CarNotConnectedException;
+ method public java.lang.String[] getExternalSources() throws android.car.CarNotConnectedException;
+ method public int getGroupMaxVolume(int) throws android.car.CarNotConnectedException;
+ method public int getGroupMinVolume(int) throws android.car.CarNotConnectedException;
+ method public int getGroupVolume(int) throws android.car.CarNotConnectedException;
+ method public int[] getUsagesForVolumeGroupId(int) throws android.car.CarNotConnectedException;
+ method public int getVolumeGroupCount() throws android.car.CarNotConnectedException;
+ method public int getVolumeGroupIdForUsage(int) throws android.car.CarNotConnectedException;
+ method public static java.lang.String getVolumeSettingsKeyForGroup(int);
+ method public void registerVolumeCallback(android.os.IBinder) throws android.car.CarNotConnectedException;
+ method public void registerVolumeChangeObserver(android.database.ContentObserver);
+ method public void releaseAudioPatch(android.car.media.CarAudioPatchHandle) throws android.car.CarNotConnectedException;
+ method public void setBalanceTowardRight(float) throws android.car.CarNotConnectedException;
+ method public void setFadeTowardFront(float) throws android.car.CarNotConnectedException;
+ method public void setGroupVolume(int, int, int) throws android.car.CarNotConnectedException;
+ method public void unregisterVolumeCallback(android.os.IBinder) throws android.car.CarNotConnectedException;
+ method public void unregisterVolumeChangeObserver(android.database.ContentObserver);
+ }
+
+ public final class CarAudioPatchHandle implements android.os.Parcelable {
+ ctor public CarAudioPatchHandle(android.media.AudioPatch);
+ method public int describeContents();
+ method public void writeToParcel(android.os.Parcel, int);
+ field public static final android.os.Parcelable.Creator<android.car.media.CarAudioPatchHandle> CREATOR;
+ }
+
+}
+
+package android.car.navigation {
+
+ public final class CarNavigationStatusManager {
+ method public android.car.navigation.CarNavigationInstrumentCluster getInstrumentClusterInfo() throws android.car.CarNotConnectedException;
+ method public void sendEvent(int, android.os.Bundle) throws android.car.CarNotConnectedException;
}
}
package android.car.settings {
+ public class CarConfigurationManager {
+ method public android.car.settings.SpeedBumpConfiguration getSpeedBumpConfiguration() throws android.car.CarNotConnectedException;
+ }
+
public class CarSettings {
ctor public CarSettings();
}
@@ -306,5 +380,15 @@
field public static final java.lang.String KEY_GARAGE_MODE_WAKE_UP_TIME = "android.car.GARAGE_MODE_WAKE_UP_TIME";
}
+ public final class SpeedBumpConfiguration implements android.os.Parcelable {
+ ctor public SpeedBumpConfiguration(double, double, long);
+ method public int describeContents();
+ method public double getAcquiredPermitsPerSecond();
+ method public double getMaxPermitPool();
+ method public long getPermitFillDelay();
+ method public void writeToParcel(android.os.Parcel, int);
+ field public static final android.os.Parcelable.Creator<android.car.settings.SpeedBumpConfiguration> CREATOR;
+ }
+
}
diff --git a/car-lib/api/system-1.txt b/car-lib/api/system-1.txt
index 253c874..e58b9be 100644
--- a/car-lib/api/system-1.txt
+++ b/car-lib/api/system-1.txt
@@ -635,8 +635,8 @@
field public static final int ID_ZONED_AIR_RECIRCULATION_ON = 16395; // 0x400b
field public static final int ID_ZONED_AUTOMATIC_MODE_ON = 16394; // 0x400a
field public static final int ID_ZONED_DUAL_ZONE_ON = 16397; // 0x400d
- field public static final int ID_ZONED_FAN_POSITION = 16391; // 0x4007
- field public static final int ID_ZONED_FAN_POSITION_AVAILABLE = 16390; // 0x4006
+ field public static final int ID_ZONED_FAN_DIRECTION = 16391; // 0x4007
+ field public static final int ID_ZONED_FAN_DIRECTION_AVAILABLE = 16390; // 0x4006
field public static final int ID_ZONED_FAN_SPEED_RPM = 16389; // 0x4005
field public static final int ID_ZONED_FAN_SPEED_SETPOINT = 16388; // 0x4004
field public static final int ID_ZONED_HVAC_POWER_ON = 16387; // 0x4003
diff --git a/car-lib/api/system-2.txt b/car-lib/api/system-2.txt
index e8540ad..3a2f2de 100644
--- a/car-lib/api/system-2.txt
+++ b/car-lib/api/system-2.txt
@@ -586,11 +586,11 @@
method public void setFloatProperty(int, int, float) throws android.car.CarNotConnectedException;
method public void setIntProperty(int, int, int) throws android.car.CarNotConnectedException;
method public synchronized void unregisterCallback(android.car.hardware.hvac.CarHvacManager.CarHvacEventCallback);
- field public static final int FAN_POSITION_DEFROST = 4; // 0x4
- field public static final int FAN_POSITION_DEFROST_AND_FLOOR = 5; // 0x5
- field public static final int FAN_POSITION_FACE = 1; // 0x1
- field public static final int FAN_POSITION_FACE_AND_FLOOR = 3; // 0x3
- field public static final int FAN_POSITION_FLOOR = 2; // 0x2
+ field public static final int FAN_DIRECTION_DEFROST = 4; // 0x4
+ field public static final int FAN_DIRECTION_DEFROST_AND_FLOOR = 5; // 0x5
+ field public static final int FAN_DIRECTION_FACE = 1; // 0x1
+ field public static final int FAN_DIRECTION_FACE_AND_FLOOR = 3; // 0x3
+ field public static final int FAN_DIRECTION_FLOOR = 2; // 0x2
field public static final int ID_MIRROR_DEFROSTER_ON = 1; // 0x1
field public static final int ID_OUTSIDE_AIR_TEMP = 3; // 0x3
field public static final int ID_STEERING_WHEEL_TEMP = 2; // 0x2
@@ -600,8 +600,8 @@
field public static final int ID_ZONED_AIR_RECIRCULATION_ON = 16395; // 0x400b
field public static final int ID_ZONED_AUTOMATIC_MODE_ON = 16394; // 0x400a
field public static final int ID_ZONED_DUAL_ZONE_ON = 16397; // 0x400d
- field public static final int ID_ZONED_FAN_POSITION = 16391; // 0x4007
- field public static final int ID_ZONED_FAN_POSITION_AVAILABLE = 16390; // 0x4006
+ field public static final int ID_ZONED_FAN_DIRECTION = 16391; // 0x4007
+ field public static final int ID_ZONED_FAN_DIRECTION_AVAILABLE = 16390; // 0x4006
field public static final int ID_ZONED_FAN_SPEED_RPM = 16389; // 0x4005
field public static final int ID_ZONED_FAN_SPEED_SETPOINT = 16388; // 0x4004
field public static final int ID_ZONED_HVAC_POWER_ON = 16387; // 0x4003
diff --git a/car-lib/api/system-current.txt b/car-lib/api/system-current.txt
index 6f32dd7..d611932 100644
--- a/car-lib/api/system-current.txt
+++ b/car-lib/api/system-current.txt
@@ -1,82 +1,42 @@
package android.car {
public final class Car {
- method public void connect() throws java.lang.IllegalStateException;
- method public static android.car.Car createCar(android.content.Context, android.content.ServiceConnection, android.os.Handler);
- method public static android.car.Car createCar(android.content.Context, android.content.ServiceConnection);
- method public void disconnect();
- method public int getCarConnectionType();
- method public java.lang.Object getCarManager(java.lang.String) throws android.car.CarNotConnectedException;
- method public boolean isConnected();
- method public boolean isConnecting();
- field public static final java.lang.String APP_FOCUS_SERVICE = "app_focus";
- field public static final java.lang.String AUDIO_SERVICE = "audio";
field public static final java.lang.String CABIN_SERVICE = "cabin";
- field public static final java.lang.String CAR_EXTRA_MEDIA_PACKAGE = "android.car.intent.extra.MEDIA_PACKAGE";
- field public static final java.lang.String CAR_INTENT_ACTION_MEDIA_TEMPLATE = "android.car.intent.action.MEDIA_TEMPLATE";
- field public static final int CONNECTION_TYPE_EMBEDDED = 5; // 0x5
+ field public static final java.lang.String CAR_DRIVING_STATE_SERVICE = "drivingstate";
field public static final java.lang.String DIAGNOSTIC_SERVICE = "diagnostic";
field public static final java.lang.String HVAC_SERVICE = "hvac";
- field public static final java.lang.String INFO_SERVICE = "info";
- field public static final java.lang.String PACKAGE_SERVICE = "package";
- field public static final java.lang.String PERMISSION_CAR_CABIN = "android.car.permission.CAR_CABIN";
- field public static final java.lang.String PERMISSION_CAR_CONTROL_AUDIO_VOLUME = "android.car.permission.CAR_CONTROL_AUDIO_VOLUME";
- field public static final java.lang.String PERMISSION_CAR_DIAGNOSTIC_CLEAR = "android.car.permission.DIAGNOSTIC_CLEAR";
- field public static final java.lang.String PERMISSION_CAR_DIAGNOSTIC_READ_ALL = "android.car.permission.DIAGNOSTIC_READ_ALL";
- field public static final java.lang.String PERMISSION_CAR_HVAC = "android.car.permission.CAR_HVAC";
+ field public static final java.lang.String PERMISSION_ADJUST_CAR_CABIN = "android.car.permission.ADJUST_CAR_CABIN";
+ field public static final java.lang.String PERMISSION_CAR_DIAGNOSTIC_CLEAR = "android.car.permission.CLEAR_CAR_DIAGNOSTICS";
+ field public static final java.lang.String PERMISSION_CAR_DIAGNOSTIC_READ_ALL = "android.car.permission.CAR_DIAGNOSTICS";
+ field public static final java.lang.String PERMISSION_CAR_DRIVING_STATE = "android.car.permission.CAR_DRIVING_STATE";
+ field public static final java.lang.String PERMISSION_CAR_DYNAMICS_STATE = "android.car.permission.CAR_DYNAMICS_STATE";
+ field public static final java.lang.String PERMISSION_CAR_ENGINE_DETAILED = "android.car.permission.CAR_ENGINE_DETAILED";
+ field public static final java.lang.String PERMISSION_CAR_INSTRUMENT_CLUSTER_CONTROL = "android.car.permission.CAR_INSTRUMENT_CLUSTER_CONTROL";
+ field public static final java.lang.String PERMISSION_CAR_POWER = "android.car.permission.CAR_POWER";
field public static final java.lang.String PERMISSION_CAR_PROJECTION = "android.car.permission.CAR_PROJECTION";
- field public static final java.lang.String PERMISSION_CAR_RADIO = "android.car.permission.CAR_RADIO";
field public static final java.lang.String PERMISSION_CAR_TEST_SERVICE = "android.car.permission.CAR_TEST_SERVICE";
field public static final java.lang.String PERMISSION_CONTROL_APP_BLOCKING = "android.car.permission.CONTROL_APP_BLOCKING";
- field public static final java.lang.String PERMISSION_FUEL = "android.car.permission.CAR_FUEL";
+ field public static final java.lang.String PERMISSION_CONTROL_CAR_CLIMATE = "android.car.permission.CONTROL_CAR_CLIMATE";
+ field public static final java.lang.String PERMISSION_CONTROL_CAR_DOORS = "android.car.permission.CONTROL_CAR_DOORS";
+ field public static final java.lang.String PERMISSION_CONTROL_CAR_MIRRORS = "android.car.permission.CONTROL_CAR_MIRRORS";
+ field public static final java.lang.String PERMISSION_CONTROL_CAR_SEATS = "android.car.permission.CONTROL_CAR_SEATS";
+ field public static final java.lang.String PERMISSION_CONTROL_CAR_WINDOWS = "android.car.permission.CONTROL_CAR_WINDOWS";
+ field public static final java.lang.String PERMISSION_CONTROL_EXTERIOR_LIGHTS = "android.car.permission.CONTROL_CAR_EXTERIOR_LIGHTS";
+ field public static final java.lang.String PERMISSION_EXTERIOR_LIGHTS = "android.car.permission.CAR_EXTERIOR_LIGHTS";
field public static final java.lang.String PERMISSION_MILEAGE = "android.car.permission.CAR_MILEAGE";
field public static final deprecated java.lang.String PERMISSION_MOCK_VEHICLE_HAL = "android.car.permission.CAR_MOCK_VEHICLE_HAL";
- field public static final java.lang.String PERMISSION_SPEED = "android.car.permission.CAR_SPEED";
- field public static final java.lang.String PERMISSION_VEHICLE_DYNAMICS_STATE = "android.car.permission.VEHICLE_DYNAMICS_STATE";
+ field public static final java.lang.String PERMISSION_STORAGE_MONITORING = "android.car.permission.STORAGE_MONITORING";
+ field public static final java.lang.String PERMISSION_TIRES = "android.car.permission.CAR_TIRES";
field public static final java.lang.String PERMISSION_VENDOR_EXTENSION = "android.car.permission.CAR_VENDOR_EXTENSION";
+ field public static final java.lang.String PERMISSION_VMS_PUBLISHER = "android.car.permission.VMS_PUBLISHER";
+ field public static final java.lang.String PERMISSION_VMS_SUBSCRIBER = "android.car.permission.VMS_SUBSCRIBER";
+ field public static final java.lang.String POWER_SERVICE = "power";
field public static final java.lang.String PROJECTION_SERVICE = "projection";
- field public static final java.lang.String RADIO_SERVICE = "radio";
- field public static final java.lang.String SENSOR_SERVICE = "sensor";
+ field public static final java.lang.String PROPERTY_SERVICE = "property";
+ field public static final java.lang.String STORAGE_MONITORING_SERVICE = "storage_monitoring";
field public static final java.lang.String TEST_SERVICE = "car-service-test";
field public static final java.lang.String VENDOR_EXTENSION_SERVICE = "vendor_extension";
- field public static final int VERSION = 3; // 0x3
- }
-
- public final class CarAppFocusManager {
- method public void abandonAppFocus(android.car.CarAppFocusManager.OnAppFocusOwnershipCallback, int);
- method public void abandonAppFocus(android.car.CarAppFocusManager.OnAppFocusOwnershipCallback);
- method public void addFocusListener(android.car.CarAppFocusManager.OnAppFocusChangedListener, int) throws android.car.CarNotConnectedException;
- method public boolean isOwningFocus(android.car.CarAppFocusManager.OnAppFocusOwnershipCallback, int) throws android.car.CarNotConnectedException;
- method public void removeFocusListener(android.car.CarAppFocusManager.OnAppFocusChangedListener, int);
- method public void removeFocusListener(android.car.CarAppFocusManager.OnAppFocusChangedListener);
- method public int requestAppFocus(int, android.car.CarAppFocusManager.OnAppFocusOwnershipCallback) throws android.car.CarNotConnectedException, java.lang.SecurityException;
- field public static final int APP_FOCUS_REQUEST_FAILED = 0; // 0x0
- field public static final int APP_FOCUS_REQUEST_SUCCEEDED = 1; // 0x1
- field public static final int APP_FOCUS_TYPE_NAVIGATION = 1; // 0x1
- field public static final int APP_FOCUS_TYPE_VOICE_COMMAND = 2; // 0x2
- }
-
- public static abstract interface CarAppFocusManager.OnAppFocusChangedListener {
- method public abstract void onAppFocusChanged(int, boolean);
- }
-
- public static abstract interface CarAppFocusManager.OnAppFocusOwnershipCallback {
- method public abstract void onAppFocusOwnershipGranted(int);
- method public abstract void onAppFocusOwnershipLost(int);
- }
-
- public final class CarInfoManager {
- method public java.lang.String getManufacturer() throws android.car.CarNotConnectedException;
- method public java.lang.String getModel() throws android.car.CarNotConnectedException;
- method public java.lang.String getModelYear() throws android.car.CarNotConnectedException;
- method public java.lang.String getVehicleId() throws android.car.CarNotConnectedException;
- }
-
- public class CarNotConnectedException extends java.lang.Exception {
- ctor public CarNotConnectedException();
- ctor public CarNotConnectedException(java.lang.String);
- ctor public CarNotConnectedException(java.lang.String, java.lang.Throwable);
- ctor public CarNotConnectedException(java.lang.Exception);
+ field public static final java.lang.String VMS_SUBSCRIBER_SERVICE = "vehicle_map_subscriber_service";
}
public final class CarProjectionManager {
@@ -93,16 +53,7 @@
method public abstract void onVoiceAssistantRequest(boolean);
}
- public final class VehicleAreaType {
- field public static final int VEHICLE_AREA_TYPE_DOOR = 4; // 0x4
- field public static final int VEHICLE_AREA_TYPE_MIRROR = 5; // 0x5
- field public static final int VEHICLE_AREA_TYPE_NONE = 0; // 0x0
- field public static final int VEHICLE_AREA_TYPE_SEAT = 3; // 0x3
- field public static final int VEHICLE_AREA_TYPE_WINDOW = 2; // 0x2
- field public static final int VEHICLE_AREA_TYPE_ZONE = 1; // 0x1
- }
-
- public final class VehicleDoor {
+ public final class VehicleAreaDoor {
field public static final int DOOR_HOOD = 268435456; // 0x10000000
field public static final int DOOR_REAR = 536870912; // 0x20000000
field public static final int DOOR_ROW_1_LEFT = 1; // 0x1
@@ -113,13 +64,13 @@
field public static final int DOOR_ROW_3_RIGHT = 1024; // 0x400
}
- public final class VehicleMirror {
+ public final class VehicleAreaMirror {
field public static final int MIRROR_DRIVER_CENTER = 4; // 0x4
field public static final int MIRROR_DRIVER_LEFT = 1; // 0x1
field public static final int MIRROR_DRIVER_RIGHT = 2; // 0x2
}
- public final class VehicleSeat {
+ public final class VehicleAreaSeat {
field public static final int SEAT_ROW_1_CENTER = 2; // 0x2
field public static final int SEAT_ROW_1_LEFT = 1; // 0x1
field public static final int SEAT_ROW_1_RIGHT = 4; // 0x4
@@ -131,149 +82,50 @@
field public static final int SEAT_ROW_3_RIGHT = 1024; // 0x400
}
- public final class VehicleWindow {
+ public final class VehicleAreaType {
+ field public static final int VEHICLE_AREA_TYPE_DOOR = 4; // 0x4
+ field public static final int VEHICLE_AREA_TYPE_GLOBAL = 0; // 0x0
+ field public static final int VEHICLE_AREA_TYPE_MIRROR = 5; // 0x5
+ field public static final int VEHICLE_AREA_TYPE_SEAT = 3; // 0x3
+ field public static final int VEHICLE_AREA_TYPE_WHEEL = 6; // 0x6
+ field public static final int VEHICLE_AREA_TYPE_WINDOW = 2; // 0x2
+ }
+
+ public final class VehicleAreaWheel {
+ field public static final int WHEEL_LEFT_FRONT = 1; // 0x1
+ field public static final int WHEEL_LEFT_REAR = 4; // 0x4
+ field public static final int WHEEL_RIGHT_FRONT = 2; // 0x2
+ field public static final int WHEEL_RIGHT_REAR = 8; // 0x8
+ field public static final int WHEEL_UNKNOWN = 0; // 0x0
+ }
+
+ public final class VehicleAreaWindow {
field public static final int WINDOW_FRONT_WINDSHIELD = 1; // 0x1
field public static final int WINDOW_REAR_WINDSHIELD = 2; // 0x2
- field public static final int WINDOW_ROOF_TOP = 4; // 0x4
+ field public static final int WINDOW_ROOF_TOP_1 = 65536; // 0x10000
+ field public static final int WINDOW_ROOF_TOP_2 = 131072; // 0x20000
field public static final int WINDOW_ROW_1_LEFT = 16; // 0x10
- field public static final int WINDOW_ROW_1_RIGHT = 32; // 0x20
+ field public static final int WINDOW_ROW_1_RIGHT = 64; // 0x40
field public static final int WINDOW_ROW_2_LEFT = 256; // 0x100
- field public static final int WINDOW_ROW_2_RIGHT = 512; // 0x200
+ field public static final int WINDOW_ROW_2_RIGHT = 1024; // 0x400
field public static final int WINDOW_ROW_3_LEFT = 4096; // 0x1000
- field public static final int WINDOW_ROW_3_RIGHT = 8192; // 0x2000
- }
-
- public final class VehicleZone {
- field public static final int ZONE_ALL = -2147483648; // 0x80000000
- field public static final int ZONE_ROW_1_ALL = 8; // 0x8
- field public static final int ZONE_ROW_1_CENTER = 2; // 0x2
- field public static final int ZONE_ROW_1_LEFT = 1; // 0x1
- field public static final int ZONE_ROW_1_RIGHT = 4; // 0x4
- field public static final int ZONE_ROW_2_ALL = 128; // 0x80
- field public static final int ZONE_ROW_2_CENTER = 32; // 0x20
- field public static final int ZONE_ROW_2_LEFT = 16; // 0x10
- field public static final int ZONE_ROW_2_RIGHT = 64; // 0x40
- field public static final int ZONE_ROW_3_ALL = 2048; // 0x800
- field public static final int ZONE_ROW_3_CENTER = 512; // 0x200
- field public static final int ZONE_ROW_3_LEFT = 256; // 0x100
- field public static final int ZONE_ROW_3_RIGHT = 1024; // 0x400
- field public static final int ZONE_ROW_4_ALL = 32768; // 0x8000
- field public static final int ZONE_ROW_4_CENTER = 8192; // 0x2000
- field public static final int ZONE_ROW_4_LEFT = 4096; // 0x1000
- field public static final int ZONE_ROW_4_RIGHT = 16384; // 0x4000
- }
-
- public final class VehicleZoneUtil {
- method public static int getFirstZone(int);
- method public static int getNextZone(int, int) throws java.lang.IllegalArgumentException;
- method public static int getNumberOfZones(int);
- method public static int[] listAllZones(int);
- method public static int zoneToIndex(int, int) throws java.lang.IllegalArgumentException;
+ field public static final int WINDOW_ROW_3_RIGHT = 16384; // 0x4000
}
}
-package android.car.app.menu {
+package android.car.cluster {
- public abstract class CarMenuCallbacks {
- ctor public CarMenuCallbacks();
- method public abstract android.car.app.menu.RootMenu getRootMenu(android.os.Bundle);
- method public abstract void onCarMenuClosed();
- method public abstract void onCarMenuClosing();
- method public abstract void onCarMenuOpened();
- method public abstract void onCarMenuOpening();
- method public abstract void onItemClicked(java.lang.String);
- method public abstract boolean onItemLongClicked(java.lang.String);
- method public abstract boolean onMenuClicked();
- method public abstract void subscribe(java.lang.String, android.car.app.menu.SubscriptionCallbacks);
- method public abstract void unsubscribe(java.lang.String, android.car.app.menu.SubscriptionCallbacks);
+ public class CarInstrumentClusterManager {
+ method public void registerCallback(java.lang.String, android.car.cluster.CarInstrumentClusterManager.Callback) throws android.car.CarNotConnectedException;
+ method public void startActivity(android.content.Intent) throws android.car.CarNotConnectedException;
+ method public void unregisterCallback(android.car.cluster.CarInstrumentClusterManager.Callback) throws android.car.CarNotConnectedException;
+ field public static final java.lang.String CATEGORY_NAVIGATION = "android.car.cluster.NAVIGATION";
+ field public static final java.lang.String KEY_EXTRA_ACTIVITY_STATE = "android.car.cluster.ClusterActivityState";
}
- public class CarMenuConstants {
- ctor public CarMenuConstants();
- }
-
- public static class CarMenuConstants.MenuItemConstants {
- ctor public CarMenuConstants.MenuItemConstants();
- field public static final int FLAG_BROWSABLE = 1; // 0x1
- field public static final int FLAG_FIRSTITEM = 2; // 0x2
- field public static final java.lang.String KEY_EMPTY_PLACEHOLDER = "android.car.app.menu.empty_placeholder";
- field public static final java.lang.String KEY_FLAGS = "android.car.app.menu.flags";
- field public static final java.lang.String KEY_ID = "android.car.app.menu.id";
- field public static final java.lang.String KEY_LEFTICON = "android.car.app.menu.leftIcon";
- field public static final java.lang.String KEY_REMOTEVIEWS = "android.car.app.menu.remoteViews";
- field public static final java.lang.String KEY_RIGHTICON = "android.car.app.menu.rightIcon";
- field public static final java.lang.String KEY_RIGHTTEXT = "android.car.app.menu.rightText";
- field public static final java.lang.String KEY_TEXT = "android.car.app.menu.text";
- field public static final java.lang.String KEY_TITLE = "android.car.app.menu.title";
- field public static final java.lang.String KEY_WIDGET = "android.car.app.menu.widget";
- field public static final java.lang.String KEY_WIDGET_STATE = "android.car.app.menu.widget_state";
- field public static final int WIDGET_CHECKBOX = 1; // 0x1
- field public static final int WIDGET_TEXT_VIEW = 2; // 0x2
- }
-
- public static abstract class CarMenuConstants.MenuItemConstants.MenuItemFlags implements java.lang.annotation.Annotation {
- }
-
- public static abstract class CarMenuConstants.MenuItemConstants.WidgetTypes implements java.lang.annotation.Annotation {
- }
-
- public abstract class CarUiEntry {
- ctor public CarUiEntry(android.content.Context, android.content.Context);
- method public abstract void closeDrawer();
- method public abstract android.view.View getContentView();
- method public abstract int getFragmentContainerId();
- method public abstract java.lang.CharSequence getSearchBoxText();
- method public abstract void hideMenuButton();
- method public abstract void hideTitle();
- method public abstract void onPause();
- method public abstract void onRestoreInstanceState(android.os.Bundle);
- method public abstract void onResume();
- method public abstract void onSaveInstanceState(android.os.Bundle);
- method public abstract void onStart();
- method public abstract void onStop();
- method public abstract void openDrawer();
- method public abstract void restoreMenuDrawable();
- method public abstract void setAutoLightDarkMode();
- method public abstract void setBackground(android.graphics.Bitmap);
- method public abstract void setCarMenuCallbacks(android.car.app.menu.CarMenuCallbacks);
- method public abstract void setDarkMode();
- method public abstract void setLightMode();
- method public abstract void setMenuButtonBitmap(android.graphics.Bitmap);
- method public abstract void setMenuButtonColor(int);
- method public abstract void setScrimColor(int);
- method public abstract void setSearchBoxColors(int, int, int, int);
- method public abstract void setSearchBoxEditListener(android.car.app.menu.SearchBoxEditListener);
- method public abstract void setSearchBoxEndView(android.view.View);
- method public abstract void setTitle(java.lang.CharSequence);
- method public abstract void showMenu(java.lang.String, java.lang.String);
- method public abstract void showSearchBox(android.view.View.OnClickListener);
- method public abstract void showTitle();
- method public abstract void showToast(java.lang.String, long);
- method public abstract android.widget.EditText startInput(java.lang.String, android.view.View.OnClickListener);
- method public abstract void stopInput();
- field protected final android.content.Context mAppContext;
- field protected final android.content.Context mUiLibContext;
- }
-
- public class RootMenu {
- ctor public RootMenu(java.lang.String);
- ctor public RootMenu(java.lang.String, android.os.Bundle);
- method public android.os.Bundle getBundle();
- method public java.lang.String getId();
- }
-
- public abstract class SearchBoxEditListener {
- ctor public SearchBoxEditListener();
- method public abstract void onEdit(java.lang.String);
- method public abstract void onSearch(java.lang.String);
- }
-
- public abstract class SubscriptionCallbacks {
- ctor public SubscriptionCallbacks();
- method public abstract void onChildChanged(java.lang.String, android.os.Bundle);
- method public abstract void onChildrenLoaded(java.lang.String, java.util.List<android.os.Bundle>);
- method public abstract void onError(java.lang.String);
+ public static abstract interface CarInstrumentClusterManager.Callback {
+ method public abstract void onClusterActivityStateChanged(java.lang.String, android.os.Bundle);
}
}
@@ -300,10 +152,7 @@
public abstract class NavigationRenderer {
ctor public NavigationRenderer();
method public abstract android.car.navigation.CarNavigationInstrumentCluster getNavigationProperties();
- method public abstract void onNextTurnChanged(int, java.lang.CharSequence, int, int, android.graphics.Bitmap, int);
- method public abstract void onNextTurnDistanceChanged(int, int, int, int);
- method public abstract void onStartNavigation();
- method public abstract void onStopNavigation();
+ method public abstract void onEvent(int, android.os.Bundle);
}
}
@@ -344,9 +193,7 @@
}
public final class CarPackageManager {
- method public boolean isActivityAllowedWhileDriving(java.lang.String, java.lang.String) throws android.car.CarNotConnectedException;
method public boolean isActivityBackedBySafeActivity(android.content.ComponentName) throws android.car.CarNotConnectedException;
- method public boolean isServiceAllowedWhileDriving(java.lang.String, java.lang.String) throws android.car.CarNotConnectedException;
method public void setAppBlockingPolicy(java.lang.String, android.car.content.pm.CarAppBlockingPolicy, int) throws android.car.CarNotConnectedException, java.lang.IllegalArgumentException, java.lang.SecurityException;
field public static final int FLAG_SET_POLICY_ADD = 2; // 0x2
field public static final int FLAG_SET_POLICY_REMOVE = 4; // 0x4
@@ -485,6 +332,7 @@
method public boolean isFreezeFrameNotificationSupported() throws android.car.CarNotConnectedException;
method public boolean isGetFreezeFrameSupported() throws android.car.CarNotConnectedException;
method public boolean isLiveFrameSupported() throws android.car.CarNotConnectedException;
+ method public boolean isSelectiveClearFreezeFramesSupported() throws android.car.CarNotConnectedException;
method public void onCarDisconnected();
method public boolean registerListener(android.car.diagnostic.CarDiagnosticManager.OnDiagnosticEventListener, int, int) throws android.car.CarNotConnectedException, java.lang.IllegalArgumentException;
method public void unregisterListener(android.car.diagnostic.CarDiagnosticManager.OnDiagnosticEventListener);
@@ -614,16 +462,49 @@
}
+package android.car.drivingstate {
+
+ public class CarDrivingStateEvent implements android.os.Parcelable {
+ ctor public CarDrivingStateEvent(int, long);
+ method public int describeContents();
+ method public void writeToParcel(android.os.Parcel, int);
+ field public static final android.os.Parcelable.Creator<android.car.drivingstate.CarDrivingStateEvent> CREATOR;
+ field public static final int DRIVING_STATE_IDLING = 1; // 0x1
+ field public static final int DRIVING_STATE_MOVING = 2; // 0x2
+ field public static final int DRIVING_STATE_PARKED = 0; // 0x0
+ field public static final int DRIVING_STATE_UNKNOWN = -1; // 0xffffffff
+ field public final int eventValue;
+ field public final long timeStamp;
+ }
+
+ public final class CarDrivingStateManager {
+ method public android.car.drivingstate.CarDrivingStateEvent getCurrentCarDrivingState() throws android.car.CarNotConnectedException;
+ method public synchronized void registerListener(android.car.drivingstate.CarDrivingStateManager.CarDrivingStateEventListener) throws android.car.CarNotConnectedException, java.lang.IllegalArgumentException;
+ method public synchronized void unregisterListener() throws android.car.CarNotConnectedException;
+ }
+
+ public static abstract interface CarDrivingStateManager.CarDrivingStateEventListener {
+ method public abstract void onDrivingStateChanged(android.car.drivingstate.CarDrivingStateEvent);
+ }
+
+}
+
package android.car.hardware {
public class CarPropertyConfig<T> implements android.os.Parcelable {
method public int describeContents();
+ method public int getAccess();
method public int getAreaCount();
method public int[] getAreaIds();
method public int getAreaType();
+ method public int getChangeMode();
+ method public java.util.List<java.lang.Integer> getConfigArray();
+ method public java.lang.String getConfigString();
method public int getFirstAndOnlyAreaId();
+ method public float getMaxSampleRate();
method public T getMaxValue(int);
method public T getMaxValue();
+ method public float getMinSampleRate();
method public T getMinValue(int);
method public T getMinValue();
method public int getPropertyId();
@@ -649,114 +530,37 @@
method public android.car.hardware.CarPropertyConfig.Builder<T> addAreaConfig(int, T, T);
method public android.car.hardware.CarPropertyConfig.Builder<T> addAreas(int[]);
method public android.car.hardware.CarPropertyConfig<T> build();
+ method public android.car.hardware.CarPropertyConfig.Builder<T> setAccess(int);
+ method public android.car.hardware.CarPropertyConfig.Builder<T> setChangeMode(int);
+ method public android.car.hardware.CarPropertyConfig.Builder<T> setConfigArray(java.util.ArrayList<java.lang.Integer>);
+ method public android.car.hardware.CarPropertyConfig.Builder<T> setConfigString(java.lang.String);
+ method public android.car.hardware.CarPropertyConfig.Builder<T> setMaxSampleRate(float);
+ method public android.car.hardware.CarPropertyConfig.Builder<T> setMinSampleRate(float);
}
public class CarPropertyValue<T> implements android.os.Parcelable {
- ctor public CarPropertyValue(int, T);
ctor public CarPropertyValue(int, int, T);
+ ctor public CarPropertyValue(int, int, int, long, T);
ctor public CarPropertyValue(android.os.Parcel);
method public int describeContents();
method public int getAreaId();
method public int getPropertyId();
+ method public int getStatus();
+ method public long getTimestamp();
method public T getValue();
method public void writeToParcel(android.os.Parcel, int);
field public static final android.os.Parcelable.Creator<android.car.hardware.CarPropertyValue> CREATOR;
}
- public class CarSensorEvent implements android.os.Parcelable {
- method public int describeContents();
- method public void writeToParcel(android.os.Parcel, int);
- field public static final android.os.Parcelable.Creator<android.car.hardware.CarSensorEvent> CREATOR;
- field public static final int DRIVE_STATUS_FULLY_RESTRICTED = 31; // 0x1f
- field public static final int DRIVE_STATUS_LIMIT_MESSAGE_LEN = 16; // 0x10
- field public static final int DRIVE_STATUS_NO_CONFIG = 8; // 0x8
- field public static final int DRIVE_STATUS_NO_KEYBOARD_INPUT = 2; // 0x2
- field public static final int DRIVE_STATUS_NO_VIDEO = 1; // 0x1
- field public static final int DRIVE_STATUS_NO_VOICE_INPUT = 4; // 0x4
- field public static final int DRIVE_STATUS_UNRESTRICTED = 0; // 0x0
- field public static final int GEAR_DRIVE = 100; // 0x64
- field public static final int GEAR_EIGHTH = 8; // 0x8
- field public static final int GEAR_FIFTH = 5; // 0x5
- field public static final int GEAR_FIRST = 1; // 0x1
- field public static final int GEAR_FOURTH = 4; // 0x4
- field public static final int GEAR_NEUTRAL = 0; // 0x0
- field public static final int GEAR_NINTH = 9; // 0x9
- field public static final int GEAR_PARK = 101; // 0x65
- field public static final int GEAR_REVERSE = 102; // 0x66
- field public static final int GEAR_SECOND = 2; // 0x2
- field public static final int GEAR_SEVENTH = 7; // 0x7
- field public static final int GEAR_SIXTH = 6; // 0x6
- field public static final int GEAR_TENTH = 10; // 0xa
- field public static final int GEAR_THIRD = 3; // 0x3
- field public static final int IGNITION_STATE_ACC = 3; // 0x3
- field public static final int IGNITION_STATE_LOCK = 1; // 0x1
- field public static final int IGNITION_STATE_OFF = 2; // 0x2
- field public static final int IGNITION_STATE_ON = 4; // 0x4
- field public static final int IGNITION_STATE_START = 5; // 0x5
- field public static final int IGNITION_STATE_UNDEFINED = 0; // 0x0
- field public static final int INDEX_ENVIRONMENT_PRESSURE = 1; // 0x1
- field public static final int INDEX_ENVIRONMENT_TEMPERATURE = 0; // 0x0
- field public static final int INDEX_FUEL_LEVEL_IN_DISTANCE = 1; // 0x1
- field public static final int INDEX_FUEL_LEVEL_IN_PERCENTILE = 0; // 0x0
- field public static final int INDEX_FUEL_LOW_WARNING = 0; // 0x0
- field public static final int INDEX_WHEEL_DISTANCE_FRONT_LEFT = 1; // 0x1
- field public static final int INDEX_WHEEL_DISTANCE_FRONT_RIGHT = 2; // 0x2
- field public static final int INDEX_WHEEL_DISTANCE_REAR_LEFT = 4; // 0x4
- field public static final int INDEX_WHEEL_DISTANCE_REAR_RIGHT = 3; // 0x3
- field public static final int INDEX_WHEEL_DISTANCE_RESET_COUNT = 0; // 0x0
- field public final float[] floatValues;
- field public final int[] intValues;
- field public final long[] longValues;
- field public int sensorType;
- field public long timestamp;
- }
-
- public static class CarSensorEvent.EnvironmentData {
- field public float pressure;
- field public float temperature;
- field public long timestamp;
- }
-
- public final class CarSensorManager {
- method public android.car.hardware.CarSensorEvent getLatestSensorEvent(int) throws android.car.CarNotConnectedException;
- method public int[] getSupportedSensors() throws android.car.CarNotConnectedException;
- method public boolean isSensorSupported(int) throws android.car.CarNotConnectedException;
- method public static boolean isSensorSupported(int[], int);
- method public boolean registerListener(android.car.hardware.CarSensorManager.OnSensorChangedListener, int, int) throws android.car.CarNotConnectedException, java.lang.IllegalArgumentException;
- method public void unregisterListener(android.car.hardware.CarSensorManager.OnSensorChangedListener);
- method public void unregisterListener(android.car.hardware.CarSensorManager.OnSensorChangedListener, int);
- field public static final int SENSOR_RATE_FAST = 1; // 0x1
- field public static final int SENSOR_RATE_FASTEST = 0; // 0x0
- field public static final int SENSOR_RATE_NORMAL = 3; // 0x3
- field public static final int SENSOR_RATE_UI = 2; // 0x2
- field public static final int SENSOR_TYPE_ABS_ACTIVE = 24; // 0x18
- field public static final int SENSOR_TYPE_CAR_SPEED = 2; // 0x2
- field public static final int SENSOR_TYPE_DRIVING_STATUS = 11; // 0xb
- field public static final int SENSOR_TYPE_ENVIRONMENT = 12; // 0xc
- field public static final int SENSOR_TYPE_FUEL_LEVEL = 5; // 0x5
- field public static final int SENSOR_TYPE_GEAR = 7; // 0x7
- field public static final int SENSOR_TYPE_IGNITION_STATE = 22; // 0x16
- field public static final int SENSOR_TYPE_NIGHT = 9; // 0x9
- field public static final int SENSOR_TYPE_ODOMETER = 4; // 0x4
- field public static final int SENSOR_TYPE_PARKING_BRAKE = 6; // 0x6
- field public static final int SENSOR_TYPE_RPM = 3; // 0x3
- field public static final int SENSOR_TYPE_TRACTION_CONTROL_ACTIVE = 25; // 0x19
- field public static final int SENSOR_TYPE_VENDOR_EXTENSION_END = 1879048191; // 0x6fffffff
- field public static final int SENSOR_TYPE_WHEEL_TICK_DISTANCE = 23; // 0x17
- }
-
- public static abstract interface CarSensorManager.OnSensorChangedListener {
- method public abstract void onSensorChanged(android.car.hardware.CarSensorEvent);
- }
-
public final class CarVendorExtensionManager {
method public <E> E getGlobalProperty(java.lang.Class<E>, int) throws android.car.CarNotConnectedException;
method public java.util.List<android.car.hardware.CarPropertyConfig> getProperties() throws android.car.CarNotConnectedException;
method public <E> E getProperty(java.lang.Class<E>, int, int) throws android.car.CarNotConnectedException;
+ method public boolean isPropertyAvailable(int, int) throws android.car.CarNotConnectedException;
method public void registerCallback(android.car.hardware.CarVendorExtensionManager.CarVendorExtensionCallback) throws android.car.CarNotConnectedException;
method public <E> void setGlobalProperty(java.lang.Class<E>, int, E) throws android.car.CarNotConnectedException;
method public <E> void setProperty(java.lang.Class<E>, int, int, E) throws android.car.CarNotConnectedException;
- method public void unregisterCallback(android.car.hardware.CarVendorExtensionManager.CarVendorExtensionCallback);
+ method public void unregisterCallback(android.car.hardware.CarVendorExtensionManager.CarVendorExtensionCallback) throws android.car.CarNotConnectedException;
}
public static abstract interface CarVendorExtensionManager.CarVendorExtensionCallback {
@@ -778,48 +582,46 @@
method public void setBooleanProperty(int, int, boolean) throws android.car.CarNotConnectedException;
method public void setFloatProperty(int, int, float) throws android.car.CarNotConnectedException;
method public void setIntProperty(int, int, int) throws android.car.CarNotConnectedException;
- method public synchronized void unregisterCallback(android.car.hardware.cabin.CarCabinManager.CarCabinEventCallback);
- field public static final int ID_DOOR_LOCK = 3; // 0x3
- field public static final int ID_DOOR_MOVE = 2; // 0x2
- field public static final int ID_DOOR_POS = 1; // 0x1
- field public static final int ID_MIRROR_FOLD = 4102; // 0x1006
- field public static final int ID_MIRROR_LOCK = 4101; // 0x1005
- field public static final int ID_MIRROR_Y_MOVE = 4100; // 0x1004
- field public static final int ID_MIRROR_Y_POS = 4099; // 0x1003
- field public static final int ID_MIRROR_Z_MOVE = 4098; // 0x1002
- field public static final int ID_MIRROR_Z_POS = 4097; // 0x1001
- field public static final int ID_SEAT_BACKREST_ANGLE_1_MOVE = 8201; // 0x2009
- field public static final int ID_SEAT_BACKREST_ANGLE_1_POS = 8200; // 0x2008
- field public static final int ID_SEAT_BACKREST_ANGLE_2_MOVE = 8203; // 0x200b
- field public static final int ID_SEAT_BACKREST_ANGLE_2_POS = 8202; // 0x200a
- field public static final int ID_SEAT_BELT_BUCKLED = 8195; // 0x2003
- field public static final int ID_SEAT_BELT_HEIGHT_MOVE = 8197; // 0x2005
- field public static final int ID_SEAT_BELT_HEIGHT_POS = 8196; // 0x2004
- field public static final int ID_SEAT_DEPTH_MOVE = 8207; // 0x200f
- field public static final int ID_SEAT_DEPTH_POS = 8206; // 0x200e
- field public static final int ID_SEAT_FORE_AFT_MOVE = 8199; // 0x2007
- field public static final int ID_SEAT_FORE_AFT_POS = 8198; // 0x2006
- field public static final int ID_SEAT_HEADREST_ANGLE_MOVE = 8217; // 0x2019
- field public static final int ID_SEAT_HEADREST_ANGLE_POS = 8216; // 0x2018
- field public static final int ID_SEAT_HEADREST_FORE_AFT_MOVE = 8219; // 0x201b
- field public static final int ID_SEAT_HEADREST_FORE_AFT_POS = 8218; // 0x201a
- field public static final int ID_SEAT_HEADREST_HEIGHT_MOVE = 8215; // 0x2017
- field public static final int ID_SEAT_HEADREST_HEIGHT_POS = 8214; // 0x2016
- field public static final int ID_SEAT_HEIGHT_MOVE = 8205; // 0x200d
- field public static final int ID_SEAT_HEIGHT_POS = 8204; // 0x200c
- field public static final int ID_SEAT_LUMBAR_FORE_AFT_MOVE = 8211; // 0x2013
- field public static final int ID_SEAT_LUMBAR_FORE_AFT_POS = 8210; // 0x2012
- field public static final int ID_SEAT_LUMBAR_SIDE_SUPPORT_MOVE = 8213; // 0x2015
- field public static final int ID_SEAT_LUMBAR_SIDE_SUPPORT_POS = 8212; // 0x2014
- field public static final int ID_SEAT_MEMORY_SELECT = 8193; // 0x2001
- field public static final int ID_SEAT_MEMORY_SET = 8194; // 0x2002
- field public static final int ID_SEAT_TILT_MOVE = 8209; // 0x2011
- field public static final int ID_SEAT_TILT_POS = 8208; // 0x2010
- field public static final int ID_WINDOW_LOCK = 12293; // 0x3005
- field public static final int ID_WINDOW_MOVE = 12290; // 0x3002
- field public static final int ID_WINDOW_POS = 12289; // 0x3001
- field public static final int ID_WINDOW_VENT_MOVE = 12292; // 0x3004
- field public static final int ID_WINDOW_VENT_POS = 12291; // 0x3003
+ method public synchronized void unregisterCallback(android.car.hardware.cabin.CarCabinManager.CarCabinEventCallback) throws android.car.CarNotConnectedException;
+ field public static final int ID_DOOR_LOCK = 371198722; // 0x16200b02
+ field public static final int ID_DOOR_MOVE = 373295873; // 0x16400b01
+ field public static final int ID_DOOR_POS = 373295872; // 0x16400b00
+ field public static final int ID_MIRROR_FOLD = 287312709; // 0x11200b45
+ field public static final int ID_MIRROR_LOCK = 287312708; // 0x11200b44
+ field public static final int ID_MIRROR_Y_MOVE = 339741507; // 0x14400b43
+ field public static final int ID_MIRROR_Y_POS = 339741506; // 0x14400b42
+ field public static final int ID_MIRROR_Z_MOVE = 339741505; // 0x14400b41
+ field public static final int ID_MIRROR_Z_POS = 339741504; // 0x14400b40
+ field public static final int ID_SEAT_BACKREST_ANGLE_1_MOVE = 356518792; // 0x15400b88
+ field public static final int ID_SEAT_BACKREST_ANGLE_1_POS = 356518791; // 0x15400b87
+ field public static final int ID_SEAT_BACKREST_ANGLE_2_MOVE = 356518794; // 0x15400b8a
+ field public static final int ID_SEAT_BACKREST_ANGLE_2_POS = 356518793; // 0x15400b89
+ field public static final int ID_SEAT_BELT_BUCKLED = 354421634; // 0x15200b82
+ field public static final int ID_SEAT_BELT_HEIGHT_MOVE = 356518788; // 0x15400b84
+ field public static final int ID_SEAT_BELT_HEIGHT_POS = 356518787; // 0x15400b83
+ field public static final int ID_SEAT_DEPTH_MOVE = 356518798; // 0x15400b8e
+ field public static final int ID_SEAT_DEPTH_POS = 356518797; // 0x15400b8d
+ field public static final int ID_SEAT_FORE_AFT_MOVE = 356518790; // 0x15400b86
+ field public static final int ID_SEAT_FORE_AFT_POS = 356518789; // 0x15400b85
+ field public static final int ID_SEAT_HEADREST_ANGLE_MOVE = 356518808; // 0x15400b98
+ field public static final int ID_SEAT_HEADREST_ANGLE_POS = 356518807; // 0x15400b97
+ field public static final int ID_SEAT_HEADREST_FORE_AFT_MOVE = 356518810; // 0x15400b9a
+ field public static final int ID_SEAT_HEADREST_FORE_AFT_POS = 356518809; // 0x15400b99
+ field public static final int ID_SEAT_HEADREST_HEIGHT_MOVE = 356518806; // 0x15400b96
+ field public static final int ID_SEAT_HEADREST_HEIGHT_POS = 356518805; // 0x15400b95
+ field public static final int ID_SEAT_HEIGHT_MOVE = 356518796; // 0x15400b8c
+ field public static final int ID_SEAT_HEIGHT_POS = 356518795; // 0x15400b8b
+ field public static final int ID_SEAT_LUMBAR_FORE_AFT_MOVE = 356518802; // 0x15400b92
+ field public static final int ID_SEAT_LUMBAR_FORE_AFT_POS = 356518801; // 0x15400b91
+ field public static final int ID_SEAT_LUMBAR_SIDE_SUPPORT_MOVE = 356518804; // 0x15400b94
+ field public static final int ID_SEAT_LUMBAR_SIDE_SUPPORT_POS = 356518803; // 0x15400b93
+ field public static final int ID_SEAT_MEMORY_SELECT = 356518784; // 0x15400b80
+ field public static final int ID_SEAT_MEMORY_SET = 356518785; // 0x15400b81
+ field public static final int ID_SEAT_TILT_MOVE = 356518800; // 0x15400b90
+ field public static final int ID_SEAT_TILT_POS = 356518799; // 0x15400b8f
+ field public static final int ID_WINDOW_LOCK = 322964420; // 0x13400bc4
+ field public static final int ID_WINDOW_MOVE = 322964417; // 0x13400bc1
+ field public static final int ID_WINDOW_POS = 322964416; // 0x13400bc0
}
public static abstract interface CarCabinManager.CarCabinEventCallback {
@@ -836,37 +638,35 @@
method public float getFloatProperty(int, int) throws android.car.CarNotConnectedException;
method public int getIntProperty(int, int) throws android.car.CarNotConnectedException;
method public java.util.List<android.car.hardware.CarPropertyConfig> getPropertyList() throws android.car.CarNotConnectedException;
- method public static boolean isZonedProperty(int);
+ method public boolean isPropertyAvailable(int, int) throws android.car.CarNotConnectedException;
method public synchronized void registerCallback(android.car.hardware.hvac.CarHvacManager.CarHvacEventCallback) throws android.car.CarNotConnectedException;
method public void setBooleanProperty(int, int, boolean) throws android.car.CarNotConnectedException;
method public void setFloatProperty(int, int, float) throws android.car.CarNotConnectedException;
method public void setIntProperty(int, int, int) throws android.car.CarNotConnectedException;
method public synchronized void unregisterCallback(android.car.hardware.hvac.CarHvacManager.CarHvacEventCallback);
- field public static final int FAN_POSITION_DEFROST = 4; // 0x4
- field public static final int FAN_POSITION_DEFROST_AND_FLOOR = 5; // 0x5
- field public static final int FAN_POSITION_FACE = 1; // 0x1
- field public static final int FAN_POSITION_FACE_AND_FLOOR = 3; // 0x3
- field public static final int FAN_POSITION_FLOOR = 2; // 0x2
- field public static final int ID_MIRROR_DEFROSTER_ON = 1; // 0x1
- field public static final int ID_OUTSIDE_AIR_TEMP = 3; // 0x3
- field public static final int ID_STEERING_WHEEL_TEMP = 2; // 0x2
- field public static final int ID_TEMPERATURE_UNITS = 4; // 0x4
- field public static final int ID_WINDOW_DEFROSTER_ON = 20481; // 0x5001
- field public static final int ID_ZONED_AC_ON = 16393; // 0x4009
- field public static final int ID_ZONED_AIR_RECIRCULATION_ON = 16395; // 0x400b
- field public static final int ID_ZONED_AUTOMATIC_MODE_ON = 16394; // 0x400a
- field public static final int ID_ZONED_DUAL_ZONE_ON = 16397; // 0x400d
- field public static final int ID_ZONED_FAN_POSITION = 16391; // 0x4007
- field public static final int ID_ZONED_FAN_POSITION_AVAILABLE = 16390; // 0x4006
- field public static final int ID_ZONED_FAN_SPEED_RPM = 16389; // 0x4005
- field public static final int ID_ZONED_FAN_SPEED_SETPOINT = 16388; // 0x4004
- field public static final int ID_ZONED_HVAC_AUTO_RECIRC_ON = 16399; // 0x400f
- field public static final int ID_ZONED_HVAC_POWER_ON = 16387; // 0x4003
- field public static final int ID_ZONED_MAX_AC_ON = 16396; // 0x400c
- field public static final int ID_ZONED_MAX_DEFROST_ON = 16398; // 0x400e
- field public static final int ID_ZONED_SEAT_TEMP = 16392; // 0x4008
- field public static final int ID_ZONED_TEMP_ACTUAL = 16386; // 0x4002
- field public static final int ID_ZONED_TEMP_SETPOINT = 16385; // 0x4001
+ field public static final int FAN_DIRECTION_DEFROST = 4; // 0x4
+ field public static final int FAN_DIRECTION_FACE = 1; // 0x1
+ field public static final int FAN_DIRECTION_FLOOR = 2; // 0x2
+ field public static final int ID_MIRROR_DEFROSTER_ON = 339739916; // 0x1440050c
+ field public static final int ID_OUTSIDE_AIR_TEMP = 291505923; // 0x11600703
+ field public static final int ID_STEERING_WHEEL_HEAT = 289408269; // 0x1140050d
+ field public static final int ID_TEMPERATURE_DISPLAY_UNITS = 289408270; // 0x1140050e
+ field public static final int ID_WINDOW_DEFROSTER_ON = 320865540; // 0x13200504
+ field public static final int ID_ZONED_AC_ON = 354419973; // 0x15200505
+ field public static final int ID_ZONED_AIR_RECIRCULATION_ON = 354419976; // 0x15200508
+ field public static final int ID_ZONED_AUTOMATIC_MODE_ON = 354419978; // 0x1520050a
+ field public static final int ID_ZONED_DUAL_ZONE_ON = 354419977; // 0x15200509
+ field public static final int ID_ZONED_FAN_DIRECTION = 356517121; // 0x15400501
+ field public static final int ID_ZONED_FAN_DIRECTION_AVAILABLE = 356582673; // 0x15410511
+ field public static final int ID_ZONED_FAN_SPEED_RPM = 356517135; // 0x1540050f
+ field public static final int ID_ZONED_FAN_SPEED_SETPOINT = 356517120; // 0x15400500
+ field public static final int ID_ZONED_HVAC_AUTO_RECIRC_ON = 354419986; // 0x15200512
+ field public static final int ID_ZONED_HVAC_POWER_ON = 354419984; // 0x15200510
+ field public static final int ID_ZONED_MAX_AC_ON = 354419974; // 0x15200506
+ field public static final int ID_ZONED_MAX_DEFROST_ON = 354419975; // 0x15200507
+ field public static final int ID_ZONED_SEAT_TEMP = 356517131; // 0x1540050b
+ field public static final int ID_ZONED_TEMP_ACTUAL = 358614274; // 0x15600502
+ field public static final int ID_ZONED_TEMP_SETPOINT = 358614275; // 0x15600503
}
public static abstract interface CarHvacManager.CarHvacEventCallback {
@@ -876,39 +676,22 @@
}
-package android.car.hardware.radio {
+package android.car.hardware.power {
- public class CarRadioEvent implements android.os.Parcelable {
- ctor public CarRadioEvent(int, android.car.hardware.radio.CarRadioPreset);
- method public int describeContents();
- method public int getEventType();
- method public android.car.hardware.radio.CarRadioPreset getPreset();
- method public void writeToParcel(android.os.Parcel, int);
- field public static final android.os.Parcelable.Creator<android.car.hardware.radio.CarRadioEvent> CREATOR;
- field public static final int RADIO_PRESET = 0; // 0x0
+ public class CarPowerManager {
+ field public static final int BOOT_REASON_DOOR_OPEN = 4; // 0x4
+ field public static final int BOOT_REASON_DOOR_UNLOCK = 2; // 0x2
+ field public static final int BOOT_REASON_REMOTE_START = 5; // 0x5
+ field public static final int BOOT_REASON_TIMER = 3; // 0x3
+ field public static final int BOOT_REASON_USER_POWER_ON = 1; // 0x1
}
- public final class CarRadioManager {
- method public android.car.hardware.radio.CarRadioPreset getPreset(int) throws android.car.CarNotConnectedException;
- method public int getPresetCount() throws android.car.CarNotConnectedException;
- method public synchronized void registerListener(android.car.hardware.radio.CarRadioManager.CarRadioEventListener) throws android.car.CarNotConnectedException;
- method public boolean setPreset(android.car.hardware.radio.CarRadioPreset) throws android.car.CarNotConnectedException, java.lang.IllegalArgumentException;
- method public synchronized void unregisterListener();
- }
-
- public static abstract interface CarRadioManager.CarRadioEventListener {
- method public abstract void onEvent(android.car.hardware.radio.CarRadioEvent);
- }
-
- public class CarRadioPreset implements android.os.Parcelable {
- ctor public CarRadioPreset(int, int, int, int);
- method public int describeContents();
- method public int getBand();
- method public int getChannel();
- method public int getPresetNumber();
- method public int getSubChannel();
- method public void writeToParcel(android.os.Parcel, int);
- field public static final android.os.Parcelable.Creator<android.car.hardware.radio.CarRadioPreset> CREATOR;
+ public static abstract interface CarPowerManager.CarPowerStateListener {
+ method public abstract void onStateChanged(int);
+ 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
+ field public static final int SUSPEND_EXIT = 3; // 0x3
}
}
@@ -937,27 +720,22 @@
package android.car.media {
public final class CarAudioManager {
- method public void abandonAudioFocus(android.media.AudioManager.OnAudioFocusChangeListener, android.media.AudioAttributes);
- method public android.media.AudioAttributes getAudioAttributesForCarUsage(int) throws android.car.CarNotConnectedException;
- method public int getStreamMaxVolume(int) throws android.car.CarNotConnectedException;
- method public int getStreamMinVolume(int) throws android.car.CarNotConnectedException;
- method public int getStreamVolume(int) throws android.car.CarNotConnectedException;
- method public boolean isMediaMuted() throws android.car.CarNotConnectedException;
- method public int requestAudioFocus(android.media.AudioManager.OnAudioFocusChangeListener, android.media.AudioAttributes, int, int) throws android.car.CarNotConnectedException, java.lang.IllegalArgumentException;
- method public boolean setMediaMute(boolean) throws android.car.CarNotConnectedException;
- method public void setStreamVolume(int, int, int) throws android.car.CarNotConnectedException;
- method public void setVolumeController(android.media.IVolumeController) throws android.car.CarNotConnectedException;
- field public static final int CAR_AUDIO_USAGE_ALARM = 6; // 0x6
- field public static final int CAR_AUDIO_USAGE_DEFAULT = 0; // 0x0
- field public static final int CAR_AUDIO_USAGE_MUSIC = 1; // 0x1
- field public static final int CAR_AUDIO_USAGE_NAVIGATION_GUIDANCE = 3; // 0x3
- field public static final int CAR_AUDIO_USAGE_NOTIFICATION = 7; // 0x7
- field public static final int CAR_AUDIO_USAGE_RADIO = 2; // 0x2
- field public static final int CAR_AUDIO_USAGE_RINGTONE = 10; // 0xa
- field public static final int CAR_AUDIO_USAGE_SYSTEM_SAFETY_ALERT = 9; // 0x9
- field public static final int CAR_AUDIO_USAGE_SYSTEM_SOUND = 8; // 0x8
- field public static final int CAR_AUDIO_USAGE_VOICE_CALL = 4; // 0x4
- field public static final int CAR_AUDIO_USAGE_VOICE_COMMAND = 5; // 0x5
+ method public android.car.media.CarAudioPatchHandle createAudioPatch(java.lang.String, int, int) throws android.car.CarNotConnectedException;
+ method public java.lang.String[] getExternalSources() throws android.car.CarNotConnectedException;
+ method public int getGroupMaxVolume(int) throws android.car.CarNotConnectedException;
+ method public int getGroupMinVolume(int) throws android.car.CarNotConnectedException;
+ method public int getGroupVolume(int) throws android.car.CarNotConnectedException;
+ method public int[] getUsagesForVolumeGroupId(int) throws android.car.CarNotConnectedException;
+ method public int getVolumeGroupCount() throws android.car.CarNotConnectedException;
+ method public int getVolumeGroupIdForUsage(int) throws android.car.CarNotConnectedException;
+ method public void registerVolumeCallback(android.os.IBinder) throws android.car.CarNotConnectedException;
+ method public void registerVolumeChangeObserver(android.database.ContentObserver);
+ method public void releaseAudioPatch(android.car.media.CarAudioPatchHandle) throws android.car.CarNotConnectedException;
+ method public void setBalanceTowardRight(float) throws android.car.CarNotConnectedException;
+ method public void setFadeTowardFront(float) throws android.car.CarNotConnectedException;
+ method public void setGroupVolume(int, int, int) throws android.car.CarNotConnectedException;
+ method public void unregisterVolumeCallback(android.os.IBinder) throws android.car.CarNotConnectedException;
+ method public void unregisterVolumeChangeObserver(android.database.ContentObserver);
}
}
@@ -983,17 +761,128 @@
}
-package android.car.settings {
+package android.car.storagemonitoring {
- public class CarSettings {
- ctor public CarSettings();
+ public final class CarStorageMonitoringManager {
+ method public java.util.List<android.car.storagemonitoring.IoStatsEntry> getAggregateIoStats() throws android.car.CarNotConnectedException;
+ method public java.util.List<android.car.storagemonitoring.IoStatsEntry> getBootIoStats() throws android.car.CarNotConnectedException;
+ method public java.util.List<android.car.storagemonitoring.IoStats> getIoStatsDeltas() throws android.car.CarNotConnectedException;
+ method public int getPreEolIndicatorStatus() throws android.car.CarNotConnectedException;
+ method public long getShutdownDiskWriteAmount() throws android.car.CarNotConnectedException;
+ method public android.car.storagemonitoring.WearEstimate getWearEstimate() throws android.car.CarNotConnectedException;
+ method public java.util.List<android.car.storagemonitoring.WearEstimateChange> getWearEstimateHistory() throws android.car.CarNotConnectedException;
+ method public void registerListener(android.car.storagemonitoring.CarStorageMonitoringManager.IoStatsListener) throws android.car.CarNotConnectedException;
+ method public void unregisterListener(android.car.storagemonitoring.CarStorageMonitoringManager.IoStatsListener) throws android.car.CarNotConnectedException;
+ field public static final java.lang.String INTENT_EXCESSIVE_IO = "android.car.storagemonitoring.EXCESSIVE_IO";
+ field public static final int PRE_EOL_INFO_NORMAL = 1; // 0x1
+ field public static final int PRE_EOL_INFO_UNKNOWN = 0; // 0x0
+ field public static final int PRE_EOL_INFO_URGENT = 3; // 0x3
+ field public static final int PRE_EOL_INFO_WARNING = 2; // 0x2
+ field public static final long SHUTDOWN_COST_INFO_MISSING = -1L; // 0xffffffffffffffffL
}
- 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";
+ public static abstract interface CarStorageMonitoringManager.IoStatsListener {
+ method public abstract void onSnapshot(android.car.storagemonitoring.IoStats);
+ }
+
+ public class IoStats implements android.os.Parcelable {
+ ctor public IoStats(java.util.List<android.car.storagemonitoring.IoStatsEntry>, long);
+ ctor public IoStats(android.os.Parcel);
+ ctor public IoStats(org.json.JSONObject) throws org.json.JSONException;
+ method public int describeContents();
+ method public android.car.storagemonitoring.IoStatsEntry.Metrics getBackgroundTotals();
+ method public android.car.storagemonitoring.IoStatsEntry.Metrics getForegroundTotals();
+ method public java.util.List<android.car.storagemonitoring.IoStatsEntry> getStats();
+ method public long getTimestamp();
+ method public android.car.storagemonitoring.IoStatsEntry.Metrics getTotals();
+ method public android.car.storagemonitoring.IoStatsEntry getUserIdStats(int);
+ method public void writeToJson(android.util.JsonWriter) throws java.io.IOException;
+ method public void writeToParcel(android.os.Parcel, int);
+ field public static final android.os.Parcelable.Creator<android.car.storagemonitoring.IoStats> CREATOR;
+ }
+
+ public final class IoStatsEntry implements android.os.Parcelable {
+ ctor public IoStatsEntry(int, long, android.car.storagemonitoring.IoStatsEntry.Metrics, android.car.storagemonitoring.IoStatsEntry.Metrics);
+ ctor public IoStatsEntry(android.os.Parcel);
+ ctor public IoStatsEntry(android.car.storagemonitoring.UidIoRecord, long);
+ ctor public IoStatsEntry(org.json.JSONObject) throws org.json.JSONException;
+ method public int describeContents();
+ method public void writeToJson(android.util.JsonWriter) throws java.io.IOException;
+ method public void writeToParcel(android.os.Parcel, int);
+ field public static final android.os.Parcelable.Creator<android.car.storagemonitoring.IoStatsEntry> CREATOR;
+ field public final android.car.storagemonitoring.IoStatsEntry.Metrics background;
+ field public final android.car.storagemonitoring.IoStatsEntry.Metrics foreground;
+ field public final long runtimeMillis;
+ field public final int uid;
+ }
+
+ public static final class IoStatsEntry.Metrics implements android.os.Parcelable {
+ ctor public IoStatsEntry.Metrics(long, long, long, long, long);
+ ctor public IoStatsEntry.Metrics(android.os.Parcel);
+ ctor public IoStatsEntry.Metrics(org.json.JSONObject) throws org.json.JSONException;
+ method public int describeContents();
+ method public void writeToJson(android.util.JsonWriter) throws java.io.IOException;
+ method public void writeToParcel(android.os.Parcel, int);
+ field public static final android.os.Parcelable.Creator<android.car.storagemonitoring.IoStatsEntry.Metrics> CREATOR;
+ field public final long bytesRead;
+ field public final long bytesReadFromStorage;
+ field public final long bytesWritten;
+ field public final long bytesWrittenToStorage;
+ field public final long fsyncCalls;
+ }
+
+ public class LifetimeWriteInfo implements android.os.Parcelable {
+ ctor public LifetimeWriteInfo(java.lang.String, java.lang.String, long);
+ ctor public LifetimeWriteInfo(android.os.Parcel);
+ ctor public LifetimeWriteInfo(org.json.JSONObject) throws org.json.JSONException;
+ method public int describeContents();
+ method public void writeToJson(android.util.JsonWriter) throws java.io.IOException;
+ method public void writeToParcel(android.os.Parcel, int);
+ field public static final android.os.Parcelable.Creator<android.car.storagemonitoring.IoStats> CREATOR;
+ field public final java.lang.String fstype;
+ field public final java.lang.String partition;
+ field public final long writtenBytes;
+ }
+
+ public final class UidIoRecord {
+ ctor public UidIoRecord(int, long, long, long, long, long, long, long, long, long, long);
+ field public final long background_fsync;
+ field public final long background_rchar;
+ field public final long background_read_bytes;
+ field public final long background_wchar;
+ field public final long background_write_bytes;
+ field public final long foreground_fsync;
+ field public final long foreground_rchar;
+ field public final long foreground_read_bytes;
+ field public final long foreground_wchar;
+ field public final long foreground_write_bytes;
+ field public final int uid;
+ }
+
+ public class WearEstimate implements android.os.Parcelable {
+ ctor public WearEstimate(int, int);
+ ctor public WearEstimate(android.os.Parcel);
+ ctor public WearEstimate(android.util.JsonReader) throws java.io.IOException;
+ method public int describeContents();
+ method public void writeToJson(android.util.JsonWriter) throws java.io.IOException;
+ method public void writeToParcel(android.os.Parcel, int);
+ field public static final android.os.Parcelable.Creator<android.car.storagemonitoring.WearEstimate> CREATOR;
+ field public static final int UNKNOWN = -1; // 0xffffffff
+ field public final int typeA;
+ field public final int typeB;
+ }
+
+ public class WearEstimateChange implements android.os.Parcelable {
+ ctor public WearEstimateChange(android.car.storagemonitoring.WearEstimate, android.car.storagemonitoring.WearEstimate, long, java.time.Instant, boolean);
+ ctor public WearEstimateChange(android.os.Parcel);
+ method public int describeContents();
+ method public void writeToParcel(android.os.Parcel, int);
+ field public static final android.os.Parcelable.Creator<android.car.storagemonitoring.WearEstimateChange> CREATOR;
+ field public final java.time.Instant dateAtChange;
+ field public final boolean isAcceptableDegradation;
+ field public final android.car.storagemonitoring.WearEstimate newEstimate;
+ field public final android.car.storagemonitoring.WearEstimate oldEstimate;
+ field public final long uptimeAtChange;
}
}
@@ -1008,3 +897,95 @@
}
+package android.car.vms {
+
+ public final class VmsAvailableLayers implements android.os.Parcelable {
+ ctor public VmsAvailableLayers(java.util.Set<android.car.vms.VmsAssociatedLayer>, int);
+ method public int describeContents();
+ method public java.util.Set<android.car.vms.VmsAssociatedLayer> getAssociatedLayers();
+ method public int getSequence();
+ method public void writeToParcel(android.os.Parcel, int);
+ field public static final android.os.Parcelable.Creator<android.car.vms.VmsAvailableLayers> CREATOR;
+ }
+
+ public final class VmsLayer implements android.os.Parcelable {
+ ctor public VmsLayer(int, int, int);
+ method public int describeContents();
+ method public int getSubtype();
+ method public int getType();
+ method public int getVersion();
+ method public void writeToParcel(android.os.Parcel, int);
+ field public static final android.os.Parcelable.Creator<android.car.vms.VmsLayer> CREATOR;
+ }
+
+ public final class VmsLayerDependency implements android.os.Parcelable {
+ ctor public VmsLayerDependency(android.car.vms.VmsLayer, java.util.Set<android.car.vms.VmsLayer>);
+ ctor public VmsLayerDependency(android.car.vms.VmsLayer);
+ method public int describeContents();
+ method public java.util.Set<android.car.vms.VmsLayer> getDependencies();
+ method public android.car.vms.VmsLayer getLayer();
+ method public void writeToParcel(android.os.Parcel, int);
+ field public static final android.os.Parcelable.Creator<android.car.vms.VmsLayerDependency> CREATOR;
+ }
+
+ public final class VmsLayersOffering implements android.os.Parcelable {
+ ctor public VmsLayersOffering(java.util.Set<android.car.vms.VmsLayerDependency>, int);
+ method public int describeContents();
+ method public java.util.Set<android.car.vms.VmsLayerDependency> getDependencies();
+ method public int getPublisherId();
+ method public void writeToParcel(android.os.Parcel, int);
+ field public static final android.os.Parcelable.Creator<android.car.vms.VmsLayersOffering> CREATOR;
+ }
+
+ public final class VmsOperationRecorder {
+ ctor public VmsOperationRecorder(android.car.vms.VmsOperationRecorder.Writer);
+ method public void addHalSubscription(int, android.car.vms.VmsLayer);
+ method public void addPromiscuousSubscription(int);
+ method public void addSubscription(int, android.car.vms.VmsLayer);
+ method public static android.car.vms.VmsOperationRecorder get();
+ method public void getPublisherId(int);
+ method public void removeHalSubscription(int, android.car.vms.VmsLayer);
+ method public void removePromiscuousSubscription(int);
+ method public void removeSubscription(int, android.car.vms.VmsLayer);
+ method public void setHalPublisherLayersOffering(android.car.vms.VmsLayersOffering);
+ method public void setLayersOffering(android.car.vms.VmsLayersOffering);
+ method public void setPublisherLayersOffering(android.car.vms.VmsLayersOffering);
+ method public void startMonitoring();
+ method public void stopMonitoring();
+ method public void subscribe(android.car.vms.VmsLayer);
+ method public void subscribe(android.car.vms.VmsLayer, int);
+ method public void unsubscribe(android.car.vms.VmsLayer);
+ method public void unsubscribe(android.car.vms.VmsLayer, int);
+ }
+
+ public abstract class VmsPublisherClientService extends android.app.Service {
+ ctor public VmsPublisherClientService();
+ method public final int getPublisherId(byte[]);
+ method public final android.car.vms.VmsSubscriptionState getSubscriptions();
+ method public android.os.IBinder onBind(android.content.Intent);
+ method protected abstract void onVmsPublisherServiceReady();
+ method public abstract void onVmsSubscriptionChange(android.car.vms.VmsSubscriptionState);
+ method public final void publish(android.car.vms.VmsLayer, int, byte[]);
+ method public final void setLayersOffering(android.car.vms.VmsLayersOffering);
+ }
+
+ public final class VmsSubscriberManager {
+ method public void clearVmsSubscriberClientCallback() throws android.car.CarNotConnectedException;
+ method public android.car.vms.VmsAvailableLayers getAvailableLayers() throws android.car.CarNotConnectedException, java.lang.IllegalStateException;
+ method public byte[] getPublisherInfo(int) throws android.car.CarNotConnectedException, java.lang.IllegalStateException;
+ method public void setVmsSubscriberClientCallback(java.util.concurrent.Executor, android.car.vms.VmsSubscriberManager.VmsSubscriberClientCallback) throws android.car.CarNotConnectedException;
+ method public void startMonitoring() throws android.car.CarNotConnectedException;
+ method public void stopMonitoring();
+ method public void subscribe(android.car.vms.VmsLayer) throws android.car.CarNotConnectedException;
+ method public void subscribe(android.car.vms.VmsLayer, int) throws android.car.CarNotConnectedException;
+ method public void unsubscribe(android.car.vms.VmsLayer);
+ method public void unsubscribe(android.car.vms.VmsLayer, int);
+ }
+
+ public static abstract interface VmsSubscriberManager.VmsSubscriberClientCallback {
+ method public abstract void onLayersAvailabilityChanged(android.car.vms.VmsAvailableLayers);
+ method public abstract void onVmsMessageReceived(android.car.vms.VmsLayer, byte[]);
+ }
+
+}
+
diff --git a/car-lib/native/CarPowerManager/CarPowerManager.cpp b/car-lib/native/CarPowerManager/CarPowerManager.cpp
new file mode 100644
index 0000000..856f6cd
--- /dev/null
+++ b/car-lib/native/CarPowerManager/CarPowerManager.cpp
@@ -0,0 +1,140 @@
+/*
+ * 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.
+ */
+
+#define LOG_TAG "CarPowerManagerNative"
+
+#include <binder/IServiceManager.h>
+#include <binder/IBinder.h>
+#include <binder/IInterface.h>
+#include <utils/Log.h>
+
+#include "CarPowerManager.h"
+
+namespace android {
+namespace car {
+namespace hardware {
+namespace power {
+
+// Public functions
+int CarPowerManager::clearListener() {
+ int retVal = -1;
+
+ if (mIsConnected && (mListenerToService != nullptr)) {
+ mICarPower->unregisterListener(mListenerToService);
+ mListenerToService = nullptr;
+ retVal = 0;
+ }
+ return retVal;
+}
+
+int CarPowerManager::getBootReason(BootReason *bootReason) {
+ int retVal = -1;
+
+ if ((bootReason != nullptr) && connectToCarService()) {
+ int reason = -1;
+ mICarPower->getBootReason(&reason);
+
+ if ((reason >= static_cast<int>(BootReason::kFirst)) &&
+ (reason <= static_cast<int>(BootReason::kLast))) {
+ *bootReason = static_cast<BootReason>(reason);
+ retVal = 0;
+ } else {
+ ALOGE("Received unknown bootReason = %d", reason);
+ }
+ }
+ return retVal;
+}
+
+int CarPowerManager::requestShutdownOnNextSuspend() {
+ int retVal = -1;
+
+ if (connectToCarService()) {
+ mICarPower->requestShutdownOnNextSuspend();
+ retVal = 0;
+ }
+ return retVal;
+}
+
+int CarPowerManager::setListener(Listener listener) {
+ int retVal = -1;
+
+ if (connectToCarService()) {
+ if (mListenerToService == nullptr) {
+ mListenerToService = new CarPowerStateListener(this);
+ mICarPower->registerListener(mListenerToService);
+ }
+
+ // Set the listener
+ mListener = listener;
+ retVal = 0;
+ }
+ return retVal;
+}
+
+
+// Private functions
+bool CarPowerManager::connectToCarService() {
+ if (mIsConnected) {
+ // Service is already connected
+ return true;
+ }
+
+ const String16 ICarName("car_service");
+ const String16 ICarPowerName("power");
+
+ ALOGI("Connecting to CarService" LOG_TAG);
+
+ // Get ICar
+ sp<IServiceManager> serviceManager = defaultServiceManager();
+ if (serviceManager == nullptr) {
+ ALOGE("Cannot get defaultServiceManager");
+ return(false);
+ }
+
+ sp<IBinder> binder = (serviceManager->getService(ICarName));
+ if (binder == nullptr) {
+ ALOGE("Cannot get ICar");
+ return false;
+ }
+
+ // Get ICarPower
+ sp<ICar> iCar = interface_cast<ICar>(binder);
+ if (iCar == nullptr) {
+ ALOGW("car service unavailable");
+ return false;
+ }
+
+ iCar->getCarService(ICarPowerName, &binder);
+ if (binder == nullptr) {
+ ALOGE("Cannot get ICarPower");
+ return false;
+ }
+
+ mICarPower = interface_cast<ICarPower>(binder);
+ if (mICarPower == nullptr) {
+ ALOGW("car power management service unavailable");
+ return false;
+ }
+ mIsConnected = true;
+ return true;
+}
+
+
+} // namespace power
+} // namespace hardware
+} // namespace car
+} // namespace android
+
diff --git a/car-lib/native/include/CarPowerManager.h b/car-lib/native/include/CarPowerManager.h
new file mode 100644
index 0000000..aa31030
--- /dev/null
+++ b/car-lib/native/include/CarPowerManager.h
@@ -0,0 +1,126 @@
+/*
+ * 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.
+ */
+
+#ifndef CAR_POWER_MANAGER
+#define CAR_POWER_MANAGER
+
+#include <binder/Status.h>
+#include <utils/RefBase.h>
+
+#include "android/car/ICar.h"
+#include "android/car/hardware/power/BnCarPowerStateListener.h"
+#include "android/car/hardware/power/ICarPower.h"
+
+using android::binder::Status;
+
+namespace android {
+namespace car {
+namespace hardware {
+namespace power {
+
+
+class CarPowerManager : public RefBase {
+public:
+ // Enumeration of possible boot reasons
+ // NOTE: The entries in this enum must match the ones in located CarPowerManager java class:
+ // packages/services/Car/car-lib/src/android/car/hardware/power/CarPowerManager.java
+ enum class BootReason {
+ kUserPowerOn = 1,
+ kDoorUnlock = 2,
+ kTimer = 3,
+ kDoorOpen = 4,
+ kRemoteStart = 5,
+
+ kFirst = kUserPowerOn,
+ kLast = kRemoteStart,
+ };
+
+ // Enumeration of state change events
+ // NOTE: The entries in this enum must match the ones in CarPowerStateListener located in
+ // packages/services/Car/car-lib/src/android/car/hardware/power/CarPowerManager.java
+ enum class State {
+ kShutdownCancelled = 0,
+ kShutdownEnter = 1,
+ kSuspendEnter = 2,
+ kSuspendExit = 3,
+
+ kFirst = kShutdownCancelled,
+ kLast = kSuspendExit,
+ };
+
+ using Listener = std::function<void(State)>;
+
+ CarPowerManager() = default;
+ virtual ~CarPowerManager() = default;
+
+ // Removes the listener and turns off callbacks
+ // Returns 0 on success
+ int clearListener();
+
+ // Returns the boot reason, defined in kBootReason*
+ // Returns 0 on success
+ int getBootReason(BootReason *bootReason);
+
+ // Request device to shutdown in lieu of suspend at the next opportunity
+ // Returns 0 on success
+ int requestShutdownOnNextSuspend();
+
+ // Set the callback function. This will execute in the binder thread.
+ // Returns 0 on success
+ int setListener(Listener listener);
+
+private:
+ class CarPowerStateListener final : public BnCarPowerStateListener {
+ public:
+ explicit CarPowerStateListener(CarPowerManager* parent) : mParent(parent) {};
+
+ Status onStateChanged(int state, int token) override {
+ sp<CarPowerManager> parent = mParent.promote();
+ if ((parent != nullptr) && (parent->mListener != nullptr)) {
+ if ((state >= static_cast<int>(State::kFirst)) &&
+ (state <= static_cast<int>(State::kLast))) {
+ parent->mListener(static_cast<State>(state));
+ } else {
+ ALOGE("onStateChanged unknown state received = %d", state);
+ }
+ }
+
+ if (token != 0) {
+ // Call finished() method to let CPMS know that we're ready to suspend/shutdown.
+ parent->mICarPower->finished(parent->mListenerToService, token);
+ }
+ return binder::Status::ok();
+ };
+
+ private:
+ wp<CarPowerManager> mParent;
+ };
+
+ bool connectToCarService();
+
+ sp<ICarPower> mICarPower;
+ bool mIsConnected;
+ Listener mListener;
+ sp<CarPowerStateListener> mListenerToService;
+};
+
+} // namespace power
+} // namespace hardware
+} // namespace car
+} // namespace android
+
+#endif // CAR_POWER_MANAGER
+
diff --git a/car-lib/src/android/car/Car.java b/car-lib/src/android/car/Car.java
index c0b83f7..738a423 100644
--- a/car-lib/src/android/car/Car.java
+++ b/car-lib/src/android/car/Car.java
@@ -19,18 +19,21 @@
import android.annotation.IntDef;
import android.annotation.Nullable;
import android.annotation.SystemApi;
-import android.car.annotation.FutureFeature;
import android.car.cluster.CarInstrumentClusterManager;
import android.car.content.pm.CarPackageManager;
import android.car.diagnostic.CarDiagnosticManager;
+import android.car.drivingstate.CarDrivingStateManager;
+import android.car.drivingstate.CarUxRestrictionsManager;
import android.car.hardware.CarSensorManager;
import android.car.hardware.CarVendorExtensionManager;
import android.car.hardware.cabin.CarCabinManager;
import android.car.hardware.hvac.CarHvacManager;
-import android.car.hardware.radio.CarRadioManager;
+import android.car.hardware.power.CarPowerManager;
+import android.car.hardware.property.CarPropertyManager;
import android.car.media.CarAudioManager;
import android.car.navigation.CarNavigationStatusManager;
-import android.car.CarBluetoothManager;
+import android.car.settings.CarConfigurationManager;
+import android.car.storagemonitoring.CarStorageMonitoringManager;
import android.car.test.CarTestManagerBinderWrapper;
import android.car.vms.VmsSubscriberManager;
import android.content.ComponentName;
@@ -45,7 +48,6 @@
import android.os.UserHandle;
import android.util.Log;
-import com.android.car.internal.FeatureConfiguration;
import com.android.internal.annotations.GuardedBy;
import java.lang.annotation.Retention;
@@ -82,11 +84,9 @@
/** Service name for {@link CarAudioManager} */
public static final String AUDIO_SERVICE = "audio";
- /**
- * Service name for {@link CarNavigationStatusManager}
- * @hide
- */
+ /** Service name for {@link CarNavigationStatusManager} */
public static final String CAR_NAVIGATION_SERVICE = "car_navigation_service";
+
/**
* Service name for {@link CarInstrumentClusterManager}
* @hide
@@ -109,24 +109,30 @@
* @hide
*/
@SystemApi
- public static final String RADIO_SERVICE = "radio";
-
- /**
- * @hide
- */
- @SystemApi
public static final String HVAC_SERVICE = "hvac";
/**
* @hide
*/
@SystemApi
+ public static final String POWER_SERVICE = "power";
+
+ /**
+ * @hide
+ */
+ @SystemApi
public static final String PROJECTION_SERVICE = "projection";
/**
* @hide
*/
@SystemApi
+ public static final String PROPERTY_SERVICE = "property";
+
+ /**
+ * @hide
+ */
+ @SystemApi
public static final String VENDOR_EXTENSION_SERVICE = "vendor_extension";
/**
@@ -135,12 +141,35 @@
public static final String BLUETOOTH_SERVICE = "car_bluetooth";
/**
- * @FutureFeature Cannot drop due to usage in non-flag protected place.
* @hide
*/
+ @SystemApi
public static final String VMS_SUBSCRIBER_SERVICE = "vehicle_map_subscriber_service";
/**
+ * Service name for {@link CarDrivingStateManager}
+ * @hide
+ */
+ @SystemApi
+ public static final String CAR_DRIVING_STATE_SERVICE = "drivingstate";
+
+ /**
+ * Service name for {@link CarUxRestrictionsManager}
+ */
+ public static final String CAR_UX_RESTRICTION_SERVICE = "uxrestriction";
+
+ /**
+ * Service name for {@link android.car.settings.CarConfigurationManager}
+ */
+ public static final String CAR_CONFIGURATION_SERVICE = "configuration";
+
+ /**
+ * @hide
+ */
+ @SystemApi
+ public static final String STORAGE_MONITORING_SERVICE = "storage_monitoring";
+
+ /**
* Service for testing. This is system app only feature.
* Service name for {@link CarTestManager}, to be used in {@link #getCarManager(String)}.
* @hide
@@ -148,18 +177,48 @@
@SystemApi
public static final String TEST_SERVICE = "car-service-test";
- /** Permission necessary to access car's mileage information. */
+ /** Permission necessary to access car's mileage information.
+ * @hide
+ */
+ @SystemApi
public static final String PERMISSION_MILEAGE = "android.car.permission.CAR_MILEAGE";
- /** Permission necessary to access car's fuel level. */
- public static final String PERMISSION_FUEL = "android.car.permission.CAR_FUEL";
+ /** Permission necessary to access car's energy information. */
+ public static final String PERMISSION_ENERGY = "android.car.permission.CAR_ENERGY";
+
+ /** Permission necessary to access car's VIN information */
+ public static final String PERMISSION_IDENTIFICATION =
+ "android.car.permission.CAR_IDENTIFICATION";
/** Permission necessary to access car's speed. */
public static final String PERMISSION_SPEED = "android.car.permission.CAR_SPEED";
- /** Permission necessary to access car's dynamics state. */
- public static final String PERMISSION_VEHICLE_DYNAMICS_STATE =
- "android.car.permission.VEHICLE_DYNAMICS_STATE";
+ /** Permission necessary to access car's dynamics state.
+ * @hide
+ */
+ @SystemApi
+ public static final String PERMISSION_CAR_DYNAMICS_STATE =
+ "android.car.permission.CAR_DYNAMICS_STATE";
+
+ /** Permission necessary to access car's fuel door and ev charge port. */
+ public static final String PERMISSION_ENERGY_PORTS = "android.car.permission.CAR_ENERGY_PORTS";
+
+ /** Permission necessary to read car's lights information.
+ * @hide
+ */
+ @SystemApi
+ public static final String PERMISSION_EXTERIOR_LIGHTS =
+ "android.car.permission.CAR_EXTERIOR_LIGHTS";
+
+ /** Permission necessary to control car's exterior lights.
+ * @hide
+ */
+ @SystemApi
+ public static final String PERMISSION_CONTROL_EXTERIOR_LIGHTS =
+ "android.car.permission.CONTROL_CAR_EXTERIOR_LIGHTS";
+
+ /** Permission necessary to access car's powertrain information.*/
+ public static final String PERMISSION_POWERTRAIN = "android.car.permission.CAR_POWERTRAIN";
/**
* Permission necessary to change car audio volume through {@link CarAudioManager}.
@@ -176,7 +235,6 @@
/**
* Permission necessary to use {@link CarNavigationStatusManager}.
- * @hide
*/
public static final String PERMISSION_CAR_NAVIGATION_MANAGER =
"android.car.permission.CAR_NAVIGATION_MANAGER";
@@ -187,6 +245,7 @@
*
* @hide
*/
+ @SystemApi
public static final String PERMISSION_CAR_INSTRUMENT_CLUSTER_CONTROL =
"android.car.permission.CAR_INSTRUMENT_CLUSTER_CONTROL";
@@ -199,6 +258,13 @@
public static final String PERMISSION_CAR_DISPLAY_IN_CLUSTER =
"android.car.permission.CAR_DISPLAY_IN_CLUSTER";
+ /** Permission necessary to use {@link CarInfoManager}. */
+ public static final String PERMISSION_CAR_INFO = "android.car.permission.CAR_INFO";
+
+ /** Permission necessary to read temperature of car's exterior environment. */
+ public static final String PERMISSION_EXTERIOR_ENVIRONMENT =
+ "android.car.permission.CAR_EXTERIOR_ENVIRONMENT";
+
/**
* Permission necessary to access car specific communication channel.
* @hide
@@ -219,22 +285,70 @@
* @hide
*/
@SystemApi
- public static final String PERMISSION_CAR_CABIN = "android.car.permission.CAR_CABIN";
+ public static final String PERMISSION_ADJUST_CAR_CABIN =
+ "android.car.permission.ADJUST_CAR_CABIN";
+
+ /**
+ * Permission necessary to access car's engine information.
+ * @hide
+ */
+ @SystemApi
+ public static final String PERMISSION_CAR_ENGINE_DETAILED =
+ "android.car.permission.CAR_ENGINE_DETAILED";
+
+ /**
+ * Permission necessary to access car's tire pressure information.
+ * @hide
+ */
+ @SystemApi
+ public static final String PERMISSION_TIRES = "android.car.permission.CAR_TIRES";
+
+ /**
+ * Permission necessary to control car's door.
+ * @hide
+ */
+ @SystemApi
+ public static final String PERMISSION_CONTROL_CAR_DOORS =
+ "android.car.permission.CONTROL_CAR_DOORS";
+
+ /**
+ * Permission necessary to control car's windows.
+ * @hide
+ */
+ @SystemApi
+ public static final String PERMISSION_CONTROL_CAR_WINDOWS =
+ "android.car.permission.CONTROL_CAR_WINDOWS";
+
+ /**
+ * Permission necessary to control car's seats.
+ * @hide
+ */
+ @SystemApi
+ public static final String PERMISSION_CONTROL_CAR_SEATS =
+ "android.car.permission.CONTROL_CAR_SEATS";
+
+ /**
+ * Permission necessary to control car's mirrors.
+ * @hide
+ */
+ @SystemApi
+ public static final String PERMISSION_CONTROL_CAR_MIRRORS =
+ "android.car.permission.CONTROL_CAR_MIRRORS";
/**
* Permission necessary to access Car HVAC APIs.
* @hide
*/
@SystemApi
- public static final String PERMISSION_CAR_HVAC = "android.car.permission.CAR_HVAC";
+ public static final String PERMISSION_CONTROL_CAR_CLIMATE =
+ "android.car.permission.CONTROL_CAR_CLIMATE";
/**
- * Permission necessary to access Car RADIO system APIs.
+ * Permission necessary to access Car POWER APIs.
* @hide
*/
@SystemApi
- public static final String PERMISSION_CAR_RADIO = "android.car.permission.CAR_RADIO";
-
+ public static final String PERMISSION_CAR_POWER = "android.car.permission.CAR_POWER";
/**
* Permission necessary to access Car PROJECTION system APIs.
@@ -261,11 +375,19 @@
"android.car.permission.CAR_TEST_SERVICE";
/**
+ * Permission necessary to access CarDrivingStateService to get a Car's driving state.
+ * @hide
+ */
+ @SystemApi
+ public static final String PERMISSION_CAR_DRIVING_STATE =
+ "android.car.permission.CAR_DRIVING_STATE";
+
+ /**
* Permissions necessary to access VMS publisher APIs.
*
* @hide
*/
- @FutureFeature
+ @SystemApi
public static final String PERMISSION_VMS_PUBLISHER = "android.car.permission.VMS_PUBLISHER";
/**
@@ -273,7 +395,7 @@
*
* @hide
*/
- @FutureFeature
+ @SystemApi
public static final String PERMISSION_VMS_SUBSCRIBER = "android.car.permission.VMS_SUBSCRIBER";
/**
@@ -283,7 +405,7 @@
*/
@SystemApi
public static final String PERMISSION_CAR_DIAGNOSTIC_READ_ALL =
- "android.car.permission.DIAGNOSTIC_READ_ALL";
+ "android.car.permission.CAR_DIAGNOSTICS";
/**
* Permissions necessary to clear diagnostic information.
@@ -291,7 +413,15 @@
* @hide
*/
@SystemApi
- public static final String PERMISSION_CAR_DIAGNOSTIC_CLEAR = "android.car.permission.DIAGNOSTIC_CLEAR";
+ public static final String PERMISSION_CAR_DIAGNOSTIC_CLEAR = "android.car.permission.CLEAR_CAR_DIAGNOSTICS";
+
+ /**
+ * Permissions necessary to clear diagnostic information.
+ *
+ * @hide
+ */
+ @SystemApi
+ public static final String PERMISSION_STORAGE_MONITORING = "android.car.permission.STORAGE_MONITORING";
/** Type of car connection: platform runs directly in car. */
public static final int CONNECTION_TYPE_EMBEDDED = 5;
@@ -637,11 +767,15 @@
case HVAC_SERVICE:
manager = new CarHvacManager(binder, mContext, mEventHandler);
break;
+ case POWER_SERVICE:
+ manager = new CarPowerManager(binder, mContext, mEventHandler);
+ break;
case PROJECTION_SERVICE:
manager = new CarProjectionManager(binder, mEventHandler);
break;
- case RADIO_SERVICE:
- manager = new CarRadioManager(binder, mEventHandler);
+ case PROPERTY_SERVICE:
+ manager = new CarPropertyManager(binder, mEventHandler, false,
+ "CarPropertyManager");
break;
case VENDOR_EXTENSION_SERVICE:
manager = new CarVendorExtensionManager(binder, mEventHandler);
@@ -655,12 +789,25 @@
manager = new CarTestManagerBinderWrapper(binder);
break;
case VMS_SUBSCRIBER_SERVICE:
- if (FeatureConfiguration.ENABLE_VEHICLE_MAP_SERVICE) {
- manager = new VmsSubscriberManager(binder, mEventHandler);
- }
+ manager = new VmsSubscriberManager(binder);
break;
case BLUETOOTH_SERVICE:
manager = new CarBluetoothManager(binder, mContext);
+ break;
+ case STORAGE_MONITORING_SERVICE:
+ manager = new CarStorageMonitoringManager(binder, mEventHandler);
+ break;
+ case CAR_DRIVING_STATE_SERVICE:
+ manager = new CarDrivingStateManager(binder, mContext, mEventHandler);
+ break;
+ case CAR_UX_RESTRICTION_SERVICE:
+ manager = new CarUxRestrictionsManager(binder, mContext, mEventHandler);
+ break;
+ case CAR_CONFIGURATION_SERVICE:
+ manager = new CarConfigurationManager(binder);
+ break;
+ default:
+ break;
}
return manager;
}
diff --git a/car-lib/src/android/car/CarInfoManager.java b/car-lib/src/android/car/CarInfoManager.java
index b73e879..b228ca7 100644
--- a/car-lib/src/android/car/CarInfoManager.java
+++ b/car-lib/src/android/car/CarInfoManager.java
@@ -16,46 +16,46 @@
package android.car;
+import static java.lang.Integer.toHexString;
+
import android.annotation.Nullable;
-import android.car.annotation.FutureFeature;
import android.car.annotation.ValueTypeDef;
+import android.car.hardware.CarPropertyValue;
+import android.car.hardware.property.ICarProperty;
import android.os.Bundle;
import android.os.IBinder;
import android.os.RemoteException;
-
-
-import com.android.internal.annotations.GuardedBy;
-
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
+import android.util.Log;
/**
* Utility to retrieve various static information from car. Each data are grouped as {@link Bundle}
* and relevant data can be checked from {@link Bundle} using pre-specified keys.
*/
-public final class CarInfoManager implements CarManagerBase {
+public final class CarInfoManager implements CarManagerBase{
+ private static final boolean DBG = false;
+ private static final String TAG = "CarInfoManager";
/**
* Key for manufacturer of the car. Passed in basic info Bundle.
* @hide
*/
- @ValueTypeDef(type = String.class)
- public static final String BASIC_INFO_KEY_MANUFACTURER = "android.car.manufacturer";
+ @ValueTypeDef(type = Integer.class)
+ public static final int BASIC_INFO_KEY_MANUFACTURER = 0x11100101;
/**
* Key for model name of the car. This information may not necessarily allow distinguishing
* different car models as the same name may be used for different cars depending on
* manufacturers. Passed in basic info Bundle.
* @hide
*/
- @ValueTypeDef(type = String.class)
- public static final String BASIC_INFO_KEY_MODEL = "android.car.model";
+ @ValueTypeDef(type = Integer.class)
+ public static final int BASIC_INFO_KEY_MODEL = 0x11100102;
/**
* Key for model year of the car in AC. Passed in basic info Bundle.
* @hide
*/
@ValueTypeDef(type = Integer.class)
- public static final String BASIC_INFO_KEY_MODEL_YEAR = "android.car.model-year";
+ public static final int BASIC_INFO_KEY_MODEL_YEAR = 0x11400103;
/**
* Key for unique identifier for the car. This is not VIN, and id is persistent until user
* resets it. Passed in basic info Bundle.
@@ -88,99 +88,146 @@
// add: transmission gear available selection, gear available steps
// drive wheel: FWD, RWD, AWD, 4WD */
-
- private final ICarInfo mService;
-
- @GuardedBy("this")
- private Bundle mBasicInfo;
-
/**
- * Return manufacturer of the car.
- * @return null if information is not available.
- */
- public @android.annotation.Nullable String getManufacturer() throws CarNotConnectedException {
- return getBasicInfo().getString(BASIC_INFO_KEY_MANUFACTURER);
- }
-
- /**
- * Return model name of the car. This information may not necessarily allow distinguishing
- * different car models as the same name may be used for different cars depending on
- * manufacturers.
- * @return null if information is not available.
- */
- public @Nullable String getModel() throws CarNotConnectedException {
- return getBasicInfo().getString(BASIC_INFO_KEY_MODEL);
- }
-
- /**
- * Return model year of the car in AC.
- * @return null if information is not available.
- */
- public @Nullable String getModelYear() throws CarNotConnectedException {
- return getBasicInfo().getString(BASIC_INFO_KEY_MODEL_YEAR);
- }
-
- /**
- * Return unique identifier for the car. This is not VIN, and id is persistent until user
- * resets it. This ID is guaranteed to be always available.
- * @return vehicle id
- */
- public String getVehicleId() throws CarNotConnectedException {
- return getBasicInfo().getString(BASIC_INFO_KEY_VEHICLE_ID);
- }
-
- /**
- * Get product configuration string. Contents of this string is product specific but it should
- * be composed of key-value pairs with the format of:
- * key1=value1;key2=value2;...
- * @return null if such information is not available in this car.
- * @throws CarNotConnectedException
+ * Key for Fuel Capacity in milliliters. Passed in basic info Bundle.
* @hide
*/
- @FutureFeature
- public @Nullable String getProductConfiguration() throws CarNotConnectedException {
- try {
- return mService.getStringInfo(INFO_KEY_PRODUCT_CONFIGURATION);
- } catch (IllegalStateException e) {
- CarApiUtil.checkCarNotConnectedExceptionFromCarService(e);
- } catch (RemoteException e) {
- throw new CarNotConnectedException(e);
- }
- return null;
+ @ValueTypeDef(type = Integer.class)
+ public static final int BASIC_INFO_FUEL_CAPACITY = 0x11600104;
+ /**
+ * Key for Fuel Types. This is an array of fuel types the vehicle supports.
+ * Passed in basic info Bundle.
+ * @hide
+ */
+ @ValueTypeDef(type = Integer.class)
+ public static final int BASIC_INFO_FUEL_TYPES = 0x11410105;
+ /**
+ * Key for EV Battery Capacity in WH. Passed in basic info Bundle.
+ * @hide
+ */
+ @ValueTypeDef(type = Integer.class)
+ public static final int BASIC_INFO_EV_BATTERY_CAPACITY = 0x11600106;
+ /**
+ * Key for EV Connector Types. This is an array of connector types the vehicle supports.
+ * Passed in basic info Bundle.
+ * @hide
+ */
+ @ValueTypeDef(type = Integer.class)
+ public static final int BASIC_INFO_EV_CONNECTOR_TYPES = 0x11410107;
+
+ private final ICarProperty mService;
+
+ /**
+ * @return Manufacturer of the car. Null if not available.
+ */
+ @Nullable
+ public String getManufacturer() throws CarNotConnectedException {
+ CarPropertyValue<String> carProp = getProperty(String.class,
+ BASIC_INFO_KEY_MANUFACTURER, 0);
+ return carProp != null ? carProp.getValue() : null;
}
/**
- * Get {@link android.os.Bundle} containing basic car information. Check
- * {@link #BASIC_INFO_KEY_MANUFACTURER}, {@link #BASIC_INFO_KEY_MODEL},
- * {@link #BASIC_INFO_KEY_MODEL_YEAR}, and {@link #BASIC_INFO_KEY_VEHICLE_ID} for supported
- * keys in the {@link android.os.Bundle}.
- * @return {@link android.os.Bundle} containing basic car info.
- * @throws CarNotConnectedException
+ * @return Model name of the car, null if not available. This information
+ * may not necessarily allow distinguishing different car models as the same
+ * name may be used for different cars depending on manufacturers.
*/
- private synchronized Bundle getBasicInfo() throws CarNotConnectedException {
- if (mBasicInfo != null) {
- return mBasicInfo;
- }
- try {
- mBasicInfo = mService.getBasicInfo();
- } catch (IllegalStateException e) {
- CarApiUtil.checkCarNotConnectedExceptionFromCarService(e);
- } catch (RemoteException e) {
- throw new CarNotConnectedException(e);
- }
- return mBasicInfo;
+ @Nullable
+ public String getModel() throws CarNotConnectedException {
+ CarPropertyValue<String> carProp = getProperty(String.class, BASIC_INFO_KEY_MODEL, 0);
+ return carProp != null ? carProp.getValue() : null;
+ }
+
+ /**
+ * @return Model year of the car in AC. Null if not available.
+ */
+ @Nullable
+ public String getModelYear() throws CarNotConnectedException {
+ CarPropertyValue<String> carProp = getProperty(String.class,
+ BASIC_INFO_KEY_MODEL_YEAR, 0);
+ return carProp != null ? carProp.getValue() : null;
+ }
+
+ /**
+ * @return Unique identifier for the car. This is not VIN, and vehicle id is
+ * persistent until user resets it. This ID is guaranteed to be always
+ * available.
+ * TODO: BASIC_INFO_KEY_VEHICLE_ID property?
+ */
+ public String getVehicleId() throws CarNotConnectedException {
+ return "";
+ }
+
+ /**
+ * @return Fuel capacity of the car in milliliters. 0 if car doesn't run on
+ * fuel.
+ */
+ public float getFuelCapacity() throws CarNotConnectedException {
+ CarPropertyValue<Float> carProp = getProperty(Float.class,
+ BASIC_INFO_FUEL_CAPACITY, 0);
+ return carProp != null ? carProp.getValue() : 0f;
+ }
+
+ /**
+ * @return Array of FUEL_TYPEs available in the car. Empty array if no fuel
+ * types available.
+ */
+ public @FuelType.Enum int[] getFuelTypes() throws CarNotConnectedException {
+ CarPropertyValue<int[]> carProp = getProperty(int[].class, BASIC_INFO_FUEL_TYPES, 0);
+ return carProp != null ? carProp.getValue() : new int[0];
+ }
+
+ /**
+ * @return Battery capacity of the car in WH. 0 if car doesn't run on
+ * battery.
+ */
+ public float getEvBatteryCapacity() throws CarNotConnectedException {
+ CarPropertyValue<Float> carProp = getProperty(Float.class,
+ BASIC_INFO_EV_BATTERY_CAPACITY, 0);
+ return carProp != null ? carProp.getValue() : 0f;
+ }
+
+ /**
+ * @return Array of EV_CONNECTOR_TYPEs available in the car. Empty array if
+ * no connector types available.
+ */
+ public @EvConnectorType.Enum int[] getEvConnectorTypes() throws CarNotConnectedException {
+ CarPropertyValue<int[]> carProp = getProperty(int[].class,
+ BASIC_INFO_EV_CONNECTOR_TYPES, 0);
+ return carProp != null ? carProp.getValue() : new int[0];
}
/** @hide */
CarInfoManager(IBinder service) {
- mService = ICarInfo.Stub.asInterface(service);
+ mService = ICarProperty.Stub.asInterface(service);
}
/** @hide */
- @Override
public void onCarDisconnected() {
- synchronized (this) {
- mBasicInfo = null;
+ }
+
+ private <E> CarPropertyValue<E> getProperty(Class<E> clazz, int propId, int area)
+ throws CarNotConnectedException {
+ if (DBG) {
+ Log.d(TAG, "getProperty, propId: 0x" + toHexString(propId)
+ + ", area: 0x" + toHexString(area) + ", class: " + clazz);
+ }
+ try {
+ CarPropertyValue<E> propVal = mService.getProperty(propId, area);
+ if (propVal != null && propVal.getValue() != null) {
+ Class<?> actualClass = propVal.getValue().getClass();
+ if (actualClass != clazz) {
+ throw new IllegalArgumentException("Invalid property type. " + "Expected: "
+ + clazz + ", but was: " + actualClass);
+ }
+ }
+ return propVal;
+ } catch (RemoteException e) {
+ Log.e(TAG, "getProperty failed with " + e.toString()
+ + ", propId: 0x" + toHexString(propId) + ", area: 0x" + toHexString(area), e);
+ throw new CarNotConnectedException(e);
+ } catch (IllegalArgumentException e) {
+ return null;
}
}
}
diff --git a/car-lib/src/android/car/EvConnectorType.java b/car-lib/src/android/car/EvConnectorType.java
new file mode 100644
index 0000000..15370c8
--- /dev/null
+++ b/car-lib/src/android/car/EvConnectorType.java
@@ -0,0 +1,67 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package android.car;
+
+import android.annotation.IntDef;
+import android.annotation.SystemApi;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+
+/**
+ * EvConnectorType denotes the different connectors a EV may use.
+ * @hide
+ */
+public final class EvConnectorType {
+ /**
+ * List of EV Connector Types from VHAL
+ */
+ public static final int UNKNOWN = 0;
+ public static final int J1772 = 1;
+ public static final int MENNEKES = 2;
+ public static final int CHADEMO = 3;
+ public static final int COMBO_1 = 4;
+ public static final int COMBO_2 = 5;
+ public static final int TESLA_ROADSTER = 6;
+ public static final int TESLA_HPWC = 7;
+ public static final int TESLA_SUPERCHARGER = 8;
+ public static final int GBT = 9;
+ /**
+ * Connector type to use when no other types apply. Before using this
+ * value, work with the AOSP community to see if the EvConnectorType enum can be
+ * extended with an appropriate value.
+ */
+ public static final int OTHER = 101;
+
+ /** @hide */
+ @Retention(RetentionPolicy.SOURCE)
+ @IntDef({
+ UNKNOWN,
+ J1772,
+ MENNEKES,
+ CHADEMO,
+ COMBO_1,
+ COMBO_2,
+ TESLA_ROADSTER,
+ TESLA_HPWC,
+ TESLA_SUPERCHARGER,
+ GBT,
+ OTHER
+ })
+ public @interface Enum {}
+
+
+ private EvConnectorType() {}
+}
diff --git a/car-lib/src/android/car/FuelType.java b/car-lib/src/android/car/FuelType.java
new file mode 100644
index 0000000..a808fb6
--- /dev/null
+++ b/car-lib/src/android/car/FuelType.java
@@ -0,0 +1,81 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package android.car;
+
+import android.annotation.IntDef;
+import android.annotation.SystemApi;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+
+/**
+ * FuelType denotes the different fuels a vehicle may use.
+ * @hide
+ */
+public final class FuelType {
+ /**
+ * List of Fuel Types from VHAL
+ */
+ public static final int UNKNOWN = 0;
+ /** Unleaded gasoline */
+ public static final int UNLEADED = 1;
+ /** Leaded gasoline */
+ public static final int LEADED = 2;
+ /** Diesel #1 */
+ public static final int DIESEL_1 = 3;
+ /** Diesel #2 */
+ public static final int DIESEL_2 = 4;
+ /** Biodiesel */
+ public static final int BIODIESEL = 5;
+ /** 85% ethanol/gasoline blend */
+ public static final int E85 = 6;
+ /** Liquified petroleum gas */
+ public static final int LPG = 7;
+ /** Compressed natural gas */
+ public static final int CNG = 8;
+ /** Liquified natural gas */
+ public static final int LNG = 9;
+ /** Electric */
+ public static final int ELECTRIC = 10;
+ /** Hydrogen fuel cell */
+ public static final int HYDROGEN = 11;
+ /**
+ * Fuel type to use when no other types apply. Before using this value, work with
+ * Google to see if the FuelType enum can be extended with an appropriate value.
+ */
+ public static final int OTHER = 12;
+
+ /** @hide */
+ @Retention(RetentionPolicy.SOURCE)
+ @IntDef({
+ UNKNOWN,
+ UNLEADED,
+ LEADED,
+ DIESEL_1,
+ DIESEL_2,
+ BIODIESEL,
+ E85,
+ LPG,
+ CNG,
+ LNG,
+ ELECTRIC,
+ HYDROGEN,
+ OTHER
+ })
+ public @interface Enum {}
+
+
+ private FuelType() {}
+}
diff --git a/car-lib/src/android/car/VehicleDoor.java b/car-lib/src/android/car/VehicleAreaDoor.java
similarity index 88%
rename from car-lib/src/android/car/VehicleDoor.java
rename to car-lib/src/android/car/VehicleAreaDoor.java
index 69c445d..7b06e0d 100644
--- a/car-lib/src/android/car/VehicleDoor.java
+++ b/car-lib/src/android/car/VehicleAreaDoor.java
@@ -18,12 +18,12 @@
import android.annotation.SystemApi;
/**
- * VehicleDoor is an abstraction for a door in a car. Some car APIs may provide control per
+ * VehicleAreaDoor is an abstraction for a door in a car. Some car APIs may provide control per
* door and values defined here should be used to distinguish different doors.
* @hide
*/
@SystemApi
-public final class VehicleDoor {
+public final class VehicleAreaDoor {
public static final int DOOR_ROW_1_LEFT = 0x00000001;
public static final int DOOR_ROW_1_RIGHT = 0x00000004;
public static final int DOOR_ROW_2_LEFT = 0x00000010;
@@ -33,5 +33,5 @@
public static final int DOOR_HOOD = 0x10000000;
public static final int DOOR_REAR = 0x20000000;
- private VehicleDoor() {}
+ private VehicleAreaDoor() {}
}
diff --git a/car-lib/src/android/car/VehicleMirror.java b/car-lib/src/android/car/VehicleAreaMirror.java
similarity index 84%
rename from car-lib/src/android/car/VehicleMirror.java
rename to car-lib/src/android/car/VehicleAreaMirror.java
index 21feb7a..4dd00ef 100644
--- a/car-lib/src/android/car/VehicleMirror.java
+++ b/car-lib/src/android/car/VehicleAreaMirror.java
@@ -18,15 +18,15 @@
import android.annotation.SystemApi;
/**
- * VehicleMirror is an abstraction for a mirror in a car. Some car APIs may provide control per
+ * VehicleAreaMirror is an abstraction for a mirror in a car. Some car APIs may provide control per
* mirror and values defined here should be used to distinguish different mirrors.
* @hide
*/
@SystemApi
-public final class VehicleMirror {
+public final class VehicleAreaMirror {
public static final int MIRROR_DRIVER_LEFT = 0x00000001;
public static final int MIRROR_DRIVER_RIGHT = 0x00000002;
public static final int MIRROR_DRIVER_CENTER = 0x00000004;
- private VehicleMirror() {}
+ private VehicleAreaMirror() {}
}
diff --git a/car-lib/src/android/car/VehicleSeat.java b/car-lib/src/android/car/VehicleAreaSeat.java
similarity index 90%
rename from car-lib/src/android/car/VehicleSeat.java
rename to car-lib/src/android/car/VehicleAreaSeat.java
index 3707454..b56e5a0 100644
--- a/car-lib/src/android/car/VehicleSeat.java
+++ b/car-lib/src/android/car/VehicleAreaSeat.java
@@ -19,13 +19,13 @@
import android.car.hardware.CarPropertyValue;
/**
- * VehicleSeat is an abstraction for a seat in a car. Some car APIs like
+ * VehicleAreaSeat is an abstraction for a seat in a car. Some car APIs like
* {@link CarPropertyValue} may provide control per seat and
* values defined here should be used to distinguish different seats.
* @hide
*/
@SystemApi
-public final class VehicleSeat {
+public final class VehicleAreaSeat {
public static final int SEAT_ROW_1_LEFT = 0x0001;
public static final int SEAT_ROW_1_CENTER = 0x0002;
public static final int SEAT_ROW_1_RIGHT = 0x0004;
@@ -36,5 +36,5 @@
public static final int SEAT_ROW_3_CENTER = 0x0200;
public static final int SEAT_ROW_3_RIGHT = 0x0400;
- private VehicleSeat() {}
+ private VehicleAreaSeat() {}
}
diff --git a/car-lib/src/android/car/VehicleAreaType.java b/car-lib/src/android/car/VehicleAreaType.java
index f4b5b91..971f000 100644
--- a/car-lib/src/android/car/VehicleAreaType.java
+++ b/car-lib/src/android/car/VehicleAreaType.java
@@ -22,32 +22,31 @@
import java.lang.annotation.RetentionPolicy;
/**
- * Represents vehicle area such as window, door, seat, zone, etc.
- * See also {@link android.car.VehicleDoor}, {@link android.car.VehicleSeat},
- * {@link android.car.VehicleWindow}, {@link android.car.VehicleZone}
+ * Represents vehicle area such as window, door, seat, etc.
+ * See also {@link VehicleAreaDoor}, {@link VehicleAreaSeat},
+ * {@link VehicleAreaWindow},
*
* @hide
*/
@SystemApi
public final class VehicleAreaType {
/** Used for global properties */
- public static final int VEHICLE_AREA_TYPE_NONE = 0;
-
- public static final int VEHICLE_AREA_TYPE_ZONE = 1;
+ public static final int VEHICLE_AREA_TYPE_GLOBAL = 0;
public static final int VEHICLE_AREA_TYPE_WINDOW = 2;
public static final int VEHICLE_AREA_TYPE_SEAT = 3;
public static final int VEHICLE_AREA_TYPE_DOOR = 4;
public static final int VEHICLE_AREA_TYPE_MIRROR = 5;
+ public static final int VEHICLE_AREA_TYPE_WHEEL = 6;
private VehicleAreaType() {}
/** @hide */
@IntDef({
- VEHICLE_AREA_TYPE_NONE,
- VEHICLE_AREA_TYPE_ZONE,
+ VEHICLE_AREA_TYPE_GLOBAL,
VEHICLE_AREA_TYPE_WINDOW,
VEHICLE_AREA_TYPE_SEAT,
VEHICLE_AREA_TYPE_DOOR,
- VEHICLE_AREA_TYPE_MIRROR
+ VEHICLE_AREA_TYPE_MIRROR,
+ VEHICLE_AREA_TYPE_WHEEL
})
@Retention(RetentionPolicy.SOURCE)
public @interface VehicleAreaTypeValue {}
diff --git a/car-lib/src/android/car/VehicleMirror.java b/car-lib/src/android/car/VehicleAreaWheel.java
similarity index 60%
copy from car-lib/src/android/car/VehicleMirror.java
copy to car-lib/src/android/car/VehicleAreaWheel.java
index 21feb7a..9e66ed5 100644
--- a/car-lib/src/android/car/VehicleMirror.java
+++ b/car-lib/src/android/car/VehicleAreaWheel.java
@@ -18,15 +18,18 @@
import android.annotation.SystemApi;
/**
- * VehicleMirror is an abstraction for a mirror in a car. Some car APIs may provide control per
- * mirror and values defined here should be used to distinguish different mirrors.
+ * VehicleAreaWheel is an abstraction for the wheels on a car. It exists to isolate the java APIs
+ * from the VHAL definitions.
* @hide
*/
@SystemApi
-public final class VehicleMirror {
- public static final int MIRROR_DRIVER_LEFT = 0x00000001;
- public static final int MIRROR_DRIVER_RIGHT = 0x00000002;
- public static final int MIRROR_DRIVER_CENTER = 0x00000004;
+public final class VehicleAreaWheel {
+ public static final int WHEEL_UNKNOWN = 0x00;
+ public static final int WHEEL_LEFT_FRONT = 0x01;
+ public static final int WHEEL_RIGHT_FRONT = 0x02;
+ public static final int WHEEL_LEFT_REAR = 0x04;
+ public static final int WHEEL_RIGHT_REAR = 0x08;
- private VehicleMirror() {}
+ private VehicleAreaWheel() {}
}
+
diff --git a/car-lib/src/android/car/VehicleWindow.java b/car-lib/src/android/car/VehicleAreaWindow.java
similarity index 70%
rename from car-lib/src/android/car/VehicleWindow.java
rename to car-lib/src/android/car/VehicleAreaWindow.java
index 8c147d9..57b46f5 100644
--- a/car-lib/src/android/car/VehicleWindow.java
+++ b/car-lib/src/android/car/VehicleAreaWindow.java
@@ -18,22 +18,23 @@
import android.annotation.SystemApi;
/**
- * VehicleWindow is an abstraction for a window in a car. Some car APIs may provide control per
+ * VehicleAreaWindow is an abstraction for a window in a car. Some car APIs may provide control per
* window and values defined here should be used to distinguish different windows.
* @hide
*/
@SystemApi
-public final class VehicleWindow {
+public final class VehicleAreaWindow {
public static final int WINDOW_FRONT_WINDSHIELD = 0x0001;
public static final int WINDOW_REAR_WINDSHIELD = 0x0002;
- public static final int WINDOW_ROOF_TOP = 0x0004;
public static final int WINDOW_ROW_1_LEFT = 0x0010;
- public static final int WINDOW_ROW_1_RIGHT = 0x0020;
+ public static final int WINDOW_ROW_1_RIGHT = 0x0040;
public static final int WINDOW_ROW_2_LEFT = 0x0100;
- public static final int WINDOW_ROW_2_RIGHT = 0x0200;
+ public static final int WINDOW_ROW_2_RIGHT = 0x0400;
public static final int WINDOW_ROW_3_LEFT = 0x1000;
- public static final int WINDOW_ROW_3_RIGHT = 0x2000;
+ public static final int WINDOW_ROW_3_RIGHT = 0x4000;
+ public static final int WINDOW_ROOF_TOP_1 = 0x10000;
+ public static final int WINDOW_ROOF_TOP_2 = 0x20000;
- private VehicleWindow() {}
+ private VehicleAreaWindow() {}
}
diff --git a/car-lib/src/android/car/VehicleOilLevel.java b/car-lib/src/android/car/VehicleOilLevel.java
new file mode 100644
index 0000000..5a21a2d
--- /dev/null
+++ b/car-lib/src/android/car/VehicleOilLevel.java
@@ -0,0 +1,49 @@
+/*
+ * 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;
+
+import android.annotation.IntDef;
+import android.annotation.SystemApi;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+
+/**
+ * OilLevel in the engine
+ * @hide
+ */
+public final class VehicleOilLevel {
+ /**
+ * List of Oil Levels from VHAL
+ */
+ public static final int CRITICALLY_LOW = 0;
+ public static final int LOW = 1;
+ public static final int NORMAL = 2;
+ public static final int HIGH = 3;
+ public static final int ERROR = 4;
+
+ /** @hide */
+ @Retention(RetentionPolicy.SOURCE)
+ @IntDef({
+ CRITICALLY_LOW,
+ LOW,
+ NORMAL,
+ HIGH,
+ ERROR,
+ })
+ public @interface Enum {}
+
+ private VehicleOilLevel() {}
+}
diff --git a/car-lib/src/android/car/VehiclePropertyType.java b/car-lib/src/android/car/VehiclePropertyType.java
new file mode 100644
index 0000000..b236d2d
--- /dev/null
+++ b/car-lib/src/android/car/VehiclePropertyType.java
@@ -0,0 +1,62 @@
+/*
+ * 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;
+
+import android.annotation.IntDef;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+
+
+/**
+ * Value type of VehicleProperty
+ * @hide
+ */
+public class VehiclePropertyType {
+ public static final int STRING = 0x00100000;
+ public static final int BOOLEAN = 0x00200000;
+ public static final int INT32 = 0x00400000;
+ public static final int INT32_VEC = 0x00410000;
+ public static final int INT64 = 0x00500000;
+ public static final int INT64_VEC = 0x00510000;
+ public static final int FLOAT = 0x00600000;
+ public static final int FLOAT_VEC = 0x00610000;
+ public static final int BYTES = 0x00700000;
+ public static final int MIXED = 0x00e00000;
+ public static final int MASK = 0x00ff0000;
+ /** @hide */
+ @Retention(RetentionPolicy.SOURCE)
+ @IntDef({
+ STRING,
+ BOOLEAN,
+ INT32,
+ INT32_VEC,
+ INT64,
+ INT64_VEC,
+ FLOAT,
+ FLOAT_VEC,
+ BYTES,
+ /**
+ * Any combination of scalar or vector types. The exact format must be
+ * provided in the description of the property.
+ */
+ MIXED,
+ MASK
+ })
+ public @interface Enum {}
+ private VehiclePropertyType() {}
+}
diff --git a/car-lib/src/android/car/VehicleUnit.java b/car-lib/src/android/car/VehicleUnit.java
new file mode 100644
index 0000000..a08ccb5
--- /dev/null
+++ b/car-lib/src/android/car/VehicleUnit.java
@@ -0,0 +1,80 @@
+/*
+ * 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;
+
+import android.annotation.IntDef;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+
+/**
+ * Units used for int or float type with no attached enum types.
+ * @hide
+ */
+public final class VehicleUnit {
+ /**
+ * List of Unit Types from VHAL
+ */
+ public static final int SHOULD_NOT_USE = 0x000;
+
+ public static final int METER_PER_SEC = 0x01;
+ public static final int RPM = 0x02;
+ public static final int HERTZ = 0x03;
+ public static final int PERCENTILE = 0x10;
+ public static final int MILLIMETER = 0x20;
+ public static final int METER = 0x21;
+ public static final int KILOMETER = 0x23;
+ public static final int CELSIUS = 0x30;
+ public static final int FAHRENHEIT = 0x31;
+ public static final int KELVIN = 0x32;
+ public static final int MILLILITER = 0x40;
+ public static final int NANO_SECS = 0x50;
+ public static final int SECS = 0x53;
+ public static final int YEAR = 0x59;
+ public static final int KILOPASCAL = 0x70;
+ public static final int WATT_HOUR = 0x60;
+ public static final int MILLIAMPERE = 0x61;
+ public static final int MILLIVOLT = 0x62;
+ public static final int MILLIWATTS = 0x63;
+
+ /** @hide */
+ @Retention(RetentionPolicy.SOURCE)
+ @IntDef({
+ SHOULD_NOT_USE,
+ METER_PER_SEC,
+ RPM,
+ HERTZ,
+ PERCENTILE,
+ MILLIMETER,
+ METER,
+ KILOMETER,
+ CELSIUS,
+ FAHRENHEIT,
+ KELVIN,
+ MILLILITER,
+ NANO_SECS,
+ SECS,
+ YEAR,
+ KILOPASCAL,
+ WATT_HOUR,
+ MILLIAMPERE,
+ MILLIVOLT,
+ MILLIWATTS
+ })
+ public @interface Enum {}
+
+ private VehicleUnit() {}
+}
diff --git a/car-lib/src/android/car/VehicleZone.java b/car-lib/src/android/car/VehicleZone.java
deleted file mode 100644
index 780d827..0000000
--- a/car-lib/src/android/car/VehicleZone.java
+++ /dev/null
@@ -1,48 +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;
-
-import android.annotation.SystemApi;
-import android.car.hardware.CarPropertyValue;
-
-/**
- * VehicleZone is an abstraction for an area in a car. Some car APIs like
- * {@link CarPropertyValue} needs to handle zone and values defined
- * here should be used.
- * @hide
- */
-@SystemApi
-public final class VehicleZone {
- public static final int ZONE_ROW_1_LEFT = 0x00000001;
- public static final int ZONE_ROW_1_CENTER = 0x00000002;
- public static final int ZONE_ROW_1_RIGHT = 0x00000004;
- public static final int ZONE_ROW_1_ALL = 0x00000008;
- public static final int ZONE_ROW_2_LEFT = 0x00000010;
- public static final int ZONE_ROW_2_CENTER = 0x00000020;
- public static final int ZONE_ROW_2_RIGHT = 0x00000040;
- public static final int ZONE_ROW_2_ALL = 0x00000080;
- public static final int ZONE_ROW_3_LEFT = 0x00000100;
- public static final int ZONE_ROW_3_CENTER = 0x00000200;
- public static final int ZONE_ROW_3_RIGHT = 0x00000400;
- public static final int ZONE_ROW_3_ALL = 0x00000800;
- public static final int ZONE_ROW_4_LEFT = 0x00001000;
- public static final int ZONE_ROW_4_CENTER = 0x00002000;
- public static final int ZONE_ROW_4_RIGHT = 0x00004000;
- public static final int ZONE_ROW_4_ALL = 0x00008000;
- public static final int ZONE_ALL = 0x80000000;
-
- private VehicleZone() {}
-}
diff --git a/car-lib/src/android/car/VehicleZoneUtil.java b/car-lib/src/android/car/VehicleZoneUtil.java
deleted file mode 100644
index a35bc3c..0000000
--- a/car-lib/src/android/car/VehicleZoneUtil.java
+++ /dev/null
@@ -1,122 +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;
-
-import android.annotation.SystemApi;
-
-/**
- * Collection of utilities for handling zones
- * @hide
- */
-@SystemApi
-public final class VehicleZoneUtil {
-
- /**
- * Change zone flag into index with available zones.
- * For example with zoned of 0x80000001, 0x1 will be index 0 and 0x80000000 will be index 2.
- * @param available zones, should not be zero
- * @param zone flag for the zone to get index, should not be zero and should be one of the flags
- * defined in zones.
- * @return index of desired zone.
- * @throws IllegalArgumentException if zones or zone is invalid.
- */
- public static int zoneToIndex(int zones, int zone) throws IllegalArgumentException {
- if ((zone == 0) || // check that zone is non-zero
- ((zone & zones) != zone) || // check that zone is inside of zones
- ((zone & (zone - 1)) != 0)) { // check that zone only has one bit set
- throw new IllegalArgumentException("Invalid zones 0x" + Integer.toHexString(zones) +
- " or zone 0x" + Integer.toHexString(zone));
- }
- int index = -1;
- while((zone & zones) != 0) {
- index++;
- zones &= zones - 1;
- }
- return index;
- }
-
- /**
- * Return number of zones (non-zero flag) from given zones.
- */
- public static int getNumberOfZones(int zones) {
- int numZones = 0;
- while (zones != 0) {
- zones &= zones - 1;
- numZones++;
- }
- return numZones;
- }
-
- /**
- * Return bit flag of first zone. If zones is 0, it will just return 0.
- * @param zones can be 0 if there is no zone
- * @return
- */
- public static int getFirstZone(int zones) {
- if (zones == 0) {
- return 0;
- }
- int xorFlag = zones & (zones - 1);
-
- return zones ^ xorFlag;
- }
-
- /**
- * Return bit flag of zone available after startingZone. For zones of 0x7 with startingZone of
- * 0x2, it will return 0x4. If no zone exist after startingZone, it will return 0.
- * @param zones
- * @param startingZone A bit flag representing a zone. This does not necessarily be one of flags
- * available in zones.
- * @return
- * @throws IllegalArgumentException If startingZone is invalid.
- */
- public static int getNextZone(int zones, int startingZone) throws IllegalArgumentException {
- if ((startingZone & (startingZone - 1)) != 0 || startingZone == 0) {
- throw new IllegalArgumentException(
- "Starting zone should represent only one bit flag: 0x" +
- Integer.toHexString(startingZone));
- }
-
- // Create a mask that sets all bits above the current one
- int mask = startingZone << 1;
- mask -= 1;
- mask = ~mask;
- return getFirstZone(zones & mask);
- }
-
- /**
- * Return array of zone with each active zone in one index. This can be useful for iterating
- * all available zones.
- */
- public static int[] listAllZones(int zones) {
- int numberOfZones = getNumberOfZones(zones);
- int[] list = new int[numberOfZones];
- if (numberOfZones == 0) {
- return list;
- }
-
- int arrayIndex = 0;
- while (zones != 0) {
- int xorFlag = zones & (zones - 1);
- int zone = zones ^ xorFlag;
- list[arrayIndex++] = zone;
- zones = xorFlag;
- }
- return list;
- }
-
- private VehicleZoneUtil() {}
-}
diff --git a/car-lib/src/android/car/cluster/CarInstrumentClusterManager.java b/car-lib/src/android/car/cluster/CarInstrumentClusterManager.java
index 758ce9e..0ec6d72 100644
--- a/car-lib/src/android/car/cluster/CarInstrumentClusterManager.java
+++ b/car-lib/src/android/car/cluster/CarInstrumentClusterManager.java
@@ -16,6 +16,7 @@
package android.car.cluster;
+import android.annotation.SystemApi;
import android.car.CarManagerBase;
import android.car.CarNotConnectedException;
import android.content.Intent;
@@ -40,10 +41,12 @@
*
* @hide
*/
+@SystemApi
public class CarInstrumentClusterManager implements CarManagerBase {
private static final String TAG = CarInstrumentClusterManager.class.getSimpleName();
/** @hide */
+ @SystemApi
public static final String CATEGORY_NAVIGATION = "android.car.cluster.NAVIGATION";
/**
@@ -53,6 +56,7 @@
*
* @hide
*/
+ @SystemApi
public static final String KEY_EXTRA_ACTIVITY_STATE =
"android.car.cluster.ClusterActivityState";
@@ -70,6 +74,7 @@
*
* @hide
*/
+ @SystemApi
public void startActivity(Intent intent) throws CarNotConnectedException {
try {
mService.startClusterActivity(intent);
@@ -88,6 +93,7 @@
*
* @hide
*/
+ @SystemApi
public void registerCallback(String category, Callback callback)
throws CarNotConnectedException {
Log.i(TAG, "registerCallback, category: " + category + ", callback: " + callback);
@@ -130,6 +136,7 @@
*
* @hide
*/
+ @SystemApi
public void unregisterCallback(Callback callback) throws CarNotConnectedException {
List<String> keysToRemove = new ArrayList<>(1);
synchronized (mLock) {
@@ -164,6 +171,7 @@
}
/** @hide */
+ @SystemApi
public interface Callback {
/**
diff --git a/car-lib/src/android/car/cluster/renderer/IInstrumentClusterNavigation.aidl b/car-lib/src/android/car/cluster/renderer/IInstrumentClusterNavigation.aidl
index b1fb7b1..6f33a9d 100644
--- a/car-lib/src/android/car/cluster/renderer/IInstrumentClusterNavigation.aidl
+++ b/car-lib/src/android/car/cluster/renderer/IInstrumentClusterNavigation.aidl
@@ -25,13 +25,6 @@
* @hide
*/
interface IInstrumentClusterNavigation {
- void onStartNavigation();
- void onStopNavigation();
- void onNextManeuverChanged(
- int event, CharSequence eventName, int turnAngle, int turnNumber, in Bitmap image,
- int turnSide);
- void onNextManeuverDistanceChanged(int distanceMeters, int timeSeconds,
- int displayDistanceMillis, int displayDistanceUnit);
void onEvent(int eventType, in Bundle bundle);
CarNavigationInstrumentCluster getInstrumentClusterInfo();
}
diff --git a/car-lib/src/android/car/cluster/renderer/InstrumentClusterRenderingService.java b/car-lib/src/android/car/cluster/renderer/InstrumentClusterRenderingService.java
index e34f2fa..d572d9a 100644
--- a/car-lib/src/android/car/cluster/renderer/InstrumentClusterRenderingService.java
+++ b/car-lib/src/android/car/cluster/renderer/InstrumentClusterRenderingService.java
@@ -24,7 +24,6 @@
import android.car.CarNotConnectedException;
import android.car.navigation.CarNavigationInstrumentCluster;
import android.content.Intent;
-import android.graphics.Bitmap;
import android.os.Bundle;
import android.os.Handler;
import android.os.IBinder;
@@ -239,34 +238,6 @@
}
@Override
- public void onStartNavigation() throws RemoteException {
- assertContextOwnership();
- mNavigationRenderer.onStartNavigation();
- }
-
- @Override
- public void onStopNavigation() throws RemoteException {
- assertContextOwnership();
- mNavigationRenderer.onStopNavigation();
- }
-
- @Override
- public void onNextManeuverChanged(int event, CharSequence eventName, int turnAngle,
- int turnNumber, Bitmap image, int turnSide) throws RemoteException {
- assertContextOwnership();
- mNavigationRenderer.onNextTurnChanged(event, eventName, turnAngle, turnNumber,
- image, turnSide);
- }
-
- @Override
- public void onNextManeuverDistanceChanged(int distanceMeters, int timeSeconds,
- int displayDistanceMillis, int displayDistanceUnit) throws RemoteException {
- assertContextOwnership();
- mNavigationRenderer.onNextTurnDistanceChanged(distanceMeters, timeSeconds,
- displayDistanceMillis, displayDistanceUnit);
- }
-
- @Override
public void onEvent(int eventType, Bundle bundle) throws RemoteException {
assertContextOwnership();
mNavigationRenderer.onEvent(eventType, bundle);
@@ -284,7 +255,7 @@
Pair<Integer, Integer> owner = mNavContextOwner;
if (owner == null || owner.first != uid || owner.second != pid) {
throw new IllegalStateException("Client (uid:" + uid + ", pid: " + pid + ") is"
- + "not an owner of APP_CONTEXT_NAVIGATION");
+ + " not an owner of APP_FOCUS_TYPE_NAVIGATION");
}
}
}
diff --git a/car-lib/src/android/car/cluster/renderer/NavigationRenderer.java b/car-lib/src/android/car/cluster/renderer/NavigationRenderer.java
index 0958548..4681a8b 100644
--- a/car-lib/src/android/car/cluster/renderer/NavigationRenderer.java
+++ b/car-lib/src/android/car/cluster/renderer/NavigationRenderer.java
@@ -24,7 +24,6 @@
/**
* Contains methods specified for Navigation App renderer in instrument cluster.
*
- * TODO: Consider to add methods to report time / distance to final destination. bug:32060070
* @hide
*/
@SystemApi
@@ -35,13 +34,8 @@
*/
abstract public CarNavigationInstrumentCluster getNavigationProperties();
- abstract public void onStartNavigation();
- abstract public void onStopNavigation();
- abstract public void onNextTurnChanged(int event, CharSequence eventName, int turnAngle,
- int turnNumber, Bitmap image, int turnSide);
- abstract public void onNextTurnDistanceChanged(int distanceMeters, int timeSeconds,
- int displayDistanceMillis, int displayDistanceUnit);
-
- /** @hide */
- public void onEvent(int eventType, Bundle bundle) {}
+ /**
+ * Called when an event is fired to change the navigation state.
+ */
+ abstract public void onEvent(int eventType, Bundle bundle);
}
diff --git a/car-lib/src/android/car/cluster/renderer/ThreadSafeNavigationRenderer.java b/car-lib/src/android/car/cluster/renderer/ThreadSafeNavigationRenderer.java
index 047ed90..251b670 100644
--- a/car-lib/src/android/car/cluster/renderer/ThreadSafeNavigationRenderer.java
+++ b/car-lib/src/android/car/cluster/renderer/ThreadSafeNavigationRenderer.java
@@ -30,16 +30,13 @@
* A wrapper over {@link NavigationRenderer} that runs all its methods in the context of provided
* looper. It is guaranteed that all calls will be invoked in order they were called.
*/
+// TODO(deanh): Does this class even need to exist?
/* package */ class ThreadSafeNavigationRenderer extends NavigationRenderer {
private final Handler mHandler;
private final NavigationRenderer mRenderer;
- private final static int MSG_NAV_START = 1;
- private final static int MSG_NAV_STOP = 2;
- private final static int MSG_NAV_NEXT_TURN = 3;
- private final static int MSG_NAV_NEXT_TURN_DISTANCE = 4;
- private final static int MSG_EVENT = 5;
+ private final static int MSG_EVENT = 1;
/** Creates thread-safe {@link NavigationRenderer}. Returns null if renderer == null */
@Nullable
@@ -68,31 +65,6 @@
}
@Override
- public void onStartNavigation() {
- mHandler.sendMessage(mHandler.obtainMessage(MSG_NAV_START));
- }
-
- @Override
- public void onStopNavigation() {
- mHandler.sendMessage(mHandler.obtainMessage(MSG_NAV_STOP));
- }
-
- @Override
- public void onNextTurnChanged(int event, CharSequence eventName, int turnAngle, int turnNumber,
- Bitmap image, int turnSide) {
- mHandler.sendMessage(mHandler.obtainMessage(MSG_NAV_NEXT_TURN,
- new NextTurn(event, eventName, turnAngle, turnNumber, image, turnSide)));
- }
-
- @Override
- public void onNextTurnDistanceChanged(int distanceMeters, int timeSeconds,
- int displayDistanceMillis, int displayDistanceUnit) {
- ManeuverDistance distance = new ManeuverDistance(distanceMeters, timeSeconds,
- displayDistanceMillis, displayDistanceUnit);
- mHandler.sendMessage(mHandler.obtainMessage(MSG_NAV_NEXT_TURN_DISTANCE, distance));
- }
-
- @Override
public void onEvent(int eventType, Bundle bundle) {
mHandler.sendMessage(mHandler.obtainMessage(MSG_EVENT, eventType, 0, bundle));
}
@@ -106,22 +78,6 @@
@Override
public void handleMessage(Message msg, NavigationRenderer renderer) {
switch (msg.what) {
- case MSG_NAV_START:
- renderer.onStartNavigation();
- break;
- case MSG_NAV_STOP:
- renderer.onStopNavigation();
- break;
- case MSG_NAV_NEXT_TURN:
- NextTurn nt = (NextTurn) msg.obj;
- renderer.onNextTurnChanged(nt.event, nt.eventName, nt.turnAngle, nt.turnNumber,
- nt.bitmap, nt.turnSide);
- break;
- case MSG_NAV_NEXT_TURN_DISTANCE:
- ManeuverDistance d = (ManeuverDistance) msg.obj;
- renderer.onNextTurnDistanceChanged(
- d.meters, d.seconds, d.displayDistanceMillis, d.displayDistanceUnit);
- break;
case MSG_EVENT:
Bundle bundle = (Bundle) msg.obj;
renderer.onEvent(msg.arg1, bundle);
@@ -153,25 +109,6 @@
return runnable.getResult();
}
- private static class NextTurn {
- private final int event;
- private final CharSequence eventName;
- private final int turnAngle;
- private final int turnNumber;
- private final Bitmap bitmap;
- private final int turnSide;
-
- NextTurn(int event, CharSequence eventName, int turnAngle, int turnNumber, Bitmap bitmap,
- int turnSide) {
- this.event = event;
- this.eventName = eventName;
- this.turnAngle = turnAngle;
- this.turnNumber = turnNumber;
- this.bitmap = bitmap;
- this.turnSide = turnSide;
- }
- }
-
private static abstract class RunnableWithResult<T> implements Runnable {
private volatile T result;
@@ -206,19 +143,4 @@
public abstract void handleMessage(Message msg, T renderer);
}
-
- private static class ManeuverDistance {
- final int meters;
- final int seconds;
- final int displayDistanceMillis;
- final int displayDistanceUnit;
-
- ManeuverDistance(int meters, int seconds, int displayDistanceMillis,
- int displayDistanceUnit) {
- this.meters = meters;
- this.seconds = seconds;
- this.displayDistanceMillis = displayDistanceMillis;
- this.displayDistanceUnit = displayDistanceUnit;
- }
- }
}
diff --git a/car-lib/src/android/car/content/pm/CarPackageManager.java b/car-lib/src/android/car/content/pm/CarPackageManager.java
index 380432f..b1828db 100644
--- a/car-lib/src/android/car/content/pm/CarPackageManager.java
+++ b/car-lib/src/android/car/content/pm/CarPackageManager.java
@@ -18,6 +18,7 @@
import android.annotation.IntDef;
import android.annotation.SystemApi;
+import android.annotation.TestApi;
import android.car.CarApiUtil;
import android.car.CarManagerBase;
import android.car.CarNotConnectedException;
@@ -26,6 +27,7 @@
import android.os.IBinder;
import android.os.Looper;
import android.os.RemoteException;
+import android.util.Log;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
@@ -34,6 +36,7 @@
* Provides car specific API related with package management.
*/
public final class CarPackageManager implements CarManagerBase {
+ private static final String TAG = "CarPackageManager";
/**
* Flag for {@link #setAppBlockingPolicy(String, CarAppBlockingPolicy, int)}. When this
@@ -118,7 +121,21 @@
} catch (IllegalStateException e) {
CarApiUtil.checkCarNotConnectedExceptionFromCarService(e);
} catch (RemoteException e) {
- //ignore as CarApi will handle disconnection anyway.
+ // Ignore as CarApi will handle disconnection anyway.
+ }
+ }
+
+ /**
+ * Restarts the requested task. If task with {@code taskId} does not exist, do nothing.
+ *
+ * @hide
+ */
+ public void restartTask(int taskId) {
+ try {
+ mService.restartTask(taskId);
+ } catch (RemoteException e) {
+ // Ignore as CarApi will handle disconnection anyway.
+ Log.e(TAG, "Could not restart task " + taskId, e);
}
}
@@ -150,15 +167,31 @@
}
/**
- * Check if given activity is allowed while driving.
+ * Enable/Disable Activity Blocking. This is to provide an option for toggling app blocking
+ * behavior for development purposes.
+ * @hide
+ */
+ @TestApi
+ public void setEnableActivityBlocking(boolean enable) {
+ try {
+ mService.setEnableActivityBlocking(enable);
+ } catch (RemoteException e) {
+ //ignore as CarApi will handle disconnection anyway.
+ }
+ }
+
+ /**
+ * Check if given activity is distraction optimized, i.e, allowed in a
+ * restricted driving state
+ *
* @param packageName
* @param className
* @return
*/
- public boolean isActivityAllowedWhileDriving(String packageName, String className)
+ public boolean isActivityDistractionOptimized(String packageName, String className)
throws CarNotConnectedException {
try {
- return mService.isActivityAllowedWhileDriving(packageName, className);
+ return mService.isActivityDistractionOptimized(packageName, className);
} catch (IllegalStateException e) {
CarApiUtil.checkCarNotConnectedExceptionFromCarService(e);
} catch (RemoteException e) {
@@ -168,15 +201,17 @@
}
/**
- * Check if given service is allowed while driving.
+ * Check if given service is distraction optimized, i.e, allowed in a restricted
+ * driving state.
+ *
* @param packageName
* @param className
* @return
*/
- public boolean isServiceAllowedWhileDriving(String packageName, String className)
+ public boolean isServiceDistractionOptimized(String packageName, String className)
throws CarNotConnectedException {
try {
- return mService.isServiceAllowedWhileDriving(packageName, className);
+ return mService.isServiceDistractionOptimized(packageName, className);
} catch (IllegalStateException e) {
CarApiUtil.checkCarNotConnectedExceptionFromCarService(e);
} catch (RemoteException e) {
diff --git a/car-lib/src/android/car/content/pm/ICarPackageManager.aidl b/car-lib/src/android/car/content/pm/ICarPackageManager.aidl
index 306db65..7210f90 100644
--- a/car-lib/src/android/car/content/pm/ICarPackageManager.aidl
+++ b/car-lib/src/android/car/content/pm/ICarPackageManager.aidl
@@ -22,7 +22,9 @@
/** @hide */
interface ICarPackageManager {
void setAppBlockingPolicy(in String packageName, in CarAppBlockingPolicy policy, int flags) = 0;
- boolean isActivityAllowedWhileDriving(in String packageName, in String className) = 1;
- boolean isServiceAllowedWhileDriving(in String packageName, in String className) = 2;
+ boolean isActivityDistractionOptimized(in String packageName, in String className) = 1;
+ boolean isServiceDistractionOptimized(in String packageName, in String className) = 2;
boolean isActivityBackedBySafeActivity(in ComponentName activityName) = 3;
+ void setEnableActivityBlocking(boolean enable) = 4;
+ void restartTask(int taskId) = 5;
}
diff --git a/car-lib/src/android/car/diagnostic/CarDiagnosticManager.java b/car-lib/src/android/car/diagnostic/CarDiagnosticManager.java
index 84cdd3e..88980bf 100644
--- a/car-lib/src/android/car/diagnostic/CarDiagnosticManager.java
+++ b/car-lib/src/android/car/diagnostic/CarDiagnosticManager.java
@@ -349,8 +349,13 @@
}
/**
- * Returns true if this vehicle supports clearing freeze frame timestamps.
+ * Returns true if this vehicle supports clearing all freeze frames.
* This is only meaningful if freeze frame data is also supported.
+ *
+ * A return value of true for this method indicates that it is supported to call
+ * carDiagnosticManager.clearFreezeFrames()
+ * to delete all freeze frames stored in vehicle memory.
+ *
* @return
* @throws CarNotConnectedException
*/
@@ -365,6 +370,28 @@
return false;
}
+ /**
+ * Returns true if this vehicle supports clearing specific freeze frames by timestamp.
+ * This is only meaningful if freeze frame data is also supported.
+ *
+ * A return value of true for this method indicates that it is supported to call
+ * carDiagnosticManager.clearFreezeFrames(timestamp1, timestamp2, ...)
+ * to delete the freeze frames stored for the provided input timestamps, provided any exist.
+ *
+ * @return
+ * @throws CarNotConnectedException
+ */
+ public boolean isSelectiveClearFreezeFramesSupported() throws CarNotConnectedException {
+ try {
+ return mService.isSelectiveClearFreezeFramesSupported();
+ } catch (IllegalStateException e) {
+ CarApiUtil.checkCarNotConnectedExceptionFromCarService(e);
+ } catch (RemoteException e) {
+ throw new CarNotConnectedException();
+ }
+ return false;
+ }
+
private static class CarDiagnosticEventListenerToService
extends Stub {
private final WeakReference<CarDiagnosticManager> mManager;
diff --git a/car-lib/src/android/car/diagnostic/ICarDiagnostic.aidl b/car-lib/src/android/car/diagnostic/ICarDiagnostic.aidl
index 3d1808f..57443d8 100644
--- a/car-lib/src/android/car/diagnostic/ICarDiagnostic.aidl
+++ b/car-lib/src/android/car/diagnostic/ICarDiagnostic.aidl
@@ -74,4 +74,10 @@
* Returns whether the underlying HAL supports clearing freeze frames.
*/
boolean isClearFreezeFramesSupported() = 10;
+
+ /**
+ * Returns whether the underlying HAL supports clearing specific freeze frames specified
+ * by means of their timestamps.
+ */
+ boolean isSelectiveClearFreezeFramesSupported() = 11;
}
diff --git a/car-lib/src/android/car/hardware/radio/CarRadioEvent.aidl b/car-lib/src/android/car/drivingstate/CarDrivingStateEvent.aidl
similarity index 81%
copy from car-lib/src/android/car/hardware/radio/CarRadioEvent.aidl
copy to car-lib/src/android/car/drivingstate/CarDrivingStateEvent.aidl
index 0865646..ac800ae 100644
--- a/car-lib/src/android/car/hardware/radio/CarRadioEvent.aidl
+++ b/car-lib/src/android/car/drivingstate/CarDrivingStateEvent.aidl
@@ -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.
@@ -14,6 +14,6 @@
* limitations under the License.
*/
-package android.car.hardware.radio;
+package android.car.drivingstate;
-parcelable CarRadioEvent;
+parcelable CarDrivingStateEvent;
diff --git a/car-lib/src/android/car/drivingstate/CarDrivingStateEvent.java b/car-lib/src/android/car/drivingstate/CarDrivingStateEvent.java
new file mode 100644
index 0000000..e3fa2ea
--- /dev/null
+++ b/car-lib/src/android/car/drivingstate/CarDrivingStateEvent.java
@@ -0,0 +1,113 @@
+/*
+ * 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.drivingstate;
+
+import android.annotation.IntDef;
+import android.annotation.SystemApi;
+import android.os.Parcel;
+import android.os.Parcelable;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+
+/**
+ * Driving State related events. Driving State of a car conveys if the car is currently parked,
+ * idling or moving.
+ *
+ * @hide
+ */
+@SystemApi
+public class CarDrivingStateEvent implements Parcelable {
+
+ // New Driving States
+ /**
+ * This is when we don't have enough information to infer the car's driving state.
+ */
+ public static final int DRIVING_STATE_UNKNOWN = -1;
+ /**
+ * Car is parked - Gear is in Parked mode.
+ */
+ public static final int DRIVING_STATE_PARKED = 0;
+ /**
+ * Car is idling. Gear is not in Parked mode and Speed of the vehicle is zero.
+ * TODO: (b/72157869) - Should speed that differentiates moving vs idling be configurable?
+ */
+ public static final int DRIVING_STATE_IDLING = 1;
+ /**
+ * Car is moving. Gear is not in parked mode and speed of the vehicle is non zero.
+ */
+ public static final int DRIVING_STATE_MOVING = 2;
+
+ /** @hide */
+ @IntDef({DRIVING_STATE_UNKNOWN,
+ DRIVING_STATE_PARKED,
+ DRIVING_STATE_IDLING,
+ DRIVING_STATE_MOVING})
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface CarDrivingState {
+ }
+
+ /**
+ * Time at which this driving state was inferred based on the car's sensors.
+ * It is the elapsed time in nanoseconds since system boot.
+ */
+ public final long timeStamp;
+
+ /**
+ * The Car's driving state.
+ */
+ @CarDrivingState
+ public final int eventValue;
+
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ @Override
+ public void writeToParcel(Parcel dest, int flags) {
+ dest.writeInt(eventValue);
+ dest.writeLong(timeStamp);
+ }
+
+ public static final Parcelable.Creator<CarDrivingStateEvent> CREATOR
+ = new Parcelable.Creator<CarDrivingStateEvent>() {
+ public CarDrivingStateEvent createFromParcel(Parcel in) {
+ return new CarDrivingStateEvent(in);
+ }
+
+ public CarDrivingStateEvent[] newArray(int size) {
+ return new CarDrivingStateEvent[size];
+ }
+ };
+
+ public CarDrivingStateEvent(int value, long time) {
+ eventValue = value;
+ timeStamp = time;
+ }
+
+ private CarDrivingStateEvent(Parcel in) {
+ eventValue = in.readInt();
+ timeStamp = in.readLong();
+ }
+
+ @Override
+ public String toString() {
+ return eventValue + " " + timeStamp;
+ }
+}
diff --git a/car-lib/src/android/car/drivingstate/CarDrivingStateManager.java b/car-lib/src/android/car/drivingstate/CarDrivingStateManager.java
new file mode 100644
index 0000000..8c2a24f
--- /dev/null
+++ b/car-lib/src/android/car/drivingstate/CarDrivingStateManager.java
@@ -0,0 +1,228 @@
+/*
+ * 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.drivingstate;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.annotation.SystemApi;
+import android.car.Car;
+import android.car.CarManagerBase;
+import android.car.CarNotConnectedException;
+import android.car.drivingstate.ICarDrivingState;
+import android.content.Context;
+import android.os.Handler;
+import android.os.IBinder;
+import android.os.Looper;
+import android.os.Message;
+import android.os.RemoteException;
+import android.util.Log;
+import java.lang.ref.WeakReference;
+
+/**
+ * API to register and get driving state related information in a car.
+ * @hide
+ */
+@SystemApi
+public final class CarDrivingStateManager implements CarManagerBase {
+ private static final String TAG = "CarDrivingStateMgr";
+ private static final boolean DBG = false;
+ private static final boolean VDBG = false;
+ private static final int MSG_HANDLE_DRIVING_STATE_CHANGE = 0;
+
+ private final Context mContext;
+ private final ICarDrivingState mDrivingService;
+ private final EventCallbackHandler mEventCallbackHandler;
+ private CarDrivingStateEventListener mDrvStateEventListener;
+ private CarDrivingStateChangeListenerToService mListenerToService;
+
+
+ /** @hide */
+ public CarDrivingStateManager(IBinder service, Context context, Handler handler) {
+ mContext = context;
+ mDrivingService = ICarDrivingState.Stub.asInterface(service);
+ mEventCallbackHandler = new EventCallbackHandler(this, handler.getLooper());
+ }
+
+ /** @hide */
+ @Override
+ public synchronized void onCarDisconnected() {
+ mListenerToService = null;
+ mDrvStateEventListener = null;
+ }
+
+ /**
+ * Listener Interface for clients to implement to get updated on driving state changes.
+ */
+ public interface CarDrivingStateEventListener {
+ /**
+ * Called when the car's driving state changes.
+ * @param event Car's driving state.
+ */
+ void onDrivingStateChanged(CarDrivingStateEvent event);
+ }
+
+ /**
+ * Register a {@link CarDrivingStateEventListener} to listen for driving state changes.
+ *
+ * @param listener {@link CarDrivingStateEventListener}
+ */
+ public synchronized void registerListener(@NonNull CarDrivingStateEventListener listener)
+ throws CarNotConnectedException, IllegalArgumentException {
+ if (listener == null) {
+ if (VDBG) {
+ Log.v(TAG, "registerCarDrivingStateEventListener(): null listener");
+ }
+ throw new IllegalArgumentException("Listener is null");
+ }
+ // Check if the listener has been already registered for this event type
+ if (mDrvStateEventListener != null) {
+ if (DBG) {
+ Log.d(TAG, "Listener already registered");
+ }
+ return;
+ }
+ mDrvStateEventListener = listener;
+ try {
+ if (mListenerToService == null) {
+ mListenerToService = new CarDrivingStateChangeListenerToService(this);
+ }
+ // register to the Service for getting notified
+ mDrivingService.registerDrivingStateChangeListener(mListenerToService);
+ } catch (RemoteException e) {
+ Log.e(TAG, "Could not register a listener to Driving State Service " + e);
+ throw new CarNotConnectedException(e);
+ } catch (IllegalStateException e) {
+ Log.e(TAG, "Could not register a listener to Driving State Service " + e);
+ Car.checkCarNotConnectedExceptionFromCarService(e);
+ }
+ }
+
+ /**
+ * Unregister the registered {@link CarDrivingStateEventListener} for the given driving event
+ * type.
+ */
+ public synchronized void unregisterListener()
+ throws CarNotConnectedException {
+ if (mDrvStateEventListener == null) {
+ if (DBG) {
+ Log.d(TAG, "Listener was not previously registered");
+ }
+ return;
+ }
+ try {
+ mDrivingService.unregisterDrivingStateChangeListener(mListenerToService);
+ mDrvStateEventListener = null;
+ mListenerToService = null;
+ } catch (RemoteException e) {
+ Log.e(TAG, "Could not unregister listener from Driving State Service " + e);
+ throw new CarNotConnectedException(e);
+ }
+ }
+
+ /**
+ * Get the current value of the car's driving state.
+ *
+ * @return {@link CarDrivingStateEvent} corresponding to the given eventType
+ */
+ @Nullable
+ public CarDrivingStateEvent getCurrentCarDrivingState()
+ throws CarNotConnectedException {
+ try {
+ return mDrivingService.getCurrentDrivingState();
+ } catch (RemoteException e) {
+ Log.e(TAG, "Could not get current driving state " + e);
+ throw new CarNotConnectedException(e);
+ }
+ }
+
+ /**
+ * Class that implements the listener interface and gets called back from the
+ * {@link com.android.car.CarDrivingStateService} across the binder interface.
+ */
+ private static class CarDrivingStateChangeListenerToService extends
+ ICarDrivingStateChangeListener.Stub {
+ private final WeakReference<CarDrivingStateManager> mDrvStateMgr;
+
+ public CarDrivingStateChangeListenerToService(CarDrivingStateManager manager) {
+ mDrvStateMgr = new WeakReference<>(manager);
+ }
+
+ @Override
+ public void onDrivingStateChanged(CarDrivingStateEvent event) {
+ CarDrivingStateManager manager = mDrvStateMgr.get();
+ if (manager != null) {
+ manager.handleDrivingStateChanged(event);
+ }
+ }
+ }
+
+ /**
+ * Gets the {@link CarDrivingStateEvent} from the service listener
+ * {@link CarDrivingStateChangeListenerToService} and dispatches it to a handler provided
+ * to the manager
+ *
+ * @param event {@link CarDrivingStateEvent} that has been registered to listen on
+ */
+ private void handleDrivingStateChanged(CarDrivingStateEvent event) {
+ // send a message to the handler
+ mEventCallbackHandler.sendMessage(
+ mEventCallbackHandler.obtainMessage(MSG_HANDLE_DRIVING_STATE_CHANGE, event));
+
+ }
+
+ /**
+ * Callback Handler to handle dispatching the driving state changes to the corresponding
+ * listeners
+ */
+ private static final class EventCallbackHandler extends Handler {
+ private final WeakReference<CarDrivingStateManager> mDrvStateMgr;
+
+ public EventCallbackHandler(CarDrivingStateManager manager, Looper looper) {
+ super(looper);
+ mDrvStateMgr = new WeakReference<>(manager);
+ }
+
+ @Override
+ public void handleMessage(Message msg) {
+ CarDrivingStateManager mgr = mDrvStateMgr.get();
+ if (mgr != null) {
+ mgr.dispatchDrivingStateChangeToClient((CarDrivingStateEvent) msg.obj);
+ }
+ }
+
+ }
+
+ /**
+ * Checks for the listener to {@link CarDrivingStateEvent} and calls it back
+ * in the callback handler thread
+ *
+ * @param event {@link CarDrivingStateEvent}
+ */
+ private void dispatchDrivingStateChangeToClient(CarDrivingStateEvent event) {
+ if (event == null) {
+ return;
+ }
+ CarDrivingStateEventListener listener;
+ synchronized (this) {
+ listener = mDrvStateEventListener;
+ }
+ if (listener != null) {
+ listener.onDrivingStateChanged(event);
+ }
+ }
+
+}
diff --git a/car-lib/src/android/car/hardware/radio/CarRadioEvent.aidl b/car-lib/src/android/car/drivingstate/CarUxRestrictions.aidl
similarity index 82%
copy from car-lib/src/android/car/hardware/radio/CarRadioEvent.aidl
copy to car-lib/src/android/car/drivingstate/CarUxRestrictions.aidl
index 0865646..b80b94c 100644
--- a/car-lib/src/android/car/hardware/radio/CarRadioEvent.aidl
+++ b/car-lib/src/android/car/drivingstate/CarUxRestrictions.aidl
@@ -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.
@@ -14,6 +14,6 @@
* limitations under the License.
*/
-package android.car.hardware.radio;
+package android.car.drivingstate;
-parcelable CarRadioEvent;
+parcelable CarUxRestrictions;
diff --git a/car-lib/src/android/car/drivingstate/CarUxRestrictions.java b/car-lib/src/android/car/drivingstate/CarUxRestrictions.java
new file mode 100644
index 0000000..c6c22bc
--- /dev/null
+++ b/car-lib/src/android/car/drivingstate/CarUxRestrictions.java
@@ -0,0 +1,389 @@
+/*
+ * 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.drivingstate;
+
+import android.annotation.IntDef;
+import android.os.Parcel;
+import android.os.Parcelable;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+
+/**
+ * Car UX Restrictions event. This contains information on the set of UX restrictions
+ * that is in place due to the car's driving state.
+ * <p>
+ * The restriction information is organized as follows:
+ * <ul>
+ * <li> When there are no restrictions in place, for example when the car is parked,
+ * <ul>
+ * <li> {@link #mRequiresDistractionOptimization} is set to false. Apps can display activities
+ * that are not distraction optimized.
+ * <li> {@link #mActiveRestrictions} should contain UX_RESTRICTIONS_UNRESTRICTED. Apps don't
+ * have to check for this since {@code mRequiresDistractionOptimization} is false.
+ * </ul>
+ * <li> When the driving state changes, causing the UX restrictions to come in effect,
+ * <ul>
+ * <li> {@code mRequiresDistractionOptimization} is set to true. Apps can only display
+ * activities that are distraction optimized. Distraction optimized activities follow the base
+ * design guidelines that provide a distraction free driving user experience.
+ * <li> In addition, apps will have to check for the content of mActiveRestrictions.
+ * {@code mActiveRestrictions} will have additional granular information on the set of UX
+ * restrictions that are in place for the current driving state. The content of
+ * {@code mActiveRestrictions}, for the same driving state of the vehicle, could vary depending
+ * on the car maker and the market. For example, when the car is idling, the set of active
+ * UX restrictions contained in the {@code mActiveRestrictions} will depend on the car maker
+ * and the safety standards of the market that the vehicle is deployed in.
+ * </ul>
+ * </ul>
+ * <p>
+ * Apps that intend to be run when the car is being driven need to
+ * <ul>
+ * <li> Comply with the general distraction optimization guidelines.
+ * <li> Listen and react to the UX restrictions changes as detailed above. Since the restrictions
+ * could vary depending on the market, apps are expected to react to the restriction information
+ * and not to the absolute driving state.
+ * </ul>
+ */
+public class CarUxRestrictions implements Parcelable {
+
+ // Default fallback values for the restriction related parameters if the information is
+ // not available from the underlying service.
+ private static final int DEFAULT_MAX_LENGTH = 120;
+ private static final int DEFAULT_MAX_CUMULATIVE_ITEMS = 21;
+ private static final int DEFAULT_MAX_CONTENT_DEPTH = 3;
+
+ /**
+ * No specific restrictions in place, but baseline distraction optimization guidelines need to
+ * be adhered to when {@link #isRequiresDistractionOptimization()} is true.
+ */
+ public static final int UX_RESTRICTIONS_BASELINE = 0;
+
+ // Granular UX Restrictions that are imposed when distraction optimization is required.
+ /**
+ * No dialpad for the purpose of initiating a phone call.
+ */
+ public static final int UX_RESTRICTIONS_NO_DIALPAD = 1;
+
+ /**
+ * No filtering a list.
+ */
+ public static final int UX_RESTRICTIONS_NO_FILTERING = 0x1 << 1;
+
+ /**
+ * General purpose strings length cannot exceed the character limit provided by
+ * {@link #getMaxRestrictedStringLength()}
+ */
+ public static final int UX_RESTRICTIONS_LIMIT_STRING_LENGTH = 0x1 << 2;
+
+ /**
+ * No text entry for the purpose of searching etc.
+ */
+ public static final int UX_RESTRICTIONS_NO_KEYBOARD = 0x1 << 3;
+
+ /**
+ * No video - no animated frames > 1fps.
+ */
+ public static final int UX_RESTRICTIONS_NO_VIDEO = 0x1 << 4;
+
+ /**
+ * Limit the number of items displayed on the screen.
+ * Refer to {@link #getMaxCumulativeContentItems()} and
+ * {@link #getMaxContentDepth()} for the upper bounds on content
+ * serving.
+ */
+ public static final int UX_RESTRICTIONS_LIMIT_CONTENT = 0x1 << 5;
+
+ /**
+ * No setup that requires form entry or interaction with external devices.
+ */
+ public static final int UX_RESTRICTIONS_NO_SETUP = 0x1 << 6;
+
+ /**
+ * No Text Message (SMS, email, conversational, etc.)
+ */
+ public static final int UX_RESTRICTIONS_NO_TEXT_MESSAGE = 0x1 << 7;
+
+ /**
+ * No text transcription (live or leave behind) of voice can be shown.
+ */
+ public static final int UX_RESTRICTIONS_NO_VOICE_TRANSCRIPTION = 0x1 << 8;
+
+
+ /**
+ * All the above restrictions are in effect.
+ */
+ public static final int UX_RESTRICTIONS_FULLY_RESTRICTED =
+ UX_RESTRICTIONS_NO_DIALPAD | UX_RESTRICTIONS_NO_FILTERING
+ | UX_RESTRICTIONS_LIMIT_STRING_LENGTH | UX_RESTRICTIONS_NO_KEYBOARD
+ | UX_RESTRICTIONS_NO_VIDEO | UX_RESTRICTIONS_LIMIT_CONTENT
+ | UX_RESTRICTIONS_NO_SETUP | UX_RESTRICTIONS_NO_TEXT_MESSAGE
+ | UX_RESTRICTIONS_NO_VOICE_TRANSCRIPTION;
+
+ @IntDef(flag = true,
+ prefix = {"UX_RESTRICTIONS_"},
+ value = {UX_RESTRICTIONS_BASELINE,
+ UX_RESTRICTIONS_NO_DIALPAD,
+ UX_RESTRICTIONS_NO_FILTERING,
+ UX_RESTRICTIONS_LIMIT_STRING_LENGTH,
+ UX_RESTRICTIONS_NO_KEYBOARD,
+ UX_RESTRICTIONS_NO_VIDEO,
+ UX_RESTRICTIONS_LIMIT_CONTENT,
+ UX_RESTRICTIONS_NO_SETUP,
+ UX_RESTRICTIONS_NO_TEXT_MESSAGE,
+ UX_RESTRICTIONS_NO_VOICE_TRANSCRIPTION})
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface CarUxRestrictionsInfo {
+ }
+
+ private final long mTimeStamp;
+ private final boolean mRequiresDistractionOptimization;
+ @CarUxRestrictionsInfo
+ private final int mActiveRestrictions;
+ // Restriction Parameters
+ private final int mMaxStringLength;
+ private final int mMaxCumulativeContentItems;
+ private final int mMaxContentDepth;
+
+ /**
+ * Builder class for {@link CarUxRestrictions}
+ */
+ public static class Builder {
+ private final long mTimeStamp;
+ private final boolean mRequiresDistractionOptimization;
+ @CarUxRestrictionsInfo
+ private final int mActiveRestrictions;
+ // Restriction Parameters
+ private int mMaxStringLength = DEFAULT_MAX_LENGTH;
+ private int mMaxCumulativeContentItems = DEFAULT_MAX_CUMULATIVE_ITEMS;
+ private int mMaxContentDepth = DEFAULT_MAX_CONTENT_DEPTH;
+
+ public Builder(boolean reqOpt, @CarUxRestrictionsInfo int restrictions, long time) {
+ mRequiresDistractionOptimization = reqOpt;
+ mActiveRestrictions = restrictions;
+ mTimeStamp = time;
+ }
+
+ /**
+ * Set the maximum length of general purpose strings that can be displayed when
+ * {@link CarUxRestrictions#UX_RESTRICTIONS_LIMIT_STRING_LENGTH} is imposed.
+ */
+ public Builder setMaxStringLength(int length) {
+ mMaxStringLength = length;
+ return this;
+ }
+
+ /**
+ * Set the maximum number of cumulative content items that can be displayed when
+ * {@link CarUxRestrictions#UX_RESTRICTIONS_LIMIT_CONTENT} is imposed.
+ */
+ public Builder setMaxCumulativeContentItems(int number) {
+ mMaxCumulativeContentItems = number;
+ return this;
+ }
+
+ /**
+ * Set the maximum number of levels that the user can navigate to when
+ * {@link CarUxRestrictions#UX_RESTRICTIONS_LIMIT_CONTENT} is imposed.
+ */
+ public Builder setMaxContentDepth(int depth) {
+ mMaxContentDepth = depth;
+ return this;
+ }
+
+ /**
+ * Build and return the {@link CarUxRestrictions} object
+ */
+ public CarUxRestrictions build() {
+ return new CarUxRestrictions(this);
+ }
+
+ }
+
+ /**
+ * Time at which this UX restriction event was deduced based on the car's driving state.
+ *
+ * @return Elapsed time in nanoseconds since system boot.
+ */
+ public long getTimeStamp() {
+ return mTimeStamp;
+ }
+
+ /**
+ * Conveys if the foreground activity needs to be distraction optimized.
+ * Activities that can handle distraction optimization need to be tagged as a distraction
+ * optimized in the app's manifest.
+ * <p>
+ * If the app has a foreground activity that has not been distraction optimized, the app has
+ * to switch to another activity that is distraction optimized. Failing that, the system will
+ * stop the foreground activity.
+ *
+ * @return true if distraction optimization is required, false if not
+ */
+ public boolean isRequiresDistractionOptimization() {
+ return mRequiresDistractionOptimization;
+ }
+
+ /**
+ * A combination of the Car UX Restrictions that is active for the current state of driving.
+ *
+ * @return A combination of the above {@code @CarUxRestrictionsInfo}
+ */
+ @CarUxRestrictionsInfo
+ public int getActiveRestrictions() {
+ return mActiveRestrictions;
+ }
+
+ /**
+ * Get the maximum length of general purpose strings that can be displayed when
+ * {@link CarUxRestrictions#UX_RESTRICTIONS_LIMIT_STRING_LENGTH} is imposed.
+ *
+ * @return the maximum length of string that can be displayed
+ */
+ public int getMaxRestrictedStringLength() {
+ return mMaxStringLength;
+ }
+
+ /**
+ * Get the maximum allowable number of content items that can be displayed to a user during
+ * traversal through any one path in a single task, when
+ * {@link CarUxRestrictions#UX_RESTRICTIONS_LIMIT_CONTENT} is imposed.
+ * <p>
+ * For example, if a task involving only one view, this represents the maximum allowable number
+ * of content items in this single view.
+ * <p>
+ * However, if the task involves selection of a content item in an originating view that then
+ * surfaces a secondary view to the user, then this value represents the maximum allowable
+ * number of content items between the originating and secondary views combined.
+ * <p>
+ * Specifically, if the maximum allowable value was 60 and a task involved browsing a list of
+ * countries and then viewing the top songs within a country, it would be acceptable to do
+ * either of the following:
+ * <ul>
+ * <li> list 10 countries, and then display the top 50 songs after country selection, or
+ * <li> list 20 countries, and then display the top 40 songs after country selection.
+ * </ul>
+ * <p>
+ * Please refer to this and {@link #getMaxContentDepth()} to know the upper bounds on the
+ * content display when the restriction is in place.
+ *
+ * @return maximum number of cumulative items that can be displayed
+ */
+ public int getMaxCumulativeContentItems() {
+ return mMaxCumulativeContentItems;
+ }
+
+ /**
+ * Get the maximum allowable number of content depth levels or view traversals through any one
+ * path in a single task. This is applicable when
+ * {@link CarUxRestrictions#UX_RESTRICTIONS_LIMIT_CONTENT} is imposed.
+ * <p>
+ * For example, if a task involves only selecting an item from a single list on one view,
+ * the task's content depth would be considered 1.
+ * <p>
+ * However, if the task involves selection of a content item in an originating view that then
+ * surfaces a secondary view to the user, the task's content depth would be considered 2.
+ * <p>
+ * Specifically, if a task involved browsing a list of countries, selecting a genre within the
+ * country, and then viewing the top songs within a country, the task's content depth would be
+ * considered 3.
+ * <p>
+ * Please refer to this and {@link #getMaxCumulativeContentItems()} to know the upper bounds on
+ * the content display when the restriction is in place.
+ *
+ * @return maximum number of cumulative items that can be displayed
+ */
+ public int getMaxContentDepth() {
+ return mMaxContentDepth;
+ }
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ @Override
+ public void writeToParcel(Parcel dest, int flags) {
+ dest.writeInt(mActiveRestrictions);
+ dest.writeLong(mTimeStamp);
+ dest.writeInt(mRequiresDistractionOptimization ? 1 : 0);
+ dest.writeInt(mMaxStringLength);
+ dest.writeInt(mMaxCumulativeContentItems);
+ dest.writeInt(mMaxContentDepth);
+ }
+
+ public static final Parcelable.Creator<CarUxRestrictions> CREATOR
+ = new Parcelable.Creator<CarUxRestrictions>() {
+ public CarUxRestrictions createFromParcel(Parcel in) {
+ return new CarUxRestrictions(in);
+ }
+
+ public CarUxRestrictions[] newArray(int size) {
+ return new CarUxRestrictions[size];
+ }
+ };
+
+ public CarUxRestrictions(CarUxRestrictions uxRestrictions) {
+ mTimeStamp = uxRestrictions.getTimeStamp();
+ mRequiresDistractionOptimization = uxRestrictions.isRequiresDistractionOptimization();
+ mActiveRestrictions = uxRestrictions.getActiveRestrictions();
+ mMaxStringLength = uxRestrictions.mMaxStringLength;
+ mMaxCumulativeContentItems = uxRestrictions.mMaxCumulativeContentItems;
+ mMaxContentDepth = uxRestrictions.mMaxContentDepth;
+ }
+
+ private CarUxRestrictions(Builder builder) {
+ mTimeStamp = builder.mTimeStamp;
+ mActiveRestrictions = builder.mActiveRestrictions;
+ mRequiresDistractionOptimization = builder.mRequiresDistractionOptimization;
+ mMaxStringLength = builder.mMaxStringLength;
+ mMaxCumulativeContentItems = builder.mMaxCumulativeContentItems;
+ mMaxContentDepth = builder.mMaxContentDepth;
+ }
+
+ private CarUxRestrictions(Parcel in) {
+ mActiveRestrictions = in.readInt();
+ mTimeStamp = in.readLong();
+ mRequiresDistractionOptimization = in.readInt() != 0;
+ mMaxStringLength = in.readInt();
+ mMaxCumulativeContentItems = in.readInt();
+ mMaxContentDepth = in.readInt();
+ }
+
+ @Override
+ public String toString() {
+ return "DO: " + mRequiresDistractionOptimization + " UxR: " + mActiveRestrictions
+ + " time: " + mTimeStamp;
+ }
+
+ /**
+ * Compares if the restrictions are the same. Doesn't compare the timestamps.
+ *
+ * @param other the other CarUxRestrictions object
+ * @return true if the restrictions are same, false otherwise
+ */
+ public boolean isSameRestrictions(CarUxRestrictions other) {
+ if (other == null) {
+ return false;
+ }
+ if (other == this) {
+ return true;
+ }
+ return other.mRequiresDistractionOptimization == mRequiresDistractionOptimization
+ && other.mActiveRestrictions == mActiveRestrictions;
+ }
+}
diff --git a/car-lib/src/android/car/drivingstate/CarUxRestrictionsManager.java b/car-lib/src/android/car/drivingstate/CarUxRestrictionsManager.java
new file mode 100644
index 0000000..57e7d60
--- /dev/null
+++ b/car-lib/src/android/car/drivingstate/CarUxRestrictionsManager.java
@@ -0,0 +1,229 @@
+/*
+ * 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.drivingstate;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.car.Car;
+import android.car.CarManagerBase;
+import android.car.CarNotConnectedException;
+import android.car.drivingstate.ICarUxRestrictionsManager;
+import android.content.Context;
+import android.os.Handler;
+import android.os.IBinder;
+import android.os.Looper;
+import android.os.Message;
+import android.os.RemoteException;
+import android.util.Log;
+
+import java.lang.ref.WeakReference;
+
+/**
+ * API to register and get the User Experience restrictions imposed based on the car's driving
+ * state.
+ */
+public final class CarUxRestrictionsManager implements CarManagerBase {
+ private static final String TAG = "CarUxRManager";
+ private static final boolean DBG = false;
+ private static final boolean VDBG = false;
+ private static final int MSG_HANDLE_UX_RESTRICTIONS_CHANGE = 0;
+
+ private final Context mContext;
+ private final ICarUxRestrictionsManager mUxRService;
+ private final EventCallbackHandler mEventCallbackHandler;
+ private OnUxRestrictionsChangedListener mUxRListener;
+ private CarUxRestrictionsChangeListenerToService mListenerToService;
+
+
+ /** @hide */
+ public CarUxRestrictionsManager(IBinder service, Context context, Handler handler) {
+ mContext = context;
+ mUxRService = ICarUxRestrictionsManager.Stub.asInterface(service);
+ mEventCallbackHandler = new EventCallbackHandler(this, handler.getLooper());
+ }
+
+ /** @hide */
+ @Override
+ public synchronized void onCarDisconnected() {
+ mListenerToService = null;
+ mUxRListener = null;
+ }
+
+ /**
+ * Listener Interface for clients to implement to get updated on driving state related
+ * changes.
+ */
+ public interface OnUxRestrictionsChangedListener {
+ /**
+ * Called when the UX restrictions due to a car's driving state changes.
+ *
+ * @param restrictionInfo The new UX restriction information
+ */
+ void onUxRestrictionsChanged(CarUxRestrictions restrictionInfo);
+ }
+
+ /**
+ * Register a {@link OnUxRestrictionsChangedListener} for listening to changes in the
+ * UX Restrictions to adhere to.
+ * <p>
+ * If a listener has already been registered, it has to be unregistered before registering
+ * the new one.
+ *
+ * @param listener {@link OnUxRestrictionsChangedListener}
+ */
+ public synchronized void registerListener(@NonNull OnUxRestrictionsChangedListener listener)
+ throws CarNotConnectedException, IllegalArgumentException {
+ if (listener == null) {
+ if (VDBG) {
+ Log.v(TAG, "registerListener(): null listener");
+ }
+ throw new IllegalArgumentException("Listener is null");
+ }
+ // Check if the listener has been already registered.
+ if (mUxRListener != null) {
+ if (DBG) {
+ Log.d(TAG, "Listener already registered listener");
+ }
+ return;
+ }
+ mUxRListener = listener;
+ try {
+ if (mListenerToService == null) {
+ mListenerToService = new CarUxRestrictionsChangeListenerToService(this);
+ }
+ // register to the Service to listen for changes.
+ mUxRService.registerUxRestrictionsChangeListener(mListenerToService);
+ } catch (RemoteException e) {
+ Log.e(TAG, "Could not register a listener to CarUxRestrictionsManagerService " + e);
+ throw new CarNotConnectedException(e);
+ } catch (IllegalStateException e) {
+ Log.e(TAG, "Could not register a listener to CarUxRestrictionsManagerService " + e);
+ Car.checkCarNotConnectedExceptionFromCarService(e);
+ }
+ }
+
+ /**
+ * Unregister the registered {@link OnUxRestrictionsChangedListener}
+ */
+ public synchronized void unregisterListener()
+ throws CarNotConnectedException {
+ if (mUxRListener == null) {
+ if (DBG) {
+ Log.d(TAG, "Listener was not previously registered");
+ }
+ return;
+ }
+ try {
+ mUxRService.unregisterUxRestrictionsChangeListener(mListenerToService);
+ mUxRListener = null;
+ } catch (RemoteException e) {
+ Log.e(TAG, "Could not unregister listener from Driving State Service " + e);
+ throw new CarNotConnectedException(e);
+ }
+ }
+
+ /**
+ * Get the current UX restrictions {@link CarUxRestrictions} in place.
+ *
+ * @return current UX restrictions that is in effect.
+ */
+ @Nullable
+ public CarUxRestrictions getCurrentCarUxRestrictions()
+ throws CarNotConnectedException {
+ try {
+ return mUxRService.getCurrentUxRestrictions();
+ } catch (RemoteException e) {
+ Log.e(TAG, "Could not get current UX restrictions " + e);
+ throw new CarNotConnectedException(e);
+ }
+ }
+
+ /**
+ * Class that implements the listener interface and gets called back from the
+ * {@link com.android.car.CarDrivingStateService} across the binder interface.
+ */
+ private static class CarUxRestrictionsChangeListenerToService extends
+ ICarUxRestrictionsChangeListener.Stub {
+ private final WeakReference<CarUxRestrictionsManager> mUxRestrictionsManager;
+
+ public CarUxRestrictionsChangeListenerToService(CarUxRestrictionsManager manager) {
+ mUxRestrictionsManager = new WeakReference<>(manager);
+ }
+
+ @Override
+ public void onUxRestrictionsChanged(CarUxRestrictions restrictionInfo) {
+ CarUxRestrictionsManager manager = mUxRestrictionsManager.get();
+ if (manager != null) {
+ manager.handleUxRestrictionsChanged(restrictionInfo);
+ }
+ }
+ }
+
+ /**
+ * Gets the {@link CarUxRestrictions} from the service listener
+ * {@link CarUxRestrictionsChangeListenerToService} and dispatches it to a handler provided
+ * to the manager
+ *
+ * @param restrictionInfo {@link CarUxRestrictions} that has been registered to listen on
+ */
+ private void handleUxRestrictionsChanged(CarUxRestrictions restrictionInfo) {
+ // send a message to the handler
+ mEventCallbackHandler.sendMessage(mEventCallbackHandler.obtainMessage(
+ MSG_HANDLE_UX_RESTRICTIONS_CHANGE, restrictionInfo));
+ }
+
+ /**
+ * Callback Handler to handle dispatching the UX restriction changes to the corresponding
+ * listeners
+ */
+ private static final class EventCallbackHandler extends Handler {
+ private final WeakReference<CarUxRestrictionsManager> mUxRestrictionsManager;
+
+ public EventCallbackHandler(CarUxRestrictionsManager manager, Looper looper) {
+ super(looper);
+ mUxRestrictionsManager = new WeakReference<>(manager);
+ }
+
+ @Override
+ public void handleMessage(Message msg) {
+ CarUxRestrictionsManager mgr = mUxRestrictionsManager.get();
+ if (mgr != null) {
+ mgr.dispatchUxRChangeToClient((CarUxRestrictions) msg.obj);
+ }
+ }
+
+ }
+
+ /**
+ * Checks for the listeners to list of {@link CarUxRestrictions} and calls them back
+ * in the callback handler thread
+ *
+ * @param restrictionInfo {@link CarUxRestrictions}
+ */
+ private void dispatchUxRChangeToClient(CarUxRestrictions restrictionInfo) {
+ if (restrictionInfo == null) {
+ return;
+ }
+ OnUxRestrictionsChangedListener listener;
+ synchronized (this) {
+ listener = mUxRListener;
+ }
+ if (listener != null) {
+ listener.onUxRestrictionsChanged(restrictionInfo);
+ }
+ }
+}
diff --git a/car-lib/src/android/car/drivingstate/ICarDrivingState.aidl b/car-lib/src/android/car/drivingstate/ICarDrivingState.aidl
new file mode 100644
index 0000000..30f1542
--- /dev/null
+++ b/car-lib/src/android/car/drivingstate/ICarDrivingState.aidl
@@ -0,0 +1,34 @@
+/*
+ * 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.drivingstate;
+
+import android.car.drivingstate.CarDrivingStateEvent;
+import android.car.drivingstate.ICarDrivingStateChangeListener;
+
+/**
+ * Binder interface for {@link android.car.drivingstate.CarDrivingStateManager}.
+ * Check {@link android.car.drivingstate.CarDrivingStateManager} APIs for expected behavior of
+ * each call.
+ *
+ * @hide
+ */
+
+interface ICarDrivingState {
+ void registerDrivingStateChangeListener(in ICarDrivingStateChangeListener listener) = 0;
+ void unregisterDrivingStateChangeListener(in ICarDrivingStateChangeListener listener) = 1;
+ CarDrivingStateEvent getCurrentDrivingState() = 2;
+}
diff --git a/libvehiclemonitor/java/src/com/android/car/vehiclemonitor/IVehicleMonitorListener.aidl b/car-lib/src/android/car/drivingstate/ICarDrivingStateChangeListener.aidl
similarity index 65%
copy from libvehiclemonitor/java/src/com/android/car/vehiclemonitor/IVehicleMonitorListener.aidl
copy to car-lib/src/android/car/drivingstate/ICarDrivingStateChangeListener.aidl
index ca0ac83..357d7d6 100644
--- a/libvehiclemonitor/java/src/com/android/car/vehiclemonitor/IVehicleMonitorListener.aidl
+++ b/car-lib/src/android/car/drivingstate/ICarDrivingStateChangeListener.aidl
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2016 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,12 +14,14 @@
* limitations under the License.
*/
-package com.android.car.vehiclemonitor;
+package android.car.drivingstate;
+
+import android.car.drivingstate.CarDrivingStateEvent;
/**
- * Listener for vehicle monitor service.
+ * Binder callback for onDrivingStateChange.
* @hide
*/
-oneway interface IVehicleMonitorListener {
- void onAppViolation(int pid, int uid, int action, int violation) = 0;
+oneway interface ICarDrivingStateChangeListener {
+ void onDrivingStateChanged(in CarDrivingStateEvent event) = 0;
}
diff --git a/car-lib/src/android/car/media/ICarAudioCallback.aidl b/car-lib/src/android/car/drivingstate/ICarUxRestrictionsChangeListener.aidl
similarity index 64%
copy from car-lib/src/android/car/media/ICarAudioCallback.aidl
copy to car-lib/src/android/car/drivingstate/ICarUxRestrictionsChangeListener.aidl
index 7e01c71..cf3f89f 100644
--- a/car-lib/src/android/car/media/ICarAudioCallback.aidl
+++ b/car-lib/src/android/car/drivingstate/ICarUxRestrictionsChangeListener.aidl
@@ -1,5 +1,5 @@
/*
- * 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,13 @@
* limitations under the License.
*/
-package android.car.media;
+package android.car.drivingstate;
-/** @hide */
-oneway interface ICarAudioCallback {
- void onParameterChange(in String params) = 0;
+import android.car.drivingstate.CarUxRestrictions;
+
+/**
+ * Binder callback for onUxRestrictionsChanged.
+ */
+oneway interface ICarUxRestrictionsChangeListener {
+ void onUxRestrictionsChanged(in CarUxRestrictions event) = 0;
}
diff --git a/car-lib/src/android/car/drivingstate/ICarUxRestrictionsManager.aidl b/car-lib/src/android/car/drivingstate/ICarUxRestrictionsManager.aidl
new file mode 100644
index 0000000..e5c69b8
--- /dev/null
+++ b/car-lib/src/android/car/drivingstate/ICarUxRestrictionsManager.aidl
@@ -0,0 +1,33 @@
+/*
+ * 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.drivingstate;
+
+import android.car.drivingstate.CarUxRestrictions;
+import android.car.drivingstate.ICarUxRestrictionsChangeListener;
+
+/**
+ * Binder interface for {@link android.car.drivingstate.CarUxRestrictionsManager}.
+ * Check {@link android.car.drivingstate.CarUxRestrictionsManager} APIs for expected behavior of
+ * each call.
+ *
+ * @hide
+ */
+interface ICarUxRestrictionsManager {
+ void registerUxRestrictionsChangeListener(in ICarUxRestrictionsChangeListener listener) = 0;
+ void unregisterUxRestrictionsChangeListener(in ICarUxRestrictionsChangeListener listener) = 1;
+ CarUxRestrictions getCurrentUxRestrictions() = 2;
+}
diff --git a/car-lib/src/android/car/hardware/CarPropertyConfig.java b/car-lib/src/android/car/hardware/CarPropertyConfig.java
index 36a3858..be2b86c 100644
--- a/car-lib/src/android/car/hardware/CarPropertyConfig.java
+++ b/car-lib/src/android/car/hardware/CarPropertyConfig.java
@@ -24,6 +24,9 @@
import android.util.SparseArray;
import java.lang.reflect.Array;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
/**
* Represents general information about car property such as data type and min/max ranges for car
@@ -38,26 +41,64 @@
*/
@SystemApi
public class CarPropertyConfig<T> implements Parcelable {
- private final int mPropertyId;
- private final Class<T> mType;
+ private final int mAccess;
private final int mAreaType;
+ private final int mChangeMode;
+ private final ArrayList<Integer> mConfigArray;
+ private final String mConfigString;
+ private final float mMaxSampleRate;
+ private final float mMinSampleRate;
+ private final int mPropertyId;
private final SparseArray<AreaConfig<T>> mSupportedAreas;
+ private final Class<T> mType;
- private CarPropertyConfig(Class<T> type, int propertyId, int areaType,
- SparseArray<AreaConfig<T>> supportedAreas) {
- mPropertyId = propertyId;
- mType = type;
+ private CarPropertyConfig(int access, int areaType, int changeMode,
+ ArrayList<Integer> configArray, String configString,
+ float maxSampleRate, float minSampleRate, int propertyId,
+ SparseArray<AreaConfig<T>> supportedAreas, Class<T> type) {
+ mAccess = access;
mAreaType = areaType;
+ mChangeMode = changeMode;
+ mConfigArray = configArray;
+ mConfigString = configString;
+ mMaxSampleRate = maxSampleRate;
+ mMinSampleRate = minSampleRate;
+ mPropertyId = propertyId;
mSupportedAreas = supportedAreas;
+ mType = type;
}
- public int getPropertyId() { return mPropertyId; }
- public Class<T> getPropertyType() { return mType; }
- public @VehicleAreaType.VehicleAreaTypeValue int getAreaType() { return mAreaType; }
+ public int getAccess() {
+ return mAccess;
+ }
+ public @VehicleAreaType.VehicleAreaTypeValue int getAreaType() {
+ return mAreaType;
+ }
+ public int getChangeMode() {
+ return mChangeMode;
+ }
+ public List<Integer> getConfigArray() {
+ return Collections.unmodifiableList(mConfigArray);
+ }
+ public String getConfigString() {
+ return mConfigString;
+ }
+ public float getMaxSampleRate() {
+ return mMaxSampleRate;
+ }
+ public float getMinSampleRate() {
+ return mMinSampleRate;
+ }
+ public int getPropertyId() {
+ return mPropertyId;
+ }
+ public Class<T> getPropertyType() {
+ return mType;
+ }
/** Returns true if this property doesn't hold car area-specific configuration */
public boolean isGlobalProperty() {
- return mAreaType == VehicleAreaType.VEHICLE_AREA_TYPE_NONE;
+ return mAreaType == VehicleAreaType.VEHICLE_AREA_TYPE_GLOBAL;
}
public int getAreaCount() {
@@ -119,26 +160,39 @@
@Override
public void writeToParcel(Parcel dest, int flags) {
- dest.writeInt(mPropertyId);
- dest.writeString(mType.getName());
+ dest.writeInt(mAccess);
dest.writeInt(mAreaType);
+ dest.writeInt(mChangeMode);
+ dest.writeInt(mConfigArray.size());
+ for (int i = 0; i < mConfigArray.size(); i++) {
+ dest.writeInt(mConfigArray.get(i));
+ }
+ dest.writeString(mConfigString);
+ dest.writeFloat(mMaxSampleRate);
+ dest.writeFloat(mMinSampleRate);
+ dest.writeInt(mPropertyId);
dest.writeInt(mSupportedAreas.size());
for (int i = 0; i < mSupportedAreas.size(); i++) {
dest.writeInt(mSupportedAreas.keyAt(i));
dest.writeParcelable(mSupportedAreas.valueAt(i), flags);
}
+ dest.writeString(mType.getName());
}
@SuppressWarnings("unchecked")
private CarPropertyConfig(Parcel in) {
- mPropertyId = in.readInt();
- String className = in.readString();
- try {
- mType = (Class<T>) Class.forName(className);
- } catch (ClassNotFoundException e) {
- throw new IllegalArgumentException("Class not found: " + className);
- }
+ mAccess = in.readInt();
mAreaType = in.readInt();
+ mChangeMode = in.readInt();
+ int configArraySize = in.readInt();
+ mConfigArray = new ArrayList<Integer>(configArraySize);
+ for (int i = 0; i < configArraySize; i++) {
+ mConfigArray.add(in.readInt());
+ }
+ mConfigString = in.readString();
+ mMaxSampleRate = in.readFloat();
+ mMinSampleRate = in.readFloat();
+ mPropertyId = in.readInt();
int areaSize = in.readInt();
mSupportedAreas = new SparseArray<>(areaSize);
for (int i = 0; i < areaSize; i++) {
@@ -146,6 +200,12 @@
AreaConfig<T> area = in.readParcelable(getClass().getClassLoader());
mSupportedAreas.put(areaId, area);
}
+ String className = in.readString();
+ try {
+ mType = (Class<T>) Class.forName(className);
+ } catch (ClassNotFoundException e) {
+ throw new IllegalArgumentException("Class not found: " + className);
+ }
}
public static final Creator<CarPropertyConfig> CREATOR = new Creator<CarPropertyConfig>() {
@@ -162,12 +222,18 @@
@Override
public String toString() {
- return "CarPropertyConfig{" +
- "mPropertyId=" + mPropertyId +
- ", mType=" + mType +
- ", mAreaType=" + mAreaType +
- ", mSupportedAreas=" + mSupportedAreas +
- '}';
+ return "CarPropertyConfig{"
+ + "mPropertyId=" + mPropertyId
+ + ", mAccess=" + mAccess
+ + ", mAreaType=" + mAreaType
+ + ", mChangeMode=" + mChangeMode
+ + ", mConfigArray=" + mConfigArray
+ + ", mConfigString=" + mConfigString
+ + ", mMaxSampleRate=" + mMaxSampleRate
+ + ", mMinSampleRate=" + mMinSampleRate
+ + ", mSupportedAreas=" + mSupportedAreas
+ + ", mType=" + mType
+ + '}';
}
public static class AreaConfig<T> implements Parcelable {
@@ -225,55 +291,150 @@
}
}
- public static <T> Builder<T> newBuilder(Class<T> clazz, int propertyId, int areaType,
- int areaCapacity) {
- return new Builder<>(clazz, propertyId, areaType, areaCapacity);
+ /**
+ * Prepare an instance of CarPropertyConfig
+ *
+ * @return Builder<T>
+ */
+ public static <T> Builder<T> newBuilder(Class<T> type, int propertyId, int areaType,
+ int areaCapacity) {
+ return new Builder<>(areaCapacity, areaType, propertyId, type);
}
- public static <T> Builder<T> newBuilder(Class<T> clazz, int propertyId, int areaType) {
- return newBuilder(clazz, propertyId, areaType, 0);
+ /**
+ * Prepare an instance of CarPropertyConfig
+ *
+ * @return Builder<T>
+ */
+ public static <T> Builder<T> newBuilder(Class<T> type, int propertyId, int areaType) {
+ return new Builder<>(0, areaType, propertyId, type);
}
public static class Builder<T> {
- private final Class<T> mType;
- private final int mPropertyId;
+ private int mAccess;
private final int mAreaType;
- private final SparseArray<AreaConfig<T>> mAreas;
+ private int mChangeMode;
+ private final ArrayList<Integer> mConfigArray;
+ private String mConfigString;
+ private float mMaxSampleRate;
+ private float mMinSampleRate;
+ private final int mPropertyId;
+ private final SparseArray<AreaConfig<T>> mSupportedAreas;
+ private final Class<T> mType;
- private Builder(Class<T> type, int propertyId, int areaType, int areaCapacity) {
- mType = type;
- mPropertyId = propertyId;
+ private Builder(int areaCapacity, int areaType, int propertyId, Class<T> type) {
mAreaType = areaType;
+ mConfigArray = new ArrayList<>();
+ mPropertyId = propertyId;
if (areaCapacity != 0) {
- mAreas = new SparseArray<>(areaCapacity);
+ mSupportedAreas = new SparseArray<>(areaCapacity);
} else {
- mAreas = new SparseArray<>();
+ mSupportedAreas = new SparseArray<>();
}
+ mType = type;
}
+ /**
+ * Add supported areas parameter to CarPropertyConfig
+ *
+ * @return Builder<T>
+ */
public Builder<T> addAreas(int[] areaIds) {
for (int id : areaIds) {
- mAreas.put(id, null);
+ mSupportedAreas.put(id, null);
}
return this;
}
+ /**
+ * Add area to CarPropertyConfig
+ *
+ * @return Builder<T>
+ */
public Builder<T> addArea(int areaId) {
return addAreaConfig(areaId, null, null);
}
+ /**
+ * Add areaConfig to CarPropertyConfig
+ *
+ * @return Builder<T>
+ */
public Builder<T> addAreaConfig(int areaId, T min, T max) {
if (min == null && max == null) {
- mAreas.put(areaId, null);
+ mSupportedAreas.put(areaId, null);
} else {
- mAreas.put(areaId, new AreaConfig<>(min, max));
+ mSupportedAreas.put(areaId, new AreaConfig<>(min, max));
}
return this;
}
+ /**
+ * Set access parameter to CarPropertyConfig
+ *
+ * @return Builder<T>
+ */
+ public Builder<T> setAccess(int access) {
+ mAccess = access;
+ return this;
+ }
+
+ /**
+ * Set changeMode parameter to CarPropertyConfig
+ *
+ * @return Builder<T>
+ */
+ public Builder<T> setChangeMode(int changeMode) {
+ mChangeMode = changeMode;
+ return this;
+ }
+
+ /**
+ * Set configArray parameter to CarPropertyConfig
+ *
+ * @return Builder<T>
+ */
+ public Builder<T> setConfigArray(ArrayList<Integer> configArray) {
+ mConfigArray.clear();
+ mConfigArray.addAll(configArray);
+ return this;
+ }
+
+ /**
+ * Set configString parameter to CarPropertyConfig
+ *
+ * @return Builder<T>
+ */
+ public Builder<T> setConfigString(String configString) {
+ mConfigString = configString;
+ return this;
+ }
+
+ /**
+ * Set maxSampleRate parameter to CarPropertyConfig
+ *
+ * @return Builder<T>
+ */
+ public Builder<T> setMaxSampleRate(float maxSampleRate) {
+ mMaxSampleRate = maxSampleRate;
+ return this;
+ }
+
+ /**
+ * Set minSampleRate parameter to CarPropertyConfig
+ *
+ * @return Builder<T>
+ */
+ public Builder<T> setMinSampleRate(float minSampleRate) {
+ mMinSampleRate = minSampleRate;
+ return this;
+ }
+
public CarPropertyConfig<T> build() {
- return new CarPropertyConfig<>(mType, mPropertyId, mAreaType, mAreas);
+ return new CarPropertyConfig<>(mAccess, mAreaType, mChangeMode, mConfigArray,
+ mConfigString, mMaxSampleRate, mMinSampleRate,
+ mPropertyId, mSupportedAreas, mType);
}
}
}
diff --git a/car-lib/src/android/car/hardware/CarPropertyValue.java b/car-lib/src/android/car/hardware/CarPropertyValue.java
index cd26fba..b54ac4c 100644
--- a/car-lib/src/android/car/hardware/CarPropertyValue.java
+++ b/car-lib/src/android/car/hardware/CarPropertyValue.java
@@ -18,10 +18,13 @@
import static java.lang.Integer.toHexString;
+import android.annotation.IntDef;
import android.annotation.SystemApi;
import android.os.Parcel;
import android.os.Parcelable;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
import java.nio.charset.Charset;
/**
@@ -34,20 +37,41 @@
*/
@SystemApi
public class CarPropertyValue<T> implements Parcelable {
-
private final static Charset DEFAULT_CHARSET = Charset.forName("UTF-8");
private final int mPropertyId;
private final int mAreaId;
+ private final int mStatus;
+ private final long mTimestamp;
private final T mValue;
- public CarPropertyValue(int propertyId, T value) {
- this(propertyId, 0, value);
- }
+ /** @hide */
+ @IntDef({
+ STATUS_AVAILABLE,
+ STATUS_UNAVAILABLE,
+ STATUS_ERROR
+ })
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface PropertyStatus {}
+
+ /** @hide */
+ public static final int STATUS_AVAILABLE = 0;
+
+ /** @hide */
+ public static final int STATUS_UNAVAILABLE = 1;
+
+ /** @hide */
+ public static final int STATUS_ERROR = 2;
public CarPropertyValue(int propertyId, int areaId, T value) {
+ this(propertyId, areaId, 0, 0, value);
+ }
+
+ public CarPropertyValue(int propertyId, int areaId, int status, long timestamp, T value) {
mPropertyId = propertyId;
mAreaId = areaId;
+ mStatus = status;
+ mTimestamp = timestamp;
mValue = value;
}
@@ -55,6 +79,8 @@
public CarPropertyValue(Parcel in) {
mPropertyId = in.readInt();
mAreaId = in.readInt();
+ mStatus = in.readInt();
+ mTimestamp = in.readLong();
String valueClassName = in.readString();
Class<?> valueClass;
try {
@@ -94,6 +120,8 @@
public void writeToParcel(Parcel dest, int flags) {
dest.writeInt(mPropertyId);
dest.writeInt(mAreaId);
+ dest.writeInt(mStatus);
+ dest.writeLong(mTimestamp);
Class<?> valueClass = mValue == null ? null : mValue.getClass();
dest.writeString(valueClass == null ? null : valueClass.getName());
@@ -116,6 +144,14 @@
return mAreaId;
}
+ public @PropertyStatus int getStatus() {
+ return mStatus;
+ }
+
+ public long getTimestamp() {
+ return mTimestamp;
+ }
+
public T getValue() {
return mValue;
}
@@ -125,6 +161,8 @@
return "CarPropertyValue{" +
"mPropertyId=0x" + toHexString(mPropertyId) +
", mAreaId=0x" + toHexString(mAreaId) +
+ ", mStatus=" + mStatus +
+ ", mTimestamp=" + mTimestamp +
", mValue=" + mValue +
'}';
}
diff --git a/car-lib/src/android/car/hardware/CarSensorConfig.java b/car-lib/src/android/car/hardware/CarSensorConfig.java
index 8ba456b..77f8dc5 100644
--- a/car-lib/src/android/car/hardware/CarSensorConfig.java
+++ b/car-lib/src/android/car/hardware/CarSensorConfig.java
@@ -29,7 +29,7 @@
/** List of property specific mapped elements in bundle for WHEEL_TICK_DISTANCE sensor*/
/** @hide */
public final static String WHEEL_TICK_DISTANCE_SUPPORTED_WHEELS =
- "android.car.wheelTickDistanceSupportedWhheels";
+ "android.car.wheelTickDistanceSupportedWheels";
/** @hide */
public final static String WHEEL_TICK_DISTANCE_FRONT_LEFT_UM_PER_TICK =
"android.car.wheelTickDistanceFrontLeftUmPerTick";
diff --git a/car-lib/src/android/car/hardware/CarSensorEvent.java b/car-lib/src/android/car/hardware/CarSensorEvent.java
index 52f363d..86af063 100644
--- a/car-lib/src/android/car/hardware/CarSensorEvent.java
+++ b/car-lib/src/android/car/hardware/CarSensorEvent.java
@@ -33,59 +33,43 @@
public class CarSensorEvent implements Parcelable {
/**
- * Index in {@link #floatValues} for {@link CarSensorManager#SENSOR_TYPE_FUEL_LEVEL} type of
- * sensor. This value is fuel level in percentile.
- */
- public static final int INDEX_FUEL_LEVEL_IN_PERCENTILE = 0;
- /**
- * Index in {@link #floatValues} for {@link CarSensorManager#SENSOR_TYPE_FUEL_LEVEL} type of
- * sensor. This value is fuel level in coverable distance. The unit is Km.
- */
- public static final int INDEX_FUEL_LEVEL_IN_DISTANCE = 1;
- /**
- * Index in {@link #intValues} for {@link CarSensorManager#SENSOR_TYPE_FUEL_LEVEL} type of
- * sensor. This value is set to 1 if fuel low level warning is on.
- */
- public static final int INDEX_FUEL_LOW_WARNING = 0;
-
- /**
* GEAR_* represents meaning of intValues[0] for {@link CarSensorManager#SENSOR_TYPE_GEAR}
* sensor type.
* GEAR_NEUTRAL means transmission gear is in neutral state, and the car may be moving.
*/
- public static final int GEAR_NEUTRAL = 0;
+ public static final int GEAR_NEUTRAL = 0x0001;
/**
* intValues[0] from 1 to 99 represents transmission gear number for moving forward.
* GEAR_FIRST is for gear number 1.
*/
- public static final int GEAR_FIRST = 1;
+ public static final int GEAR_FIRST = 0x0010;
/** Gear number 2. */
- public static final int GEAR_SECOND = 2;
+ public static final int GEAR_SECOND = 0x0020;
/** Gear number 3. */
- public static final int GEAR_THIRD = 3;
+ public static final int GEAR_THIRD = 0x0040;
/** Gear number 4. */
- public static final int GEAR_FOURTH = 4;
+ public static final int GEAR_FOURTH = 0x0080;
/** Gear number 5. */
- public static final int GEAR_FIFTH = 5;
+ public static final int GEAR_FIFTH = 0x0100;
/** Gear number 6. */
- public static final int GEAR_SIXTH = 6;
+ public static final int GEAR_SIXTH = 0x0200;
/** Gear number 7. */
- public static final int GEAR_SEVENTH = 7;
+ public static final int GEAR_SEVENTH = 0x0400;
/** Gear number 8. */
- public static final int GEAR_EIGHTH = 8;
+ public static final int GEAR_EIGHTH = 0x0800;
/** Gear number 9. */
- public static final int GEAR_NINTH = 9;
+ public static final int GEAR_NINTH = 0x1000;
/** Gear number 10. */
- public static final int GEAR_TENTH = 10;
+ public static final int GEAR_TENTH = 0x2000;
/**
* This is for transmission without specific gear number for moving forward like CVT. It tells
* that car is in a transmission state to move it forward.
*/
- public static final int GEAR_DRIVE = 100;
+ public static final int GEAR_DRIVE = 0x0008;
/** Gear in parking state */
- public static final int GEAR_PARK = 101;
+ public static final int GEAR_PARK = 0x0004;
/** Gear in reverse */
- public static final int GEAR_REVERSE = 102;
+ public static final int GEAR_REVERSE = 0x0002;
/**
* Ignition state is unknown.
@@ -108,26 +92,6 @@
public static final int IGNITION_STATE_START = 5;
/**
- * Bitmask of driving restrictions.
- */
- /** No restrictions. */
- public static final int DRIVE_STATUS_UNRESTRICTED = 0;
- /** No video playback allowed. */
- public static final int DRIVE_STATUS_NO_VIDEO = 0x1;
- /** No keyboard or rotary controller input allowed. */
- public static final int DRIVE_STATUS_NO_KEYBOARD_INPUT = 0x2;
- /** No voice input allowed. */
- public static final int DRIVE_STATUS_NO_VOICE_INPUT = 0x4;
- /** No setup / configuration allowed. */
- public static final int DRIVE_STATUS_NO_CONFIG = 0x8;
- /** Limit displayed message length. */
- public static final int DRIVE_STATUS_LIMIT_MESSAGE_LEN = 0x10;
- /** represents case where all of the above items are restricted */
- public static final int DRIVE_STATUS_FULLY_RESTRICTED = DRIVE_STATUS_NO_VIDEO |
- DRIVE_STATUS_NO_KEYBOARD_INPUT | DRIVE_STATUS_NO_VOICE_INPUT | DRIVE_STATUS_NO_CONFIG |
- DRIVE_STATUS_LIMIT_MESSAGE_LEN;
-
- /**
* Index for {@link CarSensorManager#SENSOR_TYPE_ENVIRONMENT} in floatValues.
* Temperature in Celsius degrees.
*/
@@ -358,12 +322,8 @@
/** @hide */
public static class FuelLevelData {
public long timestamp;
- /** Fuel level in %. If unsupported by the car, this value is -1. */
- public int level;
- /** Fuel as possible range in Km. If unsupported by the car, this value is -1. */
- public float range;
- /** If unsupported by the car, this value is false. */
- public boolean lowFuelWarning;
+ /** Fuel level in milliliters. Negative values indicate this property is unsupported. */
+ public float level;
/** @hide */
private FuelLevelData() {};
@@ -385,21 +345,14 @@
}
data.timestamp = timestamp;
if (floatValues == null) {
- data.level = -1;
- data.range = -1;
+ data.level = -1.0f;
} else {
- if (floatValues[INDEX_FUEL_LEVEL_IN_PERCENTILE] < 0) {
- data.level = -1;
+ if (floatValues[0] < 0) {
+ data.level = -1.0f;
} else {
- data.level = (int) floatValues[INDEX_FUEL_LEVEL_IN_PERCENTILE];
- }
- if (floatValues[INDEX_FUEL_LEVEL_IN_DISTANCE] < 0) {
- data.range = -1;
- } else {
- data.range = floatValues[INDEX_FUEL_LEVEL_IN_DISTANCE];
+ data.level = floatValues[0];
}
}
- data.lowFuelWarning = intValues[0] == 1;
return data;
}
@@ -488,33 +441,6 @@
}
/** @hide */
- public static class DrivingStatusData {
- public long timestamp;
- public int status;
-
- /** @hide */
- private DrivingStatusData() {};
- }
-
- /**
- * Convenience method for obtaining a {@link DrivingStatusData} object from a CarSensorEvent
- * object with type {@link CarSensorManager#SENSOR_TYPE_DRIVING_STATUS}.
- *
- * @param data an optional output parameter which, if non-null, will be used by this method
- * instead of a newly created object.
- * @return a DrivingStatusData object corresponding to the data contained in the CarSensorEvent.
- * @hide
- */
- public DrivingStatusData getDrivingStatusData(DrivingStatusData data) {
- checkType(CarSensorManager.SENSOR_TYPE_DRIVING_STATUS);
- if (data == null) {
- data = new DrivingStatusData();
- }
- data.status = intValues[0];
- return data;
- }
-
- /** @hide */
public static class CarWheelTickDistanceData {
public long timestamp;
public long sensorResetCount;
@@ -609,6 +535,195 @@
}
/** @hide */
+ public static class CarFuelDoorOpenData {
+ public long timestamp;
+ public boolean fuelDoorIsOpen;
+
+ /** @hide */
+ private CarFuelDoorOpenData() {};
+ }
+
+ /**
+ * Convenience method for obtaining a {@link CarFuelDoorOpenData} object from a
+ * CarSensorEvent object with type {@link CarSensorManager#SENSOR_TYPE_FUEL_DOOR_OPEN}.
+ *
+ * @param data an optional output parameter which, if non-null, will be used by this method
+ * instead of a newly created object.
+ * @return a CarFuelDoorOpenData object corresponding to data contained in the
+ * CarSensorEvent.
+ * @hide
+ */
+ public CarFuelDoorOpenData getCarFuelDoorOpenData(
+ CarFuelDoorOpenData data) {
+ checkType(CarSensorManager.SENSOR_TYPE_FUEL_DOOR_OPEN);
+ if (data == null) {
+ data = new CarFuelDoorOpenData();
+ }
+ data.timestamp = timestamp;
+ data.fuelDoorIsOpen = intValues[0] == 1;
+ return data;
+ }
+
+ /** @hide */
+ public static class CarEvBatteryLevelData {
+ public long timestamp;
+ /** Battery Level in Watt-hours */
+ public float evBatteryLevel;
+
+ /** @hide */
+ private CarEvBatteryLevelData() {};
+ }
+
+ /**
+ * Convenience method for obtaining a {@link CarEvBatteryLevelData} object from a
+ * CarSensorEvent object with type {@link CarSensorManager#SENSOR_TYPE_EV_BATTERY_LEVEL}.
+ *
+ * @param data an optional output parameter which, if non-null, will be used by this method
+ * instead of a newly created object.
+ * @return a CarEvBatteryLevelData object corresponding to data contained in the
+ * CarSensorEvent.
+ * @hide
+ */
+ public CarEvBatteryLevelData getCarEvBatteryLevelData(
+ CarEvBatteryLevelData data) {
+ checkType(CarSensorManager.SENSOR_TYPE_EV_BATTERY_LEVEL);
+ if (data == null) {
+ data = new CarEvBatteryLevelData();
+ }
+ data.timestamp = timestamp;
+ if (floatValues == null) {
+ data.evBatteryLevel = -1.0f;
+ } else {
+ if (floatValues[0] < 0) {
+ data.evBatteryLevel = -1.0f;
+ } else {
+ data.evBatteryLevel = floatValues[0];
+ }
+ }
+ return data;
+ }
+
+ /** @hide */
+ public static class CarEvChargePortOpenData {
+ public long timestamp;
+ public boolean evChargePortIsOpen;
+
+ /** @hide */
+ private CarEvChargePortOpenData() {};
+ }
+
+ /**
+ * Convenience method for obtaining a {@link CarEvChargePortOpenData} object from a
+ * CarSensorEvent object with type {@link CarSensorManager#SENSOR_TYPE_EV_CHARGE_PORT_OPEN}.
+ *
+ * @param data an optional output parameter which, if non-null, will be used by this method
+ * instead of a newly created object.
+ * @return a CarEvChargePortOpenData object corresponding to data contained in the
+ * CarSensorEvent.
+ * @hide
+ */
+ public CarEvChargePortOpenData getCarEvChargePortOpenData(
+ CarEvChargePortOpenData data) {
+ checkType(CarSensorManager.SENSOR_TYPE_EV_CHARGE_PORT_OPEN);
+ if (data == null) {
+ data = new CarEvChargePortOpenData();
+ }
+ data.timestamp = timestamp;
+ data.evChargePortIsOpen = intValues[0] == 1;
+ return data;
+ }
+
+ /** @hide */
+ public static class CarEvChargePortConnectedData {
+ public long timestamp;
+ public boolean evChargePortIsConnected;
+
+ /** @hide */
+ private CarEvChargePortConnectedData() {};
+ }
+
+ /**
+ * Convenience method for obtaining a {@link CarEvChargePortConnectedData} object from a
+ * CarSensorEvent object with type {@link CarSensorManager#SENSOR_TYPE_EV_CHARGE_PORT_CONNECTED}.
+ *
+ * @param data an optional output parameter which, if non-null, will be used by this method
+ * instead of a newly created object.
+ * @return a CarEvChargePortConnectedData object corresponding to data contained in the
+ * CarSensorEvent.
+ * @hide
+ */
+ public CarEvChargePortConnectedData getCarEvChargePortConnectedData(
+ CarEvChargePortConnectedData data) {
+ checkType(CarSensorManager.SENSOR_TYPE_EV_CHARGE_PORT_CONNECTED);
+ if (data == null) {
+ data = new CarEvChargePortConnectedData();
+ }
+ data.timestamp = timestamp;
+ data.evChargePortIsConnected = intValues[0] == 1;
+ return data;
+ }
+
+ /** @hide */
+ public static class CarEvBatteryChargeRateData {
+ public long timestamp;
+ /** EV battery charging rate in mW.
+ * Positive values indicates battery being charged. Negative values indicate discharge */
+ public float evChargeRate;
+
+ /** @hide */
+ private CarEvBatteryChargeRateData() {};
+ }
+
+ /**
+ * Convenience method for obtaining a {@link CarEvBatteryChargeRateData} object from a
+ * CarSensorEvent object with type {@link CarSensorManager#SENSOR_TYPE_EV_BATTERY_CHARGE_RATE}.
+ *
+ * @param data an optional output parameter which, if non-null, will be used by this method
+ * instead of a newly created object.
+ * @return a CarEvBatteryChargeRateData object corresponding to data contained in the
+ * CarSensorEvent.
+ * @hide
+ */
+ public CarEvBatteryChargeRateData getCarEvBatteryChargeRateData(
+ CarEvBatteryChargeRateData data) {
+ checkType(CarSensorManager.SENSOR_TYPE_EV_BATTERY_CHARGE_RATE);
+ if (data == null) {
+ data = new CarEvBatteryChargeRateData();
+ }
+ data.timestamp = timestamp;
+ data.evChargeRate = floatValues[0];
+ return data;
+ }
+
+ /** @hide */
+ public static class CarEngineOilLevelData {
+ public long timestamp;
+ public int engineOilLevel;
+
+ /** @hide */
+ private CarEngineOilLevelData() {};
+ }
+
+ /**
+ * Convenience method for obtaining a {@link CarEngineOilLevelData} object from a
+ * CarSensorEvent object with type {@link CarSensorManager#SENSOR_TYPE_ENGINE_OIL_LEVEL}.
+ *
+ * @param data an optional output parameter, which, if non-null, will be used by this method
+ * instead of a newly created object.
+ * @return a CarEngineOilLEvelData object corresponding to data contained in the CarSensorEvent.
+ * @hide
+ */
+ public CarEngineOilLevelData getCarEngineOilLevelData(CarEngineOilLevelData data) {
+ checkType(CarSensorManager.SENSOR_TYPE_ENGINE_OIL_LEVEL);
+ if (data == null) {
+ data = new CarEngineOilLevelData();
+ }
+ data.timestamp = timestamp;
+ data.engineOilLevel = intValues[0];
+ return data;
+ }
+
+ /** @hide */
@Override
public String toString() {
StringBuilder sb = new StringBuilder();
diff --git a/car-lib/src/android/car/hardware/CarSensorManager.java b/car-lib/src/android/car/hardware/CarSensorManager.java
index e2bce11..2536604 100644
--- a/car-lib/src/android/car/hardware/CarSensorManager.java
+++ b/car-lib/src/android/car/hardware/CarSensorManager.java
@@ -24,30 +24,31 @@
import android.car.CarLibLog;
import android.car.CarManagerBase;
import android.car.CarNotConnectedException;
+import android.car.VehiclePropertyType;
+import android.car.hardware.property.CarPropertyManager;
import android.content.Context;
import android.os.Bundle;
import android.os.Handler;
import android.os.IBinder;
import android.os.RemoteException;
+import android.util.ArraySet;
import android.util.Log;
-import android.util.SparseArray;
-import android.util.SparseIntArray;
-
-import com.android.car.internal.CarRatedListeners;
-import com.android.car.internal.SingleMessageHandler;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.ref.WeakReference;
-import java.util.ArrayList;
-import java.util.Iterator;
+import java.util.Arrays;
+import java.util.HashMap;
import java.util.List;
-import java.util.function.Consumer;
+
/**
* API for monitoring car sensor data.
*/
public final class CarSensorManager implements CarManagerBase {
+ private static final boolean DBG = false;
+ private static final String TAG = "CarSensorManager";
+ private final CarPropertyManager mCarPropertyMgr;
/** @hide */
public static final int SENSOR_TYPE_RESERVED1 = 1;
/**
@@ -55,53 +56,45 @@
* Sensor data in {@link CarSensorEvent} is a float which will be >= 0.
* This requires {@link Car#PERMISSION_SPEED} permission.
*/
- public static final int SENSOR_TYPE_CAR_SPEED = 2;
+ public static final int SENSOR_TYPE_CAR_SPEED = 0x11600207;
/**
* Represents engine RPM of the car. Sensor data in {@link CarSensorEvent} is a float.
*/
- public static final int SENSOR_TYPE_RPM = 3;
+ public static final int SENSOR_TYPE_RPM = 0x11600305;
/**
* Total travel distance of the car in Kilometer. Sensor data is a float.
* This requires {@link Car#PERMISSION_MILEAGE} permission.
*/
- public static final int SENSOR_TYPE_ODOMETER = 4;
+ public static final int SENSOR_TYPE_ODOMETER = 0x11600204;
/**
* Indicates fuel level of the car.
- * In {@link CarSensorEvent}, floatValues[{@link CarSensorEvent#INDEX_FUEL_LEVEL_IN_PERCENTILE}]
- * represents fuel level in percentile (0 to 100) while
- * floatValues[{@link CarSensorEvent#INDEX_FUEL_LEVEL_IN_DISTANCE}] represents estimated range
- * in Kilometer with the remaining fuel.
- * Note that the gas mileage used for the estimation may not represent the current driving
- * condition.
- * This requires {@link Car#PERMISSION_FUEL} permission.
+ * In {@link CarSensorEvent}, represents fuel level in milliliters.
+ * This requires {@link Car#PERMISSION_ENERGY} permission.
*/
- public static final int SENSOR_TYPE_FUEL_LEVEL = 5;
+ public static final int SENSOR_TYPE_FUEL_LEVEL = 0x11600307;
/**
* Represents the current status of parking brake. Sensor data in {@link CarSensorEvent} is an
* intValues[0]. Value of 1 represents parking brake applied while 0 means the other way
* around. For this sensor, rate in {@link #registerListener(OnSensorChangedListener, int, int)}
* will be ignored and all changes will be notified.
*/
- public static final int SENSOR_TYPE_PARKING_BRAKE = 6;
+ public static final int SENSOR_TYPE_PARKING_BRAKE = 0x11200402;
/**
* This represents the current position of transmission gear. Sensor data in
* {@link CarSensorEvent} is an intValues[0]. For the meaning of the value, check
* {@link CarSensorEvent#GEAR_NEUTRAL} and other GEAR_*.
*/
- public static final int SENSOR_TYPE_GEAR = 7;
+ public static final int SENSOR_TYPE_GEAR = 0x11400400;
/** @hide */
public static final int SENSOR_TYPE_RESERVED8 = 8;
/**
* Day/night sensor. Sensor data is intValues[0].
*/
- public static final int SENSOR_TYPE_NIGHT = 9;
+ public static final int SENSOR_TYPE_NIGHT = 0x11200407;
/** @hide */
public static final int SENSOR_TYPE_RESERVED10 = 10;
- /**
- * Represents the current driving status of car. Different user interaction should be used
- * depending on the current driving status. Driving status is intValues[0].
- */
- public static final int SENSOR_TYPE_DRIVING_STATUS = 11;
+ /** @hide */
+ public static final int SENSOR_TYPE_RESERVED11 = 11;
/**
* Environment like temperature and pressure.
*/
@@ -128,7 +121,7 @@
* Represents ignition state. The value should be one of the constants that starts with
* IGNITION_STATE_* in {@link CarSensorEvent}.
*/
- public static final int SENSOR_TYPE_IGNITION_STATE = 22;
+ public static final int SENSOR_TYPE_IGNITION_STATE = 0x11400409;
/**
* Represents wheel distance in millimeters. Some cars may not have individual sensors on each
* wheel. If a value is not available, Long.MAX_VALUE will be reported. The wheel distance
@@ -136,115 +129,180 @@
* distance shall be reset to zero each time a vehicle is started by the user.
* This requires {@link Car#PERMISSION_SPEED} permission.
*/
- public static final int SENSOR_TYPE_WHEEL_TICK_DISTANCE = 23;
+ public static final int SENSOR_TYPE_WHEEL_TICK_DISTANCE = 0x11510306;
/**
* Set to true when ABS is active. This sensor is event driven.
- * This requires {@link Car#PERMISSION_VEHICLE_DYNAMICS_STATE} permission.
+ * This requires {@link Car#PERMISSION_CAR_DYNAMICS_STATE} permission.
*/
- public static final int SENSOR_TYPE_ABS_ACTIVE = 24;
+ public static final int SENSOR_TYPE_ABS_ACTIVE = 0x1120040a;
/**
* Set to true when traction control is active. This sensor is event driven.
- * This requires {@link Car#PERMISSION_VEHICLE_DYNAMICS_STATE} permission.
+ * This requires {@link Car#PERMISSION_CAR_DYNAMICS_STATE} permission.
*/
- public static final int SENSOR_TYPE_TRACTION_CONTROL_ACTIVE = 25;
+ public static final int SENSOR_TYPE_TRACTION_CONTROL_ACTIVE = 0x1120040b;
+ /** @hide */
+ public static final int SENSOR_TYPE_RESERVED26 = 26;
+ /**
+ * Set to true if the fuel door is open.
+ */
+ public static final int SENSOR_TYPE_FUEL_DOOR_OPEN = 0x11200308;
/**
- * Sensor type bigger than this is invalid. Always update this after adding a new sensor.
- * @hide
+ * Indicates battery level of the car.
+ * In {@link CarSensorEvent}, represents battery level in WH. floatValues[{@link
+ * CarSensorEvent#INDEX_EV_BATTERY_CAPACITY_ACTUAL}] represents the actual battery capacity in
+ * WH. The battery degrades over time, so this value is expected to drop slowly over the life
+ * of the vehicle.
+ * This requires {@link Car#PERMISSION_ENERGY} permission.
*/
- private static final int SENSOR_TYPE_MAX = SENSOR_TYPE_TRACTION_CONTROL_ACTIVE;
-
+ public static final int SENSOR_TYPE_EV_BATTERY_LEVEL = 0x11600309;
/**
- * Sensors defined in this range [{@link #SENSOR_TYPE_VENDOR_EXTENSION_START},
- * {@link #SENSOR_TYPE_VENDOR_EXTENSION_END}] is for each car vendor's to use.
- * This should be only used for system app to access sensors not defined as standard types.
- * So the sensor supported in this range can vary depending on car models / manufacturers.
- * 3rd party apps should not use sensors in this range as they are not compatible across
- * different cars. Additionally 3rd party apps trying to access sensor in this range will get
- * security exception as their access is restricted to system apps.
- *
+ * Set to true if EV charging port is open.
+ */
+ public static final int SENSOR_TYPE_EV_CHARGE_PORT_OPEN = 0x1120030a;
+ /**
+ * Set to true if EV charging port is connected.
+ */
+ public static final int SENSOR_TYPE_EV_CHARGE_PORT_CONNECTED = 0x1120030b;
+ /**
+ * Indicates the instantaneous battery charging rate in mW.
+ * This requires {@link Car#PERMISSION_ENERGY} permission.
+ */
+ public static final int SENSOR_TYPE_EV_BATTERY_CHARGE_RATE = 0x1160030c;
+ /**
+ * Oil level sensor.
+ * This requires {@link Car#PERMISSION_CAR_ENGINE_DETAILED} permission
* @hide
*/
- public static final int SENSOR_TYPE_VENDOR_EXTENSION_START = 0x60000000;
- public static final int SENSOR_TYPE_VENDOR_EXTENSION_END = 0x6fffffff;
+ public static final int SENSOR_TYPE_ENGINE_OIL_LEVEL = 0x11400303;
+
/** @hide */
@IntDef({
- SENSOR_TYPE_CAR_SPEED,
- SENSOR_TYPE_RPM,
- SENSOR_TYPE_ODOMETER,
- SENSOR_TYPE_FUEL_LEVEL,
- SENSOR_TYPE_PARKING_BRAKE,
- SENSOR_TYPE_GEAR,
- SENSOR_TYPE_NIGHT,
- SENSOR_TYPE_DRIVING_STATUS,
- SENSOR_TYPE_ENVIRONMENT,
- SENSOR_TYPE_IGNITION_STATE,
- SENSOR_TYPE_WHEEL_TICK_DISTANCE,
- SENSOR_TYPE_ABS_ACTIVE,
- SENSOR_TYPE_TRACTION_CONTROL_ACTIVE,
+ SENSOR_TYPE_CAR_SPEED,
+ SENSOR_TYPE_RPM,
+ SENSOR_TYPE_ODOMETER,
+ SENSOR_TYPE_FUEL_LEVEL,
+ SENSOR_TYPE_PARKING_BRAKE,
+ SENSOR_TYPE_GEAR,
+ SENSOR_TYPE_NIGHT,
+ SENSOR_TYPE_ENVIRONMENT,
+ SENSOR_TYPE_IGNITION_STATE,
+ SENSOR_TYPE_WHEEL_TICK_DISTANCE,
+ SENSOR_TYPE_ABS_ACTIVE,
+ SENSOR_TYPE_TRACTION_CONTROL_ACTIVE,
+ SENSOR_TYPE_FUEL_DOOR_OPEN,
+ SENSOR_TYPE_EV_BATTERY_LEVEL,
+ SENSOR_TYPE_EV_CHARGE_PORT_OPEN,
+ SENSOR_TYPE_EV_CHARGE_PORT_CONNECTED,
+ SENSOR_TYPE_EV_BATTERY_CHARGE_RATE,
+ SENSOR_TYPE_ENGINE_OIL_LEVEL,
})
@Retention(RetentionPolicy.SOURCE)
public @interface SensorType {}
+ private final ArraySet<Integer> mSensorConfigIds = new ArraySet<>(Arrays.asList(new Integer[]{
+ SENSOR_TYPE_CAR_SPEED,
+ SENSOR_TYPE_RPM,
+ SENSOR_TYPE_ODOMETER,
+ SENSOR_TYPE_FUEL_LEVEL,
+ SENSOR_TYPE_PARKING_BRAKE,
+ SENSOR_TYPE_GEAR,
+ SENSOR_TYPE_NIGHT,
+ SENSOR_TYPE_ENVIRONMENT,
+ SENSOR_TYPE_IGNITION_STATE,
+ SENSOR_TYPE_WHEEL_TICK_DISTANCE,
+ SENSOR_TYPE_ABS_ACTIVE,
+ SENSOR_TYPE_TRACTION_CONTROL_ACTIVE,
+ SENSOR_TYPE_FUEL_DOOR_OPEN,
+ SENSOR_TYPE_EV_BATTERY_LEVEL,
+ SENSOR_TYPE_EV_CHARGE_PORT_OPEN,
+ SENSOR_TYPE_EV_CHARGE_PORT_CONNECTED,
+ SENSOR_TYPE_EV_BATTERY_CHARGE_RATE,
+ SENSOR_TYPE_ENGINE_OIL_LEVEL,
+ }));
+
/** Read sensor in default normal rate set for each sensors. This is default rate. */
- public static final int SENSOR_RATE_NORMAL = 3;
- public static final int SENSOR_RATE_UI = 2;
- public static final int SENSOR_RATE_FAST = 1;
+ public static final int SENSOR_RATE_NORMAL = 1;
+ public static final int SENSOR_RATE_UI = 5;
+ public static final int SENSOR_RATE_FAST = 10;
/** Read sensor at the maximum rate. Actual rate will be different depending on the sensor. */
- public static final int SENSOR_RATE_FASTEST = 0;
+ public static final int SENSOR_RATE_FASTEST = 100;
/** @hide */
@IntDef({
- SENSOR_RATE_NORMAL,
- SENSOR_RATE_UI,
- SENSOR_RATE_FAST,
- SENSOR_RATE_FASTEST
+ SENSOR_RATE_NORMAL,
+ SENSOR_RATE_UI,
+ SENSOR_RATE_FAST,
+ SENSOR_RATE_FASTEST
})
@Retention(RetentionPolicy.SOURCE)
public @interface SensorRate {}
- private static final int MSG_SENSOR_EVENTS = 0;
-
- private final ICarSensor mService;
-
- private CarSensorEventListenerToService mCarSensorEventListenerToService;
+ private CarPropertyEventListenerToBase mCarPropertyEventListener = null;
/**
- * To keep record of locally active sensors. Key is sensor type. This is used as a basic lock
- * for all client accesses.
+ * To keep record of CarPropertyEventListenerToBase
*/
- private final SparseArray<CarSensorListeners> mActiveSensorListeners = new SparseArray<>();
+ private final HashMap<OnSensorChangedListener, CarPropertyEventListenerToBase> mListenerMap =
+ new HashMap<>();
+ /**
+ * Listener for car sensor data change.
+ * Callbacks are called in the Looper context.
+ */
+ public interface OnSensorChangedListener {
+ /**
+ * Called when there is a new sensor data from car.
+ * @param event Incoming sensor event for the given sensor type.
+ */
+ void onSensorChanged(CarSensorEvent event);
+ }
- /** Handles call back into clients. */
- private final SingleMessageHandler<CarSensorEvent> mHandlerCallback;
+ private static class CarPropertyEventListenerToBase implements
+ CarPropertyManager.CarPropertyEventListener{
+ private final WeakReference<CarSensorManager> mManager;
+ private final OnSensorChangedListener mListener;
+ CarPropertyEventListenerToBase(CarSensorManager manager, OnSensorChangedListener listener) {
+ mManager = new WeakReference<>(manager);
+ mListener = listener;
+ }
+ @Override
+ public void onChangeEvent(CarPropertyValue value) {
+ CarSensorManager manager = mManager.get();
+ if (manager != null) {
+ manager.handleOnChangeEvent(value, mListener);
+ }
+ }
+ @Override
+ public void onErrorEvent(int propertyId, int zone) {
+
+ }
+ }
+
+ private void handleOnChangeEvent(CarPropertyValue value, OnSensorChangedListener listener) {
+ synchronized (mListenerMap) {
+ CarSensorEvent event = createCarSensorEvent(value);
+ listener.onSensorChanged(event);
+ }
+ }
+
+ private void handleOnErrorEvent(int propertyId, int zone) {
+
+ }
/** @hide */
public CarSensorManager(IBinder service, Context context, Handler handler) {
- mService = ICarSensor.Stub.asInterface(service);
- mHandlerCallback = new SingleMessageHandler<CarSensorEvent>(handler.getLooper(),
- MSG_SENSOR_EVENTS) {
- @Override
- protected void handleEvent(CarSensorEvent event) {
- CarSensorListeners listeners;
- synchronized (mActiveSensorListeners) {
- listeners = mActiveSensorListeners.get(event.sensorType);
- }
- if (listeners != null) {
- listeners.onSensorChanged(event);
- }
- }
- };
+ mCarPropertyMgr = new CarPropertyManager(service, handler, DBG, TAG);
}
/** @hide */
@Override
public void onCarDisconnected() {
- synchronized(mActiveSensorListeners) {
- mActiveSensorListeners.clear();
- mCarSensorEventListenerToService = null;
+ synchronized (mListenerMap) {
+ mListenerMap.clear();
}
+ mCarPropertyMgr.onCarDisconnected();
}
/**
@@ -254,16 +312,28 @@
*/
public int[] getSupportedSensors() throws CarNotConnectedException {
try {
- return mService.getSupportedSensors();
+ List<CarPropertyConfig> carPropertyConfigList = getPropertyList();
+ int[] supportedSensors = new int[carPropertyConfigList.size()];
+ for (int i = 0; i < supportedSensors.length; i++) {
+ supportedSensors[i] = carPropertyConfigList.get(i).getPropertyId();
+ }
+ return supportedSensors;
} catch (IllegalStateException e) {
CarApiUtil.checkCarNotConnectedExceptionFromCarService(e);
- } catch (RemoteException e) {
- throw new CarNotConnectedException(e);
}
return new int[0];
}
/**
+ * Get list of properties represented by CarSensorManager for this car.
+ * @return List of CarPropertyConfig objects available via Car Cabin Manager.
+ * @throws CarNotConnectedException if the connection to the car service has been lost.
+ */
+ public List<CarPropertyConfig> getPropertyList() throws CarNotConnectedException {
+ return mCarPropertyMgr.getPropertyList(mSensorConfigIds);
+ }
+
+ /**
* Tells if given sensor is supported or not.
* @param sensorType
* @return true if the sensor is supported.
@@ -295,18 +365,6 @@
}
/**
- * Listener for car sensor data change.
- * Callbacks are called in the Looper context.
- */
- public interface OnSensorChangedListener {
- /**
- * Called when there is a new sensor data from car.
- * @param event Incoming sensor event for the given sensor type.
- */
- void onSensorChanged(final CarSensorEvent event);
- }
-
- /**
* Register {@link OnSensorChangedListener} to get repeated sensor updates. Multiple listeners
* can be registered for a single sensor or the same listener can be used for different sensors.
* If the same listener is registered again for the same sensor, it will be either ignored or
@@ -314,8 +372,9 @@
* <p>
* Requires {@link Car#PERMISSION_SPEED} for {@link #SENSOR_TYPE_CAR_SPEED} and
* {@link #SENSOR_TYPE_WHEEL_TICK_DISTANCE}, {@link Car#PERMISSION_MILEAGE} for
- * {@link #SENSOR_TYPE_ODOMETER}, {@link Car#PERMISSION_FUEL} for
- * {@link #SENSOR_TYPE_FUEL_LEVEL}, or {@link Car#PERMISSION_VEHICLE_DYNAMICS_STATE} for
+ * {@link #SENSOR_TYPE_ODOMETER}, {@link Car#PERMISSION_ENERGY} for
+ * {@link #SENSOR_TYPE_FUEL_LEVEL} and (@link #SENSOR_TYPE_EV_BATTERY_LEVEL and
+ * {@link #SENSOR_TYPE_EV_CHARGE_RATE}, {@link Car#PERMISSION_CAR_DYNAMICS_STATE} for
* {@link #SENSOR_TYPE_ABS_ACTIVE} and {@link #SENSOR_TYPE_TRACTION_CONTROL_ACTIVE}
*
* @param listener
@@ -333,37 +392,25 @@
* @throws SecurityException if missing the appropriate permission
*/
@RequiresPermission(anyOf={Manifest.permission.ACCESS_FINE_LOCATION, Car.PERMISSION_SPEED,
- Car.PERMISSION_MILEAGE, Car.PERMISSION_FUEL, Car.PERMISSION_VEHICLE_DYNAMICS_STATE},
+ Car.PERMISSION_MILEAGE, Car.PERMISSION_ENERGY, Car.PERMISSION_CAR_DYNAMICS_STATE},
conditional=true)
public boolean registerListener(OnSensorChangedListener listener, @SensorType int sensorType,
@SensorRate int rate) throws CarNotConnectedException, IllegalArgumentException {
- assertSensorType(sensorType);
if (rate != SENSOR_RATE_FASTEST && rate != SENSOR_RATE_NORMAL
&& rate != SENSOR_RATE_UI && rate != SENSOR_RATE_FAST) {
throw new IllegalArgumentException("wrong rate " + rate);
}
- synchronized(mActiveSensorListeners) {
- if (mCarSensorEventListenerToService == null) {
- mCarSensorEventListenerToService = new CarSensorEventListenerToService(this);
- }
- boolean needsServerUpdate = false;
- CarSensorListeners listeners;
- listeners = mActiveSensorListeners.get(sensorType);
- if (listeners == null) {
- listeners = new CarSensorListeners(rate);
- mActiveSensorListeners.put(sensorType, listeners);
- needsServerUpdate = true;
- }
- if (listeners.addAndUpdateRate(listener, rate)) {
- needsServerUpdate = true;
- }
- if (needsServerUpdate) {
- if (!registerOrUpdateSensorListener(sensorType, rate)) {
- return false;
- }
- }
+ if (mListenerMap.get(listener) == null) {
+ mCarPropertyEventListener = new CarPropertyEventListenerToBase(this, listener);
+ } else {
+ mCarPropertyEventListener = mListenerMap.get(listener);
}
- return true;
+ if (mCarPropertyMgr.registerListener(mCarPropertyEventListener, sensorType, rate)) {
+ mListenerMap.put(listener, mCarPropertyEventListener);
+ return true;
+ } else {
+ return false;
+ }
}
/**
@@ -373,10 +420,10 @@
*/
public void unregisterListener(OnSensorChangedListener listener) {
//TODO: removing listener should reset update rate, bug: 32060307
- synchronized(mActiveSensorListeners) {
- for (int i = 0; i < mActiveSensorListeners.size(); i++) {
- doUnregisterListenerLocked(listener, mActiveSensorListeners.keyAt(i));
- }
+ synchronized (mListenerMap) {
+ mCarPropertyEventListener = mListenerMap.get(listener);
+ mCarPropertyMgr.unregisterListener(mCarPropertyEventListener);
+ mListenerMap.remove(listener);
}
}
@@ -387,49 +434,10 @@
* @param sensorType
*/
public void unregisterListener(OnSensorChangedListener listener, @SensorType int sensorType) {
- synchronized(mActiveSensorListeners) {
- doUnregisterListenerLocked(listener, sensorType);
+ synchronized (mListenerMap) {
+ mCarPropertyEventListener = mListenerMap.get(listener);
}
- }
-
- private void doUnregisterListenerLocked(OnSensorChangedListener listener, Integer sensor) {
- CarSensorListeners listeners = mActiveSensorListeners.get(sensor);
- if (listeners != null) {
- boolean needsServerUpdate = false;
- if (listeners.contains(listener)) {
- needsServerUpdate = listeners.remove(listener);
- }
- if (listeners.isEmpty()) {
- try {
- mService.unregisterSensorListener(sensor.intValue(),
- mCarSensorEventListenerToService);
- } catch (RemoteException e) {
- //ignore
- }
- mActiveSensorListeners.remove(sensor);
- } else if (needsServerUpdate) {
- try {
- registerOrUpdateSensorListener(sensor, listeners.getRate());
- } catch (CarNotConnectedException e) {
- // ignore
- }
- }
- }
- }
-
- private boolean registerOrUpdateSensorListener(int sensor, int rate)
- throws CarNotConnectedException {
- try {
- if (!mService.registerOrUpdateSensorListener(sensor, rate,
- mCarSensorEventListenerToService)) {
- return false;
- }
- } catch (IllegalStateException e) {
- CarApiUtil.checkCarNotConnectedExceptionFromCarService(e);
- } catch (RemoteException e) {
- throw new CarNotConnectedException(e);
- }
- return true;
+ mCarPropertyMgr.unregisterListener(mCarPropertyEventListener, sensorType);
}
/**
@@ -442,13 +450,11 @@
*/
public CarSensorEvent getLatestSensorEvent(@SensorType int type)
throws CarNotConnectedException {
- assertSensorType(type);
try {
- return mService.getLatestSensorEvent(type);
+ CarPropertyValue propertyValue = mCarPropertyMgr.getProperty(type, 0);
+ return createCarSensorEvent(propertyValue);
} catch (IllegalStateException e) {
CarApiUtil.checkCarNotConnectedExceptionFromCarService(e);
- } catch(RemoteException e) {
- handleCarServiceRemoteExceptionAndThrow(e);
}
return null;
}
@@ -461,58 +467,38 @@
throw new CarNotConnectedException();
}
- private void assertSensorType(int sensorType) {
- if (sensorType == 0 || !((sensorType <= SENSOR_TYPE_MAX) ||
- ((sensorType >= SENSOR_TYPE_VENDOR_EXTENSION_START) &&
- (sensorType <= SENSOR_TYPE_VENDOR_EXTENSION_END)))) {
- throw new IllegalArgumentException("invalid sensor type " + sensorType);
- }
- }
-
- private void handleOnSensorChanged(List<CarSensorEvent> events) {
- mHandlerCallback.sendEvents(events);
- }
-
- private static class CarSensorEventListenerToService extends ICarSensorEventListener.Stub {
- private final WeakReference<CarSensorManager> mManager;
-
- public CarSensorEventListenerToService(CarSensorManager manager) {
- mManager = new WeakReference<>(manager);
- }
-
- @Override
- public void onSensorChanged(List<CarSensorEvent> events) {
- CarSensorManager manager = mManager.get();
- if (manager != null) {
- manager.handleOnSensorChanged(events);
- }
- }
- }
-
- private class CarSensorListeners extends CarRatedListeners<OnSensorChangedListener> {
- CarSensorListeners(int rate) {
- super(rate);
- }
-
- void onSensorChanged(final CarSensorEvent event) {
- // throw away old sensor data as oneway binder call can change order.
- long updateTime = event.timestamp;
- if (updateTime < mLastUpdateTime) {
- Log.w(CarLibLog.TAG_SENSOR, "dropping old sensor data");
- return;
- }
- mLastUpdateTime = updateTime;
- List<OnSensorChangedListener> listeners;
- synchronized (mActiveSensorListeners) {
- listeners = new ArrayList<>(getListeners());
- }
- listeners.forEach(new Consumer<OnSensorChangedListener>() {
- @Override
- public void accept(OnSensorChangedListener listener) {
- listener.onSensorChanged(event);
+ private CarSensorEvent createCarSensorEvent(CarPropertyValue propertyValue) {
+ CarSensorEvent event = null;
+ switch (propertyValue.getPropertyId() & VehiclePropertyType.MASK) {
+ case VehiclePropertyType.FLOAT:
+ event = new CarSensorEvent(propertyValue.getPropertyId(),
+ propertyValue.getTimestamp(), 1, 0, 0);
+ event.floatValues[0] = (float) propertyValue.getValue();
+ break;
+ case VehiclePropertyType.INT32:
+ event = new CarSensorEvent(propertyValue.getPropertyId(),
+ propertyValue.getTimestamp(), 0, 1, 0);
+ event.intValues[0] = (int) propertyValue.getValue();
+ break;
+ case VehiclePropertyType.BOOLEAN:
+ event = new CarSensorEvent(propertyValue.getPropertyId(),
+ propertyValue.getTimestamp(), 0, 1, 0);
+ event.intValues[0] = (boolean) propertyValue.getValue() ? 1 : 0;
+ break;
+ case VehiclePropertyType.INT64_VEC:
+ Object[] value = (Object[]) propertyValue.getValue();
+ event = new CarSensorEvent(propertyValue.getPropertyId(),
+ propertyValue.getTimestamp(), 0, 0, value.length);
+ for (int i = 0; i < value.length; i++) {
+ event.longValues[i] = (Long) value[i];
}
- });
+ break;
+ default:
+ Log.e(TAG, "unhandled VehiclePropertyType for propId="
+ + propertyValue.getPropertyId());
+ break;
}
+ return event;
}
/**
@@ -527,15 +513,44 @@
* @hide
*/
public CarSensorConfig getSensorConfig(@SensorType int type)
- throws CarNotConnectedException {
- assertSensorType(type);
- try {
- return mService.getSensorConfig(type);
- } catch (IllegalStateException e) {
- CarApiUtil.checkCarNotConnectedExceptionFromCarService(e);
- } catch(RemoteException e) {
- handleCarServiceRemoteExceptionAndThrow(e);
+ throws CarNotConnectedException {
+ Bundle b = null;
+ switch (type) {
+ case SENSOR_TYPE_WHEEL_TICK_DISTANCE:
+ List<CarPropertyConfig> propertyConfigs = mCarPropertyMgr.getPropertyList();
+ for (CarPropertyConfig p : propertyConfigs) {
+ if (p.getPropertyId() == type) {
+ b = createWheelDistanceTickBundle(p.getConfigArray());
+ break;
+ }
+ }
+ break;
+ default:
+ b = Bundle.EMPTY;
+ break;
}
- return new CarSensorConfig(0, Bundle.EMPTY);
+ return new CarSensorConfig(type, b);
+ }
+
+ private static final int INDEX_WHEEL_DISTANCE_ENABLE_FLAG = 0;
+ private static final int INDEX_WHEEL_DISTANCE_FRONT_LEFT = 1;
+ private static final int INDEX_WHEEL_DISTANCE_FRONT_RIGHT = 2;
+ private static final int INDEX_WHEEL_DISTANCE_REAR_RIGHT = 3;
+ private static final int INDEX_WHEEL_DISTANCE_REAR_LEFT = 4;
+ private static final int WHEEL_TICK_DISTANCE_BUNDLE_SIZE = 6;
+
+ private Bundle createWheelDistanceTickBundle(List<Integer> configArray) {
+ Bundle b = new Bundle(WHEEL_TICK_DISTANCE_BUNDLE_SIZE);
+ b.putInt(CarSensorConfig.WHEEL_TICK_DISTANCE_SUPPORTED_WHEELS,
+ configArray.get(INDEX_WHEEL_DISTANCE_ENABLE_FLAG));
+ b.putInt(CarSensorConfig.WHEEL_TICK_DISTANCE_FRONT_LEFT_UM_PER_TICK,
+ configArray.get(INDEX_WHEEL_DISTANCE_FRONT_LEFT));
+ b.putInt(CarSensorConfig.WHEEL_TICK_DISTANCE_FRONT_RIGHT_UM_PER_TICK,
+ configArray.get(INDEX_WHEEL_DISTANCE_FRONT_RIGHT));
+ b.putInt(CarSensorConfig.WHEEL_TICK_DISTANCE_REAR_RIGHT_UM_PER_TICK,
+ configArray.get(INDEX_WHEEL_DISTANCE_REAR_RIGHT));
+ b.putInt(CarSensorConfig.WHEEL_TICK_DISTANCE_REAR_LEFT_UM_PER_TICK,
+ configArray.get(INDEX_WHEEL_DISTANCE_REAR_LEFT));
+ return b;
}
}
diff --git a/car-lib/src/android/car/hardware/CarVendorExtensionManager.java b/car-lib/src/android/car/hardware/CarVendorExtensionManager.java
index b153d22..9f06764 100644
--- a/car-lib/src/android/car/hardware/CarVendorExtensionManager.java
+++ b/car-lib/src/android/car/hardware/CarVendorExtensionManager.java
@@ -20,15 +20,16 @@
import android.car.Car;
import android.car.CarManagerBase;
import android.car.CarNotConnectedException;
-import android.car.hardware.property.CarPropertyManagerBase;
-import android.car.hardware.property.CarPropertyManagerBase.CarPropertyEventCallback;
+import android.car.hardware.property.CarPropertyManager;
import android.os.Handler;
import android.os.IBinder;
-import android.os.Looper;
import android.util.ArraySet;
import com.android.internal.annotations.GuardedBy;
+import java.lang.ref.WeakReference;
+import java.util.ArrayList;
+import java.util.Collection;
import java.util.List;
/**
@@ -43,12 +44,36 @@
private final static boolean DBG = false;
private final static String TAG = CarVendorExtensionManager.class.getSimpleName();
- private final CarPropertyManagerBase mPropertyManager;
+ private final CarPropertyManager mPropertyManager;
@GuardedBy("mLock")
- private ArraySet<CarVendorExtensionCallback> mCallbacks;
+ private final ArraySet<CarVendorExtensionCallback> mCallbacks = new ArraySet<>();
private final Object mLock = new Object();
+ @GuardedBy("mLock")
+ private CarPropertyEventListenerToBase mListenerToBase = null;
+
+ private void handleOnChangeEvent(CarPropertyValue value) {
+ Collection<CarVendorExtensionCallback> callbacks;
+ synchronized (mLock) {
+ callbacks = new ArrayList<>(mCallbacks);
+ }
+ for (CarVendorExtensionCallback l: callbacks) {
+ l.onChangeEvent(value);
+ }
+ }
+
+ private void handleOnErrorEvent(int propertyId, int zone) {
+ Collection<CarVendorExtensionCallback> listeners;
+ synchronized (mLock) {
+ listeners = new ArrayList<>(mCallbacks);
+ }
+ for (CarVendorExtensionCallback l: listeners) {
+ l.onErrorEvent(propertyId, zone);
+ }
+
+ }
+
/**
* Creates an instance of the {@link CarVendorExtensionManager}.
*
@@ -56,7 +81,7 @@
* @hide
*/
public CarVendorExtensionManager(IBinder service, Handler handler) {
- mPropertyManager = new CarPropertyManagerBase(service, handler, DBG, TAG);
+ mPropertyManager = new CarPropertyManager(service, handler, DBG, TAG);
}
/**
@@ -78,51 +103,50 @@
public void registerCallback(CarVendorExtensionCallback callback)
throws CarNotConnectedException {
synchronized (mLock) {
- if (mCallbacks == null) {
- mPropertyManager.registerCallback(new CarPropertyEventCallback() {
- @Override
- public void onChangeEvent(CarPropertyValue value) {
- for (CarVendorExtensionCallback listener: getCallbacks()) {
- listener.onChangeEvent(value);
- }
- }
+ if (mCallbacks.isEmpty()) {
+ mListenerToBase = new CarPropertyEventListenerToBase(this);
+ }
- @Override
- public void onErrorEvent(int propertyId, int zone) {
- for (CarVendorExtensionCallback listener: getCallbacks()) {
- listener.onErrorEvent(propertyId, zone);
- }
- }
- });
- mCallbacks = new ArraySet<>(1 /* We expect at least one element */);
+ List<CarPropertyConfig> configs = mPropertyManager.getPropertyList();
+ for (CarPropertyConfig c : configs) {
+ // Register each individual propertyId
+ mPropertyManager.registerListener(mListenerToBase, c.getPropertyId(), 0);
}
mCallbacks.add(callback);
}
}
/** Unregisters listener that was previously registered. */
- public void unregisterCallback(CarVendorExtensionCallback callback) {
+ public void unregisterCallback(CarVendorExtensionCallback callback)
+ throws CarNotConnectedException {
synchronized (mLock) {
mCallbacks.remove(callback);
+ List<CarPropertyConfig> configs = mPropertyManager.getPropertyList();
+ for (CarPropertyConfig c : configs) {
+ // Register each individual propertyId
+ mPropertyManager.unregisterListener(mListenerToBase, c.getPropertyId());
+ }
if (mCallbacks.isEmpty()) {
- mPropertyManager.unregisterCallback();
- mCallbacks = null;
+ mListenerToBase = null;
}
}
}
- /** Returns copy of listeners. Thread safe. */
- private CarVendorExtensionCallback[] getCallbacks() {
- synchronized (mLock) {
- return mCallbacks.toArray(new CarVendorExtensionCallback[mCallbacks.size()]);
- }
- }
-
+ /** Get list of properties represented by CarVendorExtensionManager for this car. */
public List<CarPropertyConfig> getProperties() throws CarNotConnectedException {
return mPropertyManager.getPropertyList();
}
/**
+ * Check whether a given property is available or disabled based on the cars current state.
+ * @return true if the property is AVAILABLE, false otherwise
+ */
+ public boolean isPropertyAvailable(int propertyId, int area)
+ throws CarNotConnectedException {
+ return mPropertyManager.isPropertyAvailable(propertyId, area);
+ }
+
+ /**
* Returns property value. Use this function for global vehicle properties.
*
* @param propertyClass - data type of the given property, for example property that was
@@ -144,7 +168,7 @@
* defined as {@code VEHICLE_VALUE_TYPE_INT32} in vehicle HAL could be accessed using
* {@code Integer.class}.
* @param propId - property id which is matched with the one defined in vehicle HAL
- * @param area - vehicle area (e.g. {@code VehicleAreaZone.ROW_1_LEFT}
+ * @param area - vehicle area (e.g. {@code VehicleAreaSeat.ROW_1_LEFT}
* or {@code VEHICLE_MIRROR_DRIVER_LEFT}
*
* @throws CarNotConnectedException if the connection to the car service has been lost.
@@ -178,7 +202,7 @@
* defined as {@code VEHICLE_VALUE_TYPE_INT32} in vehicle HAL could be accessed using
* {@code Integer.class}.
* @param propId - property id which is matched with the one defined in vehicle HAL
- * @param area - vehicle area (e.g. {@code VehicleAreaZone.ROW_1_LEFT}
+ * @param area - vehicle area (e.g. {@code VehicleAreaSeat.ROW_1_LEFT}
* or {@code VEHICLE_MIRROR_DRIVER_LEFT}
* @param value - new value, this object should match a class provided in {@code propertyClass}
* argument.
@@ -195,4 +219,28 @@
public void onCarDisconnected() {
mPropertyManager.onCarDisconnected();
}
+ private static class CarPropertyEventListenerToBase implements
+ CarPropertyManager.CarPropertyEventListener {
+ private final WeakReference<CarVendorExtensionManager> mManager;
+
+ CarPropertyEventListenerToBase(CarVendorExtensionManager manager) {
+ mManager = new WeakReference<>(manager);
+ }
+
+ @Override
+ public void onChangeEvent(CarPropertyValue value) {
+ CarVendorExtensionManager manager = mManager.get();
+ if (manager != null) {
+ manager.handleOnChangeEvent(value);
+ }
+ }
+
+ @Override
+ public void onErrorEvent(int propertyId, int zone) {
+ CarVendorExtensionManager manager = mManager.get();
+ if (manager != null) {
+ manager.handleOnErrorEvent(propertyId, zone);
+ }
+ }
+ }
}
diff --git a/car-lib/src/android/car/hardware/cabin/CarCabinManager.java b/car-lib/src/android/car/hardware/cabin/CarCabinManager.java
index b925984..1dee2b0 100644
--- a/car-lib/src/android/car/hardware/cabin/CarCabinManager.java
+++ b/car-lib/src/android/car/hardware/cabin/CarCabinManager.java
@@ -23,17 +23,16 @@
import android.car.CarNotConnectedException;
import android.car.hardware.CarPropertyConfig;
import android.car.hardware.CarPropertyValue;
-import android.car.hardware.property.CarPropertyManagerBase;
-import android.car.hardware.property.CarPropertyManagerBase.CarPropertyEventCallback;
+import android.car.hardware.property.CarPropertyManager;
import android.content.Context;
import android.os.Handler;
import android.os.IBinder;
-import android.os.Looper;
import android.util.ArraySet;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.ref.WeakReference;
+import java.util.Arrays;
import java.util.Collection;
import java.util.List;
@@ -43,7 +42,7 @@
*
* The MOVE parameter will start moving the device in the indicated direction. Magnitude
* indicates relative speed. For instance, setting the WINDOW_MOVE parameter to +1 rolls
- * the window up. Setting it to +2 (if available) will roll it up faster.
+ * the window down. Setting it to +2 (if available) will roll it down faster.
*
* POSITION parameter will move the device to the desired position. For instance, if the
* WINDOW_POS has a range of 0-100, setting this parameter to 50 will open the window
@@ -58,11 +57,11 @@
public final class CarCabinManager implements CarManagerBase {
private final static boolean DBG = false;
private final static String TAG = "CarCabinManager";
- private final CarPropertyManagerBase mMgr;
+ private final CarPropertyManager mCarPropertyMgr;
private final ArraySet<CarCabinEventCallback> mCallbacks = new ArraySet<>();
private CarPropertyEventListenerToBase mListenerToBase = null;
- /** Door properties are zoned by VehicleDoor */
+ /** Door properties are zoned by VehicleAreaDoor */
/**
* door position, int type
* Max value indicates fully open, min value (0) indicates fully closed.
@@ -70,47 +69,47 @@
* Some vehicles (minivans) can open the door electronically. Hence, the ability
* to write this property.
*/
- public static final int ID_DOOR_POS = 0x0001;
+ public static final int ID_DOOR_POS = 0x16400b00;
/** door move, int type
* Positive values open the door, negative values close it.
*/
- public static final int ID_DOOR_MOVE = 0x0002;
+ public static final int ID_DOOR_MOVE = 0x16400b01;
/** door lock, bool type
* 'true' indicates door is locked.
*/
- public static final int ID_DOOR_LOCK = 0x0003;
+ public static final int ID_DOOR_LOCK = 0x16200b02;
- /** Mirror properties are zoned by VehicleMirror */
+ /** Mirror properties are zoned by VehicleAreaMirror */
/**
* mirror z position, int type
* Positive value indicates tilt upwards, negative value tilt downwards.
*/
- public static final int ID_MIRROR_Z_POS = 0x1001;
+ public static final int ID_MIRROR_Z_POS = 0x14400b40;
/** mirror z move, int type
* Positive value tilts the mirror upwards, negative value tilts downwards.
*/
- public static final int ID_MIRROR_Z_MOVE = 0x1002;
+ public static final int ID_MIRROR_Z_MOVE = 0x14400b41;
/**
* mirror y position, int type
* Positive value indicates tilt right, negative value tilt left
*/
- public static final int ID_MIRROR_Y_POS = 0x1003;
+ public static final int ID_MIRROR_Y_POS = 0x14400b42;
/** mirror y move, int type
* Positive value tilts the mirror right, negative value tilts left.
*/
- public static final int ID_MIRROR_Y_MOVE = 0x1004;
+ public static final int ID_MIRROR_Y_MOVE = 0x14400b43;
/**
* mirror lock, bool type
* True indicates mirror positions are locked and not changeable.
*/
- public static final int ID_MIRROR_LOCK = 0x1005;
+ public static final int ID_MIRROR_LOCK = 0x11200b44;
/**
* mirror fold, bool type
* True indicates mirrors are folded.
*/
- public static final int ID_MIRROR_FOLD = 0x1006;
+ public static final int ID_MIRROR_FOLD = 0x11200b45;
- /** Seat properties are zoned by VehicleSeat */
+ /** Seat properties are zoned by VehicleAreaSeat */
/**
* seat memory select, int type
* This parameter selects the memory preset to use to select the seat position.
@@ -121,251 +120,277 @@
* When the user wants to select a preset, the desired preset number (1, 2, or 3)
* is set.
*/
- public static final int ID_SEAT_MEMORY_SELECT = 0x2001;
+ public static final int ID_SEAT_MEMORY_SELECT = 0x15400b80;
/**
* seat memory set, int type
* This setting allows the user to save the current seat position settings into
* the selected preset slot. The maxValue for each seat position shall match
* the maxValue for VEHICLE_PROPERTY_SEAT_MEMORY_SELECT.
*/
- public static final int ID_SEAT_MEMORY_SET = 0x2002;
+ public static final int ID_SEAT_MEMORY_SET = 0x15400b81;
/**
* seat belt buckled, bool type
* True indicates belt is buckled.
*/
- public static final int ID_SEAT_BELT_BUCKLED = 0x2003;
+ public static final int ID_SEAT_BELT_BUCKLED = 0x15200b82;
/**
* seat belt height position, int type
* Adjusts the shoulder belt anchor point.
* Max value indicates highest position.
* Min value indicates lowest position.
*/
- public static final int ID_SEAT_BELT_HEIGHT_POS = 0x2004;
+ public static final int ID_SEAT_BELT_HEIGHT_POS = 0x15400b83;
/** seat belt height move, int type
* Adjusts the shoulder belt anchor point.
* Positive value moves towards highest point.
* Negative value moves towards lowest point.
*/
- public static final int ID_SEAT_BELT_HEIGHT_MOVE = 0x2005;
+ public static final int ID_SEAT_BELT_HEIGHT_MOVE = 0x15400b84;
/**
* seat fore/aft position, int type
* Sets the seat position forward (closer to steering wheel) and backwards.
* Max value indicates closest to wheel, min value indicates most rearward position.
*/
- public static final int ID_SEAT_FORE_AFT_POS = 0x2006;
+ public static final int ID_SEAT_FORE_AFT_POS = 0x15400b85;
/**
* seat fore/aft move, int type
* Positive value moves seat forward (closer to steering wheel).
* Negative value moves seat rearward.
*/
- public static final int ID_SEAT_FORE_AFT_MOVE = 0x2007;
+ public static final int ID_SEAT_FORE_AFT_MOVE = 0x15400b86;
/**
* seat backrest angle #1 position, int type
* Backrest angle 1 is the actuator closest to the bottom of the seat.
* Max value indicates angling forward towards the steering wheel.
* Min value indicates full recline.
*/
- public static final int ID_SEAT_BACKREST_ANGLE_1_POS = 0x2008;
+ public static final int ID_SEAT_BACKREST_ANGLE_1_POS = 0x15400b87;
/** seat backrest angle #1 move, int type
* Backrest angle 1 is the actuator closest to the bottom of the seat.
* Positive value angles seat towards the steering wheel.
* Negatie value angles away from steering wheel.
*/
- public static final int ID_SEAT_BACKREST_ANGLE_1_MOVE = 0x2009;
+ public static final int ID_SEAT_BACKREST_ANGLE_1_MOVE = 0x15400b88;
/**
* seat backrest angle #2 position, int type
* Backrest angle 2 is the next actuator up from the bottom of the seat.
* Max value indicates angling forward towards the steering wheel.
* Min value indicates full recline.
*/
- public static final int ID_SEAT_BACKREST_ANGLE_2_POS = 0x200A;
+ public static final int ID_SEAT_BACKREST_ANGLE_2_POS = 0x15400b89;
/** seat backrest angle #2 move, int type
* Backrest angle 2 is the next actuator up from the bottom of the seat.
* Positive value tilts forward towards the steering wheel.
* Negative value tilts backwards.
*/
- public static final int ID_SEAT_BACKREST_ANGLE_2_MOVE = 0x200B;
+ public static final int ID_SEAT_BACKREST_ANGLE_2_MOVE = 0x15400b8a;
/**
* seat height position, int type
* Sets the seat height.
* Max value indicates highest position.
* Min value indicates lowest position.
*/
- public static final int ID_SEAT_HEIGHT_POS = 0x200C;
+ public static final int ID_SEAT_HEIGHT_POS = 0x15400b8b;
/** seat height move, int type
* Sets the seat height.
* Positive value raises the seat.
* Negative value lowers the seat.
* */
- public static final int ID_SEAT_HEIGHT_MOVE = 0x200D;
+ public static final int ID_SEAT_HEIGHT_MOVE = 0x15400b8c;
/**
* seat depth position, int type
* Sets the seat depth, distance from back rest to front edge of seat.
* Max value indicates longest depth position.
* Min value indicates shortest position.
*/
- public static final int ID_SEAT_DEPTH_POS = 0x200E;
+ public static final int ID_SEAT_DEPTH_POS = 0x15400b8d;
/** seat depth move, int type
* Adjusts the seat depth, distance from back rest to front edge of seat.
* Positive value increases the distance from back rest to front edge of seat.
* Negative value decreases this distance.
*/
- public static final int ID_SEAT_DEPTH_MOVE = 0x200F;
+ public static final int ID_SEAT_DEPTH_MOVE = 0x15400b8e;
/**
* seat tilt position, int type
* Sets the seat tilt.
* Max value indicates front edge of seat higher than back edge.
* Min value indicates front edge of seat lower than back edge.
*/
- public static final int ID_SEAT_TILT_POS = 0x2010;
+ public static final int ID_SEAT_TILT_POS = 0x15400b8f;
/** seat tilt move, int type
* Adjusts the seat tilt.
* Positive value lifts front edge of seat higher than back edge.
* Negative value lowers front edge of seat in relation to back edge.
*/
- public static final int ID_SEAT_TILT_MOVE = 0x2011;
+ public static final int ID_SEAT_TILT_MOVE = 0x15400b90;
/**
* seat lumbar fore/aft position, int type
* Pushes the lumbar support forward and backwards.
* Max value indicates most forward position.
* Min value indicates most rearward position.
*/
- public static final int ID_SEAT_LUMBAR_FORE_AFT_POS = 0x2012;
+ public static final int ID_SEAT_LUMBAR_FORE_AFT_POS = 0x15400b91;
/** seat lumbar fore/aft move, int type
* Adjusts the lumbar support forwards and backwards.
* Positive value moves lumbar support forward.
* Negative value moves lumbar support rearward.
*/
- public static final int ID_SEAT_LUMBAR_FORE_AFT_MOVE = 0x2013;
+ public static final int ID_SEAT_LUMBAR_FORE_AFT_MOVE = 0x15400b92;
/**
* seat lumbar side support position, int type
* Sets the amount of lateral lumbar support.
* Max value indicates widest lumbar setting (i.e. least support)
* Min value indicates thinnest lumbar setting.
*/
- public static final int ID_SEAT_LUMBAR_SIDE_SUPPORT_POS = 0x2014;
+ public static final int ID_SEAT_LUMBAR_SIDE_SUPPORT_POS = 0x15400b93;
/** seat lumbar side support move, int type
* Adjusts the amount of lateral lumbar support.
* Positive value widens the lumbar area.
* Negative value makes the lumbar area thinner.
*/
- public static final int ID_SEAT_LUMBAR_SIDE_SUPPORT_MOVE = 0x2015;
+ public static final int ID_SEAT_LUMBAR_SIDE_SUPPORT_MOVE = 0x15400b94;
/**
* seat headrest height position, int type
* Sets the headrest height.
* Max value indicates tallest setting.
* Min value indicates shortest setting.
*/
- public static final int ID_SEAT_HEADREST_HEIGHT_POS = 0x2016;
+ public static final int ID_SEAT_HEADREST_HEIGHT_POS = 0x15400b95;
/** seat headrest height move, int type
* Postive value moves the headrest higher.
* Negative value moves the headrest lower.
*/
- public static final int ID_SEAT_HEADREST_HEIGHT_MOVE = 0x2017;
+ public static final int ID_SEAT_HEADREST_HEIGHT_MOVE = 0x15400b96;
/**
* seat headrest angle position, int type
* Sets the angle of the headrest.
* Max value indicates most upright angle.
* Min value indicates shallowest headrest angle.
*/
- public static final int ID_SEAT_HEADREST_ANGLE_POS = 0x2018;
+ public static final int ID_SEAT_HEADREST_ANGLE_POS = 0x15400b97;
/** seat headrest angle move, int type
* Adjusts the angle of the headrest.
* Positive value angles headrest towards most upright angle.
* Negative value angles headrest towards shallowest headrest angle.
*/
- public static final int ID_SEAT_HEADREST_ANGLE_MOVE = 0x2019;
+ public static final int ID_SEAT_HEADREST_ANGLE_MOVE = 0x15400b98;
/**
* seat headrest fore/aft position, int type
* Sets the headrest forwards and backwards.
* Max value indicates position closest to front of car.
* Min value indicates position closest to rear of car.
*/
- public static final int ID_SEAT_HEADREST_FORE_AFT_POS = 0x201A;
+ public static final int ID_SEAT_HEADREST_FORE_AFT_POS = 0x15400b99;
/** seat headrest fore/aft move, int type
* Adjsuts the headrest forwards and backwards.
* Positive value moves the headrest closer to front of car.
* Negative value moves the headrest closer to rear of car.
*/
- public static final int ID_SEAT_HEADREST_FORE_AFT_MOVE = 0x201B;
+ public static final int ID_SEAT_HEADREST_FORE_AFT_MOVE = 0x15400b9a;
- /** Window properties are zoned by VehicleWindow */
+ /** Window properties are zoned by VehicleAreaWindow */
/**
* window position, int type
- * Max = window up / closed.
- * Min = window down / open.
+ * Max = window down / open.
+ * Min = window up / closed.
*/
- public static final int ID_WINDOW_POS = 0x3001;
+ public static final int ID_WINDOW_POS = 0x13400bc0;
/** window move, int type
- * Positive value moves window up / closes window.
- * Negative value moves window down / opens window.
+ * Positive value moves window down / opens window.
+ * Negative value moves window up / closes window.
*/
- public static final int ID_WINDOW_MOVE = 0x3002;
- /**
- * window vent position, int type
- * This feature is used to control the vent feature on a sunroof.
- * Max = vent open.
- * Min = vent closed.
- */
- public static final int ID_WINDOW_VENT_POS = 0x3003;
- /** window vent move, int type
- * This feature is used to control the vent feature on a sunroof.
- * Positive value opens the vent.
- * Negative value closes the vent.
- */
- public static final int ID_WINDOW_VENT_MOVE = 0x3004;
+ public static final int ID_WINDOW_MOVE = 0x13400bc1;
/**
* window lock, bool type
* True indicates windows are locked and can't be moved.
*/
- public static final int ID_WINDOW_LOCK = 0x3005;
+ public static final int ID_WINDOW_LOCK = 0x13400bc4;
/** @hide */
@IntDef({
- ID_DOOR_POS,
- ID_DOOR_MOVE,
- ID_DOOR_LOCK,
- ID_MIRROR_Z_POS,
- ID_MIRROR_Z_MOVE,
- ID_MIRROR_Y_POS,
- ID_MIRROR_Y_MOVE,
- ID_MIRROR_LOCK,
- ID_MIRROR_FOLD,
- ID_SEAT_MEMORY_SELECT,
- ID_SEAT_MEMORY_SET,
- ID_SEAT_BELT_BUCKLED,
- ID_SEAT_BELT_HEIGHT_POS,
- ID_SEAT_BELT_HEIGHT_MOVE,
- ID_SEAT_FORE_AFT_POS,
- ID_SEAT_FORE_AFT_MOVE,
- ID_SEAT_BACKREST_ANGLE_1_POS,
- ID_SEAT_BACKREST_ANGLE_1_MOVE,
- ID_SEAT_BACKREST_ANGLE_2_POS,
- ID_SEAT_BACKREST_ANGLE_2_MOVE,
- ID_SEAT_HEIGHT_POS,
- ID_SEAT_HEIGHT_MOVE,
- ID_SEAT_DEPTH_POS,
- ID_SEAT_DEPTH_MOVE,
- ID_SEAT_TILT_POS,
- ID_SEAT_TILT_MOVE,
- ID_SEAT_LUMBAR_FORE_AFT_POS,
- ID_SEAT_LUMBAR_FORE_AFT_MOVE,
- ID_SEAT_LUMBAR_SIDE_SUPPORT_POS,
- ID_SEAT_LUMBAR_SIDE_SUPPORT_MOVE,
- ID_SEAT_HEADREST_HEIGHT_POS,
- ID_SEAT_HEADREST_HEIGHT_MOVE,
- ID_SEAT_HEADREST_ANGLE_POS,
- ID_SEAT_HEADREST_ANGLE_MOVE,
- ID_SEAT_HEADREST_FORE_AFT_POS,
- ID_SEAT_HEADREST_FORE_AFT_MOVE,
- ID_WINDOW_POS,
- ID_WINDOW_MOVE,
- ID_WINDOW_VENT_POS,
- ID_WINDOW_VENT_MOVE,
- ID_WINDOW_LOCK
+ ID_DOOR_POS,
+ ID_DOOR_MOVE,
+ ID_DOOR_LOCK,
+ ID_MIRROR_Z_POS,
+ ID_MIRROR_Z_MOVE,
+ ID_MIRROR_Y_POS,
+ ID_MIRROR_Y_MOVE,
+ ID_MIRROR_LOCK,
+ ID_MIRROR_FOLD,
+ ID_SEAT_MEMORY_SELECT,
+ ID_SEAT_MEMORY_SET,
+ ID_SEAT_BELT_BUCKLED,
+ ID_SEAT_BELT_HEIGHT_POS,
+ ID_SEAT_BELT_HEIGHT_MOVE,
+ ID_SEAT_FORE_AFT_POS,
+ ID_SEAT_FORE_AFT_MOVE,
+ ID_SEAT_BACKREST_ANGLE_1_POS,
+ ID_SEAT_BACKREST_ANGLE_1_MOVE,
+ ID_SEAT_BACKREST_ANGLE_2_POS,
+ ID_SEAT_BACKREST_ANGLE_2_MOVE,
+ ID_SEAT_HEIGHT_POS,
+ ID_SEAT_HEIGHT_MOVE,
+ ID_SEAT_DEPTH_POS,
+ ID_SEAT_DEPTH_MOVE,
+ ID_SEAT_TILT_POS,
+ ID_SEAT_TILT_MOVE,
+ ID_SEAT_LUMBAR_FORE_AFT_POS,
+ ID_SEAT_LUMBAR_FORE_AFT_MOVE,
+ ID_SEAT_LUMBAR_SIDE_SUPPORT_POS,
+ ID_SEAT_LUMBAR_SIDE_SUPPORT_MOVE,
+ ID_SEAT_HEADREST_HEIGHT_POS,
+ ID_SEAT_HEADREST_HEIGHT_MOVE,
+ ID_SEAT_HEADREST_ANGLE_POS,
+ ID_SEAT_HEADREST_ANGLE_MOVE,
+ ID_SEAT_HEADREST_FORE_AFT_POS,
+ ID_SEAT_HEADREST_FORE_AFT_MOVE,
+ ID_WINDOW_POS,
+ ID_WINDOW_MOVE,
+ ID_WINDOW_LOCK
})
@Retention(RetentionPolicy.SOURCE)
public @interface PropertyId {}
+ private final ArraySet<Integer> mCabinPropertyIds = new ArraySet<>(Arrays.asList(new Integer[]{
+ ID_DOOR_POS,
+ ID_DOOR_MOVE,
+ ID_DOOR_LOCK,
+ ID_MIRROR_Z_POS,
+ ID_MIRROR_Z_MOVE,
+ ID_MIRROR_Y_POS,
+ ID_MIRROR_Y_MOVE,
+ ID_MIRROR_LOCK,
+ ID_MIRROR_FOLD,
+ ID_SEAT_MEMORY_SELECT,
+ ID_SEAT_MEMORY_SET,
+ ID_SEAT_BELT_BUCKLED,
+ ID_SEAT_BELT_HEIGHT_POS,
+ ID_SEAT_BELT_HEIGHT_MOVE,
+ ID_SEAT_FORE_AFT_POS,
+ ID_SEAT_FORE_AFT_MOVE,
+ ID_SEAT_BACKREST_ANGLE_1_POS,
+ ID_SEAT_BACKREST_ANGLE_1_MOVE,
+ ID_SEAT_BACKREST_ANGLE_2_POS,
+ ID_SEAT_BACKREST_ANGLE_2_MOVE,
+ ID_SEAT_HEIGHT_POS,
+ ID_SEAT_HEIGHT_MOVE,
+ ID_SEAT_DEPTH_POS,
+ ID_SEAT_DEPTH_MOVE,
+ ID_SEAT_TILT_POS,
+ ID_SEAT_TILT_MOVE,
+ ID_SEAT_LUMBAR_FORE_AFT_POS,
+ ID_SEAT_LUMBAR_FORE_AFT_MOVE,
+ ID_SEAT_LUMBAR_SIDE_SUPPORT_POS,
+ ID_SEAT_LUMBAR_SIDE_SUPPORT_MOVE,
+ ID_SEAT_HEADREST_HEIGHT_POS,
+ ID_SEAT_HEADREST_HEIGHT_MOVE,
+ ID_SEAT_HEADREST_ANGLE_POS,
+ ID_SEAT_HEADREST_ANGLE_MOVE,
+ ID_SEAT_HEADREST_FORE_AFT_POS,
+ ID_SEAT_HEADREST_FORE_AFT_MOVE,
+ ID_WINDOW_POS,
+ ID_WINDOW_MOVE,
+ ID_WINDOW_LOCK
+ }));
/**
* Application registers CarCabinEventCallback object to receive updates and changes to
@@ -386,7 +411,8 @@
void onErrorEvent(@PropertyId int propertyId, int zone);
}
- private static class CarPropertyEventListenerToBase implements CarPropertyEventCallback {
+ private static class CarPropertyEventListenerToBase implements
+ CarPropertyManager.CarPropertyEventListener{
private final WeakReference<CarCabinManager> mManager;
public CarPropertyEventListenerToBase(CarCabinManager manager) {
@@ -442,7 +468,7 @@
* @hide
*/
public CarCabinManager(IBinder service, Context context, Handler handler) {
- mMgr = new CarPropertyManagerBase(service, handler, DBG, TAG);
+ mCarPropertyMgr = new CarPropertyManager(service, handler, DBG, TAG);
}
/**
@@ -463,9 +489,15 @@
CarNotConnectedException {
if (mCallbacks.isEmpty()) {
mListenerToBase = new CarPropertyEventListenerToBase(this);
- mMgr.registerCallback(mListenerToBase);
+ }
+ List<CarPropertyConfig> configs = getPropertyList();
+ for (CarPropertyConfig c : configs) {
+ // Register each individual propertyId
+ mCarPropertyMgr.registerListener(mListenerToBase, c.getPropertyId(), 0);
}
mCallbacks.add(callback);
+
+
}
/**
@@ -473,21 +505,26 @@
* this listener, all listening will be stopped.
* @param callback
*/
- public synchronized void unregisterCallback(CarCabinEventCallback callback) {
+ public synchronized void unregisterCallback(CarCabinEventCallback callback)
+ throws CarNotConnectedException {
mCallbacks.remove(callback);
+ List<CarPropertyConfig> configs = getPropertyList();
+ for (CarPropertyConfig c : configs) {
+ // Register each individual propertyId
+ mCarPropertyMgr.unregisterListener(mListenerToBase, c.getPropertyId());
+ }
if (mCallbacks.isEmpty()) {
- mMgr.unregisterCallback();
mListenerToBase = null;
}
}
/**
- * Get list of properties available to Car Cabin Manager
+ * Get list of properties represented by CarCabinManager for this car.
* @return List of CarPropertyConfig objects available via Car Cabin Manager.
* @throws CarNotConnectedException if the connection to the car service has been lost.
*/
public List<CarPropertyConfig> getPropertyList() throws CarNotConnectedException {
- return mMgr.getPropertyList();
+ return mCarPropertyMgr.getPropertyList(mCabinPropertyIds);
}
/**
@@ -499,7 +536,7 @@
*/
public boolean getBooleanProperty(@PropertyId int propertyId, int area)
throws CarNotConnectedException {
- return mMgr.getBooleanProperty(propertyId, area);
+ return mCarPropertyMgr.getBooleanProperty(propertyId, area);
}
/**
@@ -511,7 +548,7 @@
*/
public float getFloatProperty(@PropertyId int propertyId, int area)
throws CarNotConnectedException {
- return mMgr.getFloatProperty(propertyId, area);
+ return mCarPropertyMgr.getFloatProperty(propertyId, area);
}
/**
@@ -523,7 +560,7 @@
*/
public int getIntProperty(@PropertyId int propertyId, int area)
throws CarNotConnectedException {
- return mMgr.getIntProperty(propertyId, area);
+ return mCarPropertyMgr.getIntProperty(propertyId, area);
}
/**
@@ -535,7 +572,9 @@
*/
public void setBooleanProperty(@PropertyId int propertyId, int area, boolean val)
throws CarNotConnectedException {
- mMgr.setBooleanProperty(propertyId, area, val);
+ if (mCabinPropertyIds.contains(propertyId)) {
+ mCarPropertyMgr.setBooleanProperty(propertyId, area, val);
+ }
}
/**
@@ -547,7 +586,9 @@
*/
public void setFloatProperty(@PropertyId int propertyId, int area, float val)
throws CarNotConnectedException {
- mMgr.setFloatProperty(propertyId, area, val);
+ if (mCabinPropertyIds.contains(propertyId)) {
+ mCarPropertyMgr.setFloatProperty(propertyId, area, val);
+ }
}
/**
@@ -559,12 +600,14 @@
*/
public void setIntProperty(@PropertyId int propertyId, int area, int val)
throws CarNotConnectedException {
- mMgr.setIntProperty(propertyId, area, val);
+ if (mCabinPropertyIds.contains(propertyId)) {
+ mCarPropertyMgr.setIntProperty(propertyId, area, val);
+ }
}
/** @hide */
@Override
public void onCarDisconnected() {
- mMgr.onCarDisconnected();
+ mCarPropertyMgr.onCarDisconnected();
}
}
diff --git a/car-lib/src/android/car/hardware/hvac/CarHvacManager.java b/car-lib/src/android/car/hardware/hvac/CarHvacManager.java
index a2f6e6d..c953d6f 100644
--- a/car-lib/src/android/car/hardware/hvac/CarHvacManager.java
+++ b/car-lib/src/android/car/hardware/hvac/CarHvacManager.java
@@ -23,16 +23,17 @@
import android.car.CarNotConnectedException;
import android.car.hardware.CarPropertyConfig;
import android.car.hardware.CarPropertyValue;
-import android.car.hardware.property.CarPropertyManagerBase;
-import android.car.hardware.property.CarPropertyManagerBase.CarPropertyEventCallback;
+import android.car.hardware.property.CarPropertyManager;
import android.content.Context;
import android.os.Handler;
import android.os.IBinder;
import android.util.ArraySet;
+import android.util.Log;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.ref.WeakReference;
+import java.util.Arrays;
import java.util.Collection;
import java.util.List;
@@ -44,10 +45,11 @@
public final class CarHvacManager implements CarManagerBase {
private final static boolean DBG = false;
private final static String TAG = "CarHvacManager";
- private final CarPropertyManagerBase mMgr;
+ private final CarPropertyManager mCarPropertyMgr;
private final ArraySet<CarHvacEventCallback> mCallbacks = new ArraySet<>();
private CarPropertyEventListenerToBase mListenerToBase = null;
+
/**
* HVAC property IDs for get/set methods
*/
@@ -59,31 +61,24 @@
* Mirror defrosters state, bool type
* true indicates mirror defroster is on
*/
- public static final int ID_MIRROR_DEFROSTER_ON = 0x0001;
+ public static final int ID_MIRROR_DEFROSTER_ON = 0x1440050c;
/**
* Steering wheel temp, int type
* Positive values indicate heating.
* Negative values indicate cooling
*/
- public static final int ID_STEERING_WHEEL_TEMP = 0x0002;
+ public static final int ID_STEERING_WHEEL_HEAT = 0x1140050d;
/**
* Outside air temperature, float type
- * Value is in degrees of ID_TEMPERATURE_UNITS
+ * Value is in degrees Celsius
*/
- public static final int ID_OUTSIDE_AIR_TEMP = 0x0003;
+ public static final int ID_OUTSIDE_AIR_TEMP = 0x11600703;
/**
* Temperature units being used, int type
* 0x30 = Celsius
* 0x31 = Fahrenheit
*/
- public static final int ID_TEMPERATURE_UNITS = 0x0004;
-
-
- /**
- * The maximum id that can be assigned to global (non-zoned) property.
- * @hide
- */
- public static final int ID_MAX_GLOBAL_PROPERTY_ID = 0x3fff;
+ 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
@@ -91,99 +86,100 @@
*/
/**
* Temperature setpoint, float type
- * Temperature set by the user, units are determined by ID_TEMPERTURE_UNITS property.
+ * Temperature set by the user, units are in degrees Celsius.
*/
- public static final int ID_ZONED_TEMP_SETPOINT = 0x4001;
+ public static final int ID_ZONED_TEMP_SETPOINT = 0x15600503;
/**
* Actual temperature, float type
* Actual zone temperature is read only value, in terms of F or C.
*/
- public static final int ID_ZONED_TEMP_ACTUAL = 0x4002;
+ public static final int ID_ZONED_TEMP_ACTUAL = 0x15600502;
/**
* HVAC system powered on / off, bool type
* In many vehicles, if the HVAC system is powered off, the SET and GET command will
* throw an IllegalStateException. To correct this, need to turn on the HVAC module first
* before manipulating a parameter.
*/
- public static final int ID_ZONED_HVAC_POWER_ON = 0x4003;
+ public static final int ID_ZONED_HVAC_POWER_ON = 0x15200510;
/**
* Fan speed setpoint, int type
* Fan speed is an integer from 0-n, depending on number of fan speeds available.
*/
- public static final int ID_ZONED_FAN_SPEED_SETPOINT = 0x4004;
+ public static final int ID_ZONED_FAN_SPEED_SETPOINT = 0x15400500;
/**
* Actual fan speed, int type
* Actual fan speed is a read-only value, expressed in RPM.
*/
- public static final int ID_ZONED_FAN_SPEED_RPM = 0x4005;
- /** Fan position available, int type
- * Fan position is a bitmask of positions available for each zone.
- */
- public static final int ID_ZONED_FAN_POSITION_AVAILABLE = 0x4006;
+ public static final int ID_ZONED_FAN_SPEED_RPM = 0x1540050f;
/**
- * Current fan position setting, int type. The value must be one of the FAN_POSITION_*
- * constants declared in {@link CarHvacManager}.
+ * Fan direction available, int vector type
+ * Fan direction is a bitmask of directions available for each zone.
*/
- public static final int ID_ZONED_FAN_POSITION = 0x4007;
+ public static final int ID_ZONED_FAN_DIRECTION_AVAILABLE = 0x15410511;
+ /**
+ * Current fan direction setting, int type. The value must be one of the FAN_DIRECTION_AVAILABLE
+ * values declared above.
+ */
+ public static final int ID_ZONED_FAN_DIRECTION = 0x15400501;
/**
* Seat temperature, int type
* Seat temperature is negative for cooling, positive for heating. Temperature is a
* setting, i.e. -3 to 3 for 3 levels of cooling and 3 levels of heating.
*/
- public static final int ID_ZONED_SEAT_TEMP = 0x4008;
+ public static final int ID_ZONED_SEAT_TEMP = 0x1540050b;
/**
* Air ON, bool type
* true indicates AC is ON.
*/
- public static final int ID_ZONED_AC_ON = 0x4009;
+ public static final int ID_ZONED_AC_ON = 0x15200505;
/**
* Automatic Mode ON, bool type
* true indicates HVAC is in automatic mode
*/
- public static final int ID_ZONED_AUTOMATIC_MODE_ON = 0x400A;
+ public static final int ID_ZONED_AUTOMATIC_MODE_ON = 0x1520050A;
/**
* Air recirculation ON, bool type
* true indicates recirculation is active.
*/
- public static final int ID_ZONED_AIR_RECIRCULATION_ON = 0x400B;
+ public static final int ID_ZONED_AIR_RECIRCULATION_ON = 0x15200508;
/**
* Max AC ON, bool type
* true indicates MAX AC is ON
*/
- public static final int ID_ZONED_MAX_AC_ON = 0x400C;
+ public static final int ID_ZONED_MAX_AC_ON = 0x15200506;
/** Dual zone ON, bool type
* true indicates dual zone mode is ON
*/
- public static final int ID_ZONED_DUAL_ZONE_ON = 0x400D;
+ public static final int ID_ZONED_DUAL_ZONE_ON = 0x15200509;
/**
* Max Defrost ON, bool type
* true indicates max defrost is active.
*/
- public static final int ID_ZONED_MAX_DEFROST_ON = 0x400E;
+ public static final int ID_ZONED_MAX_DEFROST_ON = 0x15200507;
/**
* Automatic recirculation mode ON
* true indicates recirculation is in automatic mode
*/
- public static final int ID_ZONED_HVAC_AUTO_RECIRC_ON = 0x400F;
+ public static final int ID_ZONED_HVAC_AUTO_RECIRC_ON = 0x15200512;
/**
* Defroster ON, bool type
* Defroster controls are based on window position.
* True indicates the defroster is ON.
*/
- public static final int ID_WINDOW_DEFROSTER_ON = 0x5001;
+ public static final int ID_WINDOW_DEFROSTER_ON = 0x13200504;
/** @hide */
@IntDef({
ID_MIRROR_DEFROSTER_ON,
- ID_STEERING_WHEEL_TEMP,
+ ID_STEERING_WHEEL_HEAT,
ID_OUTSIDE_AIR_TEMP,
- ID_TEMPERATURE_UNITS,
+ ID_TEMPERATURE_DISPLAY_UNITS,
ID_ZONED_TEMP_SETPOINT,
ID_ZONED_TEMP_ACTUAL,
ID_ZONED_FAN_SPEED_SETPOINT,
ID_ZONED_FAN_SPEED_RPM,
- ID_ZONED_FAN_POSITION_AVAILABLE,
- ID_ZONED_FAN_POSITION,
+ ID_ZONED_FAN_DIRECTION_AVAILABLE,
+ ID_ZONED_FAN_DIRECTION,
ID_ZONED_SEAT_TEMP,
ID_ZONED_AC_ON,
ID_ZONED_AUTOMATIC_MODE_ON,
@@ -193,36 +189,49 @@
ID_ZONED_MAX_DEFROST_ON,
ID_ZONED_HVAC_POWER_ON,
ID_ZONED_HVAC_AUTO_RECIRC_ON,
- ID_WINDOW_DEFROSTER_ON,
+ ID_WINDOW_DEFROSTER_ON
})
@Retention(RetentionPolicy.SOURCE)
public @interface PropertyId {}
+ private final ArraySet<Integer> mHvacPropertyIds = new ArraySet<>(Arrays.asList(new Integer [] {
+ ID_MIRROR_DEFROSTER_ON,
+ ID_STEERING_WHEEL_HEAT,
+ ID_OUTSIDE_AIR_TEMP,
+ ID_TEMPERATURE_DISPLAY_UNITS,
+ ID_ZONED_TEMP_SETPOINT,
+ ID_ZONED_TEMP_ACTUAL,
+ ID_ZONED_FAN_SPEED_SETPOINT,
+ ID_ZONED_FAN_SPEED_RPM,
+ ID_ZONED_FAN_DIRECTION_AVAILABLE,
+ ID_ZONED_FAN_DIRECTION,
+ ID_ZONED_SEAT_TEMP,
+ ID_ZONED_AC_ON,
+ ID_ZONED_AUTOMATIC_MODE_ON,
+ ID_ZONED_AIR_RECIRCULATION_ON,
+ ID_ZONED_MAX_AC_ON,
+ ID_ZONED_DUAL_ZONE_ON,
+ ID_ZONED_MAX_DEFROST_ON,
+ ID_ZONED_HVAC_POWER_ON,
+ ID_ZONED_HVAC_AUTO_RECIRC_ON,
+ ID_WINDOW_DEFROSTER_ON
+ }));
+
/**
- * Represents fan position when air flows through face directed vents.
- * This constant must be used with {@link #ID_ZONED_FAN_POSITION} property.
+ * Represents fan direction when air flows through face directed vents.
+ * This constant must be used with {@link #ID_ZONED_FAN_DIRECTION} property.
*/
- public static final int FAN_POSITION_FACE = 1;
+ public static final int FAN_DIRECTION_FACE = 0x1;
/**
- * Represents fan position when air flows through floor directed vents.
- * This constant must be used with {@link #ID_ZONED_FAN_POSITION} property.
+ * Represents fan direction when air flows through floor directed vents.
+ * This constant must be used with {@link #ID_ZONED_FAN_DIRECTION} property.
*/
- public static final int FAN_POSITION_FLOOR = 2;
+ public static final int FAN_DIRECTION_FLOOR = 0x2;
/**
- * Represents fan position when air flows through face and floor directed vents.
- * This constant must be used with {@link #ID_ZONED_FAN_POSITION} property.
+ * Represents fan direction when air flows through defrost vents.
+ * This constant must be used with {@link #ID_ZONED_FAN_DIRECTION} property.
*/
- public static final int FAN_POSITION_FACE_AND_FLOOR = 3;
- /**
- * Represents fan position when air flows through defrost vents.
- * This constant must be used with {@link #ID_ZONED_FAN_POSITION} property.
- */
- public static final int FAN_POSITION_DEFROST = 4;
- /**
- * Represents fan position when air flows through defrost and floor directed vents.
- * This constant must be used with {@link #ID_ZONED_FAN_POSITION} property.
- */
- public static final int FAN_POSITION_DEFROST_AND_FLOOR = 5;
+ public static final int FAN_DIRECTION_DEFROST = 0x4;
/**
* Application registers {@link CarHvacEventCallback} object to receive updates and changes to
@@ -243,7 +252,8 @@
void onErrorEvent(@PropertyId int propertyId, int zone);
}
- private static class CarPropertyEventListenerToBase implements CarPropertyEventCallback {
+ private static class CarPropertyEventListenerToBase implements
+ CarPropertyManager.CarPropertyEventListener {
private final WeakReference<CarHvacManager> mManager;
public CarPropertyEventListenerToBase(CarHvacManager manager) {
@@ -301,28 +311,22 @@
* @hide
*/
public CarHvacManager(IBinder service, Context context, Handler handler) {
- mMgr = new CarPropertyManagerBase(service, handler, DBG, TAG);
+ mCarPropertyMgr = new CarPropertyManager(service, handler, DBG, TAG);
}
-
/**
- * Determine if a property is zoned or not.
- * @param propertyId
- * @return true if property is a zoned type.
- */
- public static boolean isZonedProperty(@PropertyId int propertyId) {
- return propertyId > ID_MAX_GLOBAL_PROPERTY_ID;
- }
-
- /**
- * Implement wrappers for contained CarPropertyManagerBase object
+ * Implement wrappers for contained CarPropertyManager object
* @param callback
* @throws CarNotConnectedException
*/
- public synchronized void registerCallback(CarHvacEventCallback callback) throws
- CarNotConnectedException {
+ public synchronized void registerCallback(CarHvacEventCallback callback)
+ throws CarNotConnectedException {
if (mCallbacks.isEmpty()) {
mListenerToBase = new CarPropertyEventListenerToBase(this);
- mMgr.registerCallback(mListenerToBase);
+ }
+ List<CarPropertyConfig> configs = getPropertyList();
+ for (CarPropertyConfig c : configs) {
+ // Register each individual propertyId
+ mCarPropertyMgr.registerListener(mListenerToBase, c.getPropertyId(), 0);
}
mCallbacks.add(callback);
}
@@ -334,19 +338,37 @@
*/
public synchronized void unregisterCallback(CarHvacEventCallback callback) {
mCallbacks.remove(callback);
+ try {
+ List<CarPropertyConfig> configs = getPropertyList();
+ for (CarPropertyConfig c : configs) {
+ // Register each individual propertyId
+ mCarPropertyMgr.unregisterListener(mListenerToBase, c.getPropertyId());
+ }
+ } catch (Exception e) {
+ Log.e(TAG, "getPropertyList exception ", e);
+ }
if (mCallbacks.isEmpty()) {
- mMgr.unregisterCallback();
+ mCarPropertyMgr.unregisterListener(mListenerToBase);
mListenerToBase = null;
}
}
/**
- * Get list of properties available to Car Hvac Manager
+ * Get list of properties represented by Car Hvac Manager for this car.
* @return List of CarPropertyConfig objects available via Car Hvac Manager.
* @throws CarNotConnectedException if the connection to the car service has been lost.
*/
public List<CarPropertyConfig> getPropertyList() throws CarNotConnectedException {
- return mMgr.getPropertyList();
+ return mCarPropertyMgr.getPropertyList(mHvacPropertyIds);
+ }
+
+ /**
+ * Check whether a given property is available or disabled based on the cars current state.
+ * @return true if the property is AVAILABLE, false otherwise
+ */
+ public boolean isPropertyAvailable(@PropertyId int propertyId, int area)
+ throws CarNotConnectedException {
+ return mCarPropertyMgr.isPropertyAvailable(propertyId, area);
}
/**
@@ -358,7 +380,7 @@
*/
public boolean getBooleanProperty(@PropertyId int propertyId, int area)
throws CarNotConnectedException {
- return mMgr.getBooleanProperty(propertyId, area);
+ return mCarPropertyMgr.getBooleanProperty(propertyId, area);
}
/**
@@ -370,7 +392,7 @@
*/
public float getFloatProperty(@PropertyId int propertyId, int area)
throws CarNotConnectedException {
- return mMgr.getFloatProperty(propertyId, area);
+ return mCarPropertyMgr.getFloatProperty(propertyId, area);
}
/**
@@ -382,7 +404,7 @@
*/
public int getIntProperty(@PropertyId int propertyId, int area)
throws CarNotConnectedException {
- return mMgr.getIntProperty(propertyId, area);
+ return mCarPropertyMgr.getIntProperty(propertyId, area);
}
/**
@@ -394,7 +416,9 @@
*/
public void setBooleanProperty(@PropertyId int propertyId, int area, boolean val)
throws CarNotConnectedException {
- mMgr.setBooleanProperty(propertyId, area, val);
+ if (mHvacPropertyIds.contains(propertyId)) {
+ mCarPropertyMgr.setBooleanProperty(propertyId, area, val);
+ }
}
/**
@@ -406,7 +430,9 @@
*/
public void setFloatProperty(@PropertyId int propertyId, int area, float val)
throws CarNotConnectedException {
- mMgr.setFloatProperty(propertyId, area, val);
+ if (mHvacPropertyIds.contains(propertyId)) {
+ mCarPropertyMgr.setFloatProperty(propertyId, area, val);
+ }
}
/**
@@ -418,12 +444,13 @@
*/
public void setIntProperty(@PropertyId int propertyId, int area, int val)
throws CarNotConnectedException {
- mMgr.setIntProperty(propertyId, area, val);
+ if (mHvacPropertyIds.contains(propertyId)) {
+ mCarPropertyMgr.setIntProperty(propertyId, area, val);
+ }
}
/** @hide */
- @Override
public void onCarDisconnected() {
- mMgr.onCarDisconnected();
+ mCarPropertyMgr.onCarDisconnected();
}
}
diff --git a/car-lib/src/android/car/hardware/power/CarPowerManager.java b/car-lib/src/android/car/hardware/power/CarPowerManager.java
new file mode 100644
index 0000000..38c5cd1
--- /dev/null
+++ b/car-lib/src/android/car/hardware/power/CarPowerManager.java
@@ -0,0 +1,286 @@
+/*
+ * 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.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;
+import android.car.CarNotConnectedException;
+import android.content.Context;
+import android.os.Handler;
+import android.os.IBinder;
+import android.os.Message;
+import android.os.RemoteException;
+import android.util.Log;
+
+/**
+ * API for receiving power state change notifications.
+ * @hide
+ */
+@SystemApi
+public class CarPowerManager implements CarManagerBase {
+ private final static boolean DBG = false;
+ private final static String TAG = "CarPowerManager";
+ private CarPowerStateListener mListener;
+ private final ICarPower mService;
+ private Executor mExecutor;
+
+ @GuardedBy("mLock")
+ private ICarPowerStateListener mListenerToService;
+
+ private final Object mLock = new Object();
+
+ /**
+ * Power boot up reasons, returned by {@link getBootReason}
+ */
+ /**
+ * User powered on the vehicle. These definitions must match the ones located in the native
+ * CarPowerManager: packages/services/Car/car-lib/native/CarPowerManager/CarPowerManager.h
+ *
+ */
+ public static final int BOOT_REASON_USER_POWER_ON = 1;
+ /**
+ * Door unlock caused device to boot
+ */
+ public static final int BOOT_REASON_DOOR_UNLOCK = 2;
+ /**
+ * Timer expired and vehicle woke up the AP
+ */
+ public static final int BOOT_REASON_TIMER = 3;
+ /**
+ * Door open caused device to boot
+ */
+ public static final int BOOT_REASON_DOOR_OPEN = 4;
+ /**
+ * User activated remote start
+ */
+ public static final int BOOT_REASON_REMOTE_START = 5;
+
+ /** @hide */
+ @IntDef({
+ BOOT_REASON_USER_POWER_ON,
+ BOOT_REASON_DOOR_UNLOCK,
+ BOOT_REASON_TIMER,
+ BOOT_REASON_DOOR_OPEN,
+ BOOT_REASON_REMOTE_START,
+ })
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface BootReason{}
+
+ /**
+ * Applications set a {@link CarPowerStateListener} for power state event updates.
+ */
+ public interface CarPowerStateListener {
+ /**
+ * 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;
+ /**
+ * Enter shutdown state. Application is expected to cleanup and be ready to shutdown.
+ */
+ public static final int SHUTDOWN_ENTER = 1;
+ /**
+ * Enter suspend state. Application is expected to cleanup and be ready to suspend.
+ */
+ public static final 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;
+
+ /**
+ * Called when power state changes
+ * @param state New power state of device.
+ * @param token Opaque identifier to keep track of listener events.
+ */
+ void onStateChanged(int state);
+ }
+
+ /**
+ * Get an instance of the CarPowerManager.
+ *
+ * Should not be obtained directly by clients, use {@link Car#getCarManager(String)} instead.
+ * @param service
+ * @param context
+ * @param handler
+ * @hide
+ */
+ public CarPowerManager(IBinder service, Context context, Handler handler) {
+ mService = ICarPower.Stub.asInterface(service);
+ }
+
+ /**
+ * Returns the current {@link BootReason}. This value does not change until the device goes
+ * through a suspend/resume cycle.
+ * @return int
+ * @throws CarNotConnectedException
+ * @hide
+ */
+ public int getBootReason() throws CarNotConnectedException {
+ try {
+ return mService.getBootReason();
+ } catch (RemoteException e) {
+ Log.e(TAG, "Exception in getBootReason", e);
+ throw new CarNotConnectedException(e);
+ }
+ }
+
+ /**
+ * Request power manager to shutdown in lieu of suspend at the next opportunity.
+ * @throws CarNotConnectedException
+ * @hide
+ */
+ public void requestShutdownOnNextSuspend() throws CarNotConnectedException {
+ try {
+ mService.requestShutdownOnNextSuspend();
+ } catch (RemoteException e) {
+ Log.e(TAG, "Exception in requestShutdownOnNextSuspend", 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.
+ *
+ * @param executor
+ * @param listener
+ * @throws CarNotConnectedException, IllegalStateException
+ * @hide
+ */
+ public void setListener(CarPowerStateListener listener, Executor executor) 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);
+ }
+ };
+ try {
+ mService.registerListener(listenerToService);
+ mListenerToService = listenerToService;
+ } catch (RemoteException ex) {
+ Log.e(TAG, "Could not connect: ", ex);
+ throw new CarNotConnectedException(ex);
+ } catch (IllegalStateException ex) {
+ Car.checkCarNotConnectedExceptionFromCarService(ex);
+ }
+ }
+ if ((mExecutor == null) && (mListener == null)) {
+ // Update listener and executor
+ mExecutor = executor;
+ mListener = listener;
+ } else {
+ throw new IllegalStateException("Listener must be cleared first");
+ }
+ }
+ }
+
+ /**
+ * Removes the listener from {@link CarPowerManagementService}
+ * @hide
+ */
+ public void clearListener() {
+ ICarPowerStateListener listenerToService;
+ synchronized (mLock) {
+ listenerToService = mListenerToService;
+ mListenerToService = null;
+ mListener = null;
+ mExecutor = null;
+ }
+
+ if (listenerToService == null) {
+ Log.w(TAG, "unregisterListener: listener was not registered");
+ return;
+ }
+
+ try {
+ mService.unregisterListener(listenerToService);
+ } catch (RemoteException ex) {
+ Log.e(TAG, "Failed to unregister listener", ex);
+ //ignore
+ } catch (IllegalStateException ex) {
+ Car.hideCarNotConnectedExceptionFromCarService(ex);
+ }
+ }
+
+ private void handleEvent(int state, int token) {
+ Executor executor;
+ synchronized (mLock) {
+ executor = mExecutor;
+ }
+ if (executor != null) {
+ executor.execute(() -> {
+ handleEventInternal(state, token);
+ });
+ } 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);
+ }
+ }
+ }
+
+ /** @hide */
+ @Override
+ public void onCarDisconnected() {
+ ICarPowerStateListener listenerToService;
+ synchronized (mLock) {
+ listenerToService = mListenerToService;
+ }
+
+ if (listenerToService != null) {
+ clearListener();
+ }
+ }
+}
diff --git a/car-lib/src/android/car/hardware/power/ICarPower.aidl b/car-lib/src/android/car/hardware/power/ICarPower.aidl
new file mode 100644
index 0000000..851ed0c
--- /dev/null
+++ b/car-lib/src/android/car/hardware/power/ICarPower.aidl
@@ -0,0 +1,32 @@
+/*
+ * 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.hardware.power;
+
+import android.car.hardware.power.ICarPowerStateListener;
+
+/** @hide */
+interface ICarPower {
+ void registerListener(in ICarPowerStateListener listener) = 0;
+
+ void unregisterListener(in ICarPowerStateListener listener) = 1;
+
+ void requestShutdownOnNextSuspend() = 2;
+
+ int getBootReason() = 3;
+
+ void finished(in ICarPowerStateListener listener, int token) = 4;
+}
diff --git a/libvehiclemonitor/java/src/com/android/car/vehiclemonitor/IVehicleMonitorListener.aidl b/car-lib/src/android/car/hardware/power/ICarPowerStateListener.aidl
similarity index 66%
rename from libvehiclemonitor/java/src/com/android/car/vehiclemonitor/IVehicleMonitorListener.aidl
rename to car-lib/src/android/car/hardware/power/ICarPowerStateListener.aidl
index ca0ac83..a738b98 100644
--- a/libvehiclemonitor/java/src/com/android/car/vehiclemonitor/IVehicleMonitorListener.aidl
+++ b/car-lib/src/android/car/hardware/power/ICarPowerStateListener.aidl
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2016 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,12 +14,16 @@
* limitations under the License.
*/
-package com.android.car.vehiclemonitor;
+package android.car.hardware.power;
/**
- * Listener for vehicle monitor service.
+ * Binder callback for CarPowerStateListener.
* @hide
*/
-oneway interface IVehicleMonitorListener {
- void onAppViolation(int pid, int uid, int action, int violation) = 0;
+oneway interface ICarPowerStateListener {
+ /**
+ * Called when a power state change occurs
+ */
+ void onStateChanged(int state, int token) = 0;
}
+
diff --git a/car-lib/src/android/car/hardware/property/CarPropertyManager.java b/car-lib/src/android/car/hardware/property/CarPropertyManager.java
new file mode 100644
index 0000000..5c094e7
--- /dev/null
+++ b/car-lib/src/android/car/hardware/property/CarPropertyManager.java
@@ -0,0 +1,420 @@
+/*
+ * 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.hardware.property;
+
+import static java.lang.Integer.toHexString;
+
+import android.car.CarApiUtil;
+import android.car.CarManagerBase;
+import android.car.CarNotConnectedException;
+import android.car.hardware.CarPropertyConfig;
+import android.car.hardware.CarPropertyValue;
+import android.os.Handler;
+import android.os.IBinder;
+import android.os.RemoteException;
+import android.util.ArraySet;
+import android.util.Log;
+import android.util.SparseArray;
+
+import com.android.car.internal.CarRatedFloatListeners;
+import com.android.car.internal.SingleMessageHandler;
+
+import java.lang.ref.WeakReference;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.function.Consumer;
+
+
+/**
+ * API for creating Car*Manager
+ * @hide
+ */
+public class CarPropertyManager implements CarManagerBase {
+ private final boolean mDbg;
+ private final SingleMessageHandler<CarPropertyEvent> mHandler;
+ private final ICarProperty mService;
+ private final String mTag;
+ private static final int MSG_GENERIC_EVENT = 0;
+
+ private CarPropertyEventListenerToService mCarPropertyEventToService;
+
+
+ /** Record of locally active properties. Key is propertyId */
+ private final SparseArray<CarPropertyListeners> mActivePropertyListener =
+ new SparseArray<>();
+
+ /** Callback functions for property events */
+ public interface CarPropertyEventListener {
+ /** Called when a property is updated */
+ void onChangeEvent(CarPropertyValue value);
+
+ /** Called when an error is detected with a property */
+ void onErrorEvent(int propId, int zone);
+ }
+
+ /**
+ * Get an instance of the CarPropertyManager.
+ */
+ public CarPropertyManager(IBinder service, Handler handler, boolean dbg, String tag) {
+ mDbg = dbg;
+ mTag = tag;
+ mService = ICarProperty.Stub.asInterface(service);
+ mHandler = new SingleMessageHandler<CarPropertyEvent>(handler.getLooper(),
+ MSG_GENERIC_EVENT) {
+ @Override
+ protected void handleEvent(CarPropertyEvent event) {
+ CarPropertyListeners listeners;
+ synchronized (mActivePropertyListener) {
+ listeners = mActivePropertyListener.get(
+ event.getCarPropertyValue().getPropertyId());
+ }
+ if (listeners != null) {
+ switch (event.getEventType()) {
+ case CarPropertyEvent.PROPERTY_EVENT_PROPERTY_CHANGE:
+ listeners.onPropertyChanged(event);
+ break;
+ case CarPropertyEvent.PROPERTY_EVENT_ERROR:
+ listeners.onErrorEvent(event);
+ break;
+ default:
+ throw new IllegalArgumentException();
+ }
+ }
+ }
+ };
+ }
+
+ /** Use to register or update Callback for properties */
+ public boolean registerListener(CarPropertyEventListener listener, int propertyId, float rate)
+ throws CarNotConnectedException {
+ synchronized (mActivePropertyListener) {
+ if (mCarPropertyEventToService == null) {
+ mCarPropertyEventToService = new CarPropertyEventListenerToService(this);
+ }
+ boolean needsServerUpdate = false;
+ CarPropertyListeners listeners;
+ listeners = mActivePropertyListener.get(propertyId);
+ if (listeners == null) {
+ listeners = new CarPropertyListeners(rate);
+ mActivePropertyListener.put(propertyId, listeners);
+ needsServerUpdate = true;
+ }
+ if (listeners.addAndUpdateRate(listener, rate)) {
+ needsServerUpdate = true;
+ }
+ if (needsServerUpdate) {
+ if (!registerOrUpdatePropertyListener(propertyId, rate)) {
+ return false;
+ }
+ }
+ }
+ return true;
+ }
+
+ private boolean registerOrUpdatePropertyListener(int propertyId, float rate)
+ throws CarNotConnectedException {
+ try {
+ mService.registerListener(propertyId, rate, mCarPropertyEventToService);
+ } catch (IllegalStateException e) {
+ CarApiUtil.checkCarNotConnectedExceptionFromCarService(e);
+ } catch (RemoteException e) {
+ throw new CarNotConnectedException(e);
+ }
+ return true;
+ }
+
+ private class CarPropertyEventListenerToService extends ICarPropertyEventListener.Stub{
+ private final WeakReference<CarPropertyManager> mMgr;
+
+ CarPropertyEventListenerToService(CarPropertyManager mgr) {
+ mMgr = new WeakReference<>(mgr);
+ }
+
+ @Override
+ public void onEvent(List<CarPropertyEvent> events) throws RemoteException {
+ CarPropertyManager manager = mMgr.get();
+ if (manager != null) {
+ manager.handleEvent(events);
+ }
+ }
+ }
+
+ private void handleEvent(List<CarPropertyEvent> events) {
+ mHandler.sendEvents(events);
+ }
+
+ /**
+ * Stop getting sensor update for the given listener. If there are multiple registrations for
+ * this listener, all listening will be stopped.
+ * @param listener
+ */
+ public void unregisterListener(CarPropertyEventListener listener) {
+ synchronized (mActivePropertyListener) {
+ for (int i = 0; i < mActivePropertyListener.size(); i++) {
+ doUnregisterListenerLocked(listener, mActivePropertyListener.keyAt(i));
+ }
+ }
+ }
+
+ /**
+ * Stop getting sensor update for the given listener and sensor. If the same listener is used
+ * for other sensors, those subscriptions will not be affected.
+ * @param listener
+ * @param propertyId
+ */
+ public void unregisterListener(CarPropertyEventListener listener, int propertyId) {
+ synchronized (mActivePropertyListener) {
+ doUnregisterListenerLocked(listener, propertyId);
+ }
+ }
+
+ private void doUnregisterListenerLocked(CarPropertyEventListener listener, int propertyId) {
+ CarPropertyListeners listeners = mActivePropertyListener.get(propertyId);
+ if (listeners != null) {
+ boolean needsServerUpdate = false;
+ if (listeners.contains(listener)) {
+ needsServerUpdate = listeners.remove(listener);
+ }
+ if (listeners.isEmpty()) {
+ try {
+ mService.unregisterListener(propertyId, mCarPropertyEventToService);
+ } catch (RemoteException e) {
+ //ignore
+ }
+ mActivePropertyListener.remove(propertyId);
+ } else if (needsServerUpdate) {
+ try {
+ registerOrUpdatePropertyListener(propertyId, listeners.getRate());
+ } catch (CarNotConnectedException e) {
+ // ignore
+ }
+ }
+ }
+ }
+
+ /**
+ * Returns the list of properties implemented by this car.
+ *
+ * @return Caller must check the property type and typecast to the appropriate subclass
+ * (CarPropertyBooleanProperty, CarPropertyFloatProperty, CarrPropertyIntProperty)
+ */
+ public List<CarPropertyConfig> getPropertyList() throws CarNotConnectedException {
+ try {
+ return mService.getPropertyList();
+ } catch (RemoteException e) {
+ Log.e(mTag, "getPropertyList exception ", e);
+ throw new CarNotConnectedException(e);
+ }
+ }
+
+ /**
+ * Returns the list of properties implemented by this car in given property id list.
+ *
+ * @return Caller must check the property type and typecast to the appropriate subclass
+ * (CarPropertyBooleanProperty, CarPropertyFloatProperty, CarrPropertyIntProperty)
+ */
+ public List<CarPropertyConfig> getPropertyList(ArraySet<Integer> propertyIds)
+ throws CarNotConnectedException {
+ try {
+ List<CarPropertyConfig> configs = new ArrayList<>();
+ for (CarPropertyConfig c : mService.getPropertyList()) {
+ if (propertyIds.contains(c.getPropertyId())) {
+ configs.add(c);
+ }
+ }
+ return configs;
+ } catch (RemoteException e) {
+ Log.e(mTag, "getPropertyList exception ", e);
+ throw new CarNotConnectedException(e);
+ }
+
+ }
+
+ /**
+ * Check whether a given property is available or disabled based on the car's current state.
+ * @return true if STATUS_AVAILABLE, false otherwise (eg STATUS_UNAVAILABLE)
+ * @throws CarNotConnectedException
+ */
+ public boolean isPropertyAvailable(int propId, int area) throws CarNotConnectedException {
+ try {
+ CarPropertyValue propValue = mService.getProperty(propId, area);
+ return (propValue != null)
+ && (propValue.getStatus() == CarPropertyValue.STATUS_AVAILABLE);
+ } catch (RemoteException e) {
+ Log.e(mTag, "isPropertyAvailable failed with " + e.toString()
+ + ", propId: 0x" + toHexString(propId) + ", area: 0x" + toHexString(area), e);
+ throw new CarNotConnectedException(e);
+ }
+ }
+
+ /**
+ * Returns value of a bool property
+ *
+ * @param prop Property ID to get
+ * @param area Area of the property to get
+ */
+ public boolean getBooleanProperty(int prop, int area) throws CarNotConnectedException {
+ CarPropertyValue<Boolean> carProp = getProperty(Boolean.class, prop, area);
+ return carProp != null ? carProp.getValue() : false;
+ }
+
+ /**
+ * Returns value of a float property
+ *
+ * @param prop Property ID to get
+ * @param area Area of the property to get
+ */
+ public float getFloatProperty(int prop, int area) throws CarNotConnectedException {
+ CarPropertyValue<Float> carProp = getProperty(Float.class, prop, area);
+ return carProp != null ? carProp.getValue() : 0f;
+ }
+
+ /**
+ * Returns value of a integer property
+ *
+ * @param prop Property ID to get
+ * @param area Zone of the property to get
+ */
+ public int getIntProperty(int prop, int area) throws CarNotConnectedException {
+ CarPropertyValue<Integer> carProp = getProperty(Integer.class, prop, area);
+ return carProp != null ? carProp.getValue() : 0;
+ }
+
+ /** Return CarPropertyValue */
+ @SuppressWarnings("unchecked")
+ public <E> CarPropertyValue<E> getProperty(Class<E> clazz, int propId, int area)
+ throws CarNotConnectedException {
+ if (mDbg) {
+ Log.d(mTag, "getProperty, propId: 0x" + toHexString(propId)
+ + ", area: 0x" + toHexString(area) + ", class: " + clazz);
+ }
+ try {
+ CarPropertyValue<E> propVal = mService.getProperty(propId, area);
+ if (propVal != null && propVal.getValue() != null) {
+ Class<?> actualClass = propVal.getValue().getClass();
+ if (actualClass != clazz) {
+ throw new IllegalArgumentException("Invalid property type. " + "Expected: "
+ + clazz + ", but was: " + actualClass);
+ }
+ }
+ return propVal;
+ } catch (RemoteException e) {
+ Log.e(mTag, "getProperty failed with " + e.toString()
+ + ", propId: 0x" + toHexString(propId) + ", area: 0x" + toHexString(area), e);
+ throw new CarNotConnectedException(e);
+ }
+ }
+
+ /** Return raw CarPropertyValue */
+ public <E> CarPropertyValue<E> getProperty(int propId, int area)
+ throws CarNotConnectedException {
+ try {
+ CarPropertyValue<E> propVal = mService.getProperty(propId, area);
+ return propVal;
+ } catch (RemoteException e) {
+ Log.e(mTag, "getProperty failed with " + e.toString()
+ + ", propId: 0x" + toHexString(propId) + ", area: 0x" + toHexString(area), e);
+ throw new CarNotConnectedException(e);
+ }
+ }
+
+ /** Set CarPropertyValue */
+ public <E> void setProperty(Class<E> clazz, int propId, int area, E val)
+ throws CarNotConnectedException {
+ if (mDbg) {
+ Log.d(mTag, "setProperty, propId: 0x" + toHexString(propId)
+ + ", area: 0x" + toHexString(area) + ", class: " + clazz + ", val: " + val);
+ }
+ try {
+ mService.setProperty(new CarPropertyValue<>(propId, area, val));
+ } catch (RemoteException e) {
+ Log.e(mTag, "setProperty failed with " + e.toString(), e);
+ throw new CarNotConnectedException(e);
+ }
+ }
+
+ /**
+ * Modifies a property. If the property modification doesn't occur, an error event shall be
+ * generated and propagated back to the application.
+ *
+ * @param prop Property ID to modify
+ * @param area Area to apply the modification.
+ * @param val Value to set
+ */
+ public void setBooleanProperty(int prop, int area, boolean val)
+ throws CarNotConnectedException {
+ setProperty(Boolean.class, prop, area, val);
+ }
+
+ /** Set float value of property*/
+ public void setFloatProperty(int prop, int area, float val) throws CarNotConnectedException {
+ setProperty(Float.class, prop, area, val);
+ }
+ /** Set int value of property*/
+ public void setIntProperty(int prop, int area, int val) throws CarNotConnectedException {
+ setProperty(Integer.class, prop, area, val);
+ }
+
+
+ private class CarPropertyListeners extends CarRatedFloatListeners<CarPropertyEventListener> {
+ CarPropertyListeners(float rate) {
+ super(rate);
+ }
+ void onPropertyChanged(final CarPropertyEvent event) {
+ // throw away old sensor data as oneway binder call can change order.
+ long updateTime = event.getCarPropertyValue().getTimestamp();
+ if (updateTime < mLastUpdateTime) {
+ Log.w(mTag, "dropping old property data");
+ return;
+ }
+ mLastUpdateTime = updateTime;
+ List<CarPropertyEventListener> listeners;
+ synchronized (mActivePropertyListener) {
+ listeners = new ArrayList<>(getListeners());
+ }
+ listeners.forEach(new Consumer<CarPropertyEventListener>() {
+ @Override
+ public void accept(CarPropertyEventListener listener) {
+ listener.onChangeEvent(event.getCarPropertyValue());
+ }
+ });
+ }
+
+ void onErrorEvent(final CarPropertyEvent event) {
+ List<CarPropertyEventListener> listeners;
+ CarPropertyValue value = event.getCarPropertyValue();
+ synchronized (mActivePropertyListener) {
+ listeners = new ArrayList<>(getListeners());
+ }
+ listeners.forEach(new Consumer<CarPropertyEventListener>() {
+ @Override
+ public void accept(CarPropertyEventListener listener) {
+ listener.onErrorEvent(value.getPropertyId(), value.getAreaId());
+ }
+ });
+ }
+ }
+
+ /** @hide */
+ @Override
+ public void onCarDisconnected() {
+ synchronized (mActivePropertyListener) {
+ mActivePropertyListener.clear();
+ mCarPropertyEventToService = null;
+ }
+ }
+}
diff --git a/car-lib/src/android/car/hardware/property/CarPropertyManagerBase.java b/car-lib/src/android/car/hardware/property/CarPropertyManagerBase.java
deleted file mode 100644
index c666bc2..0000000
--- a/car-lib/src/android/car/hardware/property/CarPropertyManagerBase.java
+++ /dev/null
@@ -1,299 +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.hardware.property;
-
-import static java.lang.Integer.toHexString;
-
-import android.annotation.Nullable;
-import android.car.Car;
-import android.car.CarNotConnectedException;
-import android.car.hardware.CarPropertyConfig;
-import android.car.hardware.CarPropertyValue;
-import android.os.Handler;
-import android.os.IBinder;
-import android.os.Looper;
-import android.os.Message;
-import android.os.RemoteException;
-import android.util.Log;
-
-import com.android.internal.annotations.GuardedBy;
-
-import java.lang.ref.WeakReference;
-import java.util.List;
-
-/**
- * API for creating Car*Manager
- * @hide
- */
-public class CarPropertyManagerBase {
- private final boolean mDbg;
- private final Handler mHandler;
- private final ICarProperty mService;
- private final String mTag;
-
- @GuardedBy("mLock")
- private ICarPropertyEventListener mListenerToService;
- @GuardedBy("mLock")
- private CarPropertyEventCallback mCallback;
-
- private final Object mLock = new Object();
-
- /** Callback functions for property events */
- public interface CarPropertyEventCallback {
- /** Called when a property is updated */
- void onChangeEvent(CarPropertyValue value);
-
- /** Called when an error is detected with a property */
- void onErrorEvent(int propertyId, int zone);
- }
-
- private final static class EventCallbackHandler extends Handler {
- /** Constants handled in the handler */
- private static final int MSG_GENERIC_EVENT = 0;
-
- private final WeakReference<CarPropertyManagerBase> mMgr;
-
- EventCallbackHandler(CarPropertyManagerBase mgr, Looper looper) {
- super(looper);
- mMgr = new WeakReference<>(mgr);
- }
-
- @Override
- public void handleMessage(Message msg) {
- switch (msg.what) {
- case MSG_GENERIC_EVENT:
- CarPropertyManagerBase mgr = mMgr.get();
- if (mgr != null) {
- mgr.dispatchEventToClient((CarPropertyEvent) msg.obj);
- }
- break;
- default:
- Log.e("EventtCallbackHandler", "Event type not handled: " + msg);
- break;
- }
- }
- }
-
- /**
- * Get an instance of the CarPropertyManagerBase.
- */
- public CarPropertyManagerBase(IBinder service, Handler handler, boolean dbg,
- String tag) {
- mDbg = dbg;
- mTag = tag;
- mService = ICarProperty.Stub.asInterface(service);
- mHandler = new EventCallbackHandler(this, handler.getLooper());
- }
-
- public void registerCallback(CarPropertyEventCallback callback)
- throws CarNotConnectedException {
- synchronized (mLock) {
- if (mCallback != null) {
- throw new IllegalStateException("Callback is already registered.");
- }
-
- mCallback = callback;
- mListenerToService = new ICarPropertyEventListener.Stub() {
- @Override
- public void onEvent(CarPropertyEvent event) throws RemoteException {
- handleEvent(event);
- }
- };
- }
-
- try {
- mService.registerListener(mListenerToService);
- } catch (RemoteException ex) {
- Log.e(mTag, "Could not connect: ", ex);
- throw new CarNotConnectedException(ex);
- } catch (IllegalStateException ex) {
- Car.checkCarNotConnectedExceptionFromCarService(ex);
- }
- }
-
- public void unregisterCallback() {
- ICarPropertyEventListener listenerToService;
- synchronized (mLock) {
- listenerToService = mListenerToService;
- mCallback = null;
- mListenerToService = null;
- }
-
- if (listenerToService == null) {
- Log.w(mTag, "unregisterListener: listener was not registered");
- return;
- }
-
- try {
- mService.unregisterListener(listenerToService);
- } catch (RemoteException ex) {
- Log.e(mTag, "Failed to unregister listener", ex);
- //ignore
- } catch (IllegalStateException ex) {
- Car.hideCarNotConnectedExceptionFromCarService(ex);
- }
- }
-
- /**
- * Returns the list of properties available.
- *
- * @return Caller must check the property type and typecast to the appropriate subclass
- * (CarPropertyBooleanProperty, CarPropertyFloatProperty, CarrPropertyIntProperty)
- */
- public List<CarPropertyConfig> getPropertyList() throws CarNotConnectedException {
- try {
- return mService.getPropertyList();
- } catch (RemoteException e) {
- Log.e(mTag, "Exception in getPropertyList", e);
- throw new CarNotConnectedException(e);
- }
- }
-
- /**
- * Returns value of a bool property
- *
- * @param prop Property ID to get
- * @param area Area of the property to get
- */
- public boolean getBooleanProperty(int prop, int area) throws CarNotConnectedException {
- CarPropertyValue<Boolean> carProp = getProperty(Boolean.class, prop, area);
- return carProp != null ? carProp.getValue() : false;
- }
-
- /**
- * Returns value of a float property
- *
- * @param prop Property ID to get
- * @param area Area of the property to get
- */
- public float getFloatProperty(int prop, int area) throws CarNotConnectedException {
- CarPropertyValue<Float> carProp = getProperty(Float.class, prop, area);
- return carProp != null ? carProp.getValue() : 0f;
- }
-
- /**
- * Returns value of a integer property
- *
- * @param prop Property ID to get
- * @param area Zone of the property to get
- */
- public int getIntProperty(int prop, int area) throws CarNotConnectedException {
- CarPropertyValue<Integer> carProp = getProperty(Integer.class, prop, area);
- return carProp != null ? carProp.getValue() : 0;
- }
-
- @Nullable
- @SuppressWarnings("unchecked")
- public <E> CarPropertyValue<E> getProperty(Class<E> clazz, int propId, int area)
- throws CarNotConnectedException {
- if (mDbg) {
- Log.d(mTag, "getProperty, propId: 0x" + toHexString(propId)
- + ", area: 0x" + toHexString(area) + ", class: " + clazz);
- }
- try {
- CarPropertyValue<E> propVal = mService.getProperty(propId, area);
- if (propVal != null && propVal.getValue() != null) {
- Class<?> actualClass = propVal.getValue().getClass();
- if (actualClass != clazz) {
- throw new IllegalArgumentException("Invalid property type. " + "Expected: "
- + clazz + ", but was: " + actualClass);
- }
- }
- return propVal;
- } catch (RemoteException e) {
- Log.e(mTag, "getProperty failed with " + e.toString()
- + ", propId: 0x" + toHexString(propId) + ", area: 0x" + toHexString(area), e);
- throw new CarNotConnectedException(e);
- }
- }
-
- public <E> void setProperty(Class<E> clazz, int propId, int area, E val)
- throws CarNotConnectedException {
- if (mDbg) {
- Log.d(mTag, "setProperty, propId: 0x" + toHexString(propId)
- + ", area: 0x" + toHexString(area) + ", class: " + clazz + ", val: " + val);
- }
- try {
- mService.setProperty(new CarPropertyValue<>(propId, area, val));
- } catch (RemoteException e) {
- Log.e(mTag, "setProperty failed with " + e.toString(), e);
- throw new CarNotConnectedException(e);
- }
- }
-
- /**
- * Modifies a property. If the property modification doesn't occur, an error event shall be
- * generated and propagated back to the application.
- *
- * @param prop Property ID to modify
- * @param area Area to apply the modification.
- * @param val Value to set
- */
- public void setBooleanProperty(int prop, int area, boolean val)
- throws CarNotConnectedException {
- setProperty(Boolean.class, prop, area, val);
- }
-
- public void setFloatProperty(int prop, int area, float val) throws CarNotConnectedException {
- setProperty(Float.class, prop, area, val);
- }
-
- public void setIntProperty(int prop, int area, int val) throws CarNotConnectedException {
- setProperty(Integer.class, prop, area, val);
- }
-
- private void dispatchEventToClient(CarPropertyEvent event) {
- CarPropertyEventCallback listener;
- synchronized (mLock) {
- listener = mCallback;
- }
-
- if (listener == null) {
- Log.e(mTag, "Listener died, not dispatching event.");
- return;
- }
-
- CarPropertyValue propVal = event.getCarPropertyValue();
- switch(event.getEventType()) {
- case CarPropertyEvent.PROPERTY_EVENT_PROPERTY_CHANGE:
- listener.onChangeEvent(propVal);
- break;
- case CarPropertyEvent.PROPERTY_EVENT_ERROR:
- listener.onErrorEvent(propVal.getPropertyId(), propVal.getAreaId());
- break;
- default:
- throw new IllegalArgumentException();
- }
- }
-
- private void handleEvent(CarPropertyEvent event) {
- mHandler.sendMessage(mHandler.obtainMessage(EventCallbackHandler.MSG_GENERIC_EVENT, event));
- }
-
- /** @hide */
- public void onCarDisconnected() {
-
- ICarPropertyEventListener listenerToService;
- synchronized (mLock) {
- listenerToService = mListenerToService;
- }
-
- if (listenerToService != null) {
- unregisterCallback();
- }
- }
-}
diff --git a/car-lib/src/android/car/hardware/property/ICarProperty.aidl b/car-lib/src/android/car/hardware/property/ICarProperty.aidl
index 2121ebb..3e7e5c9 100644
--- a/car-lib/src/android/car/hardware/property/ICarProperty.aidl
+++ b/car-lib/src/android/car/hardware/property/ICarProperty.aidl
@@ -25,9 +25,9 @@
*/
interface ICarProperty {
- void registerListener(in ICarPropertyEventListener callback) = 0;
+ void registerListener(int propId, float rate, in ICarPropertyEventListener callback) = 0;
- void unregisterListener(in ICarPropertyEventListener callback) = 1;
+ void unregisterListener(int propId, in ICarPropertyEventListener callback) = 1;
List<CarPropertyConfig> getPropertyList() = 2;
diff --git a/car-lib/src/android/car/hardware/property/ICarPropertyEventListener.aidl b/car-lib/src/android/car/hardware/property/ICarPropertyEventListener.aidl
index b0d57fc..ebda47c 100644
--- a/car-lib/src/android/car/hardware/property/ICarPropertyEventListener.aidl
+++ b/car-lib/src/android/car/hardware/property/ICarPropertyEventListener.aidl
@@ -28,6 +28,6 @@
* Called when an event is triggered in response to one of the calls (such as on tune) or
* asynchronously (such as on announcement).
*/
- void onEvent(in CarPropertyEvent event) = 0;
+ void onEvent(in List<CarPropertyEvent> events) = 0;
}
diff --git a/car-lib/src/android/car/hardware/radio/CarRadioEvent.java b/car-lib/src/android/car/hardware/radio/CarRadioEvent.java
deleted file mode 100644
index 332cb56..0000000
--- a/car-lib/src/android/car/hardware/radio/CarRadioEvent.java
+++ /dev/null
@@ -1,95 +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 android.car.hardware.radio;
-
-import android.annotation.SystemApi;
-import android.os.Parcel;
-import android.os.Parcelable;
-
-/**
- * A CarRadioEvent object corresponds to a single radio event coming from the car.
- *
- * This works in conjunction with the callbacks already defined in {@link RadioCallback.Callback}.
- * @hide
- */
-@SystemApi
-public class CarRadioEvent implements Parcelable {
- /**
- * Event specifying that a radio preset has been changed.
- */
- public static final int RADIO_PRESET = 0;
-
- /**
- * Event type.
- */
- private final int mType;
-
- /**
- * CarRadioPreset for the event type EVENT_RADIO_PRESET.
- */
- private final CarRadioPreset mPreset;
-
- // Getters.
- public CarRadioPreset getPreset() {
- return mPreset;
- }
-
- public int getEventType() {
- return mType;
- }
-
- @Override
- public int describeContents() {
- return 0;
- }
-
- @Override
- public void writeToParcel(Parcel dest, int flags) {
- dest.writeInt(mType);
- dest.writeParcelable(mPreset, 0);
- }
-
- public static final Parcelable.Creator<CarRadioEvent> CREATOR
- = new Parcelable.Creator<CarRadioEvent>() {
- public CarRadioEvent createFromParcel(Parcel in) {
- return new CarRadioEvent(in);
- }
-
- public CarRadioEvent[] newArray(int size) {
- return new CarRadioEvent[size];
- }
- };
-
- public CarRadioEvent(int type, CarRadioPreset preset) {
- mType = type;
- mPreset = preset;
- }
-
- private CarRadioEvent(Parcel in) {
- mType = in.readInt();
- mPreset = in.readParcelable(CarRadioPreset.class.getClassLoader());
- }
-
- public String toString() {
- String data = "";
- switch (mType) {
- case RADIO_PRESET:
- data = mPreset.toString();
- }
- return mType + " " + data;
- }
-}
diff --git a/car-lib/src/android/car/hardware/radio/CarRadioManager.java b/car-lib/src/android/car/hardware/radio/CarRadioManager.java
deleted file mode 100644
index a590864..0000000
--- a/car-lib/src/android/car/hardware/radio/CarRadioManager.java
+++ /dev/null
@@ -1,237 +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 android.car.hardware.radio;
-
-import android.annotation.SystemApi;
-import android.car.Car;
-import android.car.CarManagerBase;
-import android.car.CarNotConnectedException;
-import android.hardware.radio.RadioManager;
-import android.os.Handler;
-import android.os.IBinder;
-import android.os.Looper;
-import android.os.Message;
-import android.os.RemoteException;
-import android.util.Log;
-
-import com.android.internal.annotations.GuardedBy;
-
-import java.lang.ref.WeakReference;
-
-/**
- * Car Radio manager.
- *
- * This API works in conjunction with the {@link RadioManager.java} and provides
- * features additional to the ones provided in there. It supports:
- *
- * 1. Capability to control presets.
- * @hide
- */
-@SystemApi
-public final class CarRadioManager implements CarManagerBase {
- private final static boolean DBG = false;
- private final static String TAG = "CarRadioManager";
-
- // Constants handled in the handler (see mHandler below).
- private final static int MSG_RADIO_EVENT = 0;
-
- private int mCount = 0;
- private final ICarRadio mService;
- @GuardedBy("this")
- private CarRadioEventListener mListener = null;
- @GuardedBy("this")
- private CarRadioEventListenerToService mListenerToService = null;
- private static final class EventCallbackHandler extends Handler {
- WeakReference<CarRadioManager> mMgr;
-
- EventCallbackHandler(CarRadioManager mgr, Looper looper) {
- super(looper);
- mMgr = new WeakReference<CarRadioManager>(mgr);
- }
-
- @Override
- public void handleMessage(Message msg) {
- switch (msg.what) {
- case MSG_RADIO_EVENT:
- CarRadioManager mgr = mMgr.get();
- if (mgr != null) {
- mgr.dispatchEventToClient((CarRadioEvent) msg.obj);
- }
- break;
- default:
- Log.e(TAG, "Event type not handled?" + msg);
- }
- }
- }
-
- private final Handler mHandler;
-
- private static class CarRadioEventListenerToService extends ICarRadioEventListener.Stub {
- private final WeakReference<CarRadioManager> mManager;
-
- public CarRadioEventListenerToService(CarRadioManager manager) {
- mManager = new WeakReference<CarRadioManager>(manager);
- }
-
- @Override
- public void onEvent(CarRadioEvent event) {
- CarRadioManager manager = mManager.get();
- if (manager != null) {
- manager.handleEvent(event);
- }
- }
- }
-
-
- /** Listener for car radio events.
- */
- public interface CarRadioEventListener {
- /**
- * Called when there is a preset value is reprogrammed.
- */
- void onEvent(final CarRadioEvent event);
- }
-
- /**
- * Get an instance of the CarRadioManager.
- *
- * Should not be obtained directly by clients, use {@link Car#getCarManager(String)} instead.
- * @hide
- */
- public CarRadioManager(IBinder service, Handler handler) throws CarNotConnectedException {
- mService = ICarRadio.Stub.asInterface(service);
- mHandler = new EventCallbackHandler(this, handler.getLooper());
-
- // Populate the fixed values.
- try {
- mCount = mService.getPresetCount();
- } catch (RemoteException ex) {
- Log.e(TAG, "Could not connect: " + ex.toString());
- throw new CarNotConnectedException(ex);
- }
- }
-
- /**
- * Register {@link CarRadioEventListener} to get radio unit changes.
- */
- public synchronized void registerListener(CarRadioEventListener listener)
- throws CarNotConnectedException {
- if (mListener != null) {
- throw new IllegalStateException("Listener already registered. Did you call " +
- "registerListener() twice?");
- }
-
- mListener = listener;
- try {
- mListenerToService = new CarRadioEventListenerToService(this);
- mService.registerListener(mListenerToService);
- } catch (RemoteException ex) {
- // Do nothing.
- Log.e(TAG, "Could not connect: " + ex.toString());
- throw new CarNotConnectedException(ex);
- } catch (IllegalStateException ex) {
- Car.checkCarNotConnectedExceptionFromCarService(ex);
- }
- }
-
- /**
- * Unregister {@link CarRadioEventListener}.
- */
- public synchronized void unregisterListener() {
- if (DBG) {
- Log.d(TAG, "unregisterListener");
- }
- try {
- mService.unregisterListener(mListenerToService);
- } catch (RemoteException ex) {
- Log.e(TAG, "Could not connect: " + ex.toString());
- //ignore
- }
- mListenerToService = null;
- mListener = null;
- }
-
- /**
- * Get the number of (hard) presets supported by car radio unit.
- *
- * @return: A positive value if the call succeeded, -1 if it failed.
- */
- public int getPresetCount() throws CarNotConnectedException {
- return mCount;
- }
-
- /**
- * Get preset value for a specific radio preset.
- * @return: a {@link CarRadioPreset} object, {@link null} if the call failed.
- */
- public CarRadioPreset getPreset(int presetNumber) throws CarNotConnectedException {
- if (DBG) {
- Log.d(TAG, "getPreset");
- }
- try {
- CarRadioPreset preset = mService.getPreset(presetNumber);
- return preset;
- } catch (RemoteException ex) {
- Log.e(TAG, "getPreset failed with " + ex.toString());
- throw new CarNotConnectedException(ex);
- }
- }
-
- /**
- * Set the preset value to a specific radio preset.
- *
- * In order to ensure that the preset value indeed get updated, wait for event on the listener
- * registered via registerListener().
- *
- * @return: {@link boolean} value which returns true if the request succeeded and false
- * otherwise. Common reasons for the failure could be:
- * a) Preset is invalid (the preset number is out of range from {@link getPresetCount()}.
- * b) Listener is not set correctly, since otherwise the user of this API cannot confirm if the
- * request succeeded.
- */
- public boolean setPreset(CarRadioPreset preset) throws IllegalArgumentException,
- CarNotConnectedException {
- try {
- return mService.setPreset(preset);
- } catch (RemoteException ex) {
- throw new CarNotConnectedException(ex);
- }
- }
-
- private void dispatchEventToClient(CarRadioEvent event) {
- CarRadioEventListener listener;
- synchronized (this) {
- listener = mListener;
- }
- if (listener != null) {
- listener.onEvent(event);
- } else {
- Log.e(TAG, "Listener died, not dispatching event.");
- }
- }
-
- private void handleEvent(CarRadioEvent event) {
- mHandler.sendMessage(mHandler.obtainMessage(MSG_RADIO_EVENT, event));
- }
-
- /** @hide */
- @Override
- public synchronized void onCarDisconnected() {
- mListener = null;
- mListenerToService = null;
- }
-}
diff --git a/car-lib/src/android/car/hardware/radio/CarRadioPreset.aidl b/car-lib/src/android/car/hardware/radio/CarRadioPreset.aidl
deleted file mode 100644
index 8a1c7b2..0000000
--- a/car-lib/src/android/car/hardware/radio/CarRadioPreset.aidl
+++ /dev/null
@@ -1,19 +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 android.car.hardware.radio;
-
-parcelable CarRadioPreset;
diff --git a/car-lib/src/android/car/hardware/radio/CarRadioPreset.java b/car-lib/src/android/car/hardware/radio/CarRadioPreset.java
deleted file mode 100644
index 38713ad..0000000
--- a/car-lib/src/android/car/hardware/radio/CarRadioPreset.java
+++ /dev/null
@@ -1,113 +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 android.car.hardware.radio;
-
-import android.annotation.SystemApi;
-import android.os.Parcel;
-import android.os.Parcelable;
-
-/**
- * CarPreset object corresponds to a preset that is stored on the car's Radio unit.
- * @hide
- */
-@SystemApi
-public class CarRadioPreset implements Parcelable {
-
- /*
- * Preset number at which this preset is stored.
- *
- * The value is 1 index based.
- */
- private final int mPresetNumber;
- /**
- * Radio band this preset belongs to.
- * See {@link RadioManager.BAND_FM}, {@link RadioManager.BAND_AM} etc.
- */
- private final int mBand;
- /**
- * Channel number.
- */
- private final int mChannel;
- /**
- * Sub channel number.
- */
- private final int mSubChannel;
-
- public int describeContents() {
- return 0;
- }
-
- public void writeToParcel(Parcel out, int flags) {
- out.writeInt(mPresetNumber);
- out.writeInt(mBand);
- out.writeInt(mChannel);
- out.writeInt(mSubChannel);
- }
-
- public static final Parcelable.Creator<CarRadioPreset> CREATOR
- = new Parcelable.Creator<CarRadioPreset>() {
- public CarRadioPreset createFromParcel(Parcel in) {
- return new CarRadioPreset(in);
- }
-
- public CarRadioPreset[] newArray(int size) {
- return new CarRadioPreset[size];
- }
- };
-
- private CarRadioPreset(Parcel in) {
- mPresetNumber = in.readInt();
- mBand = in.readInt();
- mChannel = in.readInt();
- mSubChannel = in.readInt();
- }
-
- public CarRadioPreset(int presetNumber, int bandType, int channel, int subChannel) {
- mPresetNumber = presetNumber;
- mBand = bandType;
- mChannel = channel;
- mSubChannel = subChannel;
- }
-
- // Getters.
- public int getPresetNumber() { return mPresetNumber; }
-
- public int getBand() { return mBand; }
-
- public int getChannel() { return mChannel; }
-
- public int getSubChannel() { return mSubChannel; }
-
- // Printer.
- public String toString() {
- return "Preset Number: " + mPresetNumber + "\n" +
- "Band: " + mBand + "\n" +
- "Channel: " + mChannel + "\n" +
- "Sub channel: " + mSubChannel;
- }
-
- // Comparator.
- public boolean equals(Object o) {
- CarRadioPreset that = (CarRadioPreset) o;
-
- return that.getPresetNumber() == mPresetNumber &&
- that.getBand() == mBand &&
- that.getChannel() == mChannel &&
- that.getSubChannel() == mSubChannel;
-
- }
-}
diff --git a/car-lib/src/android/car/hardware/radio/ICarRadio.aidl b/car-lib/src/android/car/hardware/radio/ICarRadio.aidl
deleted file mode 100644
index 4afa211..0000000
--- a/car-lib/src/android/car/hardware/radio/ICarRadio.aidl
+++ /dev/null
@@ -1,49 +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 android.car.hardware.radio;
-
-import android.car.hardware.radio.CarRadioPreset;
-import android.car.hardware.radio.ICarRadioEventListener;
-
-/** @hide */
-interface ICarRadio {
- /**
- * Returns the number of hard presets on the radio unit that may be programmed.
- */
- int getPresetCount() = 0;
-
- /**
- * Registers the client for updates to radio changes.
- */
- void registerListener(in ICarRadioEventListener callback) = 1;
-
- /**
- * Unregisters the client for updates to radio changes.
- */
- void unregisterListener(in ICarRadioEventListener callback) = 2;
-
- /**
- * Gets the preset values stored for a particular preset number.
- */
- CarRadioPreset getPreset(int presetNumber) = 3;
-
- /**
- * Sets a specified preset (hard button) in the car. In order to check for success listen to
- * events using {@link registerOrUpdateRadioListener}.
- */
- boolean setPreset(in CarRadioPreset preset) = 4;
-}
diff --git a/car-lib/src/android/car/hardware/radio/ICarRadioEventListener.aidl b/car-lib/src/android/car/hardware/radio/ICarRadioEventListener.aidl
deleted file mode 100644
index e006b65..0000000
--- a/car-lib/src/android/car/hardware/radio/ICarRadioEventListener.aidl
+++ /dev/null
@@ -1,32 +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 android.car.hardware.radio;
-
-import android.car.hardware.radio.CarRadioEvent;
-
-/**
- * Binder callback for CarRadioEventListener.
- * This is generated per each CarClient.
- * @hide
- */
-oneway interface ICarRadioEventListener {
- /**
- * Called when an event is triggered in response to one of the calls (such as on tune) or
- * asynchronously (such as on announcement).
- */
- void onEvent(in CarRadioEvent event) = 0;
-}
diff --git a/car-lib/src/android/car/media/CarAudioManager.java b/car-lib/src/android/car/media/CarAudioManager.java
index 49a7ca4..c9aef74 100644
--- a/car-lib/src/android/car/media/CarAudioManager.java
+++ b/car-lib/src/android/car/media/CarAudioManager.java
@@ -15,467 +15,350 @@
*/
package android.car.media;
-import android.annotation.IntDef;
-import android.annotation.Nullable;
+import android.annotation.NonNull;
import android.annotation.SystemApi;
import android.car.CarLibLog;
+import android.car.CarManagerBase;
import android.car.CarNotConnectedException;
+import android.content.ContentResolver;
import android.content.Context;
+import android.database.ContentObserver;
import android.media.AudioAttributes;
-import android.media.AudioManager;
-import android.media.AudioManager.OnAudioFocusChangeListener;
-import android.media.IVolumeController;
import android.os.Handler;
import android.os.IBinder;
import android.os.RemoteException;
-import android.car.CarManagerBase;
+import android.provider.Settings;
import android.util.Log;
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-import java.lang.ref.WeakReference;
-
/**
* APIs for handling car specific audio stuff.
*/
public final class CarAudioManager implements CarManagerBase {
- /**
- * Audio usage for unspecified type.
- */
- public static final int CAR_AUDIO_USAGE_DEFAULT = 0;
- /**
- * Audio usage for playing music.
- */
- public static final int CAR_AUDIO_USAGE_MUSIC = 1;
- /**
- * Audio usage for H/W radio.
- */
- public static final int CAR_AUDIO_USAGE_RADIO = 2;
- /**
- * Audio usage for playing navigation guidance.
- */
- public static final int CAR_AUDIO_USAGE_NAVIGATION_GUIDANCE = 3;
- /**
- * Audio usage for voice call
- */
- public static final int CAR_AUDIO_USAGE_VOICE_CALL = 4;
- /**
- * Audio usage for voice search or voice command.
- */
- public static final int CAR_AUDIO_USAGE_VOICE_COMMAND = 5;
- /**
- * Audio usage for playing alarm.
- */
- public static final int CAR_AUDIO_USAGE_ALARM = 6;
- /**
- * Audio usage for notification sound.
- */
- public static final int CAR_AUDIO_USAGE_NOTIFICATION = 7;
- /**
- * Audio usage for system sound like UI feedback.
- */
- public static final int CAR_AUDIO_USAGE_SYSTEM_SOUND = 8;
- /**
- * Audio usage for playing safety alert.
- */
- public static final int CAR_AUDIO_USAGE_SYSTEM_SAFETY_ALERT = 9;
- /**
- * Audio usage for the ringing of a phone call.
- */
- public static final int CAR_AUDIO_USAGE_RINGTONE = 10;
- /**
- * Audio usage for external audio usage.
- * @hide
- */
- public static final int CAR_AUDIO_USAGE_EXTERNAL_AUDIO_SOURCE = 11;
+ // The trailing slash forms a directory-liked hierarchy and
+ // allows listening for both GROUP/MEDIA and GROUP/NAVIGATION.
+ private static final String VOLUME_SETTINGS_KEY_FOR_GROUP_PREFIX = "android.car.VOLUME_GROUP/";
- /** @hide */
- public static final int CAR_AUDIO_USAGE_MAX = CAR_AUDIO_USAGE_EXTERNAL_AUDIO_SOURCE;
+ /**
+ * @param groupId The volume group id
+ * @return Key to persist volume index for volume group in {@link Settings.Global}
+ */
+ public static String getVolumeSettingsKeyForGroup(int groupId) {
+ return VOLUME_SETTINGS_KEY_FOR_GROUP_PREFIX + groupId;
+ }
- /** @hide */
- @IntDef({CAR_AUDIO_USAGE_DEFAULT, CAR_AUDIO_USAGE_MUSIC, CAR_AUDIO_USAGE_RADIO,
- CAR_AUDIO_USAGE_NAVIGATION_GUIDANCE, CAR_AUDIO_USAGE_VOICE_CALL,
- CAR_AUDIO_USAGE_VOICE_COMMAND, CAR_AUDIO_USAGE_ALARM, CAR_AUDIO_USAGE_NOTIFICATION,
- CAR_AUDIO_USAGE_SYSTEM_SOUND, CAR_AUDIO_USAGE_SYSTEM_SAFETY_ALERT,
- CAR_AUDIO_USAGE_EXTERNAL_AUDIO_SOURCE})
- @Retention(RetentionPolicy.SOURCE)
- public @interface CarAudioUsage {}
-
- /** @hide */
- public static final String CAR_RADIO_TYPE_AM_FM = "RADIO_AM_FM";
- /** @hide */
- public static final String CAR_RADIO_TYPE_AM_FM_HD = "RADIO_AM_FM_HD";
- /** @hide */
- public static final String CAR_RADIO_TYPE_DAB = "RADIO_DAB";
- /** @hide */
- public static final String CAR_RADIO_TYPE_SATELLITE = "RADIO_SATELLITE";
-
- /** @hide */
- public static final String CAR_EXTERNAL_SOURCE_TYPE_CD_DVD = "CD_DVD";
- /** @hide */
- public static final String CAR_EXTERNAL_SOURCE_TYPE_AUX_IN0 = "AUX_IN0";
- /** @hide */
- public static final String CAR_EXTERNAL_SOURCE_TYPE_AUX_IN1 = "AUX_IN1";
- /** @hide */
- public static final String CAR_EXTERNAL_SOURCE_TYPE_EXT_NAV_GUIDANCE = "EXT_NAV_GUIDANCE";
- /** @hide */
- public static final String CAR_EXTERNAL_SOURCE_TYPE_EXT_VOICE_CALL = "EXT_VOICE_CALL";
- /** @hide */
- public static final String CAR_EXTERNAL_SOURCE_TYPE_EXT_VOICE_COMMAND = "EXT_VOICE_COMMAND";
- /** @hide */
- public static final String CAR_EXTERNAL_SOURCE_TYPE_EXT_SAFETY_ALERT = "EXT_SAFETY_ALERT";
-
+ private final ContentResolver mContentResolver;
private final ICarAudio mService;
- private final AudioManager mAudioManager;
- private final Handler mHandler;
-
- private ParameterChangeCallback mParameterChangeCallback;
- private OnParameterChangeListener mOnParameterChangeListener;
/**
- * Get {@link AudioAttributes} relevant for the given usage in car.
- * @param carUsage
- * @return
+ * Registers a {@link ContentObserver} to listen for volume group changes.
+ * Note that this observer is valid for bus based car audio stack only.
+ *
+ * {@link ContentObserver#onChange(boolean)} will be called on every group volume change.
+ *
+ * @param observer The {@link ContentObserver} instance to register, non-null
*/
- public AudioAttributes getAudioAttributesForCarUsage(@CarAudioUsage int carUsage)
- throws CarNotConnectedException {
- try {
- return mService.getAudioAttributesForCarUsage(carUsage);
- } catch (RemoteException e) {
- throw new CarNotConnectedException();
- }
+ @SystemApi
+ public void registerVolumeChangeObserver(@NonNull ContentObserver observer) {
+ mContentResolver.registerContentObserver(
+ Settings.Global.getUriFor(VOLUME_SETTINGS_KEY_FOR_GROUP_PREFIX),
+ true, observer);
}
/**
- * Get AudioAttributes for radio. This is necessary when there are multiple types of radio
- * in system.
+ * Unregisters the {@link ContentObserver} which listens for volume group changes.
*
- * @param radioType String specifying the desired radio type. Should use only what is listed in
- * {@link #getSupportedRadioTypes()}.
- * @return
- * @throws IllegalArgumentException If not supported type is passed.
- *
- * @hide
+ * @param observer The {@link ContentObserver} instance to unregister, non-null
*/
- public AudioAttributes getAudioAttributesForRadio(String radioType)
- throws CarNotConnectedException, IllegalArgumentException {
- try {
- return mService.getAudioAttributesForRadio(radioType);
- } catch (RemoteException e) {
- throw new CarNotConnectedException();
- }
+ @SystemApi
+ public void unregisterVolumeChangeObserver(@NonNull ContentObserver observer) {
+ mContentResolver.unregisterContentObserver(observer);
}
/**
- * Get AudioAttributes for external audio source.
+ * Sets the volume index for a volume group.
*
- * @param externalSourceType String specifying the desired source type. Should use only what is
- * listed in {@link #getSupportedExternalSourceTypes()}.
- * @return
- * @throws IllegalArgumentException If not supported type is passed.
+ * Requires {@link android.car.Car#PERMISSION_CAR_CONTROL_AUDIO_VOLUME} permission.
*
- * @hide
- */
- public AudioAttributes getAudioAttributesForExternalSource(String externalSourceType)
- throws CarNotConnectedException, IllegalArgumentException {
- try {
- return mService.getAudioAttributesForExternalSource(externalSourceType);
- } catch (RemoteException e) {
- throw new CarNotConnectedException();
- }
- }
-
- /**
- * List all supported external audio sources.
- *
- * @return
- *
- * @hide
- */
- public String[] getSupportedExternalSourceTypes() throws CarNotConnectedException {
- try {
- return mService.getSupportedExternalSourceTypes();
- } catch (RemoteException e) {
- throw new CarNotConnectedException();
- }
- }
-
- /**
- * List all supported radio sources.
- *
- * @return
- *
- * @hide
- */
- public String[] getSupportedRadioTypes() throws CarNotConnectedException {
- try {
- return mService.getSupportedRadioTypes();
- } catch (RemoteException e) {
- throw new CarNotConnectedException();
- }
- }
-
- /**
- * Request audio focus.
- * Send a request to obtain the audio focus.
- * @param l
- * @param requestAttributes
- * @param durationHint
- * @param flags
- */
- public int requestAudioFocus(OnAudioFocusChangeListener l,
- AudioAttributes requestAttributes,
- int durationHint,
- int flags)
- throws CarNotConnectedException, IllegalArgumentException {
- return mAudioManager.requestAudioFocus(l, requestAttributes, durationHint, flags);
- }
-
- /**
- * Abandon audio focus. Causes the previous focus owner, if any, to receive focus.
- * @param l
- * @param aa
- */
- public void abandonAudioFocus(OnAudioFocusChangeListener l, AudioAttributes aa) {
- mAudioManager.abandonAudioFocus(l, aa);
- }
-
- /**
- * Sets the volume index for a particular stream.
- *
- * Requires {@link android.car.Car.PERMISSION_CAR_CONTROL_AUDIO_VOLUME} permission.
- *
- * @param streamType The stream whose volume index should be set.
+ * @param groupId The volume group id whose volume index should be set.
* @param index The volume index to set. See
- * {@link #getStreamMaxVolume(int)} for the largest valid value.
+ * {@link #getGroupMaxVolume(int)} for the largest valid value.
* @param flags One or more flags (e.g., {@link android.media.AudioManager#FLAG_SHOW_UI},
* {@link android.media.AudioManager#FLAG_PLAY_SOUND})
*/
@SystemApi
- public void setStreamVolume(int streamType, int index, int flags)
+ public void setGroupVolume(int groupId, int index, int flags) throws CarNotConnectedException {
+ try {
+ mService.setGroupVolume(groupId, index, flags);
+ } catch (RemoteException e) {
+ Log.e(CarLibLog.TAG_CAR, "setGroupVolume failed", e);
+ throw new CarNotConnectedException(e);
+ }
+ }
+
+ /**
+ * Returns the maximum volume index for a volume group.
+ *
+ * Requires {@link android.car.Car#PERMISSION_CAR_CONTROL_AUDIO_VOLUME} permission.
+ *
+ * @param groupId The volume group id whose maximum volume index is returned.
+ * @return The maximum valid volume index for the given group.
+ */
+ @SystemApi
+ public int getGroupMaxVolume(int groupId) throws CarNotConnectedException {
+ try {
+ return mService.getGroupMaxVolume(groupId);
+ } catch (RemoteException e) {
+ Log.e(CarLibLog.TAG_CAR, "getUsageMaxVolume failed", e);
+ throw new CarNotConnectedException(e);
+ }
+ }
+
+ /**
+ * Returns the minimum volume index for a volume group.
+ *
+ * Requires {@link android.car.Car#PERMISSION_CAR_CONTROL_AUDIO_VOLUME} permission.
+ *
+ * @param groupId The volume group id whose minimum volume index is returned.
+ * @return The minimum valid volume index for the given group, non-negative
+ */
+ @SystemApi
+ public int getGroupMinVolume(int groupId) throws CarNotConnectedException {
+ try {
+ return mService.getGroupMinVolume(groupId);
+ } catch (RemoteException e) {
+ Log.e(CarLibLog.TAG_CAR, "getUsageMinVolume failed", e);
+ throw new CarNotConnectedException(e);
+ }
+ }
+
+ /**
+ * Returns the current volume index for a volume group.
+ *
+ * Requires {@link android.car.Car#PERMISSION_CAR_CONTROL_AUDIO_VOLUME} permission.
+ *
+ * @param groupId The volume group id whose volume index is returned.
+ * @return The current volume index for the given group.
+ *
+ * @see #getGroupMaxVolume(int)
+ * @see #setGroupVolume(int, int, int)
+ */
+ @SystemApi
+ public int getGroupVolume(int groupId) throws CarNotConnectedException {
+ try {
+ return mService.getGroupVolume(groupId);
+ } catch (RemoteException e) {
+ Log.e(CarLibLog.TAG_CAR, "getUsageVolume failed", e);
+ throw new CarNotConnectedException(e);
+ }
+ }
+
+ /**
+ * Adjust the relative volume in the front vs back of the vehicle cabin.
+ *
+ * Requires {@link android.car.Car#PERMISSION_CAR_CONTROL_AUDIO_VOLUME} permission.
+ *
+ * @param value in the range -1.0 to 1.0 for fully toward the back through
+ * fully toward the front. 0.0 means evenly balanced.
+ *
+ * @see #setBalanceTowardRight(float)
+ */
+ @SystemApi
+ public void setFadeTowardFront(float value) throws CarNotConnectedException {
+ try {
+ mService.setFadeTowardFront(value);
+ } catch (RemoteException e) {
+ Log.e(CarLibLog.TAG_CAR, "setFadeTowardFront failed", e);
+ throw new CarNotConnectedException(e);
+ }
+ }
+
+ /**
+ * Adjust the relative volume on the left vs right side of the vehicle cabin.
+ *
+ * Requires {@link android.car.Car#PERMISSION_CAR_CONTROL_AUDIO_VOLUME} permission.
+ *
+ * @param value in the range -1.0 to 1.0 for fully toward the left through
+ * fully toward the right. 0.0 means evenly balanced.
+ *
+ * @see #setFadeTowardFront(float)
+ */
+ @SystemApi
+ public void setBalanceTowardRight(float value) throws CarNotConnectedException {
+ try {
+ mService.setBalanceTowardRight(value);
+ } catch (RemoteException e) {
+ Log.e(CarLibLog.TAG_CAR, "setBalanceTowardRight failed", e);
+ throw new CarNotConnectedException(e);
+ }
+ }
+
+ /**
+ * Queries the system configuration in order to report the available, non-microphone audio
+ * input devices.
+ *
+ * Requires {@link android.car.Car#PERMISSION_CAR_CONTROL_AUDIO_SETTINGS} permission.
+ *
+ * @return An array of strings representing the available input ports.
+ * Each port is identified by it's "address" tag in the audioPolicyConfiguration xml file.
+ * Empty array if we find nothing.
+ *
+ * @see #createAudioPatch(String, int, int)
+ * @see #releaseAudioPatch(CarAudioPatchHandle)
+ */
+ @SystemApi
+ public @NonNull String[] getExternalSources() throws CarNotConnectedException {
+ try {
+ return mService.getExternalSources();
+ } catch (RemoteException e) {
+ Log.e(CarLibLog.TAG_CAR, "getExternalSources failed", e);
+ throw new CarNotConnectedException(e);
+ }
+ }
+
+ /**
+ * Given an input port identified by getExternalSources(), request that it's audio signal
+ * be routed below the HAL to the output port associated with the given usage. For example,
+ * The output of a tuner might be routed directly to the output buss associated with
+ * AudioAttributes.USAGE_MEDIA while the tuner is playing.
+ *
+ * Requires {@link android.car.Car#PERMISSION_CAR_CONTROL_AUDIO_SETTINGS} permission.
+ *
+ * @param sourceAddress the input port name obtained from getExternalSources().
+ * @param usage the type of audio represented by this source (usually USAGE_MEDIA).
+ * @param gainInMillibels How many steps above the minimum value defined for the source port to
+ * set the gain when creating the patch.
+ * This may be used for source balancing without affecting the user
+ * controlled volumes applied to the destination ports. A value of
+ * 0 indicates no gain change is requested.
+ * @return A handle for the created patch which can be used to later remove it.
+ *
+ * @see #getExternalSources()
+ * @see #releaseAudioPatch(CarAudioPatchHandle)
+ */
+ @SystemApi
+ public CarAudioPatchHandle createAudioPatch(String sourceAddress,
+ @AudioAttributes.AttributeUsage int usage, int gainInMillibels)
throws CarNotConnectedException {
try {
- mService.setStreamVolume(streamType, index, flags);
+ return mService.createAudioPatch(sourceAddress, usage, gainInMillibels);
} catch (RemoteException e) {
- Log.e(CarLibLog.TAG_CAR, "setStreamVolume failed", e);
+ Log.e(CarLibLog.TAG_CAR, "createAudioPatch failed", e);
throw new CarNotConnectedException(e);
}
}
/**
- * Registers a global volume controller interface.
+ * Removes the association between an input port and an output port identified by the provided
+ * handle.
*
- * Requires {@link android.car.Car.PERMISSION_CAR_CONTROL_AUDIO_VOLUME} permission.
+ * Requires {@link android.car.Car#PERMISSION_CAR_CONTROL_AUDIO_SETTINGS} permission.
*
- * @hide
+ * @param patch CarAudioPatchHandle returned from createAudioPatch().
+ *
+ * @see #getExternalSources()
+ * @see #createAudioPatch(String, int, int)
*/
@SystemApi
- public void setVolumeController(IVolumeController controller)
+ public void releaseAudioPatch(CarAudioPatchHandle patch) throws CarNotConnectedException {
+ try {
+ mService.releaseAudioPatch(patch);
+ } catch (RemoteException e) {
+ Log.e(CarLibLog.TAG_CAR, "releaseAudioPatch failed", e);
+ throw new CarNotConnectedException(e);
+ }
+ }
+
+ /**
+ * Gets the count of available volume groups in the system.
+ *
+ * Requires {@link android.car.Car#PERMISSION_CAR_CONTROL_AUDIO_VOLUME} permission.
+ *
+ * @return Count of volume groups
+ */
+ @SystemApi
+ public int getVolumeGroupCount() throws CarNotConnectedException {
+ try {
+ return mService.getVolumeGroupCount();
+ } catch (RemoteException e) {
+ Log.e(CarLibLog.TAG_CAR, "getVolumeGroupCount failed", e);
+ throw new CarNotConnectedException(e);
+ }
+ }
+
+ /**
+ * Gets the volume group id for a given {@link AudioAttributes} usage.
+ *
+ * Requires {@link android.car.Car#PERMISSION_CAR_CONTROL_AUDIO_VOLUME} permission.
+ *
+ * @param usage The {@link AudioAttributes} usage to get a volume group from.
+ * @return The volume group id where the usage belongs to
+ */
+ @SystemApi
+ public int getVolumeGroupIdForUsage(@AudioAttributes.AttributeUsage int usage)
throws CarNotConnectedException {
try {
- mService.setVolumeController(controller);
+ return mService.getVolumeGroupIdForUsage(usage);
} catch (RemoteException e) {
- Log.e(CarLibLog.TAG_CAR, "setVolumeController failed", e);
+ Log.e(CarLibLog.TAG_CAR, "getVolumeGroupIdForUsage failed", e);
throw new CarNotConnectedException(e);
}
}
/**
- * Returns the maximum volume index for a particular stream.
+ * Gets array of {@link AudioAttributes} usages for a given volume group id.
*
- * Requires {@link android.car.Car.PERMISSION_CAR_CONTROL_AUDIO_VOLUME} permission.
+ * Requires {@link android.car.Car#PERMISSION_CAR_CONTROL_AUDIO_VOLUME} permission.
*
- * @param stream The stream type whose maximum volume index is returned.
- * @return The maximum valid volume index for the stream.
+ * @param groupId The volume group id whose associated audio usages is returned.
+ * @return Array of {@link AudioAttributes} usages for a given volume group id
*/
@SystemApi
- public int getStreamMaxVolume(int stream) throws CarNotConnectedException {
+ public @NonNull int[] getUsagesForVolumeGroupId(int groupId) throws CarNotConnectedException {
try {
- return mService.getStreamMaxVolume(stream);
+ return mService.getUsagesForVolumeGroupId(groupId);
} catch (RemoteException e) {
- Log.e(CarLibLog.TAG_CAR, "getStreamMaxVolume failed", e);
+ Log.e(CarLibLog.TAG_CAR, "getUsagesForVolumeGroupId failed", e);
throw new CarNotConnectedException(e);
}
}
/**
- * Returns the minimum volume index for a particular stream.
+ * Register {@link ICarVolumeCallback} to receive the volume key events
*
- * Requires {@link android.car.Car.PERMISSION_CAR_CONTROL_AUDIO_VOLUME} permission.
+ * Requires {@link android.car.Car#PERMISSION_CAR_CONTROL_AUDIO_VOLUME} permission.
*
- * @param stream The stream type whose maximum volume index is returned.
- * @return The maximum valid volume index for the stream.
- */
- @SystemApi
- public int getStreamMinVolume(int stream) throws CarNotConnectedException {
- try {
- return mService.getStreamMinVolume(stream);
- } catch (RemoteException e) {
- Log.e(CarLibLog.TAG_CAR, "getStreamMaxVolume failed", e);
- throw new CarNotConnectedException(e);
- }
- }
-
- /**
- * Returns the current volume index for a particular stream.
- *
- * Requires {@link android.car.Car.PERMISSION_CAR_CONTROL_AUDIO_VOLUME} permission.
- *
- * @param stream The stream type whose volume index is returned.
- * @return The current volume index for the stream.
- *
- * @see #getStreamMaxVolume(int)
- * @see #setStreamVolume(int, int, int)
- */
- @SystemApi
- public int getStreamVolume(int stream) throws CarNotConnectedException {
- try {
- return mService.getStreamVolume(stream);
- } catch (RemoteException e) {
- Log.e(CarLibLog.TAG_CAR, "getStreamVolume failed", e);
- throw new CarNotConnectedException(e);
- }
- }
-
- /**
- * Check if media audio is muted or not. This will include music and radio. Any application
- * taking audio focus for media stream will get it out of mute state.
- *
- * @return true if media is muted.
- * @throws CarNotConnectedException if the connection to the car service has been lost.
- * @hide
- */
- @SystemApi
- public boolean isMediaMuted() throws CarNotConnectedException {
- try {
- return mService.isMediaMuted();
- } catch (RemoteException e) {
- Log.e(CarLibLog.TAG_CAR, "isMediaMuted failed", e);
- throw new CarNotConnectedException(e);
- }
- }
-
- /**
- * Mute or unmute media stream including radio. This can involve audio focus change to stop
- * whatever app holding audio focus now. If requester is currently holding audio focus,
- * it will get LOSS_TRANSIENT focus loss.
- * This API requires {@link android.car.Car.PERMISSION_CAR_CONTROL_AUDIO_VOLUME} permission.
- *
- * @param mute
- * @return Mute state of system after the request. Note that mute request can fail if there
- * is higher priority audio already being played like phone call.
- * @throws CarNotConnectedException if the connection to the car service has been lost.
- * @hide
- */
- @SystemApi
- public boolean setMediaMute(boolean mute) throws CarNotConnectedException {
- try {
- return mService.setMediaMute(mute);
- } catch (RemoteException e) {
- Log.e(CarLibLog.TAG_CAR, "setMediaMute failed", e);
- throw new CarNotConnectedException(e);
- }
- }
-
- /**
- * Listener to monitor audio parameter changes.
- * @hide
- */
- public interface OnParameterChangeListener {
- /**
- * Parameter changed.
- * @param parameters Have format of key1=value1;key2=value2;...
- */
- void onParameterChange(String parameters);
- }
-
- /**
- * Return array of keys supported in this system.
- * Requires {@link android.car.Car.PERMISSION_CAR_CONTROL_AUDIO_SETTINGS} permission.
- * The list is static and will not change.
- * @return null if there is no audio parameters supported.
+ * @param binder {@link IBinder} instance of {@link ICarVolumeCallback} to receive
+ * volume key event callbacks
* @throws CarNotConnectedException
- *
- * @hide
*/
- public @Nullable String[] getParameterKeys() throws CarNotConnectedException {
- try {
- return mService.getParameterKeys();
- } catch (RemoteException e) {
- Log.e(CarLibLog.TAG_CAR, "getParameterKeys failed", e);
- throw new CarNotConnectedException(e);
- }
- }
-
- /**
- * Set car specific audio parameters.
- * Requires {@link android.car.Car.PERMISSION_CAR_CONTROL_AUDIO_SETTINGS} permission.
- * Only keys listed from {@link #getParameterKeys()} should be used.
- * @param parameters has format of key1=value1;key2=value2;...
- * @throws CarNotConnectedException
- *
- * @hide
- */
- public void setParameters(String parameters) throws CarNotConnectedException {
- try {
- mService.setParameters(parameters);
- } catch (RemoteException e) {
- Log.e(CarLibLog.TAG_CAR, "setParameters failed", e);
- throw new CarNotConnectedException(e);
- }
- }
-
- /**
- * Get parameters for the key passed.
- * Requires {@link android.car.Car.PERMISSION_CAR_CONTROL_AUDIO_SETTINGS} permission.
- * Only keys listed from {@link #getParameterKeys()} should be used.
- * @param keys Keys to get value. Format is key1;key2;...
- * @return Parameters in format of key1=value1;key2=value2;...
- * @throws CarNotConnectedException
- *
- * @hide
- */
- public String getParameters(String keys) throws CarNotConnectedException {
- try {
- return mService.getParameters(keys);
- } catch (RemoteException e) {
- Log.e(CarLibLog.TAG_CAR, "getParameters failed", e);
- throw new CarNotConnectedException(e);
- }
- }
-
- /**
- * Set listener to monitor audio parameter changes.
- * Requires {@link android.car.Car.PERMISSION_CAR_CONTROL_AUDIO_SETTINGS} permission.
- * @param listener Non-null listener will start monitoring. null listener will stop listening.
- * @throws CarNotConnectedException
- *
- * @hide
- */
- public void setOnParameterChangeListener(OnParameterChangeListener listener)
+ @SystemApi
+ public void registerVolumeCallback(@NonNull IBinder binder)
throws CarNotConnectedException {
- ParameterChangeCallback oldCb = null;
- ParameterChangeCallback newCb = null;
- synchronized (this) {
- if (listener != null) {
- if (mParameterChangeCallback != null) {
- oldCb = mParameterChangeCallback;
- }
- newCb = new ParameterChangeCallback(this);
- }
- mParameterChangeCallback = newCb;
- mOnParameterChangeListener = listener;
- }
try {
- if (oldCb != null) {
- mService.unregisterOnParameterChangeListener(oldCb);
- }
- if (newCb != null) {
- mService.registerOnParameterChangeListener(newCb);
- }
+ mService.registerVolumeCallback(binder);
} catch (RemoteException e) {
- Log.e(CarLibLog.TAG_CAR, "setOnParameterChangeListener failed", e);
+ Log.e(CarLibLog.TAG_CAR, "registerVolumeCallback failed", e);
+ throw new CarNotConnectedException(e);
+ }
+ }
+
+ /**
+ * Unregister {@link ICarVolumeCallback} from receiving volume key events
+ *
+ * Requires {@link android.car.Car#PERMISSION_CAR_CONTROL_AUDIO_VOLUME} permission.
+ *
+ * @param binder {@link IBinder} instance of {@link ICarVolumeCallback} to stop receiving
+ * volume key event callbacks
+ * @throws CarNotConnectedException
+ */
+ @SystemApi
+ public void unregisterVolumeCallback(@NonNull IBinder binder)
+ throws CarNotConnectedException {
+ try {
+ mService.unregisterVolumeCallback(binder);
+ } catch (RemoteException e) {
+ Log.e(CarLibLog.TAG_CAR, "unregisterVolumeCallback failed", e);
throw new CarNotConnectedException(e);
}
}
@@ -487,40 +370,7 @@
/** @hide */
public CarAudioManager(IBinder service, Context context, Handler handler) {
+ mContentResolver = context.getContentResolver();
mService = ICarAudio.Stub.asInterface(service);
- mAudioManager = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE);
- mHandler = handler;
- }
-
- private AudioAttributes createAudioAttributes(int contentType, int usage) {
- AudioAttributes.Builder builder = new AudioAttributes.Builder();
- return builder.setContentType(contentType).setUsage(usage).build();
- }
-
- private static class ParameterChangeCallback extends ICarAudioCallback.Stub {
-
- private final WeakReference<CarAudioManager> mManager;
-
- private ParameterChangeCallback(CarAudioManager manager) {
- mManager = new WeakReference<>(manager);
- }
-
- @Override
- public void onParameterChange(final String params) {
- CarAudioManager manager = mManager.get();
- if (manager == null) {
- return;
- }
- final OnParameterChangeListener listener = manager.mOnParameterChangeListener;
- if (listener == null) {
- return;
- }
- manager.mHandler.post(new Runnable() {
- @Override
- public void run() {
- listener.onParameterChange(params);
- }
- });
- }
}
}
diff --git a/car-lib/src/android/car/hardware/radio/CarRadioEvent.aidl b/car-lib/src/android/car/media/CarAudioPatchHandle.aidl
similarity index 73%
copy from car-lib/src/android/car/hardware/radio/CarRadioEvent.aidl
copy to car-lib/src/android/car/media/CarAudioPatchHandle.aidl
index 0865646..8e2a890 100644
--- a/car-lib/src/android/car/hardware/radio/CarRadioEvent.aidl
+++ b/car-lib/src/android/car/media/CarAudioPatchHandle.aidl
@@ -14,6 +14,13 @@
* limitations under the License.
*/
-package android.car.hardware.radio;
+package android.car.media;
-parcelable CarRadioEvent;
+
+/**
+ * Container for audioPatch which facilitates automatic clean up of abandoned audioPatches
+ * if/when the original patch creator quits.
+ *
+ * @hide
+ */
+parcelable CarAudioPatchHandle;
\ No newline at end of file
diff --git a/car-lib/src/android/car/media/CarAudioPatchHandle.java b/car-lib/src/android/car/media/CarAudioPatchHandle.java
new file mode 100644
index 0000000..bbcc791
--- /dev/null
+++ b/car-lib/src/android/car/media/CarAudioPatchHandle.java
@@ -0,0 +1,113 @@
+/*
+ * Copyright (C) 2014 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.media;
+
+import android.media.AudioDevicePort;
+import android.media.AudioPatch;
+import android.os.Parcel;
+import android.os.Parcelable;
+
+import com.android.internal.util.Preconditions;
+
+/**
+ * A class to encapsulate the handle for a system level audio patch. This is used
+ * to provide a "safe" way for permitted applications to route automotive audio sources
+ * outside of android.
+ */
+public final class CarAudioPatchHandle implements Parcelable {
+
+ // This is enough information to uniquely identify a patch to the system
+ private final int mHandleId;
+ private final String mSourceAddress;
+ private final String mSinkAddress;
+
+ /**
+ * Construct a audio patch handle container given the system level handle
+ * NOTE: Assumes (as it true today), that there is exactly one device port in the source
+ * and sink arrays.
+ */
+ public CarAudioPatchHandle(AudioPatch patch) {
+ Preconditions.checkArgument(patch.sources().length == 1
+ && patch.sources()[0].port() instanceof AudioDevicePort,
+ "Accepts exactly one device port as source");
+ Preconditions.checkArgument(patch.sinks().length == 1
+ && patch.sinks()[0].port() instanceof AudioDevicePort,
+ "Accepts exactly one device port as sink");
+
+ mHandleId = patch.id();
+ mSourceAddress = ((AudioDevicePort) patch.sources()[0].port()).address();
+ mSinkAddress = ((AudioDevicePort) patch.sinks()[0].port()).address();
+ }
+
+ /**
+ * Returns true if this instance matches the provided AudioPatch object.
+ * This is intended only for use by the CarAudioManager implementation when
+ * communicating with the AudioManager API.
+ *
+ * Effectively only the {@link #mHandleId} is used for comparison,
+ * {@link android.media.AudioSystem#listAudioPatches(java.util.ArrayList, int[])}
+ * does not populate the device type and address properly.
+ *
+ * @hide
+ */
+ public boolean represents(AudioPatch patch) {
+ return patch.sources().length == 1
+ && patch.sinks().length == 1
+ && patch.id() == mHandleId;
+ }
+
+ @Override
+ public String toString() {
+ return "Patch (mHandleId=" + mHandleId + "): "
+ + mSourceAddress + " => " + mSinkAddress;
+ }
+
+ /**
+ * Given a parcel, populate our data members
+ */
+ private CarAudioPatchHandle(Parcel in) {
+ mHandleId = in.readInt();
+ mSourceAddress = in.readString();
+ mSinkAddress = in.readString();
+ }
+
+ /**
+ * Serialize our internal data to a parcel
+ */
+ @Override
+ public void writeToParcel(Parcel out, int flags) {
+ out.writeInt(mHandleId);
+ out.writeString(mSourceAddress);
+ out.writeString(mSinkAddress);
+ }
+
+ public static final Parcelable.Creator<CarAudioPatchHandle> CREATOR
+ = new Parcelable.Creator<CarAudioPatchHandle>() {
+ public CarAudioPatchHandle createFromParcel(Parcel in) {
+ return new CarAudioPatchHandle(in);
+ }
+
+ public CarAudioPatchHandle[] newArray(int size) {
+ return new CarAudioPatchHandle[size];
+ }
+ };
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+}
diff --git a/car-lib/src/android/car/media/ICarAudio.aidl b/car-lib/src/android/car/media/ICarAudio.aidl
index 6d9b3ce..353c168 100644
--- a/car-lib/src/android/car/media/ICarAudio.aidl
+++ b/car-lib/src/android/car/media/ICarAudio.aidl
@@ -16,9 +16,7 @@
package android.car.media;
-import android.car.media.ICarAudioCallback;
-import android.media.AudioAttributes;
-import android.media.IVolumeController;
+import android.car.media.CarAudioPatchHandle;
/**
* Binder interface for {@link android.car.media.CarAudioManager}.
@@ -27,21 +25,25 @@
* @hide
*/
interface ICarAudio {
- AudioAttributes getAudioAttributesForCarUsage(int carUsage) = 0;
- void setStreamVolume(int streamType, int index, int flags) = 1;
- void setVolumeController(IVolumeController controller) = 2;
- int getStreamMaxVolume(int streamType) = 3;
- int getStreamMinVolume(int streamType) = 4;
- int getStreamVolume(int streamType) = 5;
- boolean isMediaMuted() = 6;
- boolean setMediaMute(boolean mute) = 7;
- AudioAttributes getAudioAttributesForRadio(in String radioType) = 8;
- AudioAttributes getAudioAttributesForExternalSource(in String externalSourceType) = 9;
- String[] getSupportedExternalSourceTypes() = 10;
- String[] getSupportedRadioTypes() = 11;
- String[] getParameterKeys() = 12;
- void setParameters(in String parameters) = 13;
- String getParameters(in String keys) = 14;
- void registerOnParameterChangeListener(in ICarAudioCallback callback) = 15;
- void unregisterOnParameterChangeListener(in ICarAudioCallback callback) = 16;
+ void setGroupVolume(int groupId, int index, int flags);
+ int getGroupMaxVolume(int groupId);
+ int getGroupMinVolume(int groupId);
+ int getGroupVolume(int groupId);
+
+ void setFadeTowardFront(float value);
+ void setBalanceTowardRight(float value);
+
+ String[] getExternalSources();
+ CarAudioPatchHandle createAudioPatch(in String sourceAddress, int usage, int gainInMillibels);
+ void releaseAudioPatch(in CarAudioPatchHandle patch);
+
+ int getVolumeGroupCount();
+ int getVolumeGroupIdForUsage(int usage);
+ int[] getUsagesForVolumeGroupId(int groupId);
+
+ /**
+ * IBinder is ICarVolumeCallback but passed as IBinder due to aidl hidden.
+ */
+ void registerVolumeCallback(in IBinder binder);
+ void unregisterVolumeCallback(in IBinder binder);
}
diff --git a/car-lib/src/android/car/media/ICarVolumeCallback.aidl b/car-lib/src/android/car/media/ICarVolumeCallback.aidl
new file mode 100644
index 0000000..8540680
--- /dev/null
+++ b/car-lib/src/android/car/media/ICarVolumeCallback.aidl
@@ -0,0 +1,38 @@
+/*
+ * 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.media;
+
+/**
+ * Binder interface to callback the volume key events.
+ *
+ * @hide
+ */
+oneway interface ICarVolumeCallback {
+ /**
+ * This is called whenever a group volume is changed.
+ * The changed-to volume index is not included, the caller is encouraged to
+ * get the current group volume index via CarAudioManager.
+ */
+ void onGroupVolumeChanged(int groupId, int flags);
+
+ /**
+ * This is called whenever the master mute state is changed.
+ * The changed-to master mute state is not included, the caller is encouraged to
+ * get the current master mute state via AudioManager.
+ */
+ void onMasterMuteChanged(int flags);
+}
diff --git a/car-lib/src/android/car/navigation/CarNavigationStatusManager.java b/car-lib/src/android/car/navigation/CarNavigationStatusManager.java
index e15a17d..df0dee9 100644
--- a/car-lib/src/android/car/navigation/CarNavigationStatusManager.java
+++ b/car-lib/src/android/car/navigation/CarNavigationStatusManager.java
@@ -15,169 +15,24 @@
*/
package android.car.navigation;
-import android.annotation.IntDef;
import android.car.CarApiUtil;
import android.car.CarLibLog;
import android.car.CarManagerBase;
import android.car.CarNotConnectedException;
import android.car.cluster.renderer.IInstrumentClusterNavigation;
-import android.graphics.Bitmap;
import android.os.Bundle;
import android.os.IBinder;
import android.os.RemoteException;
import android.util.Log;
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
/**
* API for providing navigation status for instrument cluster.
- * @hide
*/
public final class CarNavigationStatusManager implements CarManagerBase {
-
- /** Navigation status */
- public static final int STATUS_UNAVAILABLE = 0;
- public static final int STATUS_ACTIVE = 1;
- public static final int STATUS_INACTIVE = 2;
-
- /** @hide */
- @IntDef({
- STATUS_UNAVAILABLE,
- STATUS_ACTIVE,
- STATUS_INACTIVE
- })
- @Retention(RetentionPolicy.SOURCE)
- public @interface Status {}
-
- /* Turn Types */
- /** Turn is of an unknown type.*/
- public static final int TURN_UNKNOWN = 0;
- /** Starting point of the navigation. */
- public static final int TURN_DEPART = 1;
- /** No turn, but the street name changes. */
- public static final int TURN_NAME_CHANGE = 2;
- /** Slight turn. */
- public static final int TURN_SLIGHT_TURN = 3;
- /** Regular turn. */
- public static final int TURN_TURN = 4;
- /** Sharp turn. */
- public static final int TURN_SHARP_TURN = 5;
- /** U-turn. */
- public static final int TURN_U_TURN = 6;
- /** On ramp. */
- public static final int TURN_ON_RAMP = 7;
- /** Off ramp. */
- public static final int TURN_OFF_RAMP = 8;
- /** Road forks (diverges). */
- public static final int TURN_FORK = 9;
- /** Road merges. */
- public static final int TURN_MERGE = 10;
- /** Roundabout entrance on which the route ends. Instruction says "Enter roundabout". */
- public static final int TURN_ROUNDABOUT_ENTER = 11;
- /** Roundabout exit. */
- public static final int TURN_ROUNDABOUT_EXIT = 12;
- /**
- * Roundabout entrance and exit. For example, "At the roundabout, take Nth exit." Be sure to
- * specify the "turnNumber" parameter when using this type.
- */
- public static final int TURN_ROUNDABOUT_ENTER_AND_EXIT = 13;
- /** Potentially confusing intersection where the user should steer straight. */
- public static final int TURN_STRAIGHT = 14;
- /** You're on a boat! */
- public static final int TURN_FERRY_BOAT = 16;
- /** Train ferries for vehicles. */
- public static final int TURN_FERRY_TRAIN = 17;
- /** You have arrived. */
- public static final int TURN_DESTINATION = 19;
-
- /** @hide */
- @IntDef({
- TURN_UNKNOWN,
- TURN_DEPART,
- TURN_NAME_CHANGE,
- TURN_SLIGHT_TURN,
- TURN_TURN,
- TURN_SHARP_TURN,
- TURN_U_TURN,
- TURN_ON_RAMP,
- TURN_OFF_RAMP,
- TURN_FORK,
- TURN_MERGE,
- TURN_ROUNDABOUT_ENTER,
- TURN_ROUNDABOUT_EXIT,
- TURN_ROUNDABOUT_ENTER_AND_EXIT,
- TURN_STRAIGHT,
- TURN_FERRY_BOAT,
- TURN_FERRY_TRAIN,
- TURN_DESTINATION
- })
- @Retention(RetentionPolicy.SOURCE)
- public @interface TurnEvent {}
-
- /**
- * Event type that holds information about next maneuver.
- * @hide
- */
- public static final int EVENT_TYPE_NEXT_MANEUVER_INFO = 1;
- /**
- * Event type that holds information regarding distance/time to the next maneuver.
- * @hide
- */
- public static final int EVENT_TYPE_NEXT_MANEUVER_COUNTDOWN = 2;
- /**
- * All custom (vendor-specific) event types should be equal or greater than this constant.
- * @hide
- */
- public static final int EVENT_TYPE_VENDOR_FIRST = 1024;
-
- /* Turn Side */
- /** Turn is on the left side of the vehicle. */
- public static final int TURN_SIDE_LEFT = 1;
- /** Turn is on the right side of the vehicle. */
- public static final int TURN_SIDE_RIGHT = 2;
- /** Turn side is unspecified. */
- public static final int TURN_SIDE_UNSPECIFIED = 3;
-
- /** @hide */
- @IntDef({
- TURN_SIDE_LEFT,
- TURN_SIDE_RIGHT,
- TURN_SIDE_UNSPECIFIED
- })
- public @interface TurnSide {}
-
- private static final int START = 1;
- private static final int STOP = 2;
-
- /**
- * Distance units for use in {@link #sendNavigationTurnDistanceEvent(int, int, int, int)}.
- */
- /** Distance is specified in meters. */
- public static final int DISTANCE_METERS = 1;
- /** Distance is specified in kilometers. */
- public static final int DISTANCE_KILOMETERS = 2;
- /** Distance is specified in miles. */
- public static final int DISTANCE_MILES = 3;
- /** Distance is specified in feet. */
- public static final int DISTANCE_FEET = 4;
- /** Distance is specified in yards. */
- public static final int DISTANCE_YARDS = 5;
-
- /** @hide */
- @IntDef({
- DISTANCE_METERS,
- DISTANCE_KILOMETERS,
- DISTANCE_MILES,
- DISTANCE_FEET,
- DISTANCE_YARDS
- })
- public @interface DistanceUnit {}
-
private static final String TAG = CarLibLog.TAG_NAV;
private final IInstrumentClusterNavigation mService;
-
/**
* Only for CarServiceLoader
* @hide
@@ -187,101 +42,14 @@
}
/**
- * @param status new instrument cluster navigation status.
- * @throws CarNotConnectedException if the connection to the car service has been lost.
- */
- public void sendNavigationStatus(@Status int status) throws CarNotConnectedException {
- try {
- if (status == STATUS_ACTIVE) {
- mService.onStartNavigation();
- } else {
- mService.onStopNavigation();
- }
- } catch (IllegalStateException e) {
- CarApiUtil.checkCarNotConnectedExceptionFromCarService(e);
- } catch (RemoteException e) {
- handleCarServiceRemoteExceptionAndThrow(e);
- }
- }
-
- /**
- * Sends a Navigation Next Step event to the car.
- * <p>
- * Note: For an example of a roundabout: if a roundabout has 4 exits, spaced evenly, then the
- * first exit will have turnNumber=1, turnAngle=90; the second will have turnNumber=2,
- * turnAngle=180; the third will have turnNumber=3, turnAngle=270. turnNumber and turnAngle are
- * counted in the direction of travel around the roundabout (clockwise for roads where the car
- * drives on the left-hand side of the road, such as Australia; anti-clockwise for roads where
- * the car drives on the right, such as the USA).
- *
- * @param turnEvent turn event like ({@link #TURN_TURN}, {@link #TURN_U_TURN},
- * {@link #TURN_ROUNDABOUT_ENTER_AND_EXIT}, etc).
- * @param eventName Name of the turn event like road name to turn. For example "Charleston road"
- * in "Turn right to Charleston road"
- * @param turnAngle turn angle in degrees between the roundabout entry and exit (0..359). Only
- * used for event type {@link #TURN_ROUNDABOUT_ENTER_AND_EXIT}. -1 if unused.
- * @param turnNumber turn number, counting around from the roundabout entry to the exit. Only
- * used for event type {@link #TURN_ROUNDABOUT_ENTER_AND_EXIT}. -1 if unused.
- * @param image image to be shown in the instrument cluster. Null if instrument
- * cluster type doesn't support images.
- * @param turnSide turn side ({@link #TURN_SIDE_LEFT}, {@link #TURN_SIDE_RIGHT} or
- * {@link #TURN_SIDE_UNSPECIFIED}).
- * @throws CarNotConnectedException if the connection to the car service has been lost.
- *
- * @deprecated Use {@link #sendEvent(int, Bundle)} instead.
- */
- public void sendNavigationTurnEvent(@TurnEvent int turnEvent, CharSequence eventName,
- int turnAngle, int turnNumber, Bitmap image, @TurnSide int turnSide)
- throws CarNotConnectedException {
- try {
- mService.onNextManeuverChanged(turnEvent, eventName, turnAngle, turnNumber, image,
- turnSide);
- } catch (IllegalStateException e) {
- CarApiUtil.checkCarNotConnectedExceptionFromCarService(e);
- } catch (RemoteException e) {
- handleCarServiceRemoteExceptionAndThrow(e);
- }
- }
-
- /**
- * Sends a Navigation Next Step Distance event to the car.
- *
- * @param distanceMeters Distance to next event in meters.
- * @param timeSeconds Time to next event in seconds.
- * @param displayDistanceMillis Distance to the next event. This is exactly the same distance
- * that navigation app is displaying. Use it when you want to display distance, it has
- * appropriate rounding function and units are in sync with navigation app. This parameter is
- * in {@code displayDistanceUnit * 1000}.
- * @param displayDistanceUnit units for {@param displayDistanceMillis} param.
- * See {@link DistanceUnit} for acceptable values.
- * @throws CarNotConnectedException if the connection to the car service has been lost.
- *
- * @deprecated Use {@link #sendEvent(int, Bundle)} instead.
- */
- public void sendNavigationTurnDistanceEvent(int distanceMeters, int timeSeconds,
- int displayDistanceMillis, @DistanceUnit int displayDistanceUnit)
- throws CarNotConnectedException {
- try {
- mService.onNextManeuverDistanceChanged(distanceMeters, timeSeconds,
- displayDistanceMillis, displayDistanceUnit);
- } catch (IllegalStateException e) {
- CarApiUtil.checkCarNotConnectedExceptionFromCarService(e);
- } catch (RemoteException e) {
- handleCarServiceRemoteExceptionAndThrow(e);
- }
- }
-
- /**
* Sends events from navigation app to instrument cluster.
*
+ * <p>The event type and bundle can be populated by
+ * {@link android.support.car.navigation.CarNavigationStatusEvent}.
+ *
* @param eventType event type
* @param bundle object that holds data about the event
* @throws CarNotConnectedException if the connection to the car service has been lost.
- *
- * @see #EVENT_TYPE_NEXT_MANEUVER_INFO
- * @see #EVENT_TYPE_NEXT_MANEUVER_COUNTDOWN
- *
- * @hide
*/
public void sendEvent(int eventType, Bundle bundle) throws CarNotConnectedException {
try {
@@ -293,10 +61,9 @@
}
}
+ /** @hide */
@Override
- public void onCarDisconnected() {
- Log.d(TAG, "onCarDisconnected");
- }
+ public void onCarDisconnected() {}
/** Returns navigation features of instrument cluster */
public CarNavigationInstrumentCluster getInstrumentClusterInfo()
diff --git a/car-lib/src/android/car/settings/CarConfigurationManager.java b/car-lib/src/android/car/settings/CarConfigurationManager.java
new file mode 100644
index 0000000..b492c4f
--- /dev/null
+++ b/car-lib/src/android/car/settings/CarConfigurationManager.java
@@ -0,0 +1,58 @@
+/*
+ * 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.settings;
+
+import android.car.CarManagerBase;
+import android.car.CarNotConnectedException;
+import android.os.IBinder;
+import android.os.RemoteException;
+import android.util.Log;
+
+/**
+ * Manager that exposes car configuration values that are stored on the system.
+ */
+public class CarConfigurationManager implements CarManagerBase {
+ private static final String TAG = "CarConfigurationManager";
+
+ private final ICarConfigurationManager mConfigurationService;
+
+ /** @hide */
+ public CarConfigurationManager(IBinder service) {
+ mConfigurationService = ICarConfigurationManager.Stub.asInterface(service);
+ }
+
+ /**
+ * Returns a configuration for Speed Bump that will determine when it kicks in.
+ *
+ * @return A {@link SpeedBumpConfiguration} that contains the configuration values.
+ * @throws CarNotConnectedException If the configuration cannot be retrieved.
+ */
+ public SpeedBumpConfiguration getSpeedBumpConfiguration() throws CarNotConnectedException {
+ try {
+ return mConfigurationService.getSpeedBumpConfiguration();
+ } catch (RemoteException e) {
+ Log.e(TAG, "Could not retrieve SpeedBumpConfiguration", e);
+ throw new CarNotConnectedException(e);
+ }
+ }
+
+ /** @hide */
+ @Override
+ public void onCarDisconnected() {
+ // Nothing to release.
+ }
+}
diff --git a/car-lib/src/android/car/settings/CarSettings.java b/car-lib/src/android/car/settings/CarSettings.java
index 6e2a8f4..d7402b2 100644
--- a/car-lib/src/android/car/settings/CarSettings.java
+++ b/car-lib/src/android/car/settings/CarSettings.java
@@ -45,90 +45,6 @@
*/
public static final String KEY_GARAGE_MODE_MAINTENANCE_WINDOW =
"android.car.GARAGE_MODE_MAINTENANCE_WINDOW";
- /**
- * Key for music volume. This is used internally, changing this value will not change the
- * volume.
- *
- * @hide
- */
- public static final String KEY_VOLUME_MUSIC = "android.car.VOLUME_MUSIC";
- /**
- * Key for navigation volume. This is used internally, changing this value will not change
- * the volume.
- *
- * @hide
- */
- public static final String KEY_VOLUME_NAVIGATION = "android.car.VOLUME_NAVIGATION";
- /**
- * Key for voice command volume. This is used internally, changing this value will
- * not change the volume.
- *
- * @hide
- */
- public static final String KEY_VOLUME_VOICE_COMMAND = "android.car.VOLUME_VOICE_COMMAND";
- /**
- * Key for call volume. This is used internally, changing this value will not change the
- * volume.
- *
- * @hide
- */
- public static final String KEY_VOLUME_CALL = "android.car.VOLUME_CALL";
- /**
- * Key for phone ring volume. This is used internally, changing this value will not change
- * the volume.
- *
- * @hide
- */
- public static final String KEY_VOLUME_RINGTONE = "android.car.VOLUME_RINGTONE";
- /**
- * Key for alarm volume. This is used internally, changing this value will not change the
- * volume.
- *
- * @hide
- */
- public static final String KEY_VOLUME_ALARM = "android.car.VOLUME_ALARM";
- /**
- * Key for notification volume. This is used internally, changing this value will not change
- * the volume.
- *
- * @hide
- */
- public static final String KEY_VOLUME_NOTIFICATION = "android.car.VOLUME_NOTIFICATION";
- /**
- * Key for safety alert volume. This is used internally, changing this value will not
- * change the volume.
- *
- * @hide
- */
- public static final String KEY_VOLUME_SAFETY_ALERT = "android.car.VOLUME_SAFETY_ALERT";
- /**
- * Key for cd volume. This is used internally, changing this value will not change the
- * volume.
- *
- * @hide
- */
- public static final String KEY_VOLUME_CD_ROM = "android.car.VOLUME_CD_ROM";
- /**
- * Key for aux volume. This is used internally, changing this value will not change the
- * volume.
- *
- * @hide
- */
- public static final String KEY_VOLUME_AUX = "android.car.VOLUME_AUX";
- /**
- * Key for system volume. This is used internally, changing this value will not change the
- * volume.
- *
- * @hide
- */
- public static final String KEY_VOLUME_SYSTEM_SOUND = "android.car.VOLUME_SYSTEM";
- /**
- * Key for radio volume. This is used internally, changing this value will not change the
- * volume.
- *
- * @hide
- */
- public static final String KEY_VOLUME_RADIO = "android.car.VOLUME_RADIO";
}
/**
@@ -146,6 +62,20 @@
public static final int DEFAULT_GARAGE_MODE_MAINTENANCE_WINDOW = 10 * 60 * 1000; // 10 mins
/**
+ * Id for user that is set as default to boot into.
+ *
+ * @hide
+ */
+ public static final int DEFAULT_USER_ID_TO_BOOT_INTO = 10; // Default to first created user.
+
+ /**
+ * Id for user that is last logged in to.
+ *
+ * @hide
+ */
+ public static final int LAST_ACTIVE_USER_ID = 10; // Default to first created user.
+
+ /**
* @hide
*/
public static final class Secure {
@@ -175,8 +105,16 @@
"android.car.BLUETOOTH_AUTOCONNECT_MESSAGING_DEVICES";
/**
+ * Key for a list of devices to automatically connect on Bluetooth PAN profile
+ * Written to and read by {@link com.android.car.BluetoothDeviceConnectionPolicy}
+ * @hide
+ */
+ public static final String KEY_BLUETOOTH_AUTOCONNECT_NETWORK_DEVICES =
+ "android.car.BLUETOOTH_AUTOCONNECT_NETWORK_DEVICES";
+
+ /**
* Key for setting primary Music Device
- * Written to by a client with {@link com.android.car.Manifest.permission.BLUETOOTH_ADMIN}
+ * Written to by a client with {@link android.Manifest.permission#BLUETOOTH_ADMIN}
* Read by {@link com.android.car.BluetoothDeviceConnectionPolicy}
* @hide
*/
@@ -185,7 +123,7 @@
/**
* Key for setting secondary Music Device
- * Written to by a client with {@link com.android.car.Manifest.permission.BLUETOOTH_ADMIN}
+ * Written to by a client with {@link android.Manifest.permission#BLUETOOTH_ADMIN}
* Read by {@link com.android.car.BluetoothDeviceConnectionPolicy}
* @hide
*/
@@ -194,7 +132,7 @@
/**
* Key for setting Primary Phone Device
- * Written to by a client with {@link com.android.car.Manifest.permission.BLUETOOTH_ADMIN}
+ * Written to by a client with {@link android.Manifest.permission#BLUETOOTH_ADMIN}
* Read by {@link com.android.car.BluetoothDeviceConnectionPolicy}
* @hide
*/
@@ -203,7 +141,7 @@
/**
* Key for setting Secondary Phone Device
- * Written to by a client with {@link com.android.car.Manifest.permission.BLUETOOTH_ADMIN}
+ * Written to by a client with {@link android.Manifest.permission#BLUETOOTH_ADMIN}
* Read by {@link com.android.car.BluetoothDeviceConnectionPolicy}
* @hide
*/
@@ -212,7 +150,7 @@
/**
* Key for setting Primary Messaging Device
- * Written to by a client with {@link com.android.car.Manifest.permission.BLUETOOTH_ADMIN}
+ * Written to by a client with {@link android.Manifest.permission#BLUETOOTH_ADMIN}
* Read by {@link com.android.car.BluetoothDeviceConnectionPolicy}
* @hide
*/
@@ -221,12 +159,31 @@
/**
* Key for setting Secondary Messaging Device
- * Written to by a client with {@link com.android.car.Manifest.permission.BLUETOOTH_ADMIN}
+ * Written to by a client with {@link android.Manifest.permission#BLUETOOTH_ADMIN}
* Read by {@link com.android.car.BluetoothDeviceConnectionPolicy}
* @hide
*/
public static final String KEY_BLUETOOTH_AUTOCONNECT_MESSAGING_DEVICE_PRIORITY_1 =
"android.car.BLUETOOTH_AUTOCONNECT_MESSAGING_DEVICE_PRIORITY_1";
+ /**
+ * Key for setting Primary Network Device
+ * Written to by a client with {@link com.android.car.Manifest.permission.BLUETOOTH_ADMIN}
+ * Read by {@link com.android.car.BluetoothDeviceConnectionPolicy}
+ * @hide
+ */
+ public static final String KEY_BLUETOOTH_AUTOCONNECT_NETWORK_DEVICE_PRIORITY_0 =
+ "android.car.BLUETOOTH_AUTOCONNECT_NETWORK_DEVICE_PRIORITY_0";
+
+ /**
+ * Key for setting Secondary Network Device
+ * Written to by a client with {@link com.android.car.Manifest.permission.BLUETOOTH_ADMIN}
+ * Read by {@link com.android.car.BluetoothDeviceConnectionPolicy}
+ * @hide
+ */
+ public static final String KEY_BLUETOOTH_AUTOCONNECT_NETWORK_DEVICE_PRIORITY_1 =
+ "android.car.BLUETOOTH_AUTOCONNECT_NETWORK_DEVICE_PRIORITY_1";
+
+
}
}
diff --git a/car-lib/src/android/car/settings/ICarConfigurationManager.aidl b/car-lib/src/android/car/settings/ICarConfigurationManager.aidl
new file mode 100644
index 0000000..5fe4088
--- /dev/null
+++ b/car-lib/src/android/car/settings/ICarConfigurationManager.aidl
@@ -0,0 +1,32 @@
+/*
+ * 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.settings;
+
+import android.car.settings.SpeedBumpConfiguration;
+
+/**
+ * Binder interface for {@link android.car.settings.CarConfigurationManager}.
+ *
+ * @hide
+ */
+interface ICarConfigurationManager {
+ /**
+ * Returns the configuration for SpeedBump if it exists. If it does not, then a default
+ * configuration will be returned.
+ */
+ SpeedBumpConfiguration getSpeedBumpConfiguration() = 0;
+}
diff --git a/car-lib/src/android/car/hardware/radio/CarRadioEvent.aidl b/car-lib/src/android/car/settings/SpeedBumpConfiguration.aidl
similarity index 82%
rename from car-lib/src/android/car/hardware/radio/CarRadioEvent.aidl
rename to car-lib/src/android/car/settings/SpeedBumpConfiguration.aidl
index 0865646..084fca0 100644
--- a/car-lib/src/android/car/hardware/radio/CarRadioEvent.aidl
+++ b/car-lib/src/android/car/settings/SpeedBumpConfiguration.aidl
@@ -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.
@@ -14,6 +14,6 @@
* limitations under the License.
*/
-package android.car.hardware.radio;
+package android.car.settings;
-parcelable CarRadioEvent;
+parcelable SpeedBumpConfiguration;
diff --git a/car-lib/src/android/car/settings/SpeedBumpConfiguration.java b/car-lib/src/android/car/settings/SpeedBumpConfiguration.java
new file mode 100644
index 0000000..39a1eab
--- /dev/null
+++ b/car-lib/src/android/car/settings/SpeedBumpConfiguration.java
@@ -0,0 +1,122 @@
+/*
+ * 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.settings;
+
+import android.os.Parcel;
+import android.os.Parcelable;
+
+import java.util.Objects;
+
+/**
+ * A configuration struct that holds information for tweaking SpeedBump settings.
+ *
+ * @see androidx.car.moderator.SpeedBumpView
+ */
+public final class SpeedBumpConfiguration implements Parcelable {
+ private final double mAcquiredPermitsPerSecond;
+ private final double mMaxPermitPool;
+ private final long mPermitFillDelay;
+
+ public SpeedBumpConfiguration(double permitsPerSecond, double maxPermitPool,
+ long permitFillDelay) {
+ mAcquiredPermitsPerSecond = permitsPerSecond;
+ mMaxPermitPool = maxPermitPool;
+ mPermitFillDelay = permitFillDelay;
+ }
+
+ /**
+ * Returns the number of permitted actions that are acquired each second that the user has not
+ * interacted with the {@code SpeedBumpView}.
+ */
+ public double getAcquiredPermitsPerSecond() {
+ return mAcquiredPermitsPerSecond;
+ }
+
+ /**
+ * Returns the maximum number of permits that can be acquired when the user is idling.
+ */
+ public double getMaxPermitPool() {
+ return mMaxPermitPool;
+ }
+
+ /**
+ * Returns the delay time before when the permit pool has been depleted and when it begins to
+ * refill.
+ */
+ public long getPermitFillDelay() {
+ return mPermitFillDelay;
+ }
+
+ @Override
+ public String toString() {
+ return String.format(
+ "[acquired_permits_per_second: %f, max_permit_pool: %f, permit_fill_delay: %d]",
+ mAcquiredPermitsPerSecond,
+ mMaxPermitPool,
+ mPermitFillDelay);
+ }
+
+ @Override
+ public boolean equals(Object object) {
+ if (object == this) {
+ return true;
+ }
+
+ if (!(object instanceof SpeedBumpConfiguration)) {
+ return false;
+ }
+
+ SpeedBumpConfiguration other = (SpeedBumpConfiguration) object;
+ return mAcquiredPermitsPerSecond == other.getAcquiredPermitsPerSecond()
+ && mMaxPermitPool == other.getMaxPermitPool()
+ && mPermitFillDelay == other.getPermitFillDelay();
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(mAcquiredPermitsPerSecond, mMaxPermitPool, mPermitFillDelay);
+ }
+
+ @Override
+ public void writeToParcel(Parcel desk, int flags) {
+ desk.writeDouble(mAcquiredPermitsPerSecond);
+ desk.writeDouble(mMaxPermitPool);
+ desk.writeLong(mPermitFillDelay);
+ }
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ private SpeedBumpConfiguration(Parcel in) {
+ mAcquiredPermitsPerSecond = in.readDouble();
+ mMaxPermitPool = in.readDouble();
+ mPermitFillDelay = in.readLong();
+ }
+
+ public static final Parcelable.Creator<SpeedBumpConfiguration> CREATOR =
+ new Parcelable.Creator<SpeedBumpConfiguration>() {
+ public SpeedBumpConfiguration createFromParcel(Parcel in) {
+ return new SpeedBumpConfiguration(in);
+ }
+
+ public SpeedBumpConfiguration[] newArray(int size) {
+ return new SpeedBumpConfiguration[size];
+ }
+ };
+}
diff --git a/car-lib/src/android/car/storagemonitoring/CarStorageMonitoringManager.java b/car-lib/src/android/car/storagemonitoring/CarStorageMonitoringManager.java
new file mode 100644
index 0000000..2320952
--- /dev/null
+++ b/car-lib/src/android/car/storagemonitoring/CarStorageMonitoringManager.java
@@ -0,0 +1,309 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package android.car.storagemonitoring;
+
+import android.annotation.RequiresPermission;
+import android.annotation.SystemApi;
+import android.car.Car;
+import android.car.CarManagerBase;
+import android.car.CarNotConnectedException;
+import android.os.Handler;
+import android.os.IBinder;
+import android.os.RemoteException;
+import com.android.car.internal.SingleMessageHandler;
+import java.lang.ref.WeakReference;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+import static android.car.CarApiUtil.checkCarNotConnectedExceptionFromCarService;
+
+/**
+ * API for retrieving information and metrics about the flash storage.
+ *
+ * @hide
+ */
+@SystemApi
+public final class CarStorageMonitoringManager implements CarManagerBase {
+ private static final String TAG = CarStorageMonitoringManager.class.getSimpleName();
+ private static final int MSG_IO_STATS_EVENT = 0;
+
+ private final ICarStorageMonitoring mService;
+ private ListenerToService mListenerToService;
+ private final SingleMessageHandler<IoStats> mMessageHandler;
+ private final Set<IoStatsListener> mListeners = new HashSet<>();
+
+ public interface IoStatsListener {
+ void onSnapshot(IoStats snapshot);
+ }
+ private static final class ListenerToService extends IIoStatsListener.Stub {
+ private final WeakReference<CarStorageMonitoringManager> mManager;
+
+ ListenerToService(CarStorageMonitoringManager manager) {
+ mManager = new WeakReference<>(manager);
+ }
+
+ @Override
+ public void onSnapshot(IoStats snapshot) {
+ CarStorageMonitoringManager manager = mManager.get();
+ if (manager != null) {
+ manager.mMessageHandler.sendEvents(Collections.singletonList(snapshot));
+ }
+ }
+ }
+
+ public static final String INTENT_EXCESSIVE_IO = "android.car.storagemonitoring.EXCESSIVE_IO";
+
+ public static final int PRE_EOL_INFO_UNKNOWN = 0;
+ public static final int PRE_EOL_INFO_NORMAL = 1;
+ public static final int PRE_EOL_INFO_WARNING = 2;
+ public static final int PRE_EOL_INFO_URGENT = 3;
+
+ public static final long SHUTDOWN_COST_INFO_MISSING = -1;
+
+ /**
+ * @hide
+ */
+ public CarStorageMonitoringManager(IBinder service, Handler handler) {
+ mService = ICarStorageMonitoring.Stub.asInterface(service);
+ mMessageHandler = new SingleMessageHandler<IoStats>(handler, MSG_IO_STATS_EVENT) {
+ @Override
+ protected void handleEvent(IoStats event) {
+ for (IoStatsListener listener : mListeners) {
+ listener.onSnapshot(event);
+ }
+ }
+ };
+ }
+
+ /**
+ * @hide
+ */
+ @Override
+ public void onCarDisconnected() {
+ mListeners.clear();
+ mListenerToService = null;
+ }
+
+ // ICarStorageMonitoring forwards
+
+ /**
+ * This method returns the value of the "pre EOL" indicator for the flash storage
+ * as retrieved during the current boot cycle.
+ *
+ * It will return either PRE_EOL_INFO_UNKNOWN if the value can't be determined,
+ * or one of PRE_EOL_INFO_{NORMAL|WARNING|URGENT} depending on the device state.
+ */
+ @RequiresPermission(value=Car.PERMISSION_STORAGE_MONITORING)
+ public int getPreEolIndicatorStatus() throws CarNotConnectedException {
+ try {
+ return mService.getPreEolIndicatorStatus();
+ } catch (IllegalStateException e) {
+ checkCarNotConnectedExceptionFromCarService(e);
+ } catch (RemoteException e) {
+ throw new CarNotConnectedException();
+ }
+ return PRE_EOL_INFO_UNKNOWN;
+ }
+
+ /**
+ * This method returns the value of the wear estimate indicators for the flash storage
+ * as retrieved during the current boot cycle.
+ *
+ * The indicators are guaranteed to be a lower-bound on the actual wear of the storage.
+ * Current technology in common automotive usage offers estimates in 10% increments.
+ *
+ * If either or both indicators are not available, they will be reported as UNKNOWN.
+ */
+ @RequiresPermission(value=Car.PERMISSION_STORAGE_MONITORING)
+ public WearEstimate getWearEstimate() throws CarNotConnectedException {
+ try {
+ return mService.getWearEstimate();
+ } catch (IllegalStateException e) {
+ checkCarNotConnectedExceptionFromCarService(e);
+ } catch (RemoteException e) {
+ throw new CarNotConnectedException();
+ }
+ return WearEstimate.UNKNOWN_ESTIMATE;
+ }
+
+ /**
+ * This method returns a list of all changes in wear estimate indicators detected during the
+ * lifetime of the system.
+ *
+ * The indicators are not guaranteed to persist across a factory reset.
+ *
+ * The indicators are guaranteed to be a lower-bound on the actual wear of the storage.
+ * Current technology in common automotive usage offers estimates in 10% increments.
+ *
+ * If no indicators are available, an empty list will be returned.
+ */
+ @RequiresPermission(value=Car.PERMISSION_STORAGE_MONITORING)
+ public List<WearEstimateChange> getWearEstimateHistory() throws CarNotConnectedException {
+ try {
+ return mService.getWearEstimateHistory();
+ } catch (IllegalStateException e) {
+ checkCarNotConnectedExceptionFromCarService(e);
+ } catch (RemoteException e) {
+ throw new CarNotConnectedException();
+ }
+ return Collections.emptyList();
+ }
+
+ /**
+ * This method returns a list of per user-id I/O activity metrics as collected at the end of
+ * system boot.
+ *
+ * The BOOT_COMPLETE broadcast is used as the trigger to collect this data. The implementation
+ * may impose an additional, and even variable across boot cycles, delay between the sending
+ * of the broadcast and the collection of the data.
+ *
+ * If the information is not available, an empty list will be returned.
+ */
+ @RequiresPermission(value=Car.PERMISSION_STORAGE_MONITORING)
+ public List<IoStatsEntry> getBootIoStats() throws CarNotConnectedException {
+ try {
+ return mService.getBootIoStats();
+ } catch (IllegalStateException e) {
+ checkCarNotConnectedExceptionFromCarService(e);
+ } catch (RemoteException e) {
+ throw new CarNotConnectedException();
+ }
+ return Collections.emptyList();
+ }
+
+ /**
+ * This method returns an approximation of the number of bytes written to disk during
+ * the course of the previous system shutdown.
+ *
+ * <p>For purposes of this API the system shutdown is defined as starting when CarService
+ * receives the ACTION_SHUTDOWN or ACTION_REBOOT intent from the system.</p>
+ *
+ * <p>The information provided by this API does not provide attribution of the disk writes to
+ * specific applications or system daemons.</p>
+ *
+ * <p>The information returned by this call is a best effort guess, whose accuracy depends
+ * on the underlying file systems' ability to reliably track and accumulate
+ * disk write sizes.</p>
+ *
+ * <p>A corrupt file system, or one which was not cleanly unmounted during shutdown, may
+ * be unable to provide any information, or may provide incorrect data. While the API
+ * will attempt to detect these scenarios, the detection may fail and incorrect data
+ * may end up being used in calculations.</p>
+ *
+ * <p>If the information is not available, SHUTDOWN_COST_INFO_MISSING will be returned.</p>s
+ */
+ @RequiresPermission(value=Car.PERMISSION_STORAGE_MONITORING)
+ public long getShutdownDiskWriteAmount() throws CarNotConnectedException {
+ try {
+ return mService.getShutdownDiskWriteAmount();
+ } catch (IllegalStateException e) {
+ checkCarNotConnectedExceptionFromCarService(e);
+ } catch (RemoteException e) {
+ throw new CarNotConnectedException();
+ }
+ return SHUTDOWN_COST_INFO_MISSING;
+ }
+
+ /**
+ * This method returns a list of per user-id I/O activity metrics as collected from kernel
+ * start until the last snapshot.
+ *
+ * The samples provided might be as old as the value of the ioStatsRefreshRateSeconds setting.
+ *
+ * If the information is not available, an empty list will be returned.
+ */
+ @RequiresPermission(value=Car.PERMISSION_STORAGE_MONITORING)
+ public List<IoStatsEntry> getAggregateIoStats() throws CarNotConnectedException {
+ try {
+ return mService.getAggregateIoStats();
+ } catch (IllegalStateException e) {
+ checkCarNotConnectedExceptionFromCarService(e);
+ } catch (RemoteException e) {
+ throw new CarNotConnectedException();
+ }
+ return Collections.emptyList();
+ }
+
+ /**
+ * This method returns a list of the I/O stats deltas currently stored by the system.
+ *
+ * Periodically, the system gathers I/O activity metrics and computes and stores a delta from
+ * the previous cycle. The timing and the number of these stored samples are configurable
+ * by the OEM.
+ *
+ * The samples are returned in order from the oldest to the newest.
+ *
+ * If the information is not available, an empty list will be returned.
+ */
+ @RequiresPermission(value=Car.PERMISSION_STORAGE_MONITORING)
+ public List<IoStats> getIoStatsDeltas() throws CarNotConnectedException {
+ try {
+ return mService.getIoStatsDeltas();
+ } catch (IllegalStateException e) {
+ checkCarNotConnectedExceptionFromCarService(e);
+ } catch (RemoteException e) {
+ throw new CarNotConnectedException();
+ }
+ return Collections.emptyList();
+ }
+
+ /**
+ * This method registers a new listener to receive I/O stats deltas.
+ *
+ * The system periodically gathers I/O activity metrics and computes a delta of such
+ * activity. Registered listeners will receive those deltas as they are available.
+ *
+ * The timing of availability of the deltas is configurable by the OEM.
+ */
+ @RequiresPermission(value=Car.PERMISSION_STORAGE_MONITORING)
+ public void registerListener(IoStatsListener listener) throws CarNotConnectedException {
+ try {
+ if (mListeners.isEmpty()) {
+ if (mListenerToService == null) {
+ mListenerToService = new ListenerToService(this);
+ }
+ mService.registerListener(mListenerToService);
+ }
+ mListeners.add(listener);
+ } catch (IllegalStateException e) {
+ checkCarNotConnectedExceptionFromCarService(e);
+ } catch (RemoteException e) {
+ throw new CarNotConnectedException();
+ }
+ }
+
+ /**
+ * This method removes a registered listener of I/O stats deltas.
+ */
+ @RequiresPermission(value=Car.PERMISSION_STORAGE_MONITORING)
+ public void unregisterListener(IoStatsListener listener) throws CarNotConnectedException {
+ try {
+ if (!mListeners.remove(listener)) {
+ return;
+ }
+ if (mListeners.isEmpty()) {
+ mService.unregisterListener(mListenerToService);
+ mListenerToService = null;
+ }
+ } catch (IllegalStateException e) {
+ checkCarNotConnectedExceptionFromCarService(e);
+ } catch (RemoteException e) {
+ throw new CarNotConnectedException();
+ }
+ }
+}
diff --git a/car-lib/src/android/car/storagemonitoring/ICarStorageMonitoring.aidl b/car-lib/src/android/car/storagemonitoring/ICarStorageMonitoring.aidl
new file mode 100644
index 0000000..f7ef405
--- /dev/null
+++ b/car-lib/src/android/car/storagemonitoring/ICarStorageMonitoring.aidl
@@ -0,0 +1,71 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.car.storagemonitoring;
+
+import android.car.storagemonitoring.IIoStatsListener;
+import android.car.storagemonitoring.IoStatsEntry;
+import android.car.storagemonitoring.IoStats;
+import android.car.storagemonitoring.WearEstimate;
+import android.car.storagemonitoring.WearEstimateChange;
+
+/** @hide */
+interface ICarStorageMonitoring {
+ /**
+ * Returns the value of the PRE_EOL register.
+ */
+ int getPreEolIndicatorStatus() = 1;
+
+ /**
+ * Returns the current wear estimate indicators.
+ */
+ WearEstimate getWearEstimate() = 2;
+
+ /**
+ * Returns the list of all observed wear estimate changes.
+ */
+ List<WearEstimateChange> getWearEstimateHistory() = 3;
+
+ /**
+ * Returns I/O stats as collected at service boot time.
+ */
+ List<IoStatsEntry> getBootIoStats() = 4;
+
+ /**
+ * Returns total I/O stats as collected from kernel start until the last snapshot.
+ */
+ List<IoStatsEntry> getAggregateIoStats() = 5;
+
+ /**
+ * Return the I/O stats deltas currently known to the service.
+ */
+ List<IoStats> getIoStatsDeltas() = 6;
+
+ /**
+ * Register a new listener to receive new I/O activity deltas as they are generated.
+ */
+ void registerListener(IIoStatsListener listener) = 7;
+
+ /**
+ * Remove a listener registration, terminating delivery of I/O activity deltas to it.
+ */
+ void unregisterListener(IIoStatsListener listener) = 8;
+
+ /**
+ * Returns the approximate amount of bytes written to disk during the previous shutdown.
+ */
+ long getShutdownDiskWriteAmount() = 9;
+}
diff --git a/car-lib/src/android/car/media/ICarAudioCallback.aidl b/car-lib/src/android/car/storagemonitoring/IIoStatsListener.aidl
similarity index 63%
copy from car-lib/src/android/car/media/ICarAudioCallback.aidl
copy to car-lib/src/android/car/storagemonitoring/IIoStatsListener.aidl
index 7e01c71..a744564 100644
--- a/car-lib/src/android/car/media/ICarAudioCallback.aidl
+++ b/car-lib/src/android/car/storagemonitoring/IIoStatsListener.aidl
@@ -14,9 +14,16 @@
* limitations under the License.
*/
-package android.car.media;
+package android.car.storagemonitoring;
+
+import android.car.storagemonitoring.IoStats;
/** @hide */
-oneway interface ICarAudioCallback {
- void onParameterChange(in String params) = 0;
+oneway interface IIoStatsListener {
+ /**
+ * Called each time a new uid_io activity snapshot is generated by the service.
+ *
+ * The interval at which new snapshots are generated is an OEM-configurable property.
+ */
+ void onSnapshot(in IoStats snapshot) = 0;
}
diff --git a/car-lib/src/android/car/hardware/radio/CarRadioEvent.aidl b/car-lib/src/android/car/storagemonitoring/IoStats.aidl
similarity index 82%
copy from car-lib/src/android/car/hardware/radio/CarRadioEvent.aidl
copy to car-lib/src/android/car/storagemonitoring/IoStats.aidl
index 0865646..cfb991d 100644
--- a/car-lib/src/android/car/hardware/radio/CarRadioEvent.aidl
+++ b/car-lib/src/android/car/storagemonitoring/IoStats.aidl
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2015 The Android Open Source Project
+ * 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.
@@ -14,6 +14,6 @@
* limitations under the License.
*/
-package android.car.hardware.radio;
+package android.car.storagemonitoring;
-parcelable CarRadioEvent;
+parcelable IoStats;
diff --git a/car-lib/src/android/car/storagemonitoring/IoStats.java b/car-lib/src/android/car/storagemonitoring/IoStats.java
new file mode 100644
index 0000000..3fc03c6
--- /dev/null
+++ b/car-lib/src/android/car/storagemonitoring/IoStats.java
@@ -0,0 +1,191 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package android.car.storagemonitoring;
+
+import android.annotation.SystemApi;
+import android.car.storagemonitoring.IoStatsEntry.Metrics;
+import android.os.Parcel;
+import android.os.Parcelable;
+import android.util.JsonWriter;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Objects;
+import java.util.StringJoiner;
+import org.json.JSONArray;
+import org.json.JSONException;
+import org.json.JSONObject;
+
+/**
+ * Delta of uid_io stats taken at a sample point.
+ *
+ * @hide
+ */
+@SystemApi
+public class IoStats implements Parcelable {
+ public static final Creator<IoStats> CREATOR = new Creator<IoStats>() {
+ @Override
+ public IoStats createFromParcel(Parcel in) {
+ return new IoStats(in);
+ }
+
+ @Override
+ public IoStats[] newArray(int size) {
+ return new IoStats[size];
+ }
+ };
+
+ private final List<IoStatsEntry> mStats;
+ private final long mUptimeTimestamp;
+
+ public IoStats(List<IoStatsEntry> stats, long timestamp) {
+ mStats = stats;
+ mUptimeTimestamp = timestamp;
+ }
+
+ public IoStats(Parcel in) {
+ mStats = in.createTypedArrayList(IoStatsEntry.CREATOR);
+ mUptimeTimestamp = in.readLong();
+ }
+
+ public IoStats(JSONObject in) throws JSONException {
+ mUptimeTimestamp = in.getInt("uptime");
+ JSONArray statsArray = in.getJSONArray("stats");
+ mStats = new ArrayList<>();
+ for(int i = 0; i < statsArray.length(); ++i) {
+ mStats.add(new IoStatsEntry(statsArray.getJSONObject(i)));
+ }
+ }
+
+ @Override
+ public void writeToParcel(Parcel dest, int flags) {
+ dest.writeTypedList(mStats);
+ dest.writeLong(mUptimeTimestamp);
+ }
+
+ public void writeToJson(JsonWriter jsonWriter) throws IOException {
+ jsonWriter.beginObject();
+ jsonWriter.name("uptime").value(mUptimeTimestamp);
+ jsonWriter.name("stats").beginArray();
+ for (IoStatsEntry stat : mStats) {
+ stat.writeToJson(jsonWriter);
+ }
+ jsonWriter.endArray();
+ jsonWriter.endObject();
+ }
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ public long getTimestamp() {
+ return mUptimeTimestamp;
+ }
+
+ public List<IoStatsEntry> getStats() {
+ return mStats;
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(mStats, mUptimeTimestamp);
+ }
+
+ public IoStatsEntry getUserIdStats(int uid) {
+ for (IoStatsEntry stats : getStats()) {
+ if (stats.uid == uid) {
+ return stats;
+ }
+ }
+
+ return null;
+ }
+
+ public IoStatsEntry.Metrics getForegroundTotals() {
+ long bytesRead = 0;
+ long bytesWritten = 0;
+ long bytesReadFromStorage = 0;
+ long bytesWrittenToStorage = 0;
+ long fsyncCalls = 0;
+
+ for (IoStatsEntry stats : getStats()) {
+ bytesRead += stats.foreground.bytesRead;
+ bytesWritten += stats.foreground.bytesWritten;
+ bytesReadFromStorage += stats.foreground.bytesReadFromStorage;
+ bytesWrittenToStorage += stats.foreground.bytesWrittenToStorage;
+ fsyncCalls += stats.foreground.fsyncCalls;
+ }
+
+ return new Metrics(bytesRead,
+ bytesWritten,
+ bytesReadFromStorage,
+ bytesWrittenToStorage,
+ fsyncCalls);
+ }
+
+ public IoStatsEntry.Metrics getBackgroundTotals() {
+ long bytesRead = 0;
+ long bytesWritten = 0;
+ long bytesReadFromStorage = 0;
+ long bytesWrittenToStorage = 0;
+ long fsyncCalls = 0;
+
+ for (IoStatsEntry stats : getStats()) {
+ bytesRead += stats.background.bytesRead;
+ bytesWritten += stats.background.bytesWritten;
+ bytesReadFromStorage += stats.background.bytesReadFromStorage;
+ bytesWrittenToStorage += stats.background.bytesWrittenToStorage;
+ fsyncCalls += stats.background.fsyncCalls;
+ }
+
+ return new Metrics(bytesRead,
+ bytesWritten,
+ bytesReadFromStorage,
+ bytesWrittenToStorage,
+ fsyncCalls);
+ }
+
+ public IoStatsEntry.Metrics getTotals() {
+ IoStatsEntry.Metrics foreground = getForegroundTotals();
+ IoStatsEntry.Metrics background = getBackgroundTotals();
+
+ return new IoStatsEntry.Metrics(foreground.bytesRead + background.bytesRead,
+ foreground.bytesWritten + background.bytesWritten,
+ foreground.bytesReadFromStorage + background.bytesReadFromStorage,
+ foreground.bytesWrittenToStorage + background.bytesWrittenToStorage,
+ foreground.fsyncCalls + background.fsyncCalls);
+ }
+
+ @Override
+ public boolean equals(Object other) {
+ if (other instanceof IoStats) {
+ IoStats delta = (IoStats)other;
+ return delta.getTimestamp() == getTimestamp() &&
+ delta.getStats().equals(getStats());
+ }
+ return false;
+ }
+
+ @Override
+ public String toString() {
+ StringJoiner stringJoiner = new StringJoiner(", ");
+ for (IoStatsEntry stats : getStats()) {
+ stringJoiner.add(stats.toString());
+ }
+ return "timestamp = " + getTimestamp() + ", stats = " + stringJoiner.toString();
+ }
+}
diff --git a/car-lib/src/android/car/hardware/radio/CarRadioEvent.aidl b/car-lib/src/android/car/storagemonitoring/IoStatsEntry.aidl
similarity index 82%
copy from car-lib/src/android/car/hardware/radio/CarRadioEvent.aidl
copy to car-lib/src/android/car/storagemonitoring/IoStatsEntry.aidl
index 0865646..2e93fc3 100644
--- a/car-lib/src/android/car/hardware/radio/CarRadioEvent.aidl
+++ b/car-lib/src/android/car/storagemonitoring/IoStatsEntry.aidl
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2015 The Android Open Source Project
+ * 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.
@@ -14,6 +14,6 @@
* limitations under the License.
*/
-package android.car.hardware.radio;
+package android.car.storagemonitoring;
-parcelable CarRadioEvent;
+parcelable IoStatsEntry;
diff --git a/car-lib/src/android/car/storagemonitoring/IoStatsEntry.java b/car-lib/src/android/car/storagemonitoring/IoStatsEntry.java
new file mode 100644
index 0000000..2642310
--- /dev/null
+++ b/car-lib/src/android/car/storagemonitoring/IoStatsEntry.java
@@ -0,0 +1,335 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package android.car.storagemonitoring;
+
+import android.annotation.SystemApi;
+import android.os.Parcel;
+import android.os.Parcelable;
+import android.util.JsonWriter;
+import java.io.IOException;
+import java.util.Objects;
+import org.json.JSONException;
+import org.json.JSONObject;
+
+/**
+ * uid_io stats about one user ID.
+ *
+ * Contains information about I/O activity that can be attributed to processes running on
+ * behalf of one user of the system, as collected by the kernel.
+ *
+ * @hide
+ */
+@SystemApi
+public final class IoStatsEntry implements Parcelable {
+
+ public static final Parcelable.Creator<IoStatsEntry> CREATOR =
+ new Parcelable.Creator<IoStatsEntry>() {
+ public IoStatsEntry createFromParcel(Parcel in) {
+ return new IoStatsEntry(in);
+ }
+
+ public IoStatsEntry[] newArray(int size) {
+ return new IoStatsEntry[size];
+ }
+ };
+
+ /**
+ * The user id that this object contains metrics for.
+ *
+ * In many cases this can be converted to a list of Java app packages installed on the device.
+ * In other cases, the user id can refer to either the kernel itself (uid 0), or low-level
+ * system services that are running entirely natively.
+ */
+ public final int uid;
+
+ /**
+ * How long any process running on behalf of this user id running for, in milliseconds.
+ *
+ * This field is allowed to be an approximation and it does not provide any way to
+ * relate uptime to specific processes.
+ */
+ public final long runtimeMillis;
+
+ /**
+ * Statistics for apps running in foreground.
+ */
+ public final IoStatsEntry.Metrics foreground;
+
+ /**
+ * Statistics for apps running in background.
+ */
+ public final IoStatsEntry.Metrics background;
+
+ public IoStatsEntry(int uid,
+ long runtimeMillis, IoStatsEntry.Metrics foreground, IoStatsEntry.Metrics background) {
+ this.uid = uid;
+ this.runtimeMillis = runtimeMillis;
+ this.foreground = Objects.requireNonNull(foreground);
+ this.background = Objects.requireNonNull(background);
+ }
+
+ public IoStatsEntry(Parcel in) {
+ uid = in.readInt();
+ runtimeMillis = in.readLong();
+ foreground = in.readParcelable(IoStatsEntry.Metrics.class.getClassLoader());
+ background = in.readParcelable(IoStatsEntry.Metrics.class.getClassLoader());
+ }
+
+ public IoStatsEntry(UidIoRecord record, long runtimeMillis) {
+ uid = record.uid;
+ this.runtimeMillis = runtimeMillis;
+ foreground = new IoStatsEntry.Metrics(record.foreground_rchar,
+ record.foreground_wchar,
+ record.foreground_read_bytes,
+ record.foreground_write_bytes,
+ record.foreground_fsync);
+ background = new IoStatsEntry.Metrics(record.background_rchar,
+ record.background_wchar,
+ record.background_read_bytes,
+ record.background_write_bytes,
+ record.background_fsync);
+ }
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ @Override
+ public void writeToParcel(Parcel dest, int flags) {
+ dest.writeInt(uid);
+ dest.writeLong(runtimeMillis);
+ dest.writeParcelable(foreground, flags);
+ dest.writeParcelable(background, flags);
+ }
+
+ public void writeToJson(JsonWriter jsonWriter) throws IOException {
+ jsonWriter.beginObject();
+ jsonWriter.name("uid").value(uid);
+ jsonWriter.name("runtimeMillis").value(runtimeMillis);
+ jsonWriter.name("foreground"); foreground.writeToJson(jsonWriter);
+ jsonWriter.name("background"); background.writeToJson(jsonWriter);
+ jsonWriter.endObject();
+ }
+
+ public IoStatsEntry(JSONObject in) throws JSONException {
+ uid = in.getInt("uid");
+ runtimeMillis = in.getLong("runtimeMillis");
+ foreground = new IoStatsEntry.Metrics(in.getJSONObject("foreground"));
+ background = new IoStatsEntry.Metrics(in.getJSONObject("background"));
+ }
+
+ /**
+ * Returns the difference between the values stored in this object vs. those
+ * stored in other.
+ *
+ * It is the same as doing a delta() on foreground and background, plus verifying that
+ * both objects refer to the same uid.
+ *
+ * @hide
+ */
+ public IoStatsEntry delta(IoStatsEntry other) {
+ if (uid != other.uid) {
+ throw new IllegalArgumentException("cannot calculate delta between different user IDs");
+ }
+ return new IoStatsEntry(uid,
+ runtimeMillis - other.runtimeMillis,
+ foreground.delta(other.foreground), background.delta(other.background));
+ }
+
+ @Override
+ public boolean equals(Object other) {
+ if (other instanceof IoStatsEntry) {
+ IoStatsEntry uidIoStatEntry = (IoStatsEntry)other;
+
+ return uid == uidIoStatEntry.uid &&
+ runtimeMillis == uidIoStatEntry.runtimeMillis &&
+ foreground.equals(uidIoStatEntry.foreground) &&
+ background.equals(uidIoStatEntry.background);
+ }
+
+ return false;
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(uid, runtimeMillis, foreground, background);
+ }
+
+ @Override
+ public String toString() {
+ return String.format("uid = %d, runtime = %d, foreground = %s, background = %s",
+ uid, runtimeMillis, foreground, background);
+ }
+
+ /**
+ * Validates that this object contains the same I/O metrics as a UidIoStatsRecord.
+ *
+ * It matches UID, and I/O activity values, but ignores runtime.
+ * @hide
+ */
+ public boolean representsSameMetrics(UidIoRecord record) {
+ return record.uid == uid &&
+ record.foreground_rchar == foreground.bytesRead &&
+ record.foreground_wchar == foreground.bytesWritten &&
+ record.foreground_read_bytes == foreground.bytesReadFromStorage &&
+ record.foreground_write_bytes == foreground.bytesWrittenToStorage &&
+ record.foreground_fsync == foreground.fsyncCalls &&
+ record.background_rchar == background.bytesRead &&
+ record.background_wchar == background.bytesWritten &&
+ record.background_read_bytes == background.bytesReadFromStorage &&
+ record.background_write_bytes == background.bytesWrittenToStorage &&
+ record.background_fsync == background.fsyncCalls;
+ }
+
+ /**
+ * I/O activity metrics that pertain to either the foreground or the background state.
+ */
+ public static final class Metrics implements Parcelable {
+
+ public static final Parcelable.Creator<IoStatsEntry.Metrics> CREATOR =
+ new Parcelable.Creator<IoStatsEntry.Metrics>() {
+ public IoStatsEntry.Metrics createFromParcel(Parcel in) {
+ return new IoStatsEntry.Metrics(in);
+ }
+
+ public IoStatsEntry.Metrics[] newArray(int size) {
+ return new IoStatsEntry.Metrics[size];
+ }
+ };
+
+ /**
+ * Total bytes that processes running on behalf of this user obtained
+ * via read() system calls.
+ */
+ public final long bytesRead;
+
+ /**
+ * Total bytes that processes running on behalf of this user transferred
+ * via write() system calls.
+ */
+ public final long bytesWritten;
+
+ /**
+ * Total bytes that processes running on behalf of this user obtained
+ * via read() system calls that actually were served by physical storage.
+ */
+ public final long bytesReadFromStorage;
+
+ /**
+ * Total bytes that processes running on behalf of this user transferred
+ * via write() system calls that were actually sent to physical storage.
+ */
+ public final long bytesWrittenToStorage;
+
+ /**
+ * Total number of fsync() system calls that processes running on behalf of this user made.
+ */
+ public final long fsyncCalls;
+
+ public Metrics(long bytesRead, long bytesWritten, long bytesReadFromStorage,
+ long bytesWrittenToStorage, long fsyncCalls) {
+ this.bytesRead = bytesRead;
+ this.bytesWritten = bytesWritten;
+ this.bytesReadFromStorage = bytesReadFromStorage;
+ this.bytesWrittenToStorage = bytesWrittenToStorage;
+ this.fsyncCalls = fsyncCalls;
+ }
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ @Override
+ public void writeToParcel(Parcel dest, int flags) {
+ dest.writeLong(bytesRead);
+ dest.writeLong(bytesWritten);
+ dest.writeLong(bytesReadFromStorage);
+ dest.writeLong(bytesWrittenToStorage);
+ dest.writeLong(fsyncCalls);
+ }
+
+ public void writeToJson(JsonWriter jsonWriter) throws IOException {
+ jsonWriter.beginObject();
+ jsonWriter.name("bytesRead").value(bytesRead);
+ jsonWriter.name("bytesWritten").value(bytesWritten);
+ jsonWriter.name("bytesReadFromStorage").value(bytesReadFromStorage);
+ jsonWriter.name("bytesWrittenToStorage").value(bytesWrittenToStorage);
+ jsonWriter.name("fsyncCalls").value(fsyncCalls);
+ jsonWriter.endObject();
+ }
+
+ public Metrics(Parcel in) {
+ bytesRead = in.readLong();
+ bytesWritten = in.readLong();
+ bytesReadFromStorage = in.readLong();
+ bytesWrittenToStorage = in.readLong();
+ fsyncCalls = in.readLong();
+ }
+
+ public Metrics(JSONObject in) throws JSONException {
+ bytesRead = in.getLong("bytesRead");
+ bytesWritten = in.getLong("bytesWritten");
+ bytesReadFromStorage = in.getLong("bytesReadFromStorage");
+ bytesWrittenToStorage = in.getLong("bytesWrittenToStorage");
+ fsyncCalls = in.getLong("fsyncCalls");
+ }
+
+ /**
+ * Computes the difference between the values stored in this object
+ * vs. those stored in other
+ *
+ * It is the same as doing
+ * new PerStateMetrics(bytesRead-other.bytesRead,bytesWritten-other.bytesWritten, ...)
+ *
+ * @hide
+ */
+ public Metrics delta(Metrics other) {
+ return new Metrics(bytesRead-other.bytesRead,
+ bytesWritten-other.bytesWritten,
+ bytesReadFromStorage-other.bytesReadFromStorage,
+ bytesWrittenToStorage-other.bytesWrittenToStorage,
+ fsyncCalls-other.fsyncCalls);
+ }
+
+ @Override
+ public boolean equals(Object other) {
+ if (other instanceof Metrics) {
+ Metrics metrics = (Metrics)other;
+
+ return (bytesRead == metrics.bytesRead) &&
+ (bytesWritten == metrics.bytesWritten) &&
+ (bytesReadFromStorage == metrics.bytesReadFromStorage) &&
+ (bytesWrittenToStorage == metrics.bytesWrittenToStorage) &&
+ (fsyncCalls == metrics.fsyncCalls);
+ }
+ return false;
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(bytesRead, bytesWritten, bytesReadFromStorage,
+ bytesWrittenToStorage, fsyncCalls);
+ }
+
+ @Override
+ public String toString() {
+ return String.format("bytesRead=%d, bytesWritten=%d, bytesReadFromStorage=%d, bytesWrittenToStorage=%d, fsyncCalls=%d",
+ bytesRead, bytesWritten, bytesReadFromStorage, bytesWrittenToStorage, fsyncCalls);
+ }
+ }
+}
diff --git a/car-lib/src/android/car/hardware/radio/CarRadioEvent.aidl b/car-lib/src/android/car/storagemonitoring/LifetimeWriteInfo.aidl
similarity index 81%
copy from car-lib/src/android/car/hardware/radio/CarRadioEvent.aidl
copy to car-lib/src/android/car/storagemonitoring/LifetimeWriteInfo.aidl
index 0865646..98b924a 100644
--- a/car-lib/src/android/car/hardware/radio/CarRadioEvent.aidl
+++ b/car-lib/src/android/car/storagemonitoring/LifetimeWriteInfo.aidl
@@ -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.
@@ -14,6 +14,6 @@
* limitations under the License.
*/
-package android.car.hardware.radio;
+package android.car.storagemonitoring;
-parcelable CarRadioEvent;
+parcelable LifetimeWriteInfo;
diff --git a/car-lib/src/android/car/storagemonitoring/LifetimeWriteInfo.java b/car-lib/src/android/car/storagemonitoring/LifetimeWriteInfo.java
new file mode 100644
index 0000000..6313e46
--- /dev/null
+++ b/car-lib/src/android/car/storagemonitoring/LifetimeWriteInfo.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 android.car.storagemonitoring;
+
+import android.annotation.SystemApi;
+import android.os.Parcel;
+import android.os.Parcelable;
+import android.util.JsonWriter;
+import java.io.IOException;
+import java.util.Objects;
+import org.json.JSONException;
+import org.json.JSONObject;
+
+/**
+ * Information about how many bytes were written to a filesystem during its lifetime.
+ *
+ * @hide
+ */
+@SystemApi
+public class LifetimeWriteInfo implements Parcelable {
+ public static final Creator<IoStats> CREATOR = new Creator<IoStats>() {
+ @Override
+ public IoStats createFromParcel(Parcel in) {
+ return new IoStats(in);
+ }
+
+ @Override
+ public IoStats[] newArray(int size) {
+ return new IoStats[size];
+ }
+ };
+
+ public final String partition;
+ public final String fstype;
+ public final long writtenBytes;
+
+ public LifetimeWriteInfo(String partition, String fstype, long writtenBytes) {
+ this.partition = Objects.requireNonNull(partition);
+ this.fstype = Objects.requireNonNull(fstype);
+ if (writtenBytes < 0) {
+ throw new IllegalArgumentException("writtenBytes must be non-negative");
+ }
+ this.writtenBytes = writtenBytes;
+ }
+
+ public LifetimeWriteInfo(Parcel in) {
+ this.partition = in.readString();
+ this.fstype = in.readString();
+ this.writtenBytes = in.readLong();
+ }
+
+ public LifetimeWriteInfo(JSONObject in) throws JSONException {
+ partition = in.getString("partition");
+ fstype = in.getString("fstype");
+ writtenBytes = in.getLong("writtenBytes");
+ }
+
+
+ @Override
+ public void writeToParcel(Parcel dest, int flags) {
+ dest.writeString(partition);
+ dest.writeString(fstype);
+ dest.writeLong(writtenBytes);
+ }
+
+ public void writeToJson(JsonWriter jsonWriter) throws IOException {
+ jsonWriter.beginObject();
+ jsonWriter.name("partition").value(partition);
+ jsonWriter.name("fstype").value(fstype);
+ jsonWriter.name("writtenBytes").value(writtenBytes);
+ jsonWriter.endObject();
+ }
+
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ @Override
+ public boolean equals(Object other) {
+ if (other instanceof LifetimeWriteInfo) {
+ LifetimeWriteInfo lifetime = (LifetimeWriteInfo)other;
+ return partition.equals(lifetime.partition) &&
+ fstype.equals(lifetime.fstype) &&
+ writtenBytes == lifetime.writtenBytes;
+ }
+
+ return false;
+ }
+
+ @Override
+ public String toString() {
+ return String.format("for partition %s of type %s, %d bytes were written",
+ partition, fstype, writtenBytes);
+ }
+}
diff --git a/car-lib/src/android/car/storagemonitoring/UidIoRecord.java b/car-lib/src/android/car/storagemonitoring/UidIoRecord.java
new file mode 100644
index 0000000..e8adf0e
--- /dev/null
+++ b/car-lib/src/android/car/storagemonitoring/UidIoRecord.java
@@ -0,0 +1,105 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package android.car.storagemonitoring;
+
+import android.annotation.SystemApi;
+
+/**
+ * Record of data as extracted from /proc/uid_io/stats
+ *
+ * @hide
+ */
+@SystemApi
+public final class UidIoRecord {
+
+ public final int uid;
+
+ public final long foreground_rchar;
+ public final long foreground_wchar;
+ public final long foreground_read_bytes;
+ public final long foreground_write_bytes;
+ public final long foreground_fsync;
+
+ public final long background_rchar;
+ public final long background_wchar;
+ public final long background_read_bytes;
+ public final long background_write_bytes;
+ public final long background_fsync;
+
+ public UidIoRecord(int uid,
+ long foreground_rchar,
+ long foreground_wchar,
+ long foreground_read_bytes,
+ long foreground_write_bytes,
+ long foreground_fsync,
+ long background_rchar,
+ long background_wchar,
+ long background_read_bytes,
+ long background_write_bytes,
+ long background_fsync) {
+ this.uid = uid;
+
+ this.foreground_rchar = foreground_rchar;
+ this.foreground_wchar = foreground_wchar;
+ this.foreground_read_bytes = foreground_read_bytes;
+ this.foreground_write_bytes = foreground_write_bytes;
+ this.foreground_fsync = foreground_fsync;
+
+ this.background_rchar = background_rchar;
+ this.background_wchar = background_wchar;
+ this.background_read_bytes = background_read_bytes;
+ this.background_write_bytes = background_write_bytes;
+ this.background_fsync = background_fsync;
+ }
+
+ /** @hide */
+ public UidIoRecord delta(IoStatsEntry other) {
+ if (uid != other.uid) {
+ throw new IllegalArgumentException("cannot calculate delta between different user IDs");
+ }
+
+ return new UidIoRecord(uid,
+ foreground_rchar - other.foreground.bytesRead,
+ foreground_wchar - other.foreground.bytesWritten,
+ foreground_read_bytes - other.foreground.bytesReadFromStorage,
+ foreground_write_bytes - other.foreground.bytesWrittenToStorage,
+ foreground_fsync - other.foreground.fsyncCalls,
+ background_rchar - other.background.bytesRead,
+ background_wchar - other.background.bytesWritten,
+ background_read_bytes - other.background.bytesReadFromStorage,
+ background_write_bytes - other.background.bytesWrittenToStorage,
+ background_fsync - other.background.fsyncCalls);
+ }
+
+ /** @hide */
+ public UidIoRecord delta(UidIoRecord other) {
+ if (uid != other.uid) {
+ throw new IllegalArgumentException("cannot calculate delta between different user IDs");
+ }
+
+ return new UidIoRecord(uid,
+ foreground_rchar - other.foreground_rchar,
+ foreground_wchar - other.foreground_wchar,
+ foreground_read_bytes - other.foreground_read_bytes,
+ foreground_write_bytes - other.foreground_write_bytes,
+ foreground_fsync - other.foreground_fsync,
+ background_rchar - other.background_rchar,
+ background_wchar - other.background_wchar,
+ background_read_bytes - other.background_read_bytes,
+ background_write_bytes - other.background_write_bytes,
+ background_fsync - other.background_fsync);
+ }
+}
diff --git a/car-lib/src/android/car/hardware/radio/CarRadioEvent.aidl b/car-lib/src/android/car/storagemonitoring/WearEstimate.aidl
similarity index 82%
copy from car-lib/src/android/car/hardware/radio/CarRadioEvent.aidl
copy to car-lib/src/android/car/storagemonitoring/WearEstimate.aidl
index 0865646..c7ea505 100644
--- a/car-lib/src/android/car/hardware/radio/CarRadioEvent.aidl
+++ b/car-lib/src/android/car/storagemonitoring/WearEstimate.aidl
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2015 The Android Open Source Project
+ * 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.
@@ -14,6 +14,6 @@
* limitations under the License.
*/
-package android.car.hardware.radio;
+package android.car.storagemonitoring;
-parcelable CarRadioEvent;
+parcelable WearEstimate;
diff --git a/car-lib/src/android/car/storagemonitoring/WearEstimate.java b/car-lib/src/android/car/storagemonitoring/WearEstimate.java
new file mode 100644
index 0000000..507e6ed
--- /dev/null
+++ b/car-lib/src/android/car/storagemonitoring/WearEstimate.java
@@ -0,0 +1,152 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package android.car.storagemonitoring;
+
+import android.annotation.IntRange;
+import android.annotation.SystemApi;
+import android.os.Parcel;
+import android.os.Parcelable;
+import android.util.JsonReader;
+import android.util.JsonWriter;
+import java.io.IOException;
+import java.util.Objects;
+import org.json.JSONException;
+import org.json.JSONObject;
+
+/**
+ * Wear-out information for flash storage.
+ *
+ * Contains a lower-bound estimate of the wear of "type A" (SLC) and "type B" (MLC) storage.
+ *
+ * Current technology offers wear data in increments of 10% (i.e. from 0 == new device up to
+ * 100 == worn-out device). It is possible for a storage device to only support one type of memory
+ * cell, in which case it is expected that the storage type not supported will have UNKNOWN wear.
+ *
+ * @hide
+ */
+@SystemApi
+public class WearEstimate implements Parcelable {
+ public static final int UNKNOWN = -1;
+
+ /** @hide */
+ public static final WearEstimate UNKNOWN_ESTIMATE = new WearEstimate(UNKNOWN, UNKNOWN);
+
+ public static final Parcelable.Creator<WearEstimate> CREATOR =
+ new Parcelable.Creator<WearEstimate>() {
+ public WearEstimate createFromParcel(Parcel in) {
+ return new WearEstimate(in);
+ }
+
+ public WearEstimate[] newArray(int size) {
+ return new WearEstimate[size];
+ }
+ };
+
+ /**
+ * Wear estimate data for "type A" storage.
+ */
+ @IntRange(from=-1, to=100)
+ public final int typeA;
+
+ /**
+ * Wear estimate data for "type B" storage.
+ */
+ @IntRange(from=-1, to=100)
+ public final int typeB;
+
+ private static final int validateWearValue(int value) {
+ if (value == UNKNOWN) return value;
+ if ((value >= 0) && (value <= 100)) return value;
+ throw new IllegalArgumentException(value + " is not a valid wear estimate");
+ }
+
+ public WearEstimate(int typeA, int typeB) {
+ this.typeA = validateWearValue(typeA);
+ this.typeB = validateWearValue(typeB);
+ }
+
+ public WearEstimate(Parcel in) {
+ typeA = validateWearValue(in.readInt());
+ typeB = validateWearValue(in.readInt());
+ }
+
+ public WearEstimate(JsonReader in) throws IOException {
+ int typeA = UNKNOWN;
+ int typeB = UNKNOWN;
+ in.beginObject();
+ while (in.hasNext()) {
+ switch (in.nextName()) {
+ case "wearEstimateTypeA":
+ typeA = validateWearValue(in.nextInt());
+ break;
+ case "wearEstimateTypeB":
+ typeB = validateWearValue(in.nextInt());
+ break;
+ }
+ }
+ in.endObject();
+ this.typeA = typeA;
+ this.typeB = typeB;
+ }
+
+ /** @hide */
+ public WearEstimate(JSONObject in) throws JSONException {
+ typeA = in.getInt("wearEstimateTypeA");
+ typeB = in.getInt("wearEstimateTypeB");
+ }
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ @Override
+ public void writeToParcel(Parcel dest, int flags) {
+ dest.writeInt(typeA);
+ dest.writeInt(typeB);
+ }
+
+ public void writeToJson(JsonWriter jsonWriter) throws IOException {
+ jsonWriter.beginObject();
+ jsonWriter.name("wearEstimateTypeA").value(typeA);
+ jsonWriter.name("wearEstimateTypeB").value(typeB);
+ jsonWriter.endObject();
+ }
+
+ @Override
+ public boolean equals(Object other) {
+ if (other instanceof WearEstimate) {
+ WearEstimate wo = (WearEstimate)other;
+ return wo.typeA == typeA && wo.typeB == typeB;
+ }
+ return false;
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(typeA, typeB);
+ }
+
+ private static final String wearValueToString(int value) {
+ if (value == UNKNOWN) return "unknown";
+ return value + "%";
+ }
+
+ @Override
+ public String toString() {
+ return "type A: " + wearValueToString(typeA) + ", type B: " + wearValueToString(typeB);
+ }
+}
diff --git a/car-lib/src/android/car/media/ICarAudioCallback.aidl b/car-lib/src/android/car/storagemonitoring/WearEstimateChange.aidl
similarity index 82%
copy from car-lib/src/android/car/media/ICarAudioCallback.aidl
copy to car-lib/src/android/car/storagemonitoring/WearEstimateChange.aidl
index 7e01c71..49adfe5 100644
--- a/car-lib/src/android/car/media/ICarAudioCallback.aidl
+++ b/car-lib/src/android/car/storagemonitoring/WearEstimateChange.aidl
@@ -14,9 +14,6 @@
* limitations under the License.
*/
-package android.car.media;
+package android.car.storagemonitoring;
-/** @hide */
-oneway interface ICarAudioCallback {
- void onParameterChange(in String params) = 0;
-}
+parcelable WearEstimateChange;
diff --git a/car-lib/src/android/car/storagemonitoring/WearEstimateChange.java b/car-lib/src/android/car/storagemonitoring/WearEstimateChange.java
new file mode 100644
index 0000000..5c80a31
--- /dev/null
+++ b/car-lib/src/android/car/storagemonitoring/WearEstimateChange.java
@@ -0,0 +1,143 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package android.car.storagemonitoring;
+
+import android.annotation.NonNull;
+import android.annotation.SystemApi;
+import android.os.Parcel;
+import android.os.Parcelable;
+import java.time.Instant;
+import java.util.Objects;
+
+import static java.util.Objects.requireNonNull;
+
+/**
+ * Change in wear-out information.
+ *
+ * Contains information about the first cycle during which the system detected a change
+ * in wear-out information of the flash storage.
+ *
+ * @hide
+ */
+@SystemApi
+public class WearEstimateChange implements Parcelable {
+ public static final Parcelable.Creator<WearEstimateChange> CREATOR =
+ new Parcelable.Creator<WearEstimateChange>() {
+ public WearEstimateChange createFromParcel(Parcel in) {
+ return new WearEstimateChange(in);
+ }
+
+ public WearEstimateChange[] newArray(int size) {
+ return new WearEstimateChange[size];
+ }
+ };
+
+ /**
+ * The previous wear estimate.
+ */
+ public final @NonNull WearEstimate oldEstimate;
+
+ /**
+ * The new wear estimate.
+ */
+ public final @NonNull WearEstimate newEstimate;
+
+ /**
+ * Total CarService uptime when this change was detected.
+ */
+ public final long uptimeAtChange;
+
+ /**
+ * Wall-clock time when this change was detected.
+ */
+ public final @NonNull Instant dateAtChange;
+
+ /**
+ * Whether this change was within the vendor range for acceptable flash degradation.
+ */
+ public final boolean isAcceptableDegradation;
+
+ public WearEstimateChange(WearEstimate oldEstimate,
+ WearEstimate newEstimate,
+ long uptimeAtChange,
+ Instant dateAtChange,
+ boolean isAcceptableDegradation) {
+ if (uptimeAtChange < 0) {
+ throw new IllegalArgumentException("uptimeAtChange must be >= 0");
+ }
+ this.oldEstimate = requireNonNull(oldEstimate);
+ this.newEstimate = requireNonNull(newEstimate);
+ this.uptimeAtChange = uptimeAtChange;
+ this.dateAtChange = requireNonNull(dateAtChange);
+ this.isAcceptableDegradation = isAcceptableDegradation;
+ }
+
+ public WearEstimateChange(Parcel in) {
+ oldEstimate = in.readParcelable(WearEstimate.class.getClassLoader());
+ newEstimate = in.readParcelable(WearEstimate.class.getClassLoader());
+ uptimeAtChange = in.readLong();
+ dateAtChange = Instant.ofEpochMilli(in.readLong());
+ isAcceptableDegradation = in.readInt() == 1;
+ }
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ @Override
+ public void writeToParcel(Parcel dest, int flags) {
+ dest.writeParcelable(oldEstimate, flags);
+ dest.writeParcelable(newEstimate, flags);
+ dest.writeLong(uptimeAtChange);
+ dest.writeLong(dateAtChange.toEpochMilli());
+ dest.writeInt(isAcceptableDegradation ? 1 : 0);
+ }
+
+ @Override
+ public boolean equals(Object other) {
+ if (other instanceof WearEstimateChange) {
+ WearEstimateChange wo = (WearEstimateChange)other;
+ return wo.isAcceptableDegradation == isAcceptableDegradation &&
+ wo.uptimeAtChange == uptimeAtChange &&
+ wo.dateAtChange.equals(dateAtChange) &&
+ wo.oldEstimate.equals(oldEstimate) &&
+ wo.newEstimate.equals(newEstimate);
+ }
+ return false;
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(oldEstimate,
+ newEstimate,
+ uptimeAtChange,
+ dateAtChange,
+ isAcceptableDegradation);
+ }
+
+ @Override
+ public String toString() {
+ return String.format(
+ "wear change{old level=%s, new level=%s, uptime=%d, date=%s, acceptable=%s}",
+ oldEstimate,
+ newEstimate,
+ uptimeAtChange,
+ dateAtChange,
+ isAcceptableDegradation ? "yes" : "no");
+ }
+
+}
diff --git a/car-lib/src/android/car/trust/ICarTrustAgentBleCallback.aidl b/car-lib/src/android/car/trust/ICarTrustAgentBleCallback.aidl
new file mode 100644
index 0000000..9f28db9
--- /dev/null
+++ b/car-lib/src/android/car/trust/ICarTrustAgentBleCallback.aidl
@@ -0,0 +1,47 @@
+/*
+ * 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.trust;
+
+import android.bluetooth.BluetoothDevice;
+
+/**
+ * Callback interface for BLE connection state changes.
+ *
+ * @hide
+ */
+oneway interface ICarTrustAgentBleCallback {
+ /**
+ * Called when the GATT server is started and BLE is successfully advertising.
+ */
+ void onBleServerStartSuccess();
+
+ /**
+ * Called when the BLE advertisement fails to start.
+ * see AdvertiseCallback#ADVERTISE_FAILED_* for possible error codes.
+ */
+ void onBleServerStartFailure(int errorCode);
+
+ /**
+ * Called when a device is connected.
+ */
+ void onBleDeviceConnected(in BluetoothDevice device);
+
+ /**
+ * Called when a device is disconnected.
+ */
+ void onBleDeviceDisconnected(in BluetoothDevice device);
+}
diff --git a/car-lib/src/android/car/trust/ICarTrustAgentBleService.aidl b/car-lib/src/android/car/trust/ICarTrustAgentBleService.aidl
new file mode 100644
index 0000000..8b50fd3
--- /dev/null
+++ b/car-lib/src/android/car/trust/ICarTrustAgentBleService.aidl
@@ -0,0 +1,61 @@
+/*
+ * 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.trust;
+
+import android.bluetooth.BluetoothDevice;
+import android.car.trust.ICarTrustAgentBleCallback;
+import android.car.trust.ICarTrustAgentEnrolmentCallback;
+import android.car.trust.ICarTrustAgentTokenRequestDelegate;
+import android.car.trust.ICarTrustAgentTokenResponseCallback;
+import android.car.trust.ICarTrustAgentUnlockCallback;
+
+/**
+ * Binder interface for CarTrustAgentBleService.
+ *
+ * @hide
+ */
+interface ICarTrustAgentBleService {
+ /** General BLE */
+ void registerBleCallback(in ICarTrustAgentBleCallback callback);
+ void unregisterBleCallback(in ICarTrustAgentBleCallback callback);
+
+ /** Enrolment */
+ void startEnrolmentAdvertising();
+ void stopEnrolmentAdvertising();
+ void sendEnrolmentHandle(in BluetoothDevice device, long handle);
+ void registerEnrolmentCallback(in ICarTrustAgentEnrolmentCallback callback);
+ void unregisterEnrolmentCallback(in ICarTrustAgentEnrolmentCallback callback);
+
+ /** Unlock */
+ void startUnlockAdvertising();
+ void stopUnlockAdvertising();
+ void registerUnlockCallback(in ICarTrustAgentUnlockCallback callback);
+ void unregisterUnlockCallback(in ICarTrustAgentUnlockCallback callback);
+
+ /** Token request */
+ void setTokenRequestDelegate(in ICarTrustAgentTokenRequestDelegate delegate);
+ void revokeTrust();
+ void addEscrowToken(in byte[] token, int uid);
+ void removeEscrowToken(long handle, int uid);
+ void isEscrowTokenActive(long handle, int uid);
+
+ /** Token response */
+ void setTokenResponseCallback(in ICarTrustAgentTokenResponseCallback callback);
+ void onEscrowTokenAdded(in byte[] token, long handle, int uid);
+ void onEscrowTokenRemoved(long handle, boolean successful);
+ void onEscrowTokenActiveStateChanged(long handle, boolean active);
+}
diff --git a/libvehiclemonitor/java/src/com/android/car/vehiclemonitor/IVehicleMonitorListener.aidl b/car-lib/src/android/car/trust/ICarTrustAgentEnrolmentCallback.aidl
similarity index 65%
copy from libvehiclemonitor/java/src/com/android/car/vehiclemonitor/IVehicleMonitorListener.aidl
copy to car-lib/src/android/car/trust/ICarTrustAgentEnrolmentCallback.aidl
index ca0ac83..7f12404 100644
--- a/libvehiclemonitor/java/src/com/android/car/vehiclemonitor/IVehicleMonitorListener.aidl
+++ b/car-lib/src/android/car/trust/ICarTrustAgentEnrolmentCallback.aidl
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2016 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,12 +14,14 @@
* limitations under the License.
*/
-package com.android.car.vehiclemonitor;
+package android.car.trust;
/**
- * Listener for vehicle monitor service.
+ * Callback interface for CarTrustAgentService enrolment.
+ *
* @hide
*/
-oneway interface IVehicleMonitorListener {
- void onAppViolation(int pid, int uid, int action, int violation) = 0;
+oneway interface ICarTrustAgentEnrolmentCallback {
+ /** Called when the enrolment data is received */
+ void onEnrolmentDataReceived(in byte[] token);
}
diff --git a/car-lib/src/android/car/trust/ICarTrustAgentTokenRequestDelegate.aidl b/car-lib/src/android/car/trust/ICarTrustAgentTokenRequestDelegate.aidl
new file mode 100644
index 0000000..3c61d4b
--- /dev/null
+++ b/car-lib/src/android/car/trust/ICarTrustAgentTokenRequestDelegate.aidl
@@ -0,0 +1,41 @@
+/*
+ * 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.trust;
+
+/**
+ * Delegate interface for escrow token exchange request.
+ *
+ * TrustAgentService uses async pattern and we therefore divide the
+ * request and response into two separate AIDL interfaces.
+ *
+ * CarBleTrustAgent would implement this interface and set itself as a delegate.
+ *
+ * @hide
+ */
+interface ICarTrustAgentTokenRequestDelegate {
+ /** Called to revoke trust */
+ void revokeTrust();
+
+ /** Called to add escrow token for foreground user */
+ void addEscrowToken(in byte[] token, int uid);
+
+ /** Called to remove escrow token for foreground user */
+ void removeEscrowToken(long handle, int uid);
+
+ /** Called to query if the foreground user has active escrow token */
+ void isEscrowTokenActive(long handle, int uid);
+}
diff --git a/car-lib/src/android/car/trust/ICarTrustAgentTokenResponseCallback.aidl b/car-lib/src/android/car/trust/ICarTrustAgentTokenResponseCallback.aidl
new file mode 100644
index 0000000..5dbc3bc
--- /dev/null
+++ b/car-lib/src/android/car/trust/ICarTrustAgentTokenResponseCallback.aidl
@@ -0,0 +1,36 @@
+/*
+ * 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.trust;
+
+/**
+ * Callback interface for escrow token exchange response.
+ *
+ * TrustAgentService uses async pattern and we therefore divide the
+ * request and response into two separate AIDL interfaces.
+ *
+ * @hide
+ */
+interface ICarTrustAgentTokenResponseCallback {
+ /** Called after escrow token is added for foreground user */
+ void onEscrowTokenAdded(out byte[] token, long handle, int uid);
+
+ /** Called after escrow token is removed for foreground user */
+ void onEscrowTokenRemoved(long handle, boolean successful);
+
+ /** Called after escrow token active state is changed for foreground user */
+ void onEscrowTokenActiveStateChanged(long handle, boolean active);
+}
diff --git a/libvehiclemonitor/java/src/com/android/car/vehiclemonitor/IVehicleMonitorListener.aidl b/car-lib/src/android/car/trust/ICarTrustAgentUnlockCallback.aidl
similarity index 65%
copy from libvehiclemonitor/java/src/com/android/car/vehiclemonitor/IVehicleMonitorListener.aidl
copy to car-lib/src/android/car/trust/ICarTrustAgentUnlockCallback.aidl
index ca0ac83..e280bf0 100644
--- a/libvehiclemonitor/java/src/com/android/car/vehiclemonitor/IVehicleMonitorListener.aidl
+++ b/car-lib/src/android/car/trust/ICarTrustAgentUnlockCallback.aidl
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2016 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,12 +14,14 @@
* limitations under the License.
*/
-package com.android.car.vehiclemonitor;
+package android.car.trust;
/**
- * Listener for vehicle monitor service.
+ * Callback interface for CarTrustAgentService unlock.
+ *
* @hide
*/
-oneway interface IVehicleMonitorListener {
- void onAppViolation(int pid, int uid, int action, int violation) = 0;
+oneway interface ICarTrustAgentUnlockCallback {
+ /** Called when the unlock token is received */
+ void onUnlockDataReceived(in byte[] token, long handle);
}
diff --git a/car-lib/src/android/car/user/CarUserManagerHelper.java b/car-lib/src/android/car/user/CarUserManagerHelper.java
new file mode 100644
index 0000000..4a69f0b
--- /dev/null
+++ b/car-lib/src/android/car/user/CarUserManagerHelper.java
@@ -0,0 +1,579 @@
+/*
+ * 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.user;
+
+import android.annotation.Nullable;
+import android.app.ActivityManager;
+import android.car.settings.CarSettings;
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.content.pm.UserInfo;
+import android.graphics.Bitmap;
+import android.graphics.drawable.BitmapDrawable;
+import android.graphics.drawable.Drawable;
+import android.os.SystemProperties;
+import android.os.UserHandle;
+import android.os.UserManager;
+import android.util.Log;
+
+import com.android.internal.util.UserIcons;
+
+import java.util.Iterator;
+import java.util.List;
+
+/**
+ * Helper class for {@link UserManager}, this is meant to be used by builds that support
+ * Multi-user model with headless user 0. User 0 is not associated with a real person, and
+ * can not be brought to foreground.
+ *
+ * <p>This class provides method for user management, including creating, removing, adding
+ * and switching users. Methods related to get users will exclude system user by default.
+ *
+ * @hide
+ */
+public class CarUserManagerHelper {
+ private static final String TAG = "CarUserManagerHelper";
+ private static final String HEADLESS_SYSTEM_USER = "android.car.systemuser.headless";
+ private final Context mContext;
+ private final UserManager mUserManager;
+ private final ActivityManager mActivityManager;
+ private Bitmap mDefaultGuestUserIcon;
+ private OnUsersUpdateListener mUpdateListener;
+ private final BroadcastReceiver mUserChangeReceiver = new BroadcastReceiver() {
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ mUpdateListener.onUsersUpdate();
+ }
+ };
+
+ public CarUserManagerHelper(Context context) {
+ mContext = context.getApplicationContext();
+ mUserManager = (UserManager) mContext.getSystemService(Context.USER_SERVICE);
+ mActivityManager = (ActivityManager) mContext.getSystemService(Context.ACTIVITY_SERVICE);
+ }
+
+ /**
+ * Registers a listener for updates to all users - removing, adding users or changing user info.
+ *
+ * <p> Best practise is to keep one listener per helper.
+ *
+ * @param listener Instance of {@link OnUsersUpdateListener}.
+ */
+ public void registerOnUsersUpdateListener(OnUsersUpdateListener listener) {
+ if (mUpdateListener != null) {
+ unregisterOnUsersUpdateListener();
+ }
+
+ mUpdateListener = listener;
+ registerReceiver();
+ }
+
+ /**
+ * Unregisters on user update listener by unregistering {@code BroadcastReceiver}.
+ */
+ public void unregisterOnUsersUpdateListener() {
+ unregisterReceiver();
+ }
+
+ /**
+ * Returns {@code true} if the system is in the headless user 0 model.
+ *
+ * @return {@boolean true} if headless system user.
+ */
+ public boolean isHeadlessSystemUser() {
+ return SystemProperties.getBoolean(HEADLESS_SYSTEM_USER, false);
+ }
+
+ /**
+ * Gets UserInfo for the system user.
+ *
+ * @return {@link UserInfo} for the system user.
+ */
+ public UserInfo getSystemUserInfo() {
+ return mUserManager.getUserInfo(UserHandle.USER_SYSTEM);
+ }
+
+ /**
+ * Gets UserInfo for the current foreground user.
+ *
+ * Concept of foreground user is relevant for the multi-user deployment. Foreground user
+ * corresponds to the currently "logged in" user.
+ *
+ * @return {@link UserInfo} for the foreground user.
+ */
+ public UserInfo getCurrentForegroundUserInfo() {
+ return mUserManager.getUserInfo(getCurrentForegroundUserId());
+ }
+
+ /**
+ * @return Id of the current foreground user.
+ */
+ public int getCurrentForegroundUserId() {
+ return mActivityManager.getCurrentUser();
+ }
+
+ /**
+ * Gets UserInfo for the user running the caller process.
+ *
+ * <p>Differentiation between foreground user and current process user is relevant for
+ * multi-user deployments.
+ *
+ * <p>Some multi-user aware components (like SystemUI) needs to run a singleton component
+ * in system user. Current process user is always the same for that component, even when
+ * the foreground user changes.
+ *
+ * @return {@link UserInfo} for the user running the current process.
+ */
+ public UserInfo getCurrentProcessUserInfo() {
+ return mUserManager.getUserInfo(getCurrentProcessUserId());
+ }
+
+ /**
+ * @return Id for the user running the current process.
+ */
+ public int getCurrentProcessUserId() {
+ return UserHandle.myUserId();
+ }
+
+ /**
+ * Gets all the existing foreground users on the system that are not currently running as
+ * the foreground user.
+ *
+ * @return List of {@code UserInfo} for each user that is not the foreground user.
+ */
+ public List<UserInfo> getAllSwitchableUsers() {
+ if (isHeadlessSystemUser()) {
+ return getAllUsersExceptSystemUserAndSpecifiedUser(getCurrentForegroundUserId());
+ } else {
+ return getAllUsersExceptSpecifiedUser(getCurrentForegroundUserId());
+ }
+ }
+
+ /**
+ * Gets all the users that can be brought to the foreground on the system.
+ *
+ * @return List of {@code UserInfo} for users that associated with a real person.
+ */
+ public List<UserInfo> getAllUsers() {
+ if (isHeadlessSystemUser()) {
+ return getAllUsersExceptSystemUserAndSpecifiedUser(UserHandle.USER_SYSTEM);
+ } else {
+ return mUserManager.getUsers(/* excludeDying= */true);
+ }
+ }
+
+ /**
+ * Get all the users except the one with userId passed in.
+ *
+ * @param userId of the user not to be returned.
+ * @return All users other than user with userId.
+ */
+ private List<UserInfo> getAllUsersExceptSpecifiedUser(int userId) {
+ List<UserInfo> users = mUserManager.getUsers(/* excludeDying= */true);
+
+ for (Iterator<UserInfo> iterator = users.iterator(); iterator.hasNext(); ) {
+ UserInfo userInfo = iterator.next();
+ if (userInfo.id == userId) {
+ // Remove user with userId from the list.
+ iterator.remove();
+ }
+ }
+ return users;
+ }
+
+ /**
+ * Get all the users except system user and the one with userId passed in.
+ *
+ * @param userId of the user not to be returned.
+ * @return All users other than system user and user with userId.
+ */
+ private List<UserInfo> getAllUsersExceptSystemUserAndSpecifiedUser(int userId) {
+ List<UserInfo> users = mUserManager.getUsers(/* excludeDying= */true);
+
+ for (Iterator<UserInfo> iterator = users.iterator(); iterator.hasNext(); ) {
+ UserInfo userInfo = iterator.next();
+ if (userInfo.id == userId || userInfo.id == UserHandle.USER_SYSTEM) {
+ // Remove user with userId from the list.
+ iterator.remove();
+ }
+ }
+ return users;
+ }
+
+ // User information accessors
+
+ /**
+ * Checks whether the user is system user.
+ *
+ * @param userInfo User to check against system user.
+ * @return {@code true} if system user, {@code false} otherwise.
+ */
+ public boolean isSystemUser(UserInfo userInfo) {
+ return userInfo.id == UserHandle.USER_SYSTEM;
+ }
+
+ /**
+ * Checks whether the user is default user.
+ *
+ * @param userInfo User to check against system user.
+ * @return {@code true} if is default user, {@code false} otherwise.
+ */
+ public boolean isDefaultUser(UserInfo userInfo) {
+ return userInfo.id == CarSettings.DEFAULT_USER_ID_TO_BOOT_INTO;
+ }
+
+ /**
+ * Checks whether passed in user is the foreground user.
+ *
+ * @param userInfo User to check.
+ * @return {@code true} if foreground user, {@code false} otherwise.
+ */
+ public boolean isForegroundUser(UserInfo userInfo) {
+ return getCurrentForegroundUserId() == userInfo.id;
+ }
+
+ /**
+ * Checks whether passed in user is the user that's running the current process.
+ *
+ * @param userInfo User to check.
+ * @return {@code true} if user running the process, {@code false} otherwise.
+ */
+ public boolean isCurrentProcessUser(UserInfo userInfo) {
+ return getCurrentProcessUserId() == userInfo.id;
+ }
+
+ // Foreground user information accessors.
+
+ /**
+ * Checks if the foreground user is a guest user.
+ */
+ public boolean isForegroundUserGuest() {
+ return getCurrentForegroundUserInfo().isGuest();
+ }
+
+ /**
+ * Returns whether this user can be removed from the system.
+ *
+ * @param userInfo User to be removed
+ * @return {@code true} if they can be removed, {@code false} otherwise.
+ */
+ public boolean canUserBeRemoved(UserInfo userInfo) {
+ return !isSystemUser(userInfo);
+ }
+
+ /**
+ * Return whether the foreground user has a restriction.
+ *
+ * @param restriction Restriction to check. Should be a UserManager.* restriction.
+ * @return Whether that restriction exists for the foreground user.
+ */
+ public boolean foregroundUserHasUserRestriction(String restriction) {
+ return mUserManager.hasUserRestriction(
+ restriction, getCurrentForegroundUserInfo().getUserHandle());
+ }
+
+ /**
+ * Checks if the foreground user can add new users.
+ */
+ public boolean canForegroundUserAddUsers() {
+ return !foregroundUserHasUserRestriction(UserManager.DISALLOW_ADD_USER);
+ }
+
+ // Current process user information accessors
+
+ /**
+ * Checks whether this process is running under the system user.
+ */
+ public boolean isCurrentProcessSystemUser() {
+ return mUserManager.isSystemUser();
+ }
+
+ /**
+ * Checks if the calling app is running in a demo user.
+ */
+ public boolean isCurrentProcessDemoUser() {
+ return mUserManager.isDemoUser();
+ }
+
+ /**
+ * Checks if the calling app is running as a guest user.
+ */
+ public boolean isCurrentProcessGuestUser() {
+ return mUserManager.isGuestUser();
+ }
+
+ /**
+ * Check is the calling app is running as a restricted profile user (ie. a LinkedUser).
+ * Restricted profiles are only available when {@link #isHeadlessSystemUser()} is false.
+ */
+ public boolean isCurrentProcessRestrictedProfileUser() {
+ return mUserManager.isRestrictedProfile();
+ }
+
+ // Current process user restriction accessors
+
+ /**
+ * Return whether the user running the current process has a restriction.
+ *
+ * @param restriction Restriction to check. Should be a UserManager.* restriction.
+ * @return Whether that restriction exists for the user running the process.
+ */
+ public boolean isCurrentProcessUserHasRestriction(String restriction) {
+ return mUserManager.hasUserRestriction(restriction);
+ }
+
+ /**
+ * 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 canCurrentProcessModifyAccounts() {
+ return !isCurrentProcessUserHasRestriction(UserManager.DISALLOW_MODIFY_ACCOUNTS)
+ && !isCurrentProcessDemoUser()
+ && !isCurrentProcessGuestUser();
+ }
+
+ /**
+ * Checks if the user running the current process can add new users.
+ */
+ public boolean canCurrentProcessAddUsers() {
+ return !isCurrentProcessUserHasRestriction(UserManager.DISALLOW_ADD_USER);
+ }
+
+ /**
+ * Checks if the user running the current process can remove users.
+ */
+ public boolean canCurrentProcessRemoveUsers() {
+ return !isCurrentProcessUserHasRestriction(UserManager.DISALLOW_REMOVE_USER);
+ }
+
+ /**
+ * Checks if the user running the current process is allowed to switch to another user.
+ */
+ public boolean canCurrentProcessSwitchUsers() {
+ return !isCurrentProcessUserHasRestriction(UserManager.DISALLOW_USER_SWITCH);
+ }
+
+ /**
+ * Creates a new user on the system, the created user would be granted admin role.
+ *
+ * @param userName Name to give to the newly created user.
+ * @return Newly created admin user, null if failed to create a user.
+ */
+ @Nullable
+ public UserInfo createNewAdminUser(String userName) {
+ UserInfo user = mUserManager.createUser(userName, UserInfo.FLAG_ADMIN);
+ if (user == null) {
+ // Couldn't create user, most likely because there are too many, but we haven't
+ // been able to reload the list yet.
+ Log.w(TAG, "can't create admin user.");
+ return null;
+ }
+ assignDefaultIcon(user);
+ return user;
+ }
+
+ /**
+ * Creates a new restricted user on the system.
+ *
+ * @param userName Name to give to the newly created user.
+ * @return Newly created restricted user, null if failed to create a user.
+ */
+ @Nullable
+ public UserInfo createNewNonAdminUser(String userName) {
+ UserInfo user = mUserManager.createUser(userName, 0);
+ if (user == null) {
+ // Couldn't create user, most likely because there are too many, but we haven't
+ // been able to reload the list yet.
+ Log.w(TAG, "can't create non-admin user.");
+ return null;
+ }
+ assignDefaultIcon(user);
+ return user;
+ }
+
+ /**
+ * Tries to remove the user that's passed in. System user cannot be removed.
+ * If the user to be removed is user currently running the process,
+ * it switches to the guest user first, and then removes the user.
+ *
+ * @param userInfo User to be removed
+ * @return {@code true} if user is successfully removed, {@code false} otherwise.
+ */
+ public boolean removeUser(UserInfo userInfo, String guestUserName) {
+ if (isSystemUser(userInfo)) {
+ Log.w(TAG, "User " + userInfo.id + " is system user, could not be removed.");
+ return false;
+ }
+
+ // Not allow to delete the default user for now. Since default user is the one to
+ // boot into.
+ if (isHeadlessSystemUser() && isDefaultUser(userInfo)) {
+ Log.w(TAG, "User " + userInfo.id + " is the default user, could not be removed.");
+ return false;
+ }
+
+ if (userInfo.id == getCurrentForegroundUserId()) {
+ startNewGuestSession(guestUserName);
+ }
+
+ return mUserManager.removeUser(userInfo.id);
+ }
+
+ /**
+ * Switches (logs in) to another user given user id.
+ *
+ * @param id User id to switch to.
+ * @return {@code true} if user switching succeed.
+ */
+ public boolean switchToUserId(int id) {
+ if (id == UserHandle.USER_SYSTEM && isHeadlessSystemUser()) {
+ // System User doesn't associate with real person, can not be switched to.
+ return false;
+ }
+ return mActivityManager.switchUser(id);
+ }
+
+ /**
+ * Switches (logs in) to another user.
+ *
+ * @param userInfo User to switch to.
+ * @return {@code true} if user switching succeed.
+ */
+ public boolean switchToUser(UserInfo userInfo) {
+ if (userInfo.id == getCurrentForegroundUserId()) {
+ return false;
+ }
+
+ return switchToUserId(userInfo.id);
+ }
+
+ /**
+ * Creates a new guest session and switches into the guest session.
+ *
+ * @param guestName Username for the guest user.
+ * @return {@code true} if switch to guest user succeed.
+ */
+ public boolean startNewGuestSession(String guestName) {
+ UserInfo guest = mUserManager.createGuest(mContext, guestName);
+ if (guest == null) {
+ // Couldn't create user, most likely because there are too many, but we haven't
+ // been able to reload the list yet.
+ Log.w(TAG, "can't create user.");
+ return false;
+ }
+ assignDefaultIcon(guest);
+ return switchToUserId(guest.id);
+ }
+
+ /**
+ * Gets a bitmap representing the user's default avatar.
+ *
+ * @param userInfo User whose avatar should be returned.
+ * @return Default user icon
+ */
+ public Bitmap getUserDefaultIcon(UserInfo userInfo) {
+ return UserIcons.convertToBitmap(
+ UserIcons.getDefaultUserIcon(mContext.getResources(), userInfo.id, false));
+ }
+
+ /**
+ * Gets a bitmap representing the default icon for a Guest user.
+ *
+ * @return Default guest user icon
+ */
+ public Bitmap getGuestDefaultIcon() {
+ if (mDefaultGuestUserIcon == null) {
+ mDefaultGuestUserIcon = UserIcons.convertToBitmap(UserIcons.getDefaultUserIcon(
+ mContext.getResources(), UserHandle.USER_NULL, false));
+ }
+ return mDefaultGuestUserIcon;
+ }
+
+ /**
+ * Gets an icon for the user.
+ *
+ * @param userInfo User for which we want to get the icon.
+ * @return a Bitmap for the icon
+ */
+ public Bitmap getUserIcon(UserInfo userInfo) {
+ Bitmap picture = mUserManager.getUserIcon(userInfo.id);
+
+ if (picture == null) {
+ return assignDefaultIcon(userInfo);
+ }
+
+ return picture;
+ }
+
+ /**
+ * Method for scaling a Bitmap icon to a desirable size.
+ *
+ * @param icon Bitmap to scale.
+ * @param desiredSize Wanted size for the icon.
+ * @return Drawable for the icon, scaled to the new size.
+ */
+ public Drawable scaleUserIcon(Bitmap icon, int desiredSize) {
+ Bitmap scaledIcon = Bitmap.createScaledBitmap(
+ icon, desiredSize, desiredSize, true /* filter */);
+ return new BitmapDrawable(mContext.getResources(), scaledIcon);
+ }
+
+ /**
+ * Sets new Username for the user.
+ *
+ * @param user User whose name should be changed.
+ * @param name New username.
+ */
+ public void setUserName(UserInfo user, String name) {
+ mUserManager.setUserName(user.id, name);
+ }
+
+ private void registerReceiver() {
+ IntentFilter filter = new IntentFilter();
+ filter.addAction(Intent.ACTION_USER_REMOVED);
+ filter.addAction(Intent.ACTION_USER_ADDED);
+ filter.addAction(Intent.ACTION_USER_INFO_CHANGED);
+ filter.addAction(Intent.ACTION_USER_SWITCHED);
+ filter.addAction(Intent.ACTION_USER_STOPPED);
+ filter.addAction(Intent.ACTION_USER_UNLOCKED);
+ mContext.registerReceiverAsUser(mUserChangeReceiver, UserHandle.ALL, filter, null, null);
+ }
+
+ // Assigns a default icon to a user according to the user's id.
+ private Bitmap assignDefaultIcon(UserInfo userInfo) {
+ Bitmap bitmap = userInfo.isGuest()
+ ? getGuestDefaultIcon() : getUserDefaultIcon(userInfo);
+ mUserManager.setUserIcon(userInfo.id, bitmap);
+ return bitmap;
+ }
+
+ private void unregisterReceiver() {
+ mContext.unregisterReceiver(mUserChangeReceiver);
+ }
+
+ /**
+ * Interface for listeners that want to register for receiving updates to changes to the users
+ * on the system including removing and adding users, and changing user info.
+ */
+ public interface OnUsersUpdateListener {
+ /**
+ * Method that will get called when users list has been changed.
+ */
+ void onUsersUpdate();
+ }
+}
diff --git a/car-lib/src/android/car/vms/IVmsSubscriberClient.aidl b/car-lib/src/android/car/vms/IVmsSubscriberClient.aidl
index d5b5606..8f67cd5 100644
--- a/car-lib/src/android/car/vms/IVmsSubscriberClient.aidl
+++ b/car-lib/src/android/car/vms/IVmsSubscriberClient.aidl
@@ -16,7 +16,7 @@
package android.car.vms;
-import android.car.vms.VmsAssociatedLayer;
+import android.car.vms.VmsAvailableLayers;
import android.car.vms.VmsLayer;
/**
@@ -28,5 +28,5 @@
*/
void onVmsMessageReceived(in VmsLayer layer, in byte[] payload) = 0;
- void onLayersAvailabilityChanged(in List<VmsAssociatedLayer> availableLayers) = 1;
+ void onLayersAvailabilityChanged(in VmsAvailableLayers availableLayers) = 1;
}
diff --git a/car-lib/src/android/car/vms/IVmsSubscriberService.aidl b/car-lib/src/android/car/vms/IVmsSubscriberService.aidl
index d10a6e4..661065a 100644
--- a/car-lib/src/android/car/vms/IVmsSubscriberService.aidl
+++ b/car-lib/src/android/car/vms/IVmsSubscriberService.aidl
@@ -18,6 +18,7 @@
import android.car.vms.IVmsSubscriberClient;
import android.car.vms.VmsLayer;
+import android.car.vms.VmsAvailableLayers;
/**
* @hide
@@ -87,7 +88,7 @@
/**
* Returns a list of available layers from the closure of the publishers offerings.
*/
- List<VmsLayer> getAvailableLayers() = 8;
+ VmsAvailableLayers getAvailableLayers() = 8;
/**
* Returns a the publisher information for a publisher ID.
diff --git a/car-lib/src/android/car/vms/VmsAssociatedLayer.java b/car-lib/src/android/car/vms/VmsAssociatedLayer.java
index 023fd9c..d3f0e18 100644
--- a/car-lib/src/android/car/vms/VmsAssociatedLayer.java
+++ b/car-lib/src/android/car/vms/VmsAssociatedLayer.java
@@ -16,7 +16,6 @@
package android.car.vms;
-import android.car.annotation.FutureFeature;
import android.os.Parcel;
import android.os.Parcelable;
@@ -27,7 +26,6 @@
*
* @hide
*/
-@FutureFeature
public final class VmsAssociatedLayer implements Parcelable {
// The VmsLayer.
@@ -82,20 +80,22 @@
}
@Override
- public int describeContents() {
- return 0;
+ public int hashCode() {
+ return Objects.hash(mLayer, mPublisherIds);
}
@Override
- public int hashCode() {
- return Objects.hash(mLayer, mPublisherIds);
+ public int describeContents() {
+ return 0;
}
private VmsAssociatedLayer(Parcel in) {
mLayer = in.readParcelable(VmsLayer.class.getClassLoader());
+ Object[] objects = in.readArray(Integer.class.getClassLoader());
+ Integer[] integers = Arrays.copyOf(objects, objects.length, Integer[].class);
+
mPublisherIds = Collections.unmodifiableSet(
- new HashSet<>(Arrays.asList(
- (Integer[]) in.readArray(Integer.class.getClassLoader()))));
+ new HashSet<>(Arrays.asList(integers)));
}
-}
\ No newline at end of file
+}
diff --git a/car-lib/src/android/car/hardware/radio/CarRadioEvent.aidl b/car-lib/src/android/car/vms/VmsAvailableLayers.aidl
similarity index 82%
copy from car-lib/src/android/car/hardware/radio/CarRadioEvent.aidl
copy to car-lib/src/android/car/vms/VmsAvailableLayers.aidl
index 0865646..79a2283 100644
--- a/car-lib/src/android/car/hardware/radio/CarRadioEvent.aidl
+++ b/car-lib/src/android/car/vms/VmsAvailableLayers.aidl
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2015 The Android Open Source Project
+ * 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.
@@ -14,6 +14,6 @@
* limitations under the License.
*/
-package android.car.hardware.radio;
+package android.car.vms;
-parcelable CarRadioEvent;
+parcelable VmsAvailableLayers;
diff --git a/car-lib/src/android/car/vms/VmsAvailableLayers.java b/car-lib/src/android/car/vms/VmsAvailableLayers.java
new file mode 100644
index 0000000..b0324f6
--- /dev/null
+++ b/car-lib/src/android/car/vms/VmsAvailableLayers.java
@@ -0,0 +1,110 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.car.vms;
+
+import android.annotation.SystemApi;
+import android.os.Parcel;
+import android.os.Parcelable;
+
+
+import java.util.Set;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.HashSet;
+import java.util.Collections;
+
+import java.util.Objects;
+
+/**
+ * VMS Layers that can be subscribed to by VMS clients.
+ *
+ * @hide
+ */
+@SystemApi
+public final class VmsAvailableLayers implements Parcelable {
+
+ // A sequence number.
+ private final int mSeq;
+
+ // The list of AssociatedLayers
+ private final Set<VmsAssociatedLayer> mAssociatedLayers;
+
+ public VmsAvailableLayers(Set<VmsAssociatedLayer> associatedLayers, int sequence) {
+ mSeq = sequence;
+
+ mAssociatedLayers = Collections.unmodifiableSet(associatedLayers);
+ }
+
+ public int getSequence() {
+ return mSeq;
+ }
+
+ public Set<VmsAssociatedLayer> getAssociatedLayers() {
+ return mAssociatedLayers;
+ }
+
+ @Override
+ public String toString() {
+ return "VmsAvailableLayers{ seq: " +
+ mSeq +
+ ", AssociatedLayers: " +
+ mAssociatedLayers +
+ "}";
+ }
+
+
+ // Parcelable related methods.
+ public static final Parcelable.Creator<VmsAvailableLayers> CREATOR = new
+ Parcelable.Creator<VmsAvailableLayers>() {
+ public VmsAvailableLayers createFromParcel(Parcel in) {
+ return new VmsAvailableLayers(in);
+ }
+
+ public VmsAvailableLayers[] newArray(int size) {
+ return new VmsAvailableLayers[size];
+ }
+ };
+
+ @Override
+ public void writeToParcel(Parcel out, int flags) {
+ out.writeInt(mSeq);
+ out.writeParcelableList(new ArrayList(mAssociatedLayers), flags);
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (!(o instanceof VmsAvailableLayers)) {
+ return false;
+ }
+ VmsAvailableLayers p = (VmsAvailableLayers) o;
+ return Objects.equals(p.mAssociatedLayers, mAssociatedLayers) &&
+ p.mSeq == mSeq;
+ }
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ private VmsAvailableLayers(Parcel in) {
+ mSeq = in.readInt();
+
+ List<VmsAssociatedLayer> associatedLayers = new ArrayList<>();
+ in.readParcelableList(associatedLayers, VmsAssociatedLayer.class.getClassLoader());
+ mAssociatedLayers = Collections.unmodifiableSet(new HashSet(associatedLayers));
+ }
+}
\ No newline at end of file
diff --git a/car-lib/src/android/car/vms/VmsLayer.java b/car-lib/src/android/car/vms/VmsLayer.java
index 9125796..b921230 100644
--- a/car-lib/src/android/car/vms/VmsLayer.java
+++ b/car-lib/src/android/car/vms/VmsLayer.java
@@ -16,7 +16,7 @@
package android.car.vms;
-import android.car.annotation.FutureFeature;
+import android.annotation.SystemApi;
import android.os.Parcel;
import android.os.Parcelable;
@@ -27,7 +27,7 @@
*
* @hide
*/
-@FutureFeature
+@SystemApi
public final class VmsLayer implements Parcelable {
// The layer Type.
diff --git a/car-lib/src/android/car/vms/VmsLayerDependency.java b/car-lib/src/android/car/vms/VmsLayerDependency.java
index 3b82775..f5b6007 100644
--- a/car-lib/src/android/car/vms/VmsLayerDependency.java
+++ b/car-lib/src/android/car/vms/VmsLayerDependency.java
@@ -16,14 +16,16 @@
package android.car.vms;
-import android.car.annotation.FutureFeature;
+import android.annotation.SystemApi;
import android.os.Parcel;
import android.os.Parcelable;
+
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
+import java.util.Objects;
import java.util.Set;
/**
@@ -31,7 +33,7 @@
*
* @hide
*/
-@FutureFeature
+@SystemApi
public final class VmsLayerDependency implements Parcelable {
private final VmsLayer mLayer;
private final Set<VmsLayer> mDependency;
@@ -64,20 +66,35 @@
}
public static final Parcelable.Creator<VmsLayerDependency> CREATOR = new
- Parcelable.Creator<VmsLayerDependency>() {
- public VmsLayerDependency createFromParcel(Parcel in) {
- return new VmsLayerDependency(in);
- }
- public VmsLayerDependency[] newArray(int size) {
- return new VmsLayerDependency[size];
- }
- };
+ Parcelable.Creator<VmsLayerDependency>() {
+ public VmsLayerDependency createFromParcel(Parcel in) {
+ return new VmsLayerDependency(in);
+ }
+
+ public VmsLayerDependency[] newArray(int size) {
+ return new VmsLayerDependency[size];
+ }
+ };
public String toString() {
return "VmsLayerDependency{ Layer: " + mLayer + " Dependency: " + mDependency + "}";
}
@Override
+ public boolean equals(Object o) {
+ if (!(o instanceof VmsLayerDependency)) {
+ return false;
+ }
+ VmsLayerDependency p = (VmsLayerDependency) o;
+ return Objects.equals(p.mLayer, mLayer) && p.mDependency.equals(mDependency);
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(mLayer, mDependency);
+ }
+
+ @Override
public void writeToParcel(Parcel out, int flags) {
out.writeParcelable(mLayer, flags);
out.writeParcelableList(new ArrayList<VmsLayer>(mDependency), flags);
@@ -94,4 +111,4 @@
in.readParcelableList(dependency, VmsLayer.class.getClassLoader());
mDependency = Collections.unmodifiableSet(new HashSet<VmsLayer>(dependency));
}
-}
\ No newline at end of file
+}
diff --git a/car-lib/src/android/car/vms/VmsLayersOffering.java b/car-lib/src/android/car/vms/VmsLayersOffering.java
index 6abffc6..f2f4b73 100644
--- a/car-lib/src/android/car/vms/VmsLayersOffering.java
+++ b/car-lib/src/android/car/vms/VmsLayersOffering.java
@@ -16,13 +16,15 @@
package android.car.vms;
-import android.car.annotation.FutureFeature;
+import android.annotation.SystemApi;
import android.os.Parcel;
import android.os.Parcelable;
+
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
+import java.util.Objects;
import java.util.Set;
/**
@@ -30,7 +32,7 @@
*
* @hide
*/
-@FutureFeature
+@SystemApi
public final class VmsLayersOffering implements Parcelable {
private final Set<VmsLayerDependency> mDependencies;
@@ -54,18 +56,23 @@
}
public static final Parcelable.Creator<VmsLayersOffering> CREATOR = new
- Parcelable.Creator<VmsLayersOffering>() {
- public VmsLayersOffering createFromParcel(Parcel in) {
- return new VmsLayersOffering(in);
- }
- public VmsLayersOffering[] newArray(int size) {
- return new VmsLayersOffering[size];
- }
- };
+ Parcelable.Creator<VmsLayersOffering>() {
+ public VmsLayersOffering createFromParcel(Parcel in) {
+ return new VmsLayersOffering(in);
+ }
+
+ public VmsLayersOffering[] newArray(int size) {
+ return new VmsLayersOffering[size];
+ }
+ };
@Override
public String toString() {
- return "VmsLayersOffering{" + mDependencies+ "}";
+ return "VmsLayersOffering{ Publisher: " +
+ mPublisherId +
+ " Dependencies: " +
+ mDependencies +
+ "}";
}
@Override
@@ -76,6 +83,20 @@
}
@Override
+ public boolean equals(Object o) {
+ if (!(o instanceof VmsLayersOffering)) {
+ return false;
+ }
+ VmsLayersOffering p = (VmsLayersOffering) o;
+ return Objects.equals(p.mPublisherId, mPublisherId) && p.mDependencies.equals(mDependencies);
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(mPublisherId, mDependencies);
+ }
+
+ @Override
public int describeContents() {
return 0;
}
diff --git a/car-lib/src/android/car/vms/VmsOperationRecorder.java b/car-lib/src/android/car/vms/VmsOperationRecorder.java
index c873dce..bfb6055 100644
--- a/car-lib/src/android/car/vms/VmsOperationRecorder.java
+++ b/car-lib/src/android/car/vms/VmsOperationRecorder.java
@@ -1,6 +1,6 @@
package android.car.vms;
-import android.car.annotation.FutureFeature;
+import android.annotation.SystemApi;
import android.util.Log;
import com.android.internal.annotations.VisibleForTesting;
@@ -24,7 +24,7 @@
*
* @hide
*/
-@FutureFeature
+@SystemApi
public final class VmsOperationRecorder {
private static final String TAG = "VmsOperationRecorder";
private static final VmsOperationRecorder INSTANCE = new VmsOperationRecorder(new Writer());
diff --git a/car-lib/src/android/car/vms/VmsPublisherClientService.java b/car-lib/src/android/car/vms/VmsPublisherClientService.java
index 33ca1f3..d18c06c 100644
--- a/car-lib/src/android/car/vms/VmsPublisherClientService.java
+++ b/car-lib/src/android/car/vms/VmsPublisherClientService.java
@@ -17,8 +17,8 @@
package android.car.vms;
+import android.annotation.SystemApi;
import android.app.Service;
-import android.car.annotation.FutureFeature;
import android.content.Intent;
import android.os.Handler;
import android.os.IBinder;
@@ -46,7 +46,7 @@
*
* @hide
*/
-@FutureFeature
+@SystemApi
public abstract class VmsPublisherClientService extends Service {
private static final boolean DBG = true;
private static final String TAG = "VmsPublisherClient";
@@ -60,7 +60,7 @@
private IBinder mToken = null;
@Override
- public final IBinder onBind(Intent intent) {
+ public IBinder onBind(Intent intent) {
if (DBG) {
Log.d(TAG, "onBind, intent: " + intent);
}
@@ -68,7 +68,7 @@
}
@Override
- public final boolean onUnbind(Intent intent) {
+ public boolean onUnbind(Intent intent) {
if (DBG) {
Log.d(TAG, "onUnbind, intent: " + intent);
}
diff --git a/car-lib/src/android/car/vms/VmsSubscriberManager.java b/car-lib/src/android/car/vms/VmsSubscriberManager.java
index 6f6377c..fe9e8c3 100644
--- a/car-lib/src/android/car/vms/VmsSubscriberManager.java
+++ b/car-lib/src/android/car/vms/VmsSubscriberManager.java
@@ -16,11 +16,15 @@
package android.car.vms;
+import android.annotation.CallbackExecutor;
+import android.annotation.NonNull;
+import android.annotation.SystemApi;
import android.car.Car;
import android.car.CarManagerBase;
import android.car.CarNotConnectedException;
-import android.car.annotation.FutureFeature;
+import android.car.vms.VmsSubscriberManager.VmsSubscriberClientCallback;
import android.os.Handler;
+import android.os.Binder;
import android.os.IBinder;
import android.os.Looper;
import android.os.Message;
@@ -28,29 +32,31 @@
import android.util.Log;
import com.android.internal.annotations.GuardedBy;
+import com.android.internal.util.Preconditions;
import java.lang.ref.WeakReference;
-import java.util.List;
+import java.util.concurrent.Executor;
/**
* API for interfacing with the VmsSubscriberService. It supports a single client callback that can
* (un)subscribe to different layers. Getting notifactions and managing subscriptions is enabled
- * after setting the client callback with #registerClientCallback.
+ * after setting the client callback with #setVmsSubscriberClientCallback.
* SystemApi candidate
*
* @hide
*/
-@FutureFeature
+@SystemApi
public final class VmsSubscriberManager implements CarManagerBase {
private static final boolean DBG = true;
private static final String TAG = "VmsSubscriberManager";
- private final Handler mHandler;
private final IVmsSubscriberService mVmsSubscriberService;
private final IVmsSubscriberClient mSubscriberManagerClient;
private final Object mClientCallbackLock = new Object();
@GuardedBy("mClientCallbackLock")
private VmsSubscriberClientCallback mClientCallback;
+ @GuardedBy("mClientCallbackLock")
+ private Executor mExecutor;
/**
* Interface exposed to VMS subscribers: it is a wrapper of IVmsSubscriberClient.
@@ -64,98 +70,67 @@
/**
* Called when layers availability change
*/
- void onLayersAvailabilityChanged(List<VmsLayer> availableLayers);
+ void onLayersAvailabilityChanged(VmsAvailableLayers availableLayers);
}
/**
- * Allows to asynchronously dispatch onVmsMessageReceived events.
+ * Hidden constructor - can only be used internally.
+ * @hide
*/
- private final static class VmsEventHandler extends Handler {
- /**
- * Constants handled in the handler
- */
- private static final int ON_RECEIVE_MESSAGE_EVENT = 0;
- private static final int ON_AVAILABILITY_CHANGE_EVENT = 1;
-
- private final WeakReference<VmsSubscriberManager> mMgr;
-
- VmsEventHandler(VmsSubscriberManager mgr, Looper looper) {
- super(looper);
- mMgr = new WeakReference<>(mgr);
- }
-
- @Override
- public void handleMessage(Message msg) {
- VmsSubscriberManager mgr = mMgr.get();
- switch (msg.what) {
- case ON_RECEIVE_MESSAGE_EVENT:
- if (mgr != null) {
- // Parse the message
- VmsDataMessage vmsDataMessage = (VmsDataMessage) msg.obj;
-
- // Dispatch the parsed message
- mgr.dispatchOnReceiveMessage(vmsDataMessage.getLayer(),
- vmsDataMessage.getPayload());
- }
- break;
- case ON_AVAILABILITY_CHANGE_EVENT:
- if (mgr != null) {
- // Parse the message
- List<VmsLayer> vmsAvailabilityChangeMessage = (List<VmsLayer>) msg.obj;
-
- // Dispatch the parsed message
- mgr.dispatchOnAvailabilityChangeMessage(vmsAvailabilityChangeMessage);
- }
- break;
-
- default:
- Log.e(VmsSubscriberManager.TAG, "Event type not handled: " + msg.what);
- break;
- }
- }
- }
-
- public VmsSubscriberManager(IBinder service, Handler handler) {
+ public VmsSubscriberManager(IBinder service) {
mVmsSubscriberService = IVmsSubscriberService.Stub.asInterface(service);
- mHandler = new VmsEventHandler(this, handler.getLooper());
mSubscriberManagerClient = new IVmsSubscriberClient.Stub() {
@Override
- public void onVmsMessageReceived(VmsLayer layer, byte[] payload)
- throws RemoteException {
- // Create the data message
- VmsDataMessage vmsDataMessage = new VmsDataMessage(layer, payload);
- mHandler.sendMessage(
- mHandler.obtainMessage(
- VmsEventHandler.ON_RECEIVE_MESSAGE_EVENT,
- vmsDataMessage));
+ public void onVmsMessageReceived(VmsLayer layer, byte[] payload) {
+ Executor executor;
+ synchronized (mClientCallbackLock) {
+ executor = mExecutor;
+ }
+ if (executor == null) {
+ if (DBG) {
+ Log.d(TAG, "Executor is null in onVmsMessageReceived");
+ }
+ return;
+ }
+ Binder.clearCallingIdentity();
+ executor.execute(() -> {dispatchOnReceiveMessage(layer, payload);});
}
@Override
- public void onLayersAvailabilityChanged(List<VmsAssociatedLayer> availableLayers) {
- mHandler.sendMessage(
- mHandler.obtainMessage(
- VmsEventHandler.ON_AVAILABILITY_CHANGE_EVENT,
- availableLayers));
+ public void onLayersAvailabilityChanged(VmsAvailableLayers availableLayers) {
+ Executor executor;
+ synchronized (mClientCallbackLock) {
+ executor = mExecutor;
+ }
+ if (executor == null) {
+ if (DBG) {
+ Log.d(TAG, "Executor is null in onLayersAvailabilityChanged");
+ }
+ return;
+ }
+ Binder.clearCallingIdentity();
+ executor.execute(() -> {dispatchOnAvailabilityChangeMessage(availableLayers);});
}
};
}
/**
- * Registers the client callback in order to enable communication with the client.
- * By registering, the client will start getting notifications, and will be able to subscribe
- * to layers.
- * <p>
- *
+ * Sets the callback for the notification of onVmsMessageReceived events.
+ * @param executor {@link Executor} to handle the callbacks
* @param clientCallback subscriber callback that will handle onVmsMessageReceived events.
* @throws IllegalStateException if the client callback was already set.
*/
- public void registerClientCallback(VmsSubscriberClientCallback clientCallback)
- throws CarNotConnectedException {
+ public void setVmsSubscriberClientCallback(@NonNull @CallbackExecutor Executor executor,
+ @NonNull VmsSubscriberClientCallback clientCallback)
+ throws CarNotConnectedException {
+ Preconditions.checkNotNull(clientCallback);
+ Preconditions.checkNotNull(executor);
synchronized (mClientCallbackLock) {
if (mClientCallback != null) {
throw new IllegalStateException("Client callback is already configured.");
}
mClientCallback = clientCallback;
+ mExecutor = executor;
}
try {
mVmsSubscriberService.addVmsSubscriberToNotifications(mSubscriberManagerClient);
@@ -165,25 +140,26 @@
}
}
- /**
- * Unregisters the client callback which disables communication with the client.
- * @throws CarNotConnectedException, IllegalStateException
- */
- public void unregisterClientCallback()
- throws CarNotConnectedException {
+ /**
+ * Clears the client callback which disables communication with the client.
+ *
+ * @throws CarNotConnectedException
+ */
+ public void clearVmsSubscriberClientCallback() throws CarNotConnectedException {
+ synchronized (mClientCallbackLock) {
+ if (mExecutor == null) return;
+ }
try {
mVmsSubscriberService.removeVmsSubscriberToNotifications(mSubscriberManagerClient);
} catch (RemoteException e) {
Log.e(TAG, "Could not connect: ", e);
throw new CarNotConnectedException(e);
- } catch (IllegalStateException e) {
- Log.e(TAG, "Could not unsubscribe from notifications");
- throw e;
}
synchronized (mClientCallbackLock) {
mClientCallback = null;
+ mExecutor = null;
}
}
@@ -204,11 +180,27 @@
}
/**
+ * Returns the available layers.
+ */
+ public VmsAvailableLayers getAvailableLayers()
+ throws CarNotConnectedException, IllegalStateException {
+ try {
+ return mVmsSubscriberService.getAvailableLayers();
+ } catch (RemoteException e) {
+ Log.e(TAG, "Could not connect: ", e);
+ throw new CarNotConnectedException(e);
+ } catch (IllegalStateException ex) {
+ Car.checkCarNotConnectedExceptionFromCarService(ex);
+ throw new IllegalStateException(ex);
+ }
+ }
+
+ /**
* Subscribes to listen to the layer specified.
*
* @param layer the layer to subscribe to.
* @throws IllegalStateException if the client callback was not set via
- * {@link #registerClientCallback}.
+ * {@link #setVmsSubscriberClientCallback}.
*/
public void subscribe(VmsLayer layer) throws CarNotConnectedException {
verifySubscriptionIsAllowed();
@@ -229,7 +221,7 @@
* @param layer the layer to subscribe to.
* @param publisherId the publisher of the layer.
* @throws IllegalStateException if the client callback was not set via
- * {@link #registerClientCallback}.
+ * {@link #setVmsSubscriberClientCallback}.
*/
public void subscribe(VmsLayer layer, int publisherId) throws CarNotConnectedException {
verifySubscriptionIsAllowed();
@@ -263,7 +255,7 @@
*
* @param layer the layer to unsubscribe from.
* @throws IllegalStateException if the client callback was not set via
- * {@link #registerClientCallback}.
+ * {@link #setVmsSubscriberClientCallback}.
*/
public void unsubscribe(VmsLayer layer) {
verifySubscriptionIsAllowed();
@@ -271,7 +263,7 @@
mVmsSubscriberService.removeVmsSubscriber(mSubscriberManagerClient, layer);
VmsOperationRecorder.get().unsubscribe(layer);
} catch (RemoteException e) {
- Log.e(TAG, "Failed to unregister subscriber", e);
+ Log.e(TAG, "Failed to clear subscriber", e);
// ignore
} catch (IllegalStateException ex) {
Car.hideCarNotConnectedExceptionFromCarService(ex);
@@ -284,7 +276,7 @@
* @param layer the layer to unsubscribe from.
* @param publisherId the pubisher of the layer.
* @throws IllegalStateException if the client callback was not set via
- * {@link #registerClientCallback}.
+ * {@link #setVmsSubscriberClientCallback}.
*/
public void unsubscribe(VmsLayer layer, int publisherId) {
try {
@@ -292,7 +284,7 @@
mSubscriberManagerClient, layer, publisherId);
VmsOperationRecorder.get().unsubscribe(layer, publisherId);
} catch (RemoteException e) {
- Log.e(TAG, "Failed to unregister subscriber", e);
+ Log.e(TAG, "Failed to clear subscriber", e);
// ignore
} catch (IllegalStateException ex) {
Car.hideCarNotConnectedExceptionFromCarService(ex);
@@ -304,7 +296,7 @@
mVmsSubscriberService.removeVmsSubscriberPassive(mSubscriberManagerClient);
VmsOperationRecorder.get().stopMonitoring();
} catch (RemoteException e) {
- Log.e(TAG, "Failed to unregister subscriber ", e);
+ Log.e(TAG, "Failed to clear subscriber ", e);
// ignore
} catch (IllegalStateException ex) {
Car.hideCarNotConnectedExceptionFromCarService(ex);
@@ -320,7 +312,7 @@
clientCallback.onVmsMessageReceived(layer, payload);
}
- private void dispatchOnAvailabilityChangeMessage(List<VmsLayer> availableLayers) {
+ private void dispatchOnAvailabilityChangeMessage(VmsAvailableLayers availableLayers) {
VmsSubscriberClientCallback clientCallback = getClientCallbackThreadSafe();
if (clientCallback == null) {
Log.e(TAG, "Cannot dispatch availability change message.");
diff --git a/car-lib/src/android/car/vms/VmsSubscriptionState.java b/car-lib/src/android/car/vms/VmsSubscriptionState.java
index ea433f7..7b8ce81 100644
--- a/car-lib/src/android/car/vms/VmsSubscriptionState.java
+++ b/car-lib/src/android/car/vms/VmsSubscriptionState.java
@@ -16,7 +16,6 @@
package android.car.vms;
-import android.car.annotation.FutureFeature;
import android.os.Parcel;
import android.os.Parcelable;
@@ -24,15 +23,14 @@
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
+import java.util.Objects;
import java.util.Set;
-
/**
* The list of layers with subscribers.
*
* @hide
*/
-@FutureFeature
public final class VmsSubscriptionState implements Parcelable {
private final int mSequenceNumber;
private final Set<VmsLayer> mLayers;
@@ -102,6 +100,22 @@
}
@Override
+ public boolean equals(Object o) {
+ if (!(o instanceof VmsSubscriptionState)) {
+ return false;
+ }
+ VmsSubscriptionState p = (VmsSubscriptionState) o;
+ return Objects.equals(p.mSequenceNumber, mSequenceNumber) &&
+ p.mLayers.equals(mLayers) &&
+ p.mSubscribedLayersFromPublishers.equals(mSubscribedLayersFromPublishers);
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(mSequenceNumber, mLayers, mSubscribedLayersFromPublishers);
+ }
+
+ @Override
public int describeContents() {
return 0;
}
@@ -115,6 +129,7 @@
List<VmsAssociatedLayer> associatedLayers = new ArrayList<>();
in.readParcelableList(associatedLayers, VmsAssociatedLayer.class.getClassLoader());
- mSubscribedLayersFromPublishers = Collections.unmodifiableSet(new HashSet(associatedLayers));
+ mSubscribedLayersFromPublishers =
+ Collections.unmodifiableSet(new HashSet(associatedLayers));
}
}
\ No newline at end of file
diff --git a/car-lib/src/com/android/car/internal/CarPermission.java b/car-lib/src/com/android/car/internal/CarPermission.java
index 0b3820f..6439c00 100644
--- a/car-lib/src/com/android/car/internal/CarPermission.java
+++ b/car-lib/src/com/android/car/internal/CarPermission.java
@@ -58,4 +58,10 @@
+ " uid:"
+ Binder.getCallingUid());
}
+
+ /** @hide */
+ @Override
+ public String toString() {
+ return mName;
+ }
}
diff --git a/car-lib/src/com/android/car/internal/CarRatedFloatListeners.java b/car-lib/src/com/android/car/internal/CarRatedFloatListeners.java
new file mode 100644
index 0000000..c59a2fa
--- /dev/null
+++ b/car-lib/src/com/android/car/internal/CarRatedFloatListeners.java
@@ -0,0 +1,96 @@
+/*
+ * 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.internal;
+
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * Represent listeners for a property grouped by their rate.
+ * T is a type of EventListener such as CarPropertyEventListener
+ * in {@link android.car.hardware.property.CarPropertyManager}
+ * @param <T>
+ * @hide
+ */
+public class CarRatedFloatListeners<T> {
+ private final Map<T, Float> mListenersToRate = new HashMap<>(4);
+
+ private float mUpdateRate;
+
+ protected long mLastUpdateTime = -1;
+
+ protected CarRatedFloatListeners(float rate) {
+ mUpdateRate = rate;
+ }
+
+ /** Check listener */
+ public boolean contains(T listener) {
+ return mListenersToRate.containsKey(listener);
+ }
+ /** Return current rate after updating */
+ public float getRate() {
+ return mUpdateRate;
+ }
+
+ /**
+ * Remove given listener from the list and update rate if necessary.
+ *
+ * @param listener
+ * @return true if rate was updated. Otherwise, returns false.
+ */
+ public boolean remove(T listener) {
+ mListenersToRate.remove(listener);
+ if (mListenersToRate.isEmpty()) {
+ return false;
+ }
+ Float updateRate = Collections.max(mListenersToRate.values());
+ if (updateRate != mUpdateRate) {
+ mUpdateRate = updateRate;
+ return true;
+ }
+ return false;
+ }
+
+ public boolean isEmpty() {
+ return mListenersToRate.isEmpty();
+ }
+
+ /**
+ * Add given listener to the list and update rate if necessary.
+ *
+ * @param listener if null, add part is skipped.
+ * @param updateRate
+ * @return true if rate was updated. Otherwise, returns false.
+ */
+ public boolean addAndUpdateRate(T listener, float updateRate) {
+ Float oldUpdateRate = mListenersToRate.put(listener, updateRate);
+ if (mUpdateRate < updateRate) {
+ mUpdateRate = updateRate;
+ return true;
+ } else if (oldUpdateRate != null && oldUpdateRate == mUpdateRate) {
+ mUpdateRate = Collections.max(mListenersToRate.values());
+ }
+ return false;
+ }
+
+ public Collection<T> getListeners() {
+ return mListenersToRate.keySet();
+ }
+}
+
diff --git a/car-lib/src/com/android/car/internal/SingleMessageHandler.java b/car-lib/src/com/android/car/internal/SingleMessageHandler.java
index f659f17..57788a7 100644
--- a/car-lib/src/com/android/car/internal/SingleMessageHandler.java
+++ b/car-lib/src/com/android/car/internal/SingleMessageHandler.java
@@ -20,6 +20,7 @@
import android.os.Handler.Callback;
import android.os.Looper;
import android.os.Message;
+
import java.util.List;
import java.util.function.Consumer;
@@ -36,6 +37,10 @@
mHandler = new Handler(looper, this);
}
+ public SingleMessageHandler(Handler handler, int handledMessage) {
+ this(handler.getLooper(), handledMessage);
+ }
+
protected abstract void handleEvent(EventType event);
@Override
@@ -56,4 +61,5 @@
public void sendEvents(List<EventType> events) {
mHandler.sendMessage(mHandler.obtainMessage(mHandledMessageWhat, events));
}
+
}
diff --git a/car-maps-placeholder/Android.mk b/car-maps-placeholder/Android.mk
index 3ab379a..3c60309 100644
--- a/car-maps-placeholder/Android.mk
+++ b/car-maps-placeholder/Android.mk
@@ -30,6 +30,8 @@
# TODO(b/73535841): Can build against current once the car stubs exist.
LOCAL_PRIVATE_PLATFORM_APIS := true
+LOCAL_STATIC_ANDROID_LIBRARIES := androidx.car_car
+
LOCAL_CERTIFICATE := platform
LOCAL_MODULE_TAGS := optional
@@ -38,8 +40,6 @@
LOCAL_DEX_PREOPT := false
-include packages/apps/Car/libs/car-stream-ui-lib/car-stream-ui-lib.mk
-
include $(BUILD_PACKAGE)
endif
diff --git a/car-maps-placeholder/AndroidManifest.xml b/car-maps-placeholder/AndroidManifest.xml
index e166420..38caf38 100644
--- a/car-maps-placeholder/AndroidManifest.xml
+++ b/car-maps-placeholder/AndroidManifest.xml
@@ -31,8 +31,6 @@
android:resizeableActivity="true">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
- <category android:name="android.intent.category.LAUNCHER" />
- <category android:name="android.intent.category.APP_MAPS" />
</intent-filter>
</activity>
</application>
diff --git a/car-maps-placeholder/res/layout/maps_placeholder_activity.xml b/car-maps-placeholder/res/layout/maps_placeholder_activity.xml
index d35ce29..42962b0 100644
--- a/car-maps-placeholder/res/layout/maps_placeholder_activity.xml
+++ b/car-maps-placeholder/res/layout/maps_placeholder_activity.xml
@@ -24,5 +24,6 @@
android:layout_width="@dimen/error_text_container_width"
android:layout_height="wrap_content"
android:text="@string/error_text"
- style="@style/CarBody1.Light" />
+ android:textColor="@color/car_body1_light"
+ android:textAppearance="@style/TextAppearance.Car.Body1" />
</FrameLayout>
diff --git a/car-support-lib/Android.mk b/car-support-lib/Android.mk
index 76f2587..6201f21 100644
--- a/car-support-lib/Android.mk
+++ b/car-support-lib/Android.mk
@@ -29,17 +29,15 @@
LOCAL_RESOURCE_DIR := $(LOCAL_PATH)/res
-# Build against the current public APIs of the SDK
-LOCAL_SDK_VERSION := current
+#TODO(b/72620511) support lib should be able to be using public APIs only
+#LOCAL_SDK_VERSION := current
+LOCAL_PRIVATE_PLATFORM_APIS := true
LOCAL_MANIFEST_FILE := AndroidManifest.xml
LOCAL_SRC_FILES := $(call all-java-files-under, src) $(call all-Iaidl-files-under, src)
LOCAL_JAVA_LIBRARIES += android.car\
- android-support-annotations
-# Specify 1.7 for backwards compatibility.
-# Otherwise the lib won't be usable on pre-N devices
-LOCAL_JAVA_LANGUAGE_VERSION := 1.7
+ androidx.annotation_annotation
LOCAL_PROGUARD_ENABLED := custom optimization obfuscation
LOCAL_PROGUARD_FLAGS := -dontwarn
@@ -61,17 +59,15 @@
LOCAL_RESOURCE_DIR := $(LOCAL_PATH)/res
-# Build against the current public APIs of the SDK
-LOCAL_SDK_VERSION := current
+#TODO(b/72620511) support lib should be able to be using public APIs only
+#LOCAL_SDK_VERSION := current
+LOCAL_PRIVATE_PLATFORM_APIS := true
LOCAL_MANIFEST_FILE := AndroidManifest.xml
LOCAL_SRC_FILES := $(call all-java-files-under, src) $(call all-Iaidl-files-under, src)
LOCAL_JAVA_LIBRARIES += android.car\
- android-support-annotations
-# Specify 1.7 for backwards compatibility.
-# Otherwise the lib won't be usable on pre-N devices
-LOCAL_JAVA_LANGUAGE_VERSION := 1.7
+ androidx.annotation_annotation
LOCAL_PROGUARD_ENABLED := disabled
include $(BUILD_STATIC_JAVA_LIBRARY)
@@ -85,15 +81,17 @@
include $(CLEAR_VARS)
LOCAL_MODULE := android.support.car
-LOCAL_SDK_VERSION := current
+
+#TODO(b/72620511) support lib should be able to be using public APIs only
+#LOCAL_SDK_VERSION := current
+LOCAL_PRIVATE_PLATFORM_APIS := true
LOCAL_SRC_FILES := $(call all-java-files-under, src) $(call all-Iaidl-files-under, src)
-LOCAL_STATIC_JAVA_LIBRARIES += android-support-annotations
+LOCAL_STATIC_JAVA_LIBRARIES += androidx.annotation_annotation
LOCAL_JAVA_LIBRARIES += android.car
-LOCAL_JAVA_LANGUAGE_VERSION := 1.7
include $(BUILD_STATIC_JAVA_LIBRARY)
# API Check
@@ -118,7 +116,7 @@
LOCAL_JAVA_LIBRARIES := \
android.car \
- android-support-annotations
+ androidx.annotation_annotation
LOCAL_MODULE := android.support.car
LOCAL_MODULE_TAGS := optional
diff --git a/car-support-lib/AndroidManifest.xml b/car-support-lib/AndroidManifest.xml
index 36b1649..f92f21b 100644
--- a/car-support-lib/AndroidManifest.xml
+++ b/car-support-lib/AndroidManifest.xml
@@ -17,6 +17,6 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:androidprv="http://schemas.android.com/apk/prv/res/android"
package="android.support.car.ui" >
- <uses-sdk android:minSdkVersion="23"
+ <uses-sdk android:minSdkVersion="21"
android:targetSdkVersion="23" />
</manifest>
diff --git a/car-support-lib/api/current.txt b/car-support-lib/api/current.txt
index 3d9c32b..7ee1246 100644
--- a/car-support-lib/api/current.txt
+++ b/car-support-lib/api/current.txt
@@ -50,6 +50,10 @@
public abstract class CarInfoManager {
ctor public CarInfoManager();
method public abstract int getDriverPosition() throws android.support.car.CarNotConnectedException;
+ method public abstract float getEvBatteryCapacity() throws android.support.car.CarNotConnectedException;
+ method public abstract int[] getEvConnectorTypes() throws android.support.car.CarNotConnectedException;
+ method public abstract float getFuelCapacity() throws android.support.car.CarNotConnectedException;
+ method public abstract int[] getFuelTypes() throws android.support.car.CarNotConnectedException;
method public abstract java.lang.String getHeadunitManufacturer() throws android.support.car.CarNotConnectedException;
method public abstract java.lang.String getHeadunitModel() throws android.support.car.CarNotConnectedException;
method public abstract java.lang.String getHeadunitSoftwareBuild() throws android.support.car.CarNotConnectedException;
@@ -148,11 +152,16 @@
method public abstract boolean isSensorSupported(int) throws android.support.car.CarNotConnectedException;
method public abstract void removeListener(android.support.car.hardware.CarSensorManager.OnSensorChangedListener);
method public abstract void removeListener(android.support.car.hardware.CarSensorManager.OnSensorChangedListener, int);
- field public static final int SENSOR_RATE_FASTEST = 0; // 0x0
- field public static final int SENSOR_RATE_NORMAL = 3; // 0x3
+ field public static final int SENSOR_RATE_FASTEST = 100; // 0x64
+ field public static final int SENSOR_RATE_NORMAL = 1; // 0x1
field public static final int SENSOR_TYPE_ABS_ACTIVE = 24; // 0x18
field public static final int SENSOR_TYPE_COMPASS = 1; // 0x1
field public static final int SENSOR_TYPE_DRIVING_STATUS = 11; // 0xb
+ field public static final int SENSOR_TYPE_EV_BATTERY_CHARGE_RATE = 31; // 0x1f
+ field public static final int SENSOR_TYPE_EV_BATTERY_LEVEL = 28; // 0x1c
+ field public static final int SENSOR_TYPE_EV_CHARGE_PORT_CONNECTED = 30; // 0x1e
+ field public static final int SENSOR_TYPE_EV_CHARGE_PORT_OPEN = 29; // 0x1d
+ field public static final int SENSOR_TYPE_FUEL_DOOR_OPEN = 27; // 0x1b
field public static final int SENSOR_TYPE_NIGHT = 9; // 0x9
field public static final int SENSOR_TYPE_PARKING_BRAKE = 6; // 0x6
field public static final int SENSOR_TYPE_TRACTION_CONTROL_ACTIVE = 25; // 0x19
@@ -169,24 +178,11 @@
public abstract class CarAudioManager {
ctor public CarAudioManager();
- method public abstract void abandonAudioFocus(android.media.AudioManager.OnAudioFocusChangeListener, android.media.AudioAttributes);
method public abstract android.support.car.media.CarAudioRecord createCarAudioRecord(int) throws android.support.car.CarNotConnectedException, java.lang.SecurityException;
- method public abstract android.media.AudioAttributes getAudioAttributesForCarUsage(int) throws android.support.car.CarNotConnectedException;
method public abstract android.media.AudioFormat getAudioRecordAudioFormat() throws android.support.car.CarNotConnectedException;
method public abstract int getAudioRecordMaxBufferSize() throws android.support.car.CarNotConnectedException;
method public abstract int getAudioRecordMinBufferSize() throws android.support.car.CarNotConnectedException;
method public abstract boolean isAudioRecordSupported() throws android.support.car.CarNotConnectedException;
- method public abstract boolean isMediaMuted() throws android.support.car.CarNotConnectedException;
- method public abstract int requestAudioFocus(android.media.AudioManager.OnAudioFocusChangeListener, android.media.AudioAttributes, int) throws android.support.car.CarNotConnectedException, java.lang.IllegalArgumentException;
- field public static final int CAR_AUDIO_USAGE_ALARM = 6; // 0x6
- field public static final int CAR_AUDIO_USAGE_DEFAULT = 0; // 0x0
- field public static final int CAR_AUDIO_USAGE_MUSIC = 1; // 0x1
- field public static final int CAR_AUDIO_USAGE_NAVIGATION_GUIDANCE = 3; // 0x3
- field public static final int CAR_AUDIO_USAGE_NOTIFICATION = 7; // 0x7
- field public static final int CAR_AUDIO_USAGE_SYSTEM_SAFETY_ALERT = 9; // 0x9
- field public static final int CAR_AUDIO_USAGE_SYSTEM_SOUND = 8; // 0x8
- field public static final int CAR_AUDIO_USAGE_VOICE_CALL = 4; // 0x4
- field public static final int CAR_AUDIO_USAGE_VOICE_COMMAND = 5; // 0x5
}
public abstract class CarAudioRecord {
@@ -220,38 +216,7 @@
ctor public CarNavigationStatusManager();
method public abstract void addListener(android.support.car.navigation.CarNavigationStatusManager.CarNavigationCallback) throws android.support.car.CarNotConnectedException;
method public abstract void removeListener();
- method public abstract deprecated void sendNavigationStatus(int) throws android.support.car.CarNotConnectedException;
- method public abstract deprecated void sendNavigationTurnDistanceEvent(int, int, int, int) throws android.support.car.CarNotConnectedException;
- method public abstract deprecated void sendNavigationTurnEvent(int, java.lang.CharSequence, int, int, int) throws android.support.car.CarNotConnectedException;
- field public static final int DISTANCE_FEET = 4; // 0x4
- field public static final int DISTANCE_KILOMETERS = 2; // 0x2
- field public static final int DISTANCE_METERS = 1; // 0x1
- field public static final int DISTANCE_MILES = 3; // 0x3
- field public static final int DISTANCE_YARDS = 5; // 0x5
- field public static final int STATUS_ACTIVE = 1; // 0x1
- field public static final int STATUS_INACTIVE = 2; // 0x2
- field public static final int STATUS_UNAVAILABLE = 0; // 0x0
- field public static final int TURN_DEPART = 1; // 0x1
- field public static final int TURN_DESTINATION = 19; // 0x13
- field public static final int TURN_FERRY_BOAT = 16; // 0x10
- field public static final int TURN_FERRY_TRAIN = 17; // 0x11
- field public static final int TURN_FORK = 9; // 0x9
- field public static final int TURN_MERGE = 10; // 0xa
- field public static final int TURN_NAME_CHANGE = 2; // 0x2
- field public static final int TURN_OFF_RAMP = 8; // 0x8
- field public static final int TURN_ON_RAMP = 7; // 0x7
- field public static final int TURN_ROUNDABOUT_ENTER = 11; // 0xb
- field public static final int TURN_ROUNDABOUT_ENTER_AND_EXIT = 13; // 0xd
- field public static final int TURN_ROUNDABOUT_EXIT = 12; // 0xc
- field public static final int TURN_SHARP_TURN = 5; // 0x5
- field public static final int TURN_SIDE_LEFT = 1; // 0x1
- field public static final int TURN_SIDE_RIGHT = 2; // 0x2
- field public static final int TURN_SIDE_UNSPECIFIED = 3; // 0x3
- field public static final int TURN_SLIGHT_TURN = 3; // 0x3
- field public static final int TURN_STRAIGHT = 14; // 0xe
- field public static final int TURN_TURN = 4; // 0x4
- field public static final int TURN_UNKNOWN = 0; // 0x0
- field public static final int TURN_U_TURN = 6; // 0x6
+ method public abstract void sendEvent(int, android.os.Bundle) throws android.support.car.CarNotConnectedException;
}
public static abstract interface CarNavigationStatusManager.CarNavigationCallback {
diff --git a/car-support-lib/proguard-extra-keeps.flags b/car-support-lib/proguard-extra-keeps.flags
index 5e67c6e..72ea927 100644
--- a/car-support-lib/proguard-extra-keeps.flags
+++ b/car-support-lib/proguard-extra-keeps.flags
@@ -17,3 +17,7 @@
public static ... createCluster(...);
public static ... createCustomImageCluster(...);
}
+
+-keep class android.support.car.CarManagerBase {
+ *;
+}
diff --git a/car-support-lib/proguard-release.flags b/car-support-lib/proguard-release.flags
index 6ec8b3c..91cab7e 100644
--- a/car-support-lib/proguard-release.flags
+++ b/car-support-lib/proguard-release.flags
@@ -1,9 +1,135 @@
+-keep class android.accessibilityservice.AccessibilityServiceInfo {
+ <init>();
+ <init>(android.content.pm.ResolveInfo, android.content.Context);
+
+ public static java.lang.String capabilityToString(int);
+ public int describeContents();
+ public boolean equals(java.lang.Object);
+ public static java.lang.String feedbackTypeToString(int);
+ public static java.lang.String flagToString(int);
+ public boolean getCanRetrieveWindowContent();
+ public int getCapabilities();
+ public java.util.List getCapabilityInfos();
+ public java.util.List getCapabilityInfos(android.content.Context);
+ public android.content.ComponentName getComponentName();
+ public java.lang.String getDescription();
+ public java.lang.String getId();
+ public android.content.pm.ResolveInfo getResolveInfo();
+ public java.lang.String getSettingsActivityName();
+ public int hashCode();
+ public boolean isDirectBootAware();
+ public java.lang.String loadDescription(android.content.pm.PackageManager);
+ public java.lang.CharSequence loadSummary(android.content.pm.PackageManager);
+ public void setCapabilities(int);
+ public void setComponentName(android.content.ComponentName);
+ public java.lang.String toString();
+ public void updateDynamicallyConfigurableProperties(android.accessibilityservice.AccessibilityServiceInfo);
+ public void writeToParcel(android.os.Parcel, int);
+
+
+ public static int CAPABILITY_CAN_CONTROL_MAGNIFICATION;
+ public static int CAPABILITY_CAN_PERFORM_GESTURES;
+ public static int CAPABILITY_CAN_REQUEST_ENHANCED_WEB_ACCESSIBILITY;
+ public static int CAPABILITY_CAN_REQUEST_FILTER_KEY_EVENTS;
+ public static int CAPABILITY_CAN_REQUEST_FINGERPRINT_GESTURES;
+ public static int CAPABILITY_CAN_REQUEST_TOUCH_EXPLORATION;
+ public static int CAPABILITY_CAN_RETRIEVE_WINDOW_CONTENT;
+ public static android.os.Parcelable$Creator CREATOR;
+ public static int DEFAULT;
+ public static int FEEDBACK_ALL_MASK;
+ public static int FEEDBACK_AUDIBLE;
+ public static int FEEDBACK_BRAILLE;
+ public static int FEEDBACK_GENERIC;
+ public static int FEEDBACK_HAPTIC;
+ public static int FEEDBACK_SPOKEN;
+ public static int FEEDBACK_VISUAL;
+ public static int FLAG_ENABLE_ACCESSIBILITY_VOLUME;
+ public static int FLAG_FORCE_DIRECT_BOOT_AWARE;
+ public static int FLAG_INCLUDE_NOT_IMPORTANT_VIEWS;
+ public static int FLAG_REPORT_VIEW_IDS;
+ public static int FLAG_REQUEST_ACCESSIBILITY_BUTTON;
+ public static int FLAG_REQUEST_ENHANCED_WEB_ACCESSIBILITY;
+ public static int FLAG_REQUEST_FILTER_KEY_EVENTS;
+ public static int FLAG_REQUEST_FINGERPRINT_GESTURES;
+ public static int FLAG_REQUEST_TOUCH_EXPLORATION_MODE;
+ public static int FLAG_RETRIEVE_INTERACTIVE_WINDOWS;
+ public boolean crashed;
+ public int eventTypes;
+ public int feedbackType;
+ public int flags;
+ public long notificationTimeout;
+ public java.lang.String[] packageNames;
+}
+
+-keep class android.accessibilityservice.AccessibilityServiceInfo$CapabilityInfo {
+ <init>(int, int, int);
+
+
+
+ public int capability;
+ public int descResId;
+ public int titleResId;
+}
+
+-keep class android.accessibilityservice.IAccessibilityServiceClient {
+
+ public abstract void clearAccessibilityCache();
+ public abstract void init(android.accessibilityservice.IAccessibilityServiceConnection, int, android.os.IBinder);
+ public abstract void onAccessibilityButtonAvailabilityChanged(boolean);
+ public abstract void onAccessibilityButtonClicked();
+ public abstract void onAccessibilityEvent(android.view.accessibility.AccessibilityEvent, boolean);
+ public abstract void onFingerprintCapturingGesturesChanged(boolean);
+ public abstract void onFingerprintGesture(int);
+ public abstract void onGesture(int);
+ public abstract void onInterrupt();
+ public abstract void onKeyEvent(android.view.KeyEvent, int);
+ public abstract void onMagnificationChanged(android.graphics.Region, float, float, float);
+ public abstract void onPerformGestureResult(int, boolean);
+ public abstract void onSoftKeyboardShowModeChanged(int);
+
+
+}
+
+-keep class android.accessibilityservice.IAccessibilityServiceConnection {
+
+ public abstract void disableSelf();
+ public abstract java.lang.String[] findAccessibilityNodeInfoByAccessibilityId(int, long, int, android.view.accessibility.IAccessibilityInteractionConnectionCallback, int, long, android.os.Bundle);
+ public abstract java.lang.String[] findAccessibilityNodeInfosByText(int, long, java.lang.String, int, android.view.accessibility.IAccessibilityInteractionConnectionCallback, long);
+ public abstract java.lang.String[] findAccessibilityNodeInfosByViewId(int, long, java.lang.String, int, android.view.accessibility.IAccessibilityInteractionConnectionCallback, long);
+ public abstract java.lang.String[] findFocus(int, long, int, int, android.view.accessibility.IAccessibilityInteractionConnectionCallback, long);
+ public abstract java.lang.String[] focusSearch(int, long, int, int, android.view.accessibility.IAccessibilityInteractionConnectionCallback, long);
+ public abstract float getMagnificationCenterX();
+ public abstract float getMagnificationCenterY();
+ public abstract android.graphics.Region getMagnificationRegion();
+ public abstract float getMagnificationScale();
+ public abstract android.accessibilityservice.AccessibilityServiceInfo getServiceInfo();
+ public abstract android.view.accessibility.AccessibilityWindowInfo getWindow(int);
+ public abstract java.util.List getWindows();
+ public abstract boolean isAccessibilityButtonAvailable();
+ public abstract boolean isFingerprintGestureDetectionAvailable();
+ public abstract boolean performAccessibilityAction(int, long, int, android.os.Bundle, int, android.view.accessibility.IAccessibilityInteractionConnectionCallback, long);
+ public abstract boolean performGlobalAction(int);
+ public abstract boolean resetMagnification(boolean);
+ public abstract void sendGesture(int, android.content.pm.ParceledListSlice);
+ public abstract void setMagnificationCallbackEnabled(boolean);
+ public abstract boolean setMagnificationScaleAndCenter(float, float, float, boolean);
+ public abstract void setOnKeyEventResult(boolean, int);
+ public abstract void setServiceInfo(android.accessibilityservice.AccessibilityServiceInfo);
+ public abstract void setSoftKeyboardCallbackEnabled(boolean);
+ public abstract boolean setSoftKeyboardShowMode(int);
+
+
+}
+
-keep class android.accounts.Account {
<init>(java.lang.String, java.lang.String);
+ <init>(android.accounts.Account, java.lang.String);
+ <init>(java.lang.String, java.lang.String, java.lang.String);
<init>(android.os.Parcel);
public int describeContents();
public boolean equals(java.lang.Object);
+ public java.lang.String getAccessId();
public int hashCode();
public java.lang.String toString();
public void writeToParcel(android.os.Parcel, int);
@@ -14,6 +140,3749 @@
public java.lang.String type;
}
+-keep class android.animation.AnimationHandler {
+ <init>();
+
+ public void addAnimationFrameCallback(android.animation.AnimationHandler$AnimationFrameCallback, long);
+ public void addOneShotCommitCallback(android.animation.AnimationHandler$AnimationFrameCallback);
+ public static int getAnimationCount();
+ public static long getFrameDelay();
+ public static android.animation.AnimationHandler getInstance();
+ public void removeCallback(android.animation.AnimationHandler$AnimationFrameCallback);
+ public static void setFrameDelay(long);
+ public void setProvider(android.animation.AnimationHandler$AnimationFrameCallbackProvider);
+
+
+ public static java.lang.ThreadLocal sAnimatorHandler;
+}
+
+-keep class android.animation.AnimationHandler$AnimationFrameCallback {
+
+ public abstract void commitAnimationFrame(long);
+ public abstract boolean doAnimationFrame(long);
+
+
+}
+
+-keep class android.animation.AnimationHandler$AnimationFrameCallbackProvider {
+
+ public abstract long getFrameDelay();
+ public abstract long getFrameTime();
+ public abstract void postCommitCallback(java.lang.Runnable);
+ public abstract void postFrameCallback(android.view.Choreographer$FrameCallback);
+ public abstract void setFrameDelay(long);
+
+
+}
+
+-keep class android.animation.Animator {
+ <init>();
+
+ public void addListener(android.animation.Animator$AnimatorListener);
+ public void addPauseListener(android.animation.Animator$AnimatorPauseListener);
+ public void appendChangingConfigurations(int);
+ public boolean canReverse();
+ public void cancel();
+ public android.animation.Animator clone();
+ public java.lang.Object clone();
+ public android.content.res.ConstantState createConstantState();
+ public void end();
+ public int getChangingConfigurations();
+ public abstract long getDuration();
+ public android.animation.TimeInterpolator getInterpolator();
+ public java.util.ArrayList getListeners();
+ public abstract long getStartDelay();
+ public long getTotalDuration();
+ public boolean isPaused();
+ public abstract boolean isRunning();
+ public boolean isStarted();
+ public void pause();
+ public void removeAllListeners();
+ public void removeListener(android.animation.Animator$AnimatorListener);
+ public void removePauseListener(android.animation.Animator$AnimatorPauseListener);
+ public void resume();
+ public void reverse();
+ public void setAllowRunningAsynchronously(boolean);
+ public void setChangingConfigurations(int);
+ public abstract android.animation.Animator setDuration(long);
+ public abstract void setInterpolator(android.animation.TimeInterpolator);
+ public abstract void setStartDelay(long);
+ public void setTarget(java.lang.Object);
+ public void setupEndValues();
+ public void setupStartValues();
+ public void start();
+
+
+ public static long DURATION_INFINITE;
+}
+
+-keep class android.animation.Animator$AnimatorListener {
+
+ public abstract void onAnimationCancel(android.animation.Animator);
+ public void onAnimationEnd(android.animation.Animator, boolean);
+ public abstract void onAnimationEnd(android.animation.Animator);
+ public abstract void onAnimationRepeat(android.animation.Animator);
+ public void onAnimationStart(android.animation.Animator, boolean);
+ public abstract void onAnimationStart(android.animation.Animator);
+
+
+}
+
+-keep class android.animation.Animator$AnimatorPauseListener {
+
+ public abstract void onAnimationPause(android.animation.Animator);
+ public abstract void onAnimationResume(android.animation.Animator);
+
+
+}
+
+-keep class android.animation.AnimatorSet {
+ <init>();
+
+ public boolean canReverse();
+ public void cancel();
+ public android.animation.AnimatorSet clone();
+ public android.animation.Animator clone();
+ public java.lang.Object clone();
+ public void commitAnimationFrame(long);
+ public boolean doAnimationFrame(long);
+ public void end();
+ public int getChangingConfigurations();
+ public java.util.ArrayList getChildAnimations();
+ public long getCurrentPlayTime();
+ public long getDuration();
+ public android.animation.TimeInterpolator getInterpolator();
+ public long getStartDelay();
+ public long getTotalDuration();
+ public boolean isRunning();
+ public boolean isStarted();
+ public void pause();
+ public android.animation.AnimatorSet$Builder play(android.animation.Animator);
+ public void playSequentially(android.animation.Animator[]);
+ public void playSequentially(java.util.List);
+ public void playTogether(android.animation.Animator[]);
+ public void playTogether(java.util.Collection);
+ public void resume();
+ public void reverse();
+ public void setCurrentPlayTime(long);
+ public android.animation.AnimatorSet setDuration(long);
+ public android.animation.Animator setDuration(long);
+ public void setInterpolator(android.animation.TimeInterpolator);
+ public void setStartDelay(long);
+ public void setTarget(java.lang.Object);
+ public void setupEndValues();
+ public void setupStartValues();
+ public boolean shouldPlayTogether();
+ public void start();
+ public java.lang.String toString();
+
+
+}
+
+-keep class android.animation.AnimatorSet$Builder {
+
+ public android.animation.AnimatorSet$Builder after(android.animation.Animator);
+ public android.animation.AnimatorSet$Builder after(long);
+ public android.animation.AnimatorSet$Builder before(android.animation.Animator);
+ public android.animation.AnimatorSet$Builder with(android.animation.Animator);
+
+
+}
+
+-keep class android.animation.Keyframe {
+ <init>();
+
+ public abstract android.animation.Keyframe clone();
+ public java.lang.Object clone();
+ public float getFraction();
+ public android.animation.TimeInterpolator getInterpolator();
+ public java.lang.Class getType();
+ public abstract java.lang.Object getValue();
+ public boolean hasValue();
+ public static android.animation.Keyframe ofFloat(float, float);
+ public static android.animation.Keyframe ofFloat(float);
+ public static android.animation.Keyframe ofInt(float, int);
+ public static android.animation.Keyframe ofInt(float);
+ public static android.animation.Keyframe ofObject(float, java.lang.Object);
+ public static android.animation.Keyframe ofObject(float);
+ public void setFraction(float);
+ public void setInterpolator(android.animation.TimeInterpolator);
+ public abstract void setValue(java.lang.Object);
+
+
+}
+
+-keep class android.animation.LayoutTransition {
+ <init>();
+
+ public void addChild(android.view.ViewGroup, android.view.View);
+ public void addTransitionListener(android.animation.LayoutTransition$TransitionListener);
+ public void cancel();
+ public void cancel(int);
+ public void disableTransitionType(int);
+ public void enableTransitionType(int);
+ public void endChangingAnimations();
+ public android.animation.Animator getAnimator(int);
+ public long getDuration(int);
+ public android.animation.TimeInterpolator getInterpolator(int);
+ public long getStagger(int);
+ public long getStartDelay(int);
+ public java.util.List getTransitionListeners();
+ public void hideChild(android.view.ViewGroup, android.view.View);
+ public void hideChild(android.view.ViewGroup, android.view.View, int);
+ public boolean isChangingLayout();
+ public boolean isRunning();
+ public boolean isTransitionTypeEnabled(int);
+ public void layoutChange(android.view.ViewGroup);
+ public void removeChild(android.view.ViewGroup, android.view.View);
+ public void removeTransitionListener(android.animation.LayoutTransition$TransitionListener);
+ public void setAnimateParentHierarchy(boolean);
+ public void setAnimator(int, android.animation.Animator);
+ public void setDuration(long);
+ public void setDuration(int, long);
+ public void setInterpolator(int, android.animation.TimeInterpolator);
+ public void setStagger(int, long);
+ public void setStartDelay(int, long);
+ public void showChild(android.view.ViewGroup, android.view.View);
+ public void showChild(android.view.ViewGroup, android.view.View, int);
+ public void startChangingAnimations();
+
+
+ public static int APPEARING;
+ public static int CHANGE_APPEARING;
+ public static int CHANGE_DISAPPEARING;
+ public static int CHANGING;
+ public static int DISAPPEARING;
+}
+
+-keep class android.animation.LayoutTransition$TransitionListener {
+
+ public abstract void endTransition(android.animation.LayoutTransition, android.view.ViewGroup, android.view.View, int);
+ public abstract void startTransition(android.animation.LayoutTransition, android.view.ViewGroup, android.view.View, int);
+
+
+}
+
+-keep class android.animation.PropertyValuesHolder {
+
+ public android.animation.PropertyValuesHolder clone();
+ public java.lang.Object clone();
+ public java.lang.String getPropertyName();
+ public void getPropertyValues(android.animation.PropertyValuesHolder$PropertyValues);
+ public java.lang.Class getValueType();
+ public static android.animation.PropertyValuesHolder ofFloat(java.lang.String, float[]);
+ public static android.animation.PropertyValuesHolder ofFloat(android.util.Property, float[]);
+ public static android.animation.PropertyValuesHolder ofInt(java.lang.String, int[]);
+ public static android.animation.PropertyValuesHolder ofInt(android.util.Property, int[]);
+ public static android.animation.PropertyValuesHolder ofKeyframe(java.lang.String, android.animation.Keyframe[]);
+ public static android.animation.PropertyValuesHolder ofKeyframe(android.util.Property, android.animation.Keyframe[]);
+ public static android.animation.PropertyValuesHolder ofMultiFloat(java.lang.String, float[][]);
+ public static android.animation.PropertyValuesHolder ofMultiFloat(java.lang.String, android.graphics.Path);
+ public static android.animation.PropertyValuesHolder ofMultiFloat(java.lang.String, android.animation.TypeConverter, android.animation.TypeEvaluator, java.lang.Object[]);
+ public static android.animation.PropertyValuesHolder ofMultiFloat(java.lang.String, android.animation.TypeConverter, android.animation.TypeEvaluator, android.animation.Keyframe[]);
+ public static android.animation.PropertyValuesHolder ofMultiInt(java.lang.String, int[][]);
+ public static android.animation.PropertyValuesHolder ofMultiInt(java.lang.String, android.graphics.Path);
+ public static android.animation.PropertyValuesHolder ofMultiInt(java.lang.String, android.animation.TypeConverter, android.animation.TypeEvaluator, java.lang.Object[]);
+ public static android.animation.PropertyValuesHolder ofMultiInt(java.lang.String, android.animation.TypeConverter, android.animation.TypeEvaluator, android.animation.Keyframe[]);
+ public static android.animation.PropertyValuesHolder ofObject(java.lang.String, android.animation.TypeEvaluator, java.lang.Object[]);
+ public static android.animation.PropertyValuesHolder ofObject(java.lang.String, android.animation.TypeConverter, android.graphics.Path);
+ public static android.animation.PropertyValuesHolder ofObject(android.util.Property, android.animation.TypeEvaluator, java.lang.Object[]);
+ public static android.animation.PropertyValuesHolder ofObject(android.util.Property, android.animation.TypeConverter, android.animation.TypeEvaluator, java.lang.Object[]);
+ public static android.animation.PropertyValuesHolder ofObject(android.util.Property, android.animation.TypeConverter, android.graphics.Path);
+ public void setConverter(android.animation.TypeConverter);
+ public void setEvaluator(android.animation.TypeEvaluator);
+ public void setFloatValues(float[]);
+ public void setIntValues(int[]);
+ public void setKeyframes(android.animation.Keyframe[]);
+ public void setObjectValues(java.lang.Object[]);
+ public void setProperty(android.util.Property);
+ public void setPropertyName(java.lang.String);
+ public java.lang.String toString();
+
+
+ protected android.util.Property mProperty;
+}
+
+-keep class android.animation.PropertyValuesHolder$PropertyValues {
+ <init>();
+
+ public java.lang.String toString();
+
+
+ public android.animation.PropertyValuesHolder$PropertyValues$DataSource dataSource;
+ public java.lang.Object endValue;
+ public java.lang.String propertyName;
+ public java.lang.Object startValue;
+ public java.lang.Class type;
+}
+
+-keep class android.animation.PropertyValuesHolder$PropertyValues$DataSource {
+
+ public abstract java.lang.Object getValueAtFraction(float);
+
+
+}
+
+-keep class android.animation.StateListAnimator {
+ <init>();
+
+ public void addState(int[], android.animation.Animator);
+ public void appendChangingConfigurations(int);
+ public android.animation.StateListAnimator clone();
+ public java.lang.Object clone();
+ public android.content.res.ConstantState createConstantState();
+ public int getChangingConfigurations();
+ public android.animation.Animator getRunningAnimator();
+ public android.view.View getTarget();
+ public java.util.ArrayList getTuples();
+ public void jumpToCurrentState();
+ public void setChangingConfigurations(int);
+ public void setState(int[]);
+ public void setTarget(android.view.View);
+
+
+}
+
+-keep class android.animation.StateListAnimator$Tuple {
+
+ public android.animation.Animator getAnimator();
+ public int[] getSpecs();
+
+
+}
+
+-keep class android.animation.TimeInterpolator {
+
+ public abstract float getInterpolation(float);
+
+
+}
+
+-keep class android.animation.TypeConverter {
+ <init>(java.lang.Class, java.lang.Class);
+
+ public abstract java.lang.Object convert(java.lang.Object);
+
+
+}
+
+-keep class android.animation.TypeEvaluator {
+
+ public abstract java.lang.Object evaluate(float, java.lang.Object, java.lang.Object);
+
+
+}
+
+-keep class android.animation.ValueAnimator {
+ <init>();
+
+ public void addUpdateListener(android.animation.ValueAnimator$AnimatorUpdateListener);
+ public static boolean areAnimatorsEnabled();
+ public boolean canReverse();
+ public void cancel();
+ public android.animation.ValueAnimator clone();
+ public android.animation.Animator clone();
+ public java.lang.Object clone();
+ public void commitAnimationFrame(long);
+ public boolean doAnimationFrame(long);
+ public void end();
+ public float getAnimatedFraction();
+ public java.lang.Object getAnimatedValue();
+ public java.lang.Object getAnimatedValue(java.lang.String);
+ public android.animation.AnimationHandler getAnimationHandler();
+ public static int getCurrentAnimationsCount();
+ public long getCurrentPlayTime();
+ public long getDuration();
+ public static float getDurationScale();
+ public static long getFrameDelay();
+ public android.animation.TimeInterpolator getInterpolator();
+ public int getRepeatCount();
+ public int getRepeatMode();
+ public long getStartDelay();
+ public long getTotalDuration();
+ public android.animation.PropertyValuesHolder[] getValues();
+ public boolean isRunning();
+ public boolean isStarted();
+ public static android.animation.ValueAnimator ofArgb(int[]);
+ public static android.animation.ValueAnimator ofFloat(float[]);
+ public static android.animation.ValueAnimator ofInt(int[]);
+ public static android.animation.ValueAnimator ofObject(android.animation.TypeEvaluator, java.lang.Object[]);
+ public static android.animation.ValueAnimator ofPropertyValuesHolder(android.animation.PropertyValuesHolder[]);
+ public void overrideDurationScale(float);
+ public void pause();
+ public void removeAllUpdateListeners();
+ public void removeUpdateListener(android.animation.ValueAnimator$AnimatorUpdateListener);
+ public void resume();
+ public void reverse();
+ public void setAllowRunningAsynchronously(boolean);
+ public void setCurrentFraction(float);
+ public void setCurrentPlayTime(long);
+ public android.animation.ValueAnimator setDuration(long);
+ public android.animation.Animator setDuration(long);
+ public static void setDurationScale(float);
+ public void setEvaluator(android.animation.TypeEvaluator);
+ public void setFloatValues(float[]);
+ public static void setFrameDelay(long);
+ public void setIntValues(int[]);
+ public void setInterpolator(android.animation.TimeInterpolator);
+ public void setObjectValues(java.lang.Object[]);
+ public void setRepeatCount(int);
+ public void setRepeatMode(int);
+ public void setStartDelay(long);
+ public void setValues(android.animation.PropertyValuesHolder[]);
+ public void start();
+ public java.lang.String toString();
+
+
+ public static int INFINITE;
+ public static int RESTART;
+ public static int REVERSE;
+}
+
+-keep class android.animation.ValueAnimator$AnimatorUpdateListener {
+
+ public abstract void onAnimationUpdate(android.animation.ValueAnimator);
+
+
+}
+
+-keep class android.app.ActionBar {
+ <init>();
+
+ public abstract void addOnMenuVisibilityListener(android.app.ActionBar$OnMenuVisibilityListener);
+ public abstract void addTab(android.app.ActionBar$Tab);
+ public abstract void addTab(android.app.ActionBar$Tab, boolean);
+ public abstract void addTab(android.app.ActionBar$Tab, int);
+ public abstract void addTab(android.app.ActionBar$Tab, int, boolean);
+ public boolean closeOptionsMenu();
+ public boolean collapseActionView();
+ public void dispatchMenuVisibilityChanged(boolean);
+ public abstract android.view.View getCustomView();
+ public abstract int getDisplayOptions();
+ public float getElevation();
+ public abstract int getHeight();
+ public int getHideOffset();
+ public abstract int getNavigationItemCount();
+ public abstract int getNavigationMode();
+ public abstract int getSelectedNavigationIndex();
+ public abstract android.app.ActionBar$Tab getSelectedTab();
+ public abstract java.lang.CharSequence getSubtitle();
+ public abstract android.app.ActionBar$Tab getTabAt(int);
+ public abstract int getTabCount();
+ public android.content.Context getThemedContext();
+ public abstract java.lang.CharSequence getTitle();
+ public abstract void hide();
+ public boolean invalidateOptionsMenu();
+ public boolean isHideOnContentScrollEnabled();
+ public abstract boolean isShowing();
+ public boolean isTitleTruncated();
+ public abstract android.app.ActionBar$Tab newTab();
+ public void onConfigurationChanged(android.content.res.Configuration);
+ public void onDestroy();
+ public boolean onKeyShortcut(int, android.view.KeyEvent);
+ public boolean onMenuKeyEvent(android.view.KeyEvent);
+ public boolean openOptionsMenu();
+ public abstract void removeAllTabs();
+ public abstract void removeOnMenuVisibilityListener(android.app.ActionBar$OnMenuVisibilityListener);
+ public abstract void removeTab(android.app.ActionBar$Tab);
+ public abstract void removeTabAt(int);
+ public abstract void selectTab(android.app.ActionBar$Tab);
+ public abstract void setBackgroundDrawable(android.graphics.drawable.Drawable);
+ public abstract void setCustomView(android.view.View);
+ public abstract void setCustomView(android.view.View, android.app.ActionBar$LayoutParams);
+ public abstract void setCustomView(int);
+ public void setDefaultDisplayHomeAsUpEnabled(boolean);
+ public abstract void setDisplayHomeAsUpEnabled(boolean);
+ public abstract void setDisplayOptions(int);
+ public abstract void setDisplayOptions(int, int);
+ public abstract void setDisplayShowCustomEnabled(boolean);
+ public abstract void setDisplayShowHomeEnabled(boolean);
+ public abstract void setDisplayShowTitleEnabled(boolean);
+ public abstract void setDisplayUseLogoEnabled(boolean);
+ public void setElevation(float);
+ public void setHideOffset(int);
+ public void setHideOnContentScrollEnabled(boolean);
+ public void setHomeActionContentDescription(java.lang.CharSequence);
+ public void setHomeActionContentDescription(int);
+ public void setHomeAsUpIndicator(android.graphics.drawable.Drawable);
+ public void setHomeAsUpIndicator(int);
+ public void setHomeButtonEnabled(boolean);
+ public abstract void setIcon(int);
+ public abstract void setIcon(android.graphics.drawable.Drawable);
+ public abstract void setListNavigationCallbacks(android.widget.SpinnerAdapter, android.app.ActionBar$OnNavigationListener);
+ public abstract void setLogo(int);
+ public abstract void setLogo(android.graphics.drawable.Drawable);
+ public abstract void setNavigationMode(int);
+ public abstract void setSelectedNavigationItem(int);
+ public void setShowHideAnimationEnabled(boolean);
+ public void setSplitBackgroundDrawable(android.graphics.drawable.Drawable);
+ public void setStackedBackgroundDrawable(android.graphics.drawable.Drawable);
+ public abstract void setSubtitle(java.lang.CharSequence);
+ public abstract void setSubtitle(int);
+ public abstract void setTitle(java.lang.CharSequence);
+ public abstract void setTitle(int);
+ public void setWindowTitle(java.lang.CharSequence);
+ public abstract void show();
+ public android.view.ActionMode startActionMode(android.view.ActionMode$Callback);
+
+
+ public static int DISPLAY_HOME_AS_UP;
+ public static int DISPLAY_SHOW_CUSTOM;
+ public static int DISPLAY_SHOW_HOME;
+ public static int DISPLAY_SHOW_TITLE;
+ public static int DISPLAY_TITLE_MULTIPLE_LINES;
+ public static int DISPLAY_USE_LOGO;
+ public static int NAVIGATION_MODE_LIST;
+ public static int NAVIGATION_MODE_STANDARD;
+ public static int NAVIGATION_MODE_TABS;
+}
+
+-keep class android.app.ActionBar$LayoutParams {
+ <init>(android.content.Context, android.util.AttributeSet);
+ <init>(int, int);
+ <init>(int, int, int);
+ <init>(int);
+ <init>(android.app.ActionBar$LayoutParams);
+ <init>(android.view.ViewGroup$LayoutParams);
+
+ protected void encodeProperties(android.view.ViewHierarchyEncoder);
+
+
+ public int gravity;
+}
+
+-keep class android.app.ActionBar$OnMenuVisibilityListener {
+
+ public abstract void onMenuVisibilityChanged(boolean);
+
+
+}
+
+-keep class android.app.ActionBar$OnNavigationListener {
+
+ public abstract boolean onNavigationItemSelected(int, long);
+
+
+}
+
+-keep class android.app.ActionBar$Tab {
+ <init>();
+
+ public abstract java.lang.CharSequence getContentDescription();
+ public abstract android.view.View getCustomView();
+ public abstract android.graphics.drawable.Drawable getIcon();
+ public abstract int getPosition();
+ public abstract java.lang.Object getTag();
+ public abstract java.lang.CharSequence getText();
+ public abstract void select();
+ public abstract android.app.ActionBar$Tab setContentDescription(int);
+ public abstract android.app.ActionBar$Tab setContentDescription(java.lang.CharSequence);
+ public abstract android.app.ActionBar$Tab setCustomView(android.view.View);
+ public abstract android.app.ActionBar$Tab setCustomView(int);
+ public abstract android.app.ActionBar$Tab setIcon(android.graphics.drawable.Drawable);
+ public abstract android.app.ActionBar$Tab setIcon(int);
+ public abstract android.app.ActionBar$Tab setTabListener(android.app.ActionBar$TabListener);
+ public abstract android.app.ActionBar$Tab setTag(java.lang.Object);
+ public abstract android.app.ActionBar$Tab setText(java.lang.CharSequence);
+ public abstract android.app.ActionBar$Tab setText(int);
+
+
+ public static int INVALID_POSITION;
+}
+
+-keep class android.app.ActionBar$TabListener {
+
+ public abstract void onTabReselected(android.app.ActionBar$Tab, android.app.FragmentTransaction);
+ public abstract void onTabSelected(android.app.ActionBar$Tab, android.app.FragmentTransaction);
+ public abstract void onTabUnselected(android.app.ActionBar$Tab, android.app.FragmentTransaction);
+
+
+}
+
+-keep class android.app.Activity {
+ <init>();
+
+ public void addContentView(android.view.View, android.view.ViewGroup$LayoutParams);
+ protected void attachBaseContext(android.content.Context);
+ public void autofillClientAuthenticate(int, android.content.IntentSender, android.content.Intent);
+ public void autofillClientDispatchUnhandledKey(android.view.View, android.view.KeyEvent);
+ public android.view.View autofillClientFindViewByAccessibilityIdTraversal(int, int);
+ public android.view.View autofillClientFindViewByAutofillIdTraversal(android.view.autofill.AutofillId);
+ public android.view.View[] autofillClientFindViewsByAutofillIdTraversal(android.view.autofill.AutofillId[]);
+ public android.os.IBinder autofillClientGetActivityToken();
+ public android.content.ComponentName autofillClientGetComponentName();
+ public android.view.autofill.AutofillId autofillClientGetNextAutofillId();
+ public boolean[] autofillClientGetViewVisibility(android.view.autofill.AutofillId[]);
+ public boolean autofillClientIsCompatibilityModeEnabled();
+ public boolean autofillClientIsFillUiShowing();
+ public boolean autofillClientIsVisibleForAutofill();
+ public boolean autofillClientRequestHideFillUi();
+ public boolean autofillClientRequestShowFillUi(android.view.View, int, int, android.graphics.Rect, android.view.autofill.IAutofillWindowPresenter);
+ public void autofillClientResetableStateAvailable();
+ public void autofillClientRunOnUiThread(java.lang.Runnable);
+ public boolean canStartActivityForResult();
+ public void closeContextMenu();
+ public void closeOptionsMenu();
+ public void convertFromTranslucent();
+ public boolean convertToTranslucent(android.app.Activity$TranslucentConversionListener, android.app.ActivityOptions);
+ public android.app.PendingIntent createPendingResult(int, android.content.Intent, int);
+ public void dismissDialog(int);
+ public void dismissKeyboardShortcutsHelper();
+ public void dispatchEnterAnimationComplete();
+ public boolean dispatchGenericMotionEvent(android.view.MotionEvent);
+ public boolean dispatchKeyEvent(android.view.KeyEvent);
+ public boolean dispatchKeyShortcutEvent(android.view.KeyEvent);
+ public boolean dispatchPopulateAccessibilityEvent(android.view.accessibility.AccessibilityEvent);
+ public boolean dispatchTouchEvent(android.view.MotionEvent);
+ public boolean dispatchTrackballEvent(android.view.MotionEvent);
+ public void dump(java.lang.String, java.io.FileDescriptor, java.io.PrintWriter, java.lang.String[]);
+ public void enterPictureInPictureMode();
+ public boolean enterPictureInPictureMode(android.app.PictureInPictureArgs);
+ public boolean enterPictureInPictureMode(android.app.PictureInPictureParams);
+ public void enterPictureInPictureModeIfPossible();
+ public void exitFreeformMode();
+ public android.view.View findViewById(int);
+ public void finish();
+ public void finishActivity(int);
+ public void finishActivityFromChild(android.app.Activity, int);
+ public void finishAffinity();
+ public void finishAfterTransition();
+ public void finishAndRemoveTask();
+ public void finishFromChild(android.app.Activity);
+ public android.app.ActionBar getActionBar();
+ public android.app.ActivityThread getActivityThread();
+ public android.os.IBinder getActivityToken();
+ public android.app.Application getApplication();
+ public android.view.autofill.AutofillManager$AutofillClient getAutofillClient();
+ public android.content.ComponentName getCallingActivity();
+ public java.lang.String getCallingPackage();
+ public int getChangingConfigurations();
+ public android.content.ComponentName getComponentName();
+ public android.transition.Scene getContentScene();
+ public android.transition.TransitionManager getContentTransitionManager();
+ public android.view.View getCurrentFocus();
+ public android.app.FragmentManager getFragmentManager();
+ public android.content.Intent getIntent();
+ public java.lang.Object getLastNonConfigurationInstance();
+ public android.view.LayoutInflater getLayoutInflater();
+ public android.app.LoaderManager getLoaderManager();
+ public java.lang.String getLocalClassName();
+ public int getMaxNumPictureInPictureActions();
+ public android.media.session.MediaController getMediaController();
+ public android.view.MenuInflater getMenuInflater();
+ public int getNextAutofillId();
+ public android.app.Activity getParent();
+ public android.content.Intent getParentActivityIntent();
+ public android.content.SharedPreferences getPreferences(int);
+ public android.net.Uri getReferrer();
+ public int getRequestedOrientation();
+ public android.view.SearchEvent getSearchEvent();
+ public java.lang.Object getSystemService(java.lang.String);
+ public int getTaskId();
+ public java.lang.CharSequence getTitle();
+ public int getTitleColor();
+ public android.app.VoiceInteractor getVoiceInteractor();
+ public int getVolumeControlStream();
+ public android.view.Window getWindow();
+ public android.view.WindowManager getWindowManager();
+ public boolean hasWindowFocus();
+ public void invalidateOptionsMenu();
+ public boolean isActivityTransitionRunning();
+ public boolean isBackgroundVisibleBehind();
+ public boolean isChangingConfigurations();
+ public boolean isChild();
+ public boolean isDestroyed();
+ public boolean isDisablingEnterExitEventForAutofill();
+ public boolean isFinishing();
+ public boolean isImmersive();
+ public boolean isInMultiWindowMode();
+ public boolean isInPictureInPictureMode();
+ public boolean isLocalVoiceInteractionSupported();
+ public boolean isOverlayWithDecorCaptionEnabled();
+ public boolean isResumed();
+ public boolean isTaskRoot();
+ public boolean isVoiceInteraction();
+ public boolean isVoiceInteractionRoot();
+ public android.database.Cursor managedQuery(android.net.Uri, java.lang.String[], java.lang.String, java.lang.String);
+ public android.database.Cursor managedQuery(android.net.Uri, java.lang.String[], java.lang.String, java.lang.String[], java.lang.String);
+ public boolean moveTaskToBack(boolean);
+ public boolean navigateUpTo(android.content.Intent);
+ public boolean navigateUpToFromChild(android.app.Activity, android.content.Intent);
+ public void onActionModeFinished(android.view.ActionMode);
+ public void onActionModeStarted(android.view.ActionMode);
+ public void onActivityReenter(int, android.content.Intent);
+ protected void onActivityResult(int, int, android.content.Intent);
+ protected void onApplyThemeResource(android.content.res.Resources$Theme, int, boolean);
+ public void onAttachFragment(android.app.Fragment);
+ public void onAttachedToWindow();
+ public void onBackPressed();
+ public void onBackgroundVisibleBehindChanged(boolean);
+ protected void onChildTitleChanged(android.app.Activity, java.lang.CharSequence);
+ public void onConfigurationChanged(android.content.res.Configuration);
+ public void onContentChanged();
+ public boolean onContextItemSelected(android.view.MenuItem);
+ public void onContextMenuClosed(android.view.Menu);
+ protected void onCreate(android.os.Bundle);
+ public void onCreate(android.os.Bundle, android.os.PersistableBundle);
+ public void onCreateContextMenu(android.view.ContextMenu, android.view.View, android.view.ContextMenu$ContextMenuInfo);
+ public java.lang.CharSequence onCreateDescription();
+ protected android.app.Dialog onCreateDialog(int);
+ protected android.app.Dialog onCreateDialog(int, android.os.Bundle);
+ public void onCreateNavigateUpTaskStack(android.app.TaskStackBuilder);
+ public boolean onCreateOptionsMenu(android.view.Menu);
+ public boolean onCreatePanelMenu(int, android.view.Menu);
+ public android.view.View onCreatePanelView(int);
+ public boolean onCreateThumbnail(android.graphics.Bitmap, android.graphics.Canvas);
+ public android.view.View onCreateView(java.lang.String, android.content.Context, android.util.AttributeSet);
+ public android.view.View onCreateView(android.view.View, java.lang.String, android.content.Context, android.util.AttributeSet);
+ protected void onDestroy();
+ public void onDetachedFromWindow();
+ public void onEnterAnimationComplete();
+ public boolean onGenericMotionEvent(android.view.MotionEvent);
+ public boolean onKeyDown(int, android.view.KeyEvent);
+ public boolean onKeyLongPress(int, android.view.KeyEvent);
+ public boolean onKeyMultiple(int, int, android.view.KeyEvent);
+ public boolean onKeyShortcut(int, android.view.KeyEvent);
+ public boolean onKeyUp(int, android.view.KeyEvent);
+ public void onLocalVoiceInteractionStarted();
+ public void onLocalVoiceInteractionStopped();
+ public void onLowMemory();
+ public boolean onMenuItemSelected(int, android.view.MenuItem);
+ public boolean onMenuOpened(int, android.view.Menu);
+ public void onMovedToDisplay(int, android.content.res.Configuration);
+ public void onMultiWindowModeChanged(boolean, android.content.res.Configuration);
+ public void onMultiWindowModeChanged(boolean);
+ public boolean onNavigateUp();
+ public boolean onNavigateUpFromChild(android.app.Activity);
+ public void onNewActivityOptions(android.app.ActivityOptions);
+ protected void onNewIntent(android.content.Intent);
+ public boolean onOptionsItemSelected(android.view.MenuItem);
+ public void onOptionsMenuClosed(android.view.Menu);
+ public void onPanelClosed(int, android.view.Menu);
+ protected void onPause();
+ public void onPictureInPictureModeChanged(boolean, android.content.res.Configuration);
+ public void onPictureInPictureModeChanged(boolean);
+ protected void onPostCreate(android.os.Bundle);
+ public void onPostCreate(android.os.Bundle, android.os.PersistableBundle);
+ protected void onPostResume();
+ protected void onPrepareDialog(int, android.app.Dialog);
+ protected void onPrepareDialog(int, android.app.Dialog, android.os.Bundle);
+ public void onPrepareNavigateUpTaskStack(android.app.TaskStackBuilder);
+ public boolean onPrepareOptionsMenu(android.view.Menu);
+ public boolean onPreparePanel(int, android.view.View, android.view.Menu);
+ public void onProvideAssistContent(android.app.assist.AssistContent);
+ public void onProvideAssistData(android.os.Bundle);
+ public void onProvideKeyboardShortcuts(java.util.List, android.view.Menu, int);
+ public android.net.Uri onProvideReferrer();
+ public void onRequestPermissionsResult(int, java.lang.String[], int[]);
+ protected void onRestart();
+ protected void onRestoreInstanceState(android.os.Bundle);
+ public void onRestoreInstanceState(android.os.Bundle, android.os.PersistableBundle);
+ protected void onResume();
+ public java.lang.Object onRetainNonConfigurationInstance();
+ protected void onSaveInstanceState(android.os.Bundle);
+ public void onSaveInstanceState(android.os.Bundle, android.os.PersistableBundle);
+ public boolean onSearchRequested(android.view.SearchEvent);
+ public boolean onSearchRequested();
+ protected void onStart();
+ public void onStateNotSaved();
+ protected void onStop();
+ protected void onTitleChanged(java.lang.CharSequence, int);
+ public boolean onTouchEvent(android.view.MotionEvent);
+ public boolean onTrackballEvent(android.view.MotionEvent);
+ public void onTrimMemory(int);
+ public void onUserInteraction();
+ protected void onUserLeaveHint();
+ public void onVisibleBehindCanceled();
+ public void onWindowAttributesChanged(android.view.WindowManager$LayoutParams);
+ public void onWindowDismissed(boolean, boolean);
+ public void onWindowFocusChanged(boolean);
+ public android.view.ActionMode onWindowStartingActionMode(android.view.ActionMode$Callback);
+ public android.view.ActionMode onWindowStartingActionMode(android.view.ActionMode$Callback, int);
+ public void openContextMenu(android.view.View);
+ public void openOptionsMenu();
+ public void overridePendingTransition(int, int);
+ public void postponeEnterTransition();
+ public void recreate();
+ public void registerForContextMenu(android.view.View);
+ public void registerRemoteAnimations(android.view.RemoteAnimationDefinition);
+ public boolean releaseInstance();
+ public void removeDialog(int);
+ public void reportFullyDrawn();
+ public android.view.DragAndDropPermissions requestDragAndDropPermissions(android.view.DragEvent);
+ public void requestPermissions(java.lang.String[], int);
+ public void requestShowKeyboardShortcuts();
+ public boolean requestVisibleBehind(boolean);
+ public boolean requestWindowFeature(int);
+ public android.view.View requireViewById(int);
+ public void runOnUiThread(java.lang.Runnable);
+ public void setActionBar(android.widget.Toolbar);
+ public void setContentTransitionManager(android.transition.TransitionManager);
+ public void setContentView(int);
+ public void setContentView(android.view.View);
+ public void setContentView(android.view.View, android.view.ViewGroup$LayoutParams);
+ public void setDefaultKeyMode(int);
+ public void setDisablePreviewScreenshots(boolean);
+ public void setEnterSharedElementCallback(android.app.SharedElementCallback);
+ public void setExitSharedElementCallback(android.app.SharedElementCallback);
+ public void setFeatureDrawable(int, android.graphics.drawable.Drawable);
+ public void setFeatureDrawableAlpha(int, int);
+ public void setFeatureDrawableResource(int, int);
+ public void setFeatureDrawableUri(int, android.net.Uri);
+ public void setFinishOnTouchOutside(boolean);
+ public void setImmersive(boolean);
+ public void setIntent(android.content.Intent);
+ public void setMediaController(android.media.session.MediaController);
+ public void setOverlayWithDecorCaptionEnabled(boolean);
+ public void setPersistent(boolean);
+ public void setPictureInPictureArgs(android.app.PictureInPictureArgs);
+ public void setPictureInPictureParams(android.app.PictureInPictureParams);
+ public void setProgress(int);
+ public void setProgressBarIndeterminate(boolean);
+ public void setProgressBarIndeterminateVisibility(boolean);
+ public void setProgressBarVisibility(boolean);
+ public void setRequestedOrientation(int);
+ public void setResult(int);
+ public void setResult(int, android.content.Intent);
+ public void setSecondaryProgress(int);
+ public void setShowWhenLocked(boolean);
+ public void setTaskDescription(android.app.ActivityManager$TaskDescription);
+ public void setTheme(int);
+ public void setTitle(java.lang.CharSequence);
+ public void setTitle(int);
+ public void setTitleColor(int);
+ public void setTurnScreenOn(boolean);
+ public void setVisible(boolean);
+ public void setVolumeControlStream(int);
+ public void setVrModeEnabled(boolean, android.content.ComponentName);
+ public boolean shouldShowRequestPermissionRationale(java.lang.String);
+ public boolean shouldUpRecreateTask(android.content.Intent);
+ public boolean showAssist(android.os.Bundle);
+ public void showDialog(int);
+ public boolean showDialog(int, android.os.Bundle);
+ public void showLockTaskEscapeMessage();
+ public android.view.ActionMode startActionMode(android.view.ActionMode$Callback);
+ public android.view.ActionMode startActionMode(android.view.ActionMode$Callback, int);
+ public void startActivities(android.content.Intent[]);
+ public void startActivities(android.content.Intent[], android.os.Bundle);
+ public void startActivity(android.content.Intent);
+ public void startActivity(android.content.Intent, android.os.Bundle);
+ public void startActivityAsCaller(android.content.Intent, android.os.Bundle, boolean, int);
+ public void startActivityAsUser(android.content.Intent, android.os.UserHandle);
+ public void startActivityAsUser(android.content.Intent, android.os.Bundle, android.os.UserHandle);
+ public void startActivityAsUserFromFragment(android.app.Fragment, android.content.Intent, int, android.os.Bundle, android.os.UserHandle);
+ public void startActivityForResult(android.content.Intent, int);
+ public void startActivityForResult(android.content.Intent, int, android.os.Bundle);
+ public void startActivityForResult(java.lang.String, android.content.Intent, int, android.os.Bundle);
+ public void startActivityForResultAsUser(android.content.Intent, int, android.os.UserHandle);
+ public void startActivityForResultAsUser(android.content.Intent, int, android.os.Bundle, android.os.UserHandle);
+ public void startActivityForResultAsUser(android.content.Intent, java.lang.String, int, android.os.Bundle, android.os.UserHandle);
+ public void startActivityFromChild(android.app.Activity, android.content.Intent, int);
+ public void startActivityFromChild(android.app.Activity, android.content.Intent, int, android.os.Bundle);
+ public void startActivityFromFragment(android.app.Fragment, android.content.Intent, int);
+ public void startActivityFromFragment(android.app.Fragment, android.content.Intent, int, android.os.Bundle);
+ public boolean startActivityIfNeeded(android.content.Intent, int);
+ public boolean startActivityIfNeeded(android.content.Intent, int, android.os.Bundle);
+ public void startIntentSender(android.content.IntentSender, android.content.Intent, int, int, int);
+ public void startIntentSender(android.content.IntentSender, android.content.Intent, int, int, int, android.os.Bundle);
+ public void startIntentSenderForResult(android.content.IntentSender, int, android.content.Intent, int, int, int);
+ public void startIntentSenderForResult(android.content.IntentSender, int, android.content.Intent, int, int, int, android.os.Bundle);
+ public void startIntentSenderFromChild(android.app.Activity, android.content.IntentSender, int, android.content.Intent, int, int, int);
+ public void startIntentSenderFromChild(android.app.Activity, android.content.IntentSender, int, android.content.Intent, int, int, int, android.os.Bundle);
+ public void startIntentSenderFromChildFragment(android.app.Fragment, android.content.IntentSender, int, android.content.Intent, int, int, int, android.os.Bundle);
+ public void startLocalVoiceInteraction(android.os.Bundle);
+ public void startLockTask();
+ public void startManagingCursor(android.database.Cursor);
+ public boolean startNextMatchingActivity(android.content.Intent);
+ public boolean startNextMatchingActivity(android.content.Intent, android.os.Bundle);
+ public void startPostponedEnterTransition();
+ public void startSearch(java.lang.String, boolean, android.os.Bundle, boolean);
+ public void stopLocalVoiceInteraction();
+ public void stopLockTask();
+ public void stopManagingCursor(android.database.Cursor);
+ public void takeKeyEvents(boolean);
+ public void triggerSearch(java.lang.String, android.os.Bundle);
+ public void unregisterForContextMenu(android.view.View);
+
+
+ public static int DEFAULT_KEYS_DIALER;
+ public static int DEFAULT_KEYS_DISABLE;
+ public static int DEFAULT_KEYS_SEARCH_GLOBAL;
+ public static int DEFAULT_KEYS_SEARCH_LOCAL;
+ public static int DEFAULT_KEYS_SHORTCUT;
+ public static int DONT_FINISH_TASK_WITH_ACTIVITY;
+ public static int FINISH_TASK_WITH_ACTIVITY;
+ public static int FINISH_TASK_WITH_ROOT_ACTIVITY;
+ protected static int[] FOCUSED_STATE_SET;
+ public static int RESULT_CANCELED;
+ public static int RESULT_FIRST_USER;
+ public static int RESULT_OK;
+}
+
+-keep class android.app.Activity$NonConfigurationInstances {
+
+
+
+}
+
+-keep class android.app.Activity$TranslucentConversionListener {
+
+ public abstract void onTranslucentConversionComplete(boolean);
+
+
+}
+
+-keep class android.app.ActivityManager {
+
+ public int addAppTask(android.app.Activity, android.content.Intent, android.app.ActivityManager$TaskDescription, android.graphics.Bitmap);
+ public void addOnUidImportanceListener(android.app.ActivityManager$OnUidImportanceListener, int);
+ public void alwaysShowUnsupportedCompileSdkWarning(android.content.ComponentName);
+ public static void broadcastStickyIntent(android.content.Intent, int);
+ public static void broadcastStickyIntent(android.content.Intent, int, int);
+ public static int checkComponentPermission(java.lang.String, int, int, boolean);
+ public static int checkUidPermission(java.lang.String, int);
+ public boolean clearApplicationUserData(java.lang.String, android.content.pm.IPackageDataObserver);
+ public boolean clearApplicationUserData();
+ public void clearGrantedUriPermissions(java.lang.String);
+ public void clearWatchHeapLimit();
+ public void dumpPackageState(java.io.FileDescriptor, java.lang.String);
+ public static void dumpPackageStateStatic(java.io.FileDescriptor, java.lang.String);
+ public void forceStopPackage(java.lang.String);
+ public void forceStopPackageAsUser(java.lang.String, int);
+ public android.util.Size getAppTaskThumbnailSize();
+ public java.util.List getAppTasks();
+ public static int getCurrentUser();
+ public static int getDefaultAppRecentsLimitStatic();
+ public android.content.pm.ConfigurationInfo getDeviceConfigurationInfo();
+ public int getFrontActivityScreenCompatMode();
+ public android.content.pm.ParceledListSlice getGrantedUriPermissions(java.lang.String);
+ public int getLargeMemoryClass();
+ public int getLauncherLargeIconDensity();
+ public int getLauncherLargeIconSize();
+ public int getLockTaskModeState();
+ public static int getMaxAppRecentsLimitStatic();
+ public static int getMaxNumPictureInPictureActions();
+ public static int getMaxRecentTasksStatic();
+ public int getMemoryClass();
+ public void getMemoryInfo(android.app.ActivityManager$MemoryInfo);
+ public static void getMyMemoryState(android.app.ActivityManager$RunningAppProcessInfo);
+ public boolean getPackageAskScreenCompat(java.lang.String);
+ public int getPackageImportance(java.lang.String);
+ public int getPackageScreenCompatMode(java.lang.String);
+ public android.os.Debug$MemoryInfo[] getProcessMemoryInfo(int[]);
+ public java.util.List getProcessesInErrorState();
+ public java.util.List getRecentTasks(int, int);
+ public java.util.List getRunningAppProcesses();
+ public java.util.List getRunningExternalApplications();
+ public android.app.PendingIntent getRunningServiceControlPanel(android.content.ComponentName);
+ public java.util.List getRunningServices(int);
+ public java.util.List getRunningTasks(int);
+ public static android.app.IActivityManager getService();
+ public long getTotalRam();
+ public int getUidImportance(int);
+ public static int handleIncomingUser(int, int, int, boolean, boolean, java.lang.String, java.lang.String);
+ public boolean isBackgroundRestricted();
+ public static boolean isHighEndGfx();
+ public boolean isInLockTaskMode();
+ public boolean isLowRamDevice();
+ public static boolean isLowRamDeviceStatic();
+ public static boolean isProcStateBackground(int);
+ public static boolean isRunningInTestHarness();
+ public static boolean isSmallBatteryDevice();
+ public static boolean isStartResultFatalError(int);
+ public static boolean isStartResultSuccessful(int);
+ public static boolean isSystemReady();
+ public static boolean isUserAMonkey();
+ public boolean isUserRunning(int);
+ public boolean isVrModePackageEnabled(android.content.ComponentName);
+ public void killBackgroundProcesses(java.lang.String);
+ public void killUid(int, java.lang.String);
+ public static void logoutCurrentUser();
+ public void moveTaskToFront(int, int);
+ public void moveTaskToFront(int, int, android.os.Bundle);
+ public static void noteAlarmFinish(android.app.PendingIntent, android.os.WorkSource, int, java.lang.String);
+ public static void noteAlarmStart(android.app.PendingIntent, android.os.WorkSource, int, java.lang.String);
+ public static void noteWakeupAlarm(android.app.PendingIntent, android.os.WorkSource, int, java.lang.String, java.lang.String);
+ public static int processStateAmToProto(int);
+ public void removeOnUidImportanceListener(android.app.ActivityManager$OnUidImportanceListener);
+ public void removeStacksInWindowingModes(int[]);
+ public void removeStacksWithActivityTypes(int[]);
+ public void resizeStack(int, android.graphics.Rect);
+ public void restartPackage(java.lang.String);
+ public void setFrontActivityScreenCompatMode(int);
+ public void setPackageAskScreenCompat(java.lang.String, boolean);
+ public void setPackageScreenCompatMode(java.lang.String, int);
+ public static void setPersistentVrThread(int);
+ public boolean setProcessMemoryTrimLevel(java.lang.String, int, int);
+ public void setTaskWindowingMode(int, int, boolean);
+ public void setTaskWindowingModeSplitScreenPrimary(int, int, boolean, boolean, android.graphics.Rect, boolean);
+ public static void setVrThread(int);
+ public void setWatchHeapLimit(long);
+ public static int staticGetLargeMemoryClass();
+ public static int staticGetMemoryClass();
+ public static boolean supportsMultiWindow(android.content.Context);
+ public static boolean supportsSplitScreenMultiWindow(android.content.Context);
+ public boolean switchUser(int);
+
+
+ public static java.lang.String ACTION_REPORT_HEAP_LIMIT;
+ public static int APP_START_MODE_DELAYED;
+ public static int APP_START_MODE_DELAYED_RIGID;
+ public static int APP_START_MODE_DISABLED;
+ public static int APP_START_MODE_NORMAL;
+ public static int ASSIST_CONTEXT_AUTOFILL;
+ public static int ASSIST_CONTEXT_BASIC;
+ public static int ASSIST_CONTEXT_FULL;
+ public static int BROADCAST_FAILED_USER_STOPPED;
+ public static int BROADCAST_STICKY_CANT_HAVE_PERMISSION;
+ public static int BROADCAST_SUCCESS;
+ public static int BUGREPORT_OPTION_FULL;
+ public static int BUGREPORT_OPTION_INTERACTIVE;
+ public static int BUGREPORT_OPTION_REMOTE;
+ public static int BUGREPORT_OPTION_TELEPHONY;
+ public static int BUGREPORT_OPTION_WEAR;
+ public static int BUGREPORT_OPTION_WIFI;
+ public static int COMPAT_MODE_ALWAYS;
+ public static int COMPAT_MODE_DISABLED;
+ public static int COMPAT_MODE_ENABLED;
+ public static int COMPAT_MODE_NEVER;
+ public static int COMPAT_MODE_TOGGLE;
+ public static int COMPAT_MODE_UNKNOWN;
+ public static int FLAG_AND_LOCKED;
+ public static int FLAG_AND_UNLOCKED;
+ public static int FLAG_AND_UNLOCKING_OR_UNLOCKED;
+ public static int FLAG_OR_STOPPED;
+ public static int INTENT_SENDER_ACTIVITY;
+ public static int INTENT_SENDER_ACTIVITY_RESULT;
+ public static int INTENT_SENDER_BROADCAST;
+ public static int INTENT_SENDER_FOREGROUND_SERVICE;
+ public static int INTENT_SENDER_SERVICE;
+ public static int LOCK_TASK_MODE_LOCKED;
+ public static int LOCK_TASK_MODE_NONE;
+ public static int LOCK_TASK_MODE_PINNED;
+ public static int MAX_PROCESS_STATE;
+ public static java.lang.String META_HOME_ALTERNATE;
+ public static int MIN_PROCESS_STATE;
+ public static int MOVE_TASK_NO_USER_ACTION;
+ public static int MOVE_TASK_WITH_HOME;
+ public static int PROCESS_STATE_BACKUP;
+ public static int PROCESS_STATE_BOUND_FOREGROUND_SERVICE;
+ public static int PROCESS_STATE_CACHED_ACTIVITY;
+ public static int PROCESS_STATE_CACHED_ACTIVITY_CLIENT;
+ public static int PROCESS_STATE_CACHED_EMPTY;
+ public static int PROCESS_STATE_CACHED_RECENT;
+ public static int PROCESS_STATE_FOREGROUND_SERVICE;
+ public static int PROCESS_STATE_HEAVY_WEIGHT;
+ public static int PROCESS_STATE_HOME;
+ public static int PROCESS_STATE_IMPORTANT_BACKGROUND;
+ public static int PROCESS_STATE_IMPORTANT_FOREGROUND;
+ public static int PROCESS_STATE_LAST_ACTIVITY;
+ public static int PROCESS_STATE_NONEXISTENT;
+ public static int PROCESS_STATE_PERSISTENT;
+ public static int PROCESS_STATE_PERSISTENT_UI;
+ public static int PROCESS_STATE_RECEIVER;
+ public static int PROCESS_STATE_SERVICE;
+ public static int PROCESS_STATE_TOP;
+ public static int PROCESS_STATE_TOP_SLEEPING;
+ public static int PROCESS_STATE_TRANSIENT_BACKGROUND;
+ public static int PROCESS_STATE_UNKNOWN;
+ public static int RECENT_IGNORE_UNAVAILABLE;
+ public static int RECENT_WITH_EXCLUDED;
+ public static int RESIZE_MODE_FORCED;
+ public static int RESIZE_MODE_PRESERVE_WINDOW;
+ public static int RESIZE_MODE_SYSTEM;
+ public static int RESIZE_MODE_SYSTEM_SCREEN_ROTATION;
+ public static int RESIZE_MODE_USER;
+ public static int RESIZE_MODE_USER_FORCED;
+ public static int SPLIT_SCREEN_CREATE_MODE_BOTTOM_OR_RIGHT;
+ public static int SPLIT_SCREEN_CREATE_MODE_TOP_OR_LEFT;
+ public static int START_ABORTED;
+ public static int START_ASSISTANT_HIDDEN_SESSION;
+ public static int START_ASSISTANT_NOT_ACTIVE_SESSION;
+ public static int START_CANCELED;
+ public static int START_CLASS_NOT_FOUND;
+ public static int START_DELIVERED_TO_TOP;
+ public static int START_FLAG_DEBUG;
+ public static int START_FLAG_NATIVE_DEBUGGING;
+ public static int START_FLAG_ONLY_IF_NEEDED;
+ public static int START_FLAG_TRACK_ALLOCATION;
+ public static int START_FORWARD_AND_REQUEST_CONFLICT;
+ public static int START_INTENT_NOT_RESOLVED;
+ public static int START_NOT_ACTIVITY;
+ public static int START_NOT_CURRENT_USER_ACTIVITY;
+ public static int START_NOT_VOICE_COMPATIBLE;
+ public static int START_PERMISSION_DENIED;
+ public static int START_RETURN_INTENT_TO_CALLER;
+ public static int START_RETURN_LOCK_TASK_MODE_VIOLATION;
+ public static int START_SUCCESS;
+ public static int START_SWITCHES_CANCELED;
+ public static int START_TASK_TO_FRONT;
+ public static int START_VOICE_HIDDEN_SESSION;
+ public static int START_VOICE_NOT_ACTIVE_SESSION;
+ public static int UID_OBSERVER_ACTIVE;
+ public static int UID_OBSERVER_CACHED;
+ public static int UID_OBSERVER_GONE;
+ public static int UID_OBSERVER_IDLE;
+ public static int UID_OBSERVER_PROCSTATE;
+ public static int USER_OP_ERROR_IS_SYSTEM;
+ public static int USER_OP_ERROR_RELATED_USERS_CANNOT_STOP;
+ public static int USER_OP_IS_CURRENT;
+ public static int USER_OP_SUCCESS;
+ public static int USER_OP_UNKNOWN_USER;
+}
+
+-keep class android.app.ActivityManager$AppTask {
+ <init>(android.app.IAppTask);
+
+ public void finishAndRemoveTask();
+ public android.app.ActivityManager$RecentTaskInfo getTaskInfo();
+ public void moveToFront();
+ public void setExcludeFromRecents(boolean);
+ public void startActivity(android.content.Context, android.content.Intent, android.os.Bundle);
+
+
+}
+
+-keep class android.app.ActivityManager$MemoryInfo {
+ <init>();
+
+ public int describeContents();
+ public void readFromParcel(android.os.Parcel);
+ public void writeToParcel(android.os.Parcel, int);
+
+
+ public static android.os.Parcelable$Creator CREATOR;
+ public long availMem;
+ public long foregroundAppThreshold;
+ public long hiddenAppThreshold;
+ public boolean lowMemory;
+ public long secondaryServerThreshold;
+ public long threshold;
+ public long totalMem;
+ public long visibleAppThreshold;
+}
+
+-keep class android.app.ActivityManager$OnUidImportanceListener {
+
+ public abstract void onUidImportance(int, int);
+
+
+}
+
+-keep class android.app.ActivityManager$ProcessErrorStateInfo {
+ <init>();
+
+ public int describeContents();
+ public void readFromParcel(android.os.Parcel);
+ public void writeToParcel(android.os.Parcel, int);
+
+
+ public static int CRASHED;
+ public static android.os.Parcelable$Creator CREATOR;
+ public static int NOT_RESPONDING;
+ public static int NO_ERROR;
+ public int condition;
+ public byte[] crashData;
+ public java.lang.String longMsg;
+ public int pid;
+ public java.lang.String processName;
+ public java.lang.String shortMsg;
+ public java.lang.String stackTrace;
+ public java.lang.String tag;
+ public int uid;
+}
+
+-keep class android.app.ActivityManager$RecentTaskInfo {
+ <init>();
+
+ public int describeContents();
+ public void readFromParcel(android.os.Parcel);
+ public void writeToParcel(android.os.Parcel, int);
+
+
+ public static android.os.Parcelable$Creator CREATOR;
+ public int affiliatedTaskColor;
+ public int affiliatedTaskId;
+ public android.content.ComponentName baseActivity;
+ public android.content.Intent baseIntent;
+ public android.graphics.Rect bounds;
+ public android.content.res.Configuration configuration;
+ public java.lang.CharSequence description;
+ public long firstActiveTime;
+ public int id;
+ public long lastActiveTime;
+ public int numActivities;
+ public android.content.ComponentName origActivity;
+ public int persistentId;
+ public android.content.ComponentName realActivity;
+ public int resizeMode;
+ public int stackId;
+ public boolean supportsSplitScreenMultiWindow;
+ public android.app.ActivityManager$TaskDescription taskDescription;
+ public android.content.ComponentName topActivity;
+ public int userId;
+}
+
+-keep class android.app.ActivityManager$RunningAppProcessInfo {
+ <init>();
+ <init>(java.lang.String, int, java.lang.String[]);
+
+ public int describeContents();
+ public static int importanceToProcState(int);
+ public static int procStateToImportance(int);
+ public static int procStateToImportanceForClient(int, android.content.Context);
+ public static int procStateToImportanceForTargetSdk(int, int);
+ public void readFromParcel(android.os.Parcel);
+ public void writeToParcel(android.os.Parcel, int);
+
+
+ public static android.os.Parcelable$Creator CREATOR;
+ public static int FLAG_CANT_SAVE_STATE;
+ public static int FLAG_HAS_ACTIVITIES;
+ public static int FLAG_PERSISTENT;
+ public static int IMPORTANCE_BACKGROUND;
+ public static int IMPORTANCE_CACHED;
+ public static int IMPORTANCE_CANT_SAVE_STATE;
+ public static int IMPORTANCE_CANT_SAVE_STATE_PRE_26;
+ public static int IMPORTANCE_EMPTY;
+ public static int IMPORTANCE_FOREGROUND;
+ public static int IMPORTANCE_FOREGROUND_SERVICE;
+ public static int IMPORTANCE_GONE;
+ public static int IMPORTANCE_PERCEPTIBLE;
+ public static int IMPORTANCE_PERCEPTIBLE_PRE_26;
+ public static int IMPORTANCE_SERVICE;
+ public static int IMPORTANCE_TOP_SLEEPING;
+ public static int IMPORTANCE_TOP_SLEEPING_PRE_28;
+ public static int IMPORTANCE_VISIBLE;
+ public static int REASON_PROVIDER_IN_USE;
+ public static int REASON_SERVICE_IN_USE;
+ public static int REASON_UNKNOWN;
+ public int flags;
+ public int importance;
+ public int importanceReasonCode;
+ public android.content.ComponentName importanceReasonComponent;
+ public int importanceReasonImportance;
+ public int importanceReasonPid;
+ public int lastTrimLevel;
+ public int lru;
+ public int pid;
+ public java.lang.String[] pkgList;
+ public java.lang.String processName;
+ public int processState;
+ public int uid;
+}
+
+-keep class android.app.ActivityManager$RunningServiceInfo {
+ <init>();
+
+ public int describeContents();
+ public void readFromParcel(android.os.Parcel);
+ public void writeToParcel(android.os.Parcel, int);
+
+
+ public static android.os.Parcelable$Creator CREATOR;
+ public static int FLAG_FOREGROUND;
+ public static int FLAG_PERSISTENT_PROCESS;
+ public static int FLAG_STARTED;
+ public static int FLAG_SYSTEM_PROCESS;
+ public long activeSince;
+ public int clientCount;
+ public int clientLabel;
+ public java.lang.String clientPackage;
+ public int crashCount;
+ public int flags;
+ public boolean foreground;
+ public long lastActivityTime;
+ public int pid;
+ public java.lang.String process;
+ public long restarting;
+ public android.content.ComponentName service;
+ public boolean started;
+ public int uid;
+}
+
+-keep class android.app.ActivityManager$RunningTaskInfo {
+ <init>();
+
+ public int describeContents();
+ public void readFromParcel(android.os.Parcel);
+ public void writeToParcel(android.os.Parcel, int);
+
+
+ public static android.os.Parcelable$Creator CREATOR;
+ public android.content.ComponentName baseActivity;
+ public android.content.res.Configuration configuration;
+ public java.lang.CharSequence description;
+ public int id;
+ public long lastActiveTime;
+ public int numActivities;
+ public int numRunning;
+ public int resizeMode;
+ public int stackId;
+ public boolean supportsSplitScreenMultiWindow;
+ public android.graphics.Bitmap thumbnail;
+ public android.content.ComponentName topActivity;
+}
+
+-keep class android.app.ActivityManager$StackInfo {
+ <init>();
+
+ public int describeContents();
+ public void readFromParcel(android.os.Parcel);
+ public java.lang.String toString(java.lang.String);
+ public java.lang.String toString();
+ public void writeToParcel(android.os.Parcel, int);
+
+
+ public static android.os.Parcelable$Creator CREATOR;
+ public android.graphics.Rect bounds;
+ public android.content.res.Configuration configuration;
+ public int displayId;
+ public int position;
+ public int stackId;
+ public android.graphics.Rect[] taskBounds;
+ public int[] taskIds;
+ public java.lang.String[] taskNames;
+ public int[] taskUserIds;
+ public android.content.ComponentName topActivity;
+ public int userId;
+ public boolean visible;
+}
+
+-keep class android.app.ActivityManager$TaskDescription {
+ <init>(java.lang.String, android.graphics.Bitmap, int);
+ <init>(java.lang.String, int, int);
+ <init>(java.lang.String, android.graphics.Bitmap);
+ <init>(java.lang.String, int);
+ <init>(java.lang.String);
+ <init>();
+ <init>(java.lang.String, android.graphics.Bitmap, int, java.lang.String, int, int, int, int);
+ <init>(android.app.ActivityManager$TaskDescription);
+
+ public void copyFrom(android.app.ActivityManager$TaskDescription);
+ public void copyFromPreserveHiddenFields(android.app.ActivityManager$TaskDescription);
+ public int describeContents();
+ public int getBackgroundColor();
+ public android.graphics.Bitmap getIcon();
+ public java.lang.String getIconFilename();
+ public int getIconResource();
+ public android.graphics.Bitmap getInMemoryIcon();
+ public java.lang.String getLabel();
+ public int getNavigationBarColor();
+ public int getPrimaryColor();
+ public int getStatusBarColor();
+ public static android.graphics.Bitmap loadTaskDescriptionIcon(java.lang.String, int);
+ public void readFromParcel(android.os.Parcel);
+ public void restoreFromXml(java.lang.String, java.lang.String);
+ public void saveToXml(org.xmlpull.v1.XmlSerializer);
+ public void setBackgroundColor(int);
+ public void setIcon(android.graphics.Bitmap);
+ public void setIcon(int);
+ public void setIconFilename(java.lang.String);
+ public void setLabel(java.lang.String);
+ public void setNavigationBarColor(int);
+ public void setPrimaryColor(int);
+ public void setStatusBarColor(int);
+ public java.lang.String toString();
+ public void writeToParcel(android.os.Parcel, int);
+
+
+ public static java.lang.String ATTR_TASKDESCRIPTION_PREFIX;
+ public static android.os.Parcelable$Creator CREATOR;
+}
+
+-keep class android.app.ActivityManager$TaskSnapshot {
+ <init>(android.graphics.GraphicBuffer, int, android.graphics.Rect, boolean, float, boolean, int, int, boolean);
+
+ public int describeContents();
+ public android.graphics.Rect getContentInsets();
+ public int getOrientation();
+ public float getScale();
+ public android.graphics.GraphicBuffer getSnapshot();
+ public int getSystemUiVisibility();
+ public int getWindowingMode();
+ public boolean isRealSnapshot();
+ public boolean isReducedResolution();
+ public boolean isTranslucent();
+ public java.lang.String toString();
+ public void writeToParcel(android.os.Parcel, int);
+
+
+ public static android.os.Parcelable$Creator CREATOR;
+}
+
+-keep class android.app.ActivityOptions {
+ <init>(android.os.Bundle);
+
+ public void abort();
+ public static void abort(android.app.ActivityOptions);
+ public boolean canTaskOverlayResume();
+ public boolean disallowEnterPictureInPictureWhileLaunching();
+ public android.app.ActivityOptions forTargetActivity();
+ public static android.app.ActivityOptions fromBundle(android.os.Bundle);
+ public android.view.AppTransitionAnimationSpec[] getAnimSpecs();
+ public android.os.IRemoteCallback getAnimationFinishedListener();
+ public int getAnimationType();
+ public boolean getAvoidMoveToFront();
+ public int getCustomEnterResId();
+ public int getCustomExitResId();
+ public int getCustomInPlaceResId();
+ public int getExitCoordinatorKey();
+ public int getHeight();
+ public int getLaunchActivityType();
+ public android.graphics.Rect getLaunchBounds();
+ public int getLaunchDisplayId();
+ public boolean getLaunchTaskBehind();
+ public int getLaunchTaskId();
+ public int getLaunchWindowingMode();
+ public boolean getLockTaskMode();
+ public android.os.IRemoteCallback getOnAnimationStartListener();
+ public java.lang.String getPackageName();
+ public android.view.RemoteAnimationAdapter getRemoteAnimationAdapter();
+ public int getResultCode();
+ public android.content.Intent getResultData();
+ public android.os.ResultReceiver getResultReceiver();
+ public int getRotationAnimationHint();
+ public java.util.ArrayList getSharedElementNames();
+ public android.view.IAppTransitionAnimationSpecsFuture getSpecsFuture();
+ public int getSplitScreenCreateMode();
+ public int getStartX();
+ public int getStartY();
+ public boolean getTaskOverlay();
+ public android.graphics.GraphicBuffer getThumbnail();
+ public android.app.PendingIntent getUsageTimeReport();
+ public int getWidth();
+ public boolean isReturning();
+ public static android.app.ActivityOptions makeBasic();
+ public static android.app.ActivityOptions makeClipRevealAnimation(android.view.View, int, int, int, int);
+ public static android.app.ActivityOptions makeCustomAnimation(android.content.Context, int, int);
+ public static android.app.ActivityOptions makeCustomAnimation(android.content.Context, int, int, android.os.Handler, android.app.ActivityOptions$OnAnimationStartedListener);
+ public static android.app.ActivityOptions makeCustomInPlaceAnimation(android.content.Context, int);
+ public static android.app.ActivityOptions makeMultiThumbFutureAspectScaleAnimation(android.content.Context, android.os.Handler, android.view.IAppTransitionAnimationSpecsFuture, android.app.ActivityOptions$OnAnimationStartedListener, boolean);
+ public static android.app.ActivityOptions makeOpenCrossProfileAppsAnimation();
+ public static android.app.ActivityOptions makeRemoteAnimation(android.view.RemoteAnimationAdapter);
+ public static android.app.ActivityOptions makeScaleUpAnimation(android.view.View, int, int, int, int);
+ public static android.app.ActivityOptions makeSceneTransitionAnimation(android.app.Activity, android.view.View, java.lang.String);
+ public static android.app.ActivityOptions makeSceneTransitionAnimation(android.app.Activity, android.util.Pair[]);
+ public static android.app.ActivityOptions makeTaskLaunchBehind();
+ public static android.app.ActivityOptions makeThumbnailAspectScaleDownAnimation(android.view.View, android.graphics.Bitmap, int, int, int, int, android.os.Handler, android.app.ActivityOptions$OnAnimationStartedListener);
+ public static android.app.ActivityOptions makeThumbnailAspectScaleDownAnimation(android.view.View, android.view.AppTransitionAnimationSpec[], android.os.Handler, android.app.ActivityOptions$OnAnimationStartedListener, android.app.ActivityOptions$OnAnimationFinishedListener);
+ public static android.app.ActivityOptions makeThumbnailScaleUpAnimation(android.view.View, android.graphics.Bitmap, int, int);
+ public android.os.Bundle popAppVerificationBundle();
+ public void requestUsageTimeReport(android.app.PendingIntent);
+ public android.app.ActivityOptions setAppVerificationBundle(android.os.Bundle);
+ public void setAvoidMoveToFront();
+ public void setDisallowEnterPictureInPictureWhileLaunching(boolean);
+ public void setLaunchActivityType(int);
+ public android.app.ActivityOptions setLaunchBounds(android.graphics.Rect);
+ public android.app.ActivityOptions setLaunchDisplayId(int);
+ public void setLaunchTaskId(int);
+ public void setLaunchWindowingMode(int);
+ public android.app.ActivityOptions setLockTaskEnabled(boolean);
+ public void setRemoteAnimationAdapter(android.view.RemoteAnimationAdapter);
+ public void setRotationAnimationHint(int);
+ public void setSplitScreenCreateMode(int);
+ public void setTaskOverlay(boolean, boolean);
+ public static android.app.ActivityOptions startSharedElementAnimation(android.view.Window, android.util.Pair[]);
+ public static void stopSharedElementAnimation(android.view.Window);
+ public android.os.Bundle toBundle();
+ public java.lang.String toString();
+ public void update(android.app.ActivityOptions);
+
+
+ public static int ANIM_CLIP_REVEAL;
+ public static int ANIM_CUSTOM;
+ public static int ANIM_CUSTOM_IN_PLACE;
+ public static int ANIM_DEFAULT;
+ public static int ANIM_LAUNCH_TASK_BEHIND;
+ public static int ANIM_NONE;
+ public static int ANIM_OPEN_CROSS_PROFILE_APPS;
+ public static int ANIM_REMOTE_ANIMATION;
+ public static int ANIM_SCALE_UP;
+ public static int ANIM_SCENE_TRANSITION;
+ public static int ANIM_THUMBNAIL_ASPECT_SCALE_DOWN;
+ public static int ANIM_THUMBNAIL_ASPECT_SCALE_UP;
+ public static int ANIM_THUMBNAIL_SCALE_DOWN;
+ public static int ANIM_THUMBNAIL_SCALE_UP;
+ public static java.lang.String EXTRA_USAGE_TIME_REPORT;
+ public static java.lang.String EXTRA_USAGE_TIME_REPORT_PACKAGES;
+ public static java.lang.String KEY_ANIM_ENTER_RES_ID;
+ public static java.lang.String KEY_ANIM_EXIT_RES_ID;
+ public static java.lang.String KEY_ANIM_HEIGHT;
+ public static java.lang.String KEY_ANIM_IN_PLACE_RES_ID;
+ public static java.lang.String KEY_ANIM_START_LISTENER;
+ public static java.lang.String KEY_ANIM_START_X;
+ public static java.lang.String KEY_ANIM_START_Y;
+ public static java.lang.String KEY_ANIM_THUMBNAIL;
+ public static java.lang.String KEY_ANIM_TYPE;
+ public static java.lang.String KEY_ANIM_WIDTH;
+ public static java.lang.String KEY_LAUNCH_BOUNDS;
+ public static java.lang.String KEY_PACKAGE_NAME;
+}
+
+-keep class android.app.ActivityOptions$OnAnimationFinishedListener {
+
+ public abstract void onAnimationFinished();
+
+
+}
+
+-keep class android.app.ActivityOptions$OnAnimationStartedListener {
+
+ public abstract void onAnimationStarted();
+
+
+}
+
+-keep class android.app.ActivityThread {
+
+ public android.content.IContentProvider acquireExistingProvider(android.content.Context, java.lang.String, int, boolean);
+ public android.content.IContentProvider acquireProvider(android.content.Context, java.lang.String, int, boolean);
+ public void applyConfigurationToResources(android.content.res.Configuration);
+ public static android.app.ActivityThread currentActivityThread();
+ public static android.app.Application currentApplication();
+ public static java.lang.String currentOpPackageName();
+ public static java.lang.String currentPackageName();
+ public static java.lang.String currentProcessName();
+ public static void dumpMemInfoTable(java.io.PrintWriter, android.os.Debug$MemoryInfo, boolean, boolean, boolean, boolean, int, java.lang.String, long, long, long, long, long, long);
+ public static void dumpMemInfoTable(android.util.proto.ProtoOutputStream, android.os.Debug$MemoryInfo, boolean, boolean, long, long, long, long, long, long);
+ public android.app.Activity getActivity(android.os.IBinder);
+ public android.app.ActivityThread$ActivityClientRecord getActivityClient(android.os.IBinder);
+ public android.app.Application getApplication();
+ public android.app.ActivityThread$ApplicationThread getApplicationThread();
+ public java.util.concurrent.Executor getExecutor();
+ public android.app.Instrumentation getInstrumentation();
+ public int getIntCoreSetting(java.lang.String, int);
+ public static android.content.Intent getIntentBeingBroadcast();
+ public android.os.Looper getLooper();
+ public android.app.LoadedApk getPackageInfo(java.lang.String, android.content.res.CompatibilityInfo, int);
+ public android.app.LoadedApk getPackageInfo(java.lang.String, android.content.res.CompatibilityInfo, int, int);
+ public android.app.LoadedApk getPackageInfo(android.content.pm.ApplicationInfo, android.content.res.CompatibilityInfo, int);
+ public android.app.LoadedApk getPackageInfoNoCheck(android.content.pm.ApplicationInfo, android.content.res.CompatibilityInfo);
+ public static android.content.pm.IPackageManager getPackageManager();
+ public java.lang.String getProcessName();
+ public java.lang.String getProfileFilePath();
+ public android.app.ContextImpl getSystemContext();
+ public android.app.ContextImpl getSystemUiContext();
+ public void handleActivityConfigurationChanged(android.os.IBinder, android.content.res.Configuration, int);
+ public void handleConfigurationChanged(android.content.res.Configuration);
+ public void handleDestroyActivity(android.os.IBinder, boolean, int, boolean, java.lang.String);
+ public void handleInstallProvider(android.content.pm.ProviderInfo);
+ public android.app.Activity handleLaunchActivity(android.app.ActivityThread$ActivityClientRecord, android.app.servertransaction.PendingTransactionActions, android.content.Intent);
+ public void handleMultiWindowModeChanged(android.os.IBinder, boolean, android.content.res.Configuration);
+ public void handleNewIntent(android.os.IBinder, java.util.List, boolean);
+ public void handlePauseActivity(android.os.IBinder, boolean, boolean, int, android.app.servertransaction.PendingTransactionActions, java.lang.String);
+ public void handlePictureInPictureModeChanged(android.os.IBinder, boolean, android.content.res.Configuration);
+ public void handleRelaunchActivity(android.app.ActivityThread$ActivityClientRecord, android.app.servertransaction.PendingTransactionActions);
+ public void handleRequestAssistContextExtras(android.app.ActivityThread$RequestAssistContextExtras);
+ public void handleResumeActivity(android.os.IBinder, boolean, boolean, java.lang.String);
+ public void handleSendResult(android.os.IBinder, java.util.List, java.lang.String);
+ public void handleStartActivity(android.app.ActivityThread$ActivityClientRecord, android.app.servertransaction.PendingTransactionActions);
+ public void handleStopActivity(android.os.IBinder, boolean, int, android.app.servertransaction.PendingTransactionActions, boolean, java.lang.String);
+ public void handleTranslucentConversionComplete(android.os.IBinder, boolean);
+ public void handleWindowVisibility(android.os.IBinder, boolean);
+ public void installSystemApplicationInfo(android.content.pm.ApplicationInfo, java.lang.ClassLoader);
+ public void installSystemProviders(java.util.List);
+ public boolean isProfiling();
+ public static boolean isSystem();
+ public static void main(java.lang.String[]);
+ public void onNewActivityOptions(android.os.IBinder, android.app.ActivityOptions);
+ public android.app.LoadedApk peekPackageInfo(java.lang.String, boolean);
+ public void performRestartActivity(android.os.IBinder, boolean);
+ public android.app.ActivityThread$ActivityClientRecord performResumeActivity(android.os.IBinder, boolean, java.lang.String);
+ public android.app.ActivityThread$ActivityClientRecord prepareRelaunchActivity(android.os.IBinder, java.util.List, java.util.List, int, android.util.MergedConfiguration, boolean);
+ public void registerOnActivityPausedListener(android.app.Activity, android.app.OnActivityPausedListener);
+ public boolean releaseProvider(android.content.IContentProvider, boolean);
+ public void reportRelaunch(android.os.IBinder, android.app.servertransaction.PendingTransactionActions);
+ public void reportStop(android.app.servertransaction.PendingTransactionActions);
+ public android.content.pm.ActivityInfo resolveActivityInfo(android.content.Intent);
+ public void sendActivityResult(android.os.IBinder, java.lang.String, int, int, android.content.Intent);
+ public android.app.Activity startActivityNow(android.app.Activity, java.lang.String, android.content.Intent, android.content.pm.ActivityInfo, android.os.IBinder, android.os.Bundle, android.app.Activity$NonConfigurationInstances);
+ public void stopProfiling();
+ public static android.app.ActivityThread systemMain();
+ public void unregisterOnActivityPausedListener(android.app.Activity, android.app.OnActivityPausedListener);
+ public void updatePendingConfiguration(android.content.res.Configuration);
+ public void updateProcessState(int, boolean);
+
+
+ public static boolean DEBUG_BROADCAST;
+ public static boolean DEBUG_CONFIGURATION;
+ public static boolean DEBUG_MEMORY_TRIM;
+ public static boolean DEBUG_ORDER;
+ public static long INVALID_PROC_STATE_SEQ;
+ public static java.lang.String PROC_START_SEQ_IDENT;
+ public static int SERVICE_DONE_EXECUTING_ANON;
+ public static int SERVICE_DONE_EXECUTING_START;
+ public static int SERVICE_DONE_EXECUTING_STOP;
+ public static java.lang.String TAG;
+}
+
+-keep class android.app.ActivityThread$ActivityClientRecord {
+ <init>();
+ <init>(android.os.IBinder, android.content.Intent, int, android.content.pm.ActivityInfo, android.content.res.Configuration, android.content.res.CompatibilityInfo, java.lang.String, com.android.internal.app.IVoiceInteractor, android.os.Bundle, android.os.PersistableBundle, java.util.List, java.util.List, boolean, android.app.ProfilerInfo, android.app.ClientTransactionHandler);
+
+ public int getLifecycleState();
+ public java.lang.String getStateString();
+ public boolean isPersistable();
+ public boolean isVisibleFromServer();
+ public void setState(int);
+ public java.lang.String toString();
+
+
+ public boolean isForward;
+ public android.app.LoadedApk packageInfo;
+ public android.os.IBinder token;
+}
+
+-keep class android.app.ActivityThread$ApplicationThread {
+
+ public void attachAgent(java.lang.String);
+ public void bindApplication(java.lang.String, android.content.pm.ApplicationInfo, java.util.List, android.content.ComponentName, android.app.ProfilerInfo, android.os.Bundle, android.app.IInstrumentationWatcher, android.app.IUiAutomationConnection, int, boolean, boolean, boolean, boolean, android.content.res.Configuration, android.content.res.CompatibilityInfo, java.util.Map, android.os.Bundle, java.lang.String, boolean);
+ public void clearDnsCache();
+ public void dispatchPackageBroadcast(int, java.lang.String[]);
+ public void dumpActivity(android.os.ParcelFileDescriptor, android.os.IBinder, java.lang.String, java.lang.String[]);
+ public void dumpDbInfo(android.os.ParcelFileDescriptor, java.lang.String[]);
+ public void dumpGfxInfo(android.os.ParcelFileDescriptor, java.lang.String[]);
+ public void dumpHeap(boolean, boolean, boolean, java.lang.String, android.os.ParcelFileDescriptor);
+ public void dumpMemInfo(android.os.ParcelFileDescriptor, android.os.Debug$MemoryInfo, boolean, boolean, boolean, boolean, boolean, java.lang.String[]);
+ public void dumpMemInfoProto(android.os.ParcelFileDescriptor, android.os.Debug$MemoryInfo, boolean, boolean, boolean, boolean, java.lang.String[]);
+ public void dumpProvider(android.os.ParcelFileDescriptor, android.os.IBinder, java.lang.String[]);
+ public void dumpService(android.os.ParcelFileDescriptor, android.os.IBinder, java.lang.String[]);
+ public void handleTrustStorageUpdate();
+ public void notifyCleartextNetwork(byte[]);
+ public void processInBackground();
+ public void profilerControl(boolean, android.app.ProfilerInfo, int);
+ public void requestAssistContextExtras(android.os.IBinder, android.os.IBinder, int, int, int);
+ public void runIsolatedEntryPoint(java.lang.String, java.lang.String[]);
+ public void scheduleApplicationInfoChanged(android.content.pm.ApplicationInfo);
+ public void scheduleBindService(android.os.IBinder, android.content.Intent, boolean, int);
+ public void scheduleCrash(java.lang.String);
+ public void scheduleCreateBackupAgent(android.content.pm.ApplicationInfo, android.content.res.CompatibilityInfo, int);
+ public void scheduleCreateService(android.os.IBinder, android.content.pm.ServiceInfo, android.content.res.CompatibilityInfo, int);
+ public void scheduleDestroyBackupAgent(android.content.pm.ApplicationInfo, android.content.res.CompatibilityInfo);
+ public void scheduleEnterAnimationComplete(android.os.IBinder);
+ public void scheduleExit();
+ public void scheduleInstallProvider(android.content.pm.ProviderInfo);
+ public void scheduleLocalVoiceInteractionStarted(android.os.IBinder, com.android.internal.app.IVoiceInteractor);
+ public void scheduleLowMemory();
+ public void scheduleOnNewActivityOptions(android.os.IBinder, android.os.Bundle);
+ public void scheduleReceiver(android.content.Intent, android.content.pm.ActivityInfo, android.content.res.CompatibilityInfo, int, java.lang.String, android.os.Bundle, boolean, int, int);
+ public void scheduleRegisteredReceiver(android.content.IIntentReceiver, android.content.Intent, int, java.lang.String, android.os.Bundle, boolean, boolean, int, int);
+ public void scheduleServiceArgs(android.os.IBinder, android.content.pm.ParceledListSlice);
+ public void scheduleSleeping(android.os.IBinder, boolean);
+ public void scheduleStopService(android.os.IBinder);
+ public void scheduleSuicide();
+ public void scheduleTransaction(android.app.servertransaction.ClientTransaction);
+ public void scheduleTranslucentConversionComplete(android.os.IBinder, boolean);
+ public void scheduleTrimMemory(int);
+ public void scheduleUnbindService(android.os.IBinder, android.content.Intent);
+ public void setCoreSettings(android.os.Bundle);
+ public void setHttpProxy(java.lang.String, java.lang.String, java.lang.String, android.net.Uri);
+ public void setNetworkBlockSeq(long);
+ public void setProcessState(int);
+ public void setSchedulingGroup(int);
+ public void startBinderTracking();
+ public void stopBinderTrackingAndDump(android.os.ParcelFileDescriptor);
+ public void unstableProviderDied(android.os.IBinder);
+ public void updatePackageCompatibilityInfo(java.lang.String, android.content.res.CompatibilityInfo);
+ public void updateProcessState(int, boolean);
+ public void updateTimePrefs(int);
+ public void updateTimeZone();
+
+
+}
+
+-keep class android.app.ActivityThread$RequestAssistContextExtras {
+
+
+
+}
+
+-keep class android.app.AppComponentFactory {
+ <init>();
+
+ public android.app.Activity instantiateActivity(java.lang.ClassLoader, java.lang.String, android.content.Intent);
+ public android.app.Application instantiateApplication(java.lang.ClassLoader, java.lang.String);
+ public android.content.ContentProvider instantiateProvider(java.lang.ClassLoader, java.lang.String);
+ public android.content.BroadcastReceiver instantiateReceiver(java.lang.ClassLoader, java.lang.String, android.content.Intent);
+ public android.app.Service instantiateService(java.lang.ClassLoader, java.lang.String, android.content.Intent);
+
+
+ public static android.app.AppComponentFactory DEFAULT;
+}
+
+-keep class android.app.AppOpsManager {
+
+ public int checkAudioOp(int, int, int, java.lang.String);
+ public int checkAudioOpNoThrow(int, int, int, java.lang.String);
+ public int checkOp(java.lang.String, int, java.lang.String);
+ public int checkOp(int, int, java.lang.String);
+ public int checkOpNoThrow(java.lang.String, int, java.lang.String);
+ public int checkOpNoThrow(int, int, java.lang.String);
+ public void checkPackage(int, java.lang.String);
+ public void finishOp(java.lang.String, int, java.lang.String);
+ public void finishOp(int, int, java.lang.String);
+ public void finishOp(int);
+ public static java.lang.String[] getOpStrs();
+ public java.util.List getOpsForPackage(int, java.lang.String, int[]);
+ public java.util.List getPackagesForOps(int[]);
+ public static android.os.IBinder getToken(com.android.internal.app.IAppOpsService);
+ public boolean isOperationActive(int, int, java.lang.String);
+ public static long maxTime(long[], int, int);
+ public static java.lang.String modeToName(int);
+ public int noteOp(java.lang.String, int, java.lang.String);
+ public int noteOp(int, int, java.lang.String);
+ public int noteOp(int);
+ public int noteOpNoThrow(java.lang.String, int, java.lang.String);
+ public int noteOpNoThrow(int, int, java.lang.String);
+ public int noteProxyOp(java.lang.String, java.lang.String);
+ public int noteProxyOp(int, java.lang.String);
+ public int noteProxyOpNoThrow(java.lang.String, java.lang.String);
+ public int noteProxyOpNoThrow(int, java.lang.String);
+ public static boolean opAllowSystemBypassRestriction(int);
+ public static boolean opAllowsReset(int);
+ public static int opToDefaultMode(int);
+ public static java.lang.String opToName(int);
+ public static java.lang.String opToPermission(int);
+ public static java.lang.String opToRestriction(int);
+ public static int opToSwitch(int);
+ public static java.lang.String permissionToOp(java.lang.String);
+ public static int permissionToOpCode(java.lang.String);
+ public void resetAllModes();
+ public void setMode(int, int, java.lang.String, int);
+ public void setMode(java.lang.String, int, java.lang.String, int);
+ public void setRestriction(int, int, int, java.lang.String[]);
+ public void setUidMode(int, int, int);
+ public void setUidMode(java.lang.String, int, int);
+ public void setUserRestriction(int, boolean, android.os.IBinder);
+ public void setUserRestriction(int, boolean, android.os.IBinder, java.lang.String[]);
+ public void setUserRestrictionForUser(int, boolean, android.os.IBinder, java.lang.String[], int);
+ public int startOp(java.lang.String, int, java.lang.String);
+ public int startOp(int);
+ public int startOp(int, int, java.lang.String);
+ public int startOp(int, int, java.lang.String, boolean);
+ public int startOpNoThrow(java.lang.String, int, java.lang.String);
+ public int startOpNoThrow(int, int, java.lang.String);
+ public int startOpNoThrow(int, int, java.lang.String, boolean);
+ public void startWatchingActive(int[], android.app.AppOpsManager$OnOpActiveChangedListener);
+ public void startWatchingMode(java.lang.String, java.lang.String, android.app.AppOpsManager$OnOpChangedListener);
+ public void startWatchingMode(java.lang.String, java.lang.String, int, android.app.AppOpsManager$OnOpChangedListener);
+ public void startWatchingMode(int, java.lang.String, android.app.AppOpsManager$OnOpChangedListener);
+ public void startWatchingMode(int, java.lang.String, int, android.app.AppOpsManager$OnOpChangedListener);
+ public void stopWatchingActive(android.app.AppOpsManager$OnOpActiveChangedListener);
+ public void stopWatchingMode(android.app.AppOpsManager$OnOpChangedListener);
+ public static int strDebugOpToOp(java.lang.String);
+ public static int strOpToOp(java.lang.String);
+ public int unsafeCheckOpRaw(java.lang.String, int, java.lang.String);
+
+
+ public static int MODE_ALLOWED;
+ public static int MODE_DEFAULT;
+ public static int MODE_ERRORED;
+ public static int MODE_FOREGROUND;
+ public static int MODE_IGNORED;
+ public static java.lang.String[] MODE_NAMES;
+ public static java.lang.String OPSTR_ACCEPT_HANDOVER;
+ public static java.lang.String OPSTR_ACCESS_NOTIFICATIONS;
+ public static java.lang.String OPSTR_ACTIVATE_VPN;
+ public static java.lang.String OPSTR_ADD_VOICEMAIL;
+ public static java.lang.String OPSTR_ANSWER_PHONE_CALLS;
+ public static java.lang.String OPSTR_ASSIST_SCREENSHOT;
+ public static java.lang.String OPSTR_ASSIST_STRUCTURE;
+ public static java.lang.String OPSTR_AUDIO_ACCESSIBILITY_VOLUME;
+ public static java.lang.String OPSTR_AUDIO_ALARM_VOLUME;
+ public static java.lang.String OPSTR_AUDIO_BLUETOOTH_VOLUME;
+ public static java.lang.String OPSTR_AUDIO_MASTER_VOLUME;
+ public static java.lang.String OPSTR_AUDIO_MEDIA_VOLUME;
+ public static java.lang.String OPSTR_AUDIO_NOTIFICATION_VOLUME;
+ public static java.lang.String OPSTR_AUDIO_RING_VOLUME;
+ public static java.lang.String OPSTR_AUDIO_VOICE_VOLUME;
+ public static java.lang.String OPSTR_BIND_ACCESSIBILITY_SERVICE;
+ public static java.lang.String OPSTR_BLUETOOTH_SCAN;
+ public static java.lang.String OPSTR_BODY_SENSORS;
+ public static java.lang.String OPSTR_CALL_PHONE;
+ public static java.lang.String OPSTR_CAMERA;
+ public static java.lang.String OPSTR_CHANGE_WIFI_STATE;
+ public static java.lang.String OPSTR_COARSE_LOCATION;
+ public static java.lang.String OPSTR_FINE_LOCATION;
+ public static java.lang.String OPSTR_GET_ACCOUNTS;
+ public static java.lang.String OPSTR_GET_USAGE_STATS;
+ public static java.lang.String OPSTR_GPS;
+ public static java.lang.String OPSTR_INSTANT_APP_START_FOREGROUND;
+ public static java.lang.String OPSTR_MANAGE_IPSEC_TUNNELS;
+ public static java.lang.String OPSTR_MOCK_LOCATION;
+ public static java.lang.String OPSTR_MONITOR_HIGH_POWER_LOCATION;
+ public static java.lang.String OPSTR_MONITOR_LOCATION;
+ public static java.lang.String OPSTR_MUTE_MICROPHONE;
+ public static java.lang.String OPSTR_NEIGHBORING_CELLS;
+ public static java.lang.String OPSTR_PICTURE_IN_PICTURE;
+ public static java.lang.String OPSTR_PLAY_AUDIO;
+ public static java.lang.String OPSTR_POST_NOTIFICATION;
+ public static java.lang.String OPSTR_PROCESS_OUTGOING_CALLS;
+ public static java.lang.String OPSTR_PROJECT_MEDIA;
+ public static java.lang.String OPSTR_READ_CALENDAR;
+ public static java.lang.String OPSTR_READ_CALL_LOG;
+ public static java.lang.String OPSTR_READ_CELL_BROADCASTS;
+ public static java.lang.String OPSTR_READ_CLIPBOARD;
+ public static java.lang.String OPSTR_READ_CONTACTS;
+ public static java.lang.String OPSTR_READ_EXTERNAL_STORAGE;
+ public static java.lang.String OPSTR_READ_ICC_SMS;
+ public static java.lang.String OPSTR_READ_PHONE_NUMBERS;
+ public static java.lang.String OPSTR_READ_PHONE_STATE;
+ public static java.lang.String OPSTR_READ_SMS;
+ public static java.lang.String OPSTR_RECEIVE_EMERGENCY_BROADCAST;
+ public static java.lang.String OPSTR_RECEIVE_MMS;
+ public static java.lang.String OPSTR_RECEIVE_SMS;
+ public static java.lang.String OPSTR_RECEIVE_WAP_PUSH;
+ public static java.lang.String OPSTR_RECORD_AUDIO;
+ public static java.lang.String OPSTR_REQUEST_DELETE_PACKAGES;
+ public static java.lang.String OPSTR_REQUEST_INSTALL_PACKAGES;
+ public static java.lang.String OPSTR_RUN_ANY_IN_BACKGROUND;
+ public static java.lang.String OPSTR_RUN_IN_BACKGROUND;
+ public static java.lang.String OPSTR_SEND_SMS;
+ public static java.lang.String OPSTR_START_FOREGROUND;
+ public static java.lang.String OPSTR_SYSTEM_ALERT_WINDOW;
+ public static java.lang.String OPSTR_TAKE_AUDIO_FOCUS;
+ public static java.lang.String OPSTR_TAKE_MEDIA_BUTTONS;
+ public static java.lang.String OPSTR_TOAST_WINDOW;
+ public static java.lang.String OPSTR_TURN_SCREEN_ON;
+ public static java.lang.String OPSTR_USE_FINGERPRINT;
+ public static java.lang.String OPSTR_USE_SIP;
+ public static java.lang.String OPSTR_VIBRATE;
+ public static java.lang.String OPSTR_WAKE_LOCK;
+ public static java.lang.String OPSTR_WIFI_SCAN;
+ public static java.lang.String OPSTR_WRITE_CALENDAR;
+ public static java.lang.String OPSTR_WRITE_CALL_LOG;
+ public static java.lang.String OPSTR_WRITE_CLIPBOARD;
+ public static java.lang.String OPSTR_WRITE_CONTACTS;
+ public static java.lang.String OPSTR_WRITE_EXTERNAL_STORAGE;
+ public static java.lang.String OPSTR_WRITE_ICC_SMS;
+ public static java.lang.String OPSTR_WRITE_SETTINGS;
+ public static java.lang.String OPSTR_WRITE_SMS;
+ public static java.lang.String OPSTR_WRITE_WALLPAPER;
+ public static int OP_ACCEPT_HANDOVER;
+ public static int OP_ACCESS_NOTIFICATIONS;
+ public static int OP_ACTIVATE_VPN;
+ public static int OP_ADD_VOICEMAIL;
+ public static int OP_ANSWER_PHONE_CALLS;
+ public static int OP_ASSIST_SCREENSHOT;
+ public static int OP_ASSIST_STRUCTURE;
+ public static int OP_AUDIO_ACCESSIBILITY_VOLUME;
+ public static int OP_AUDIO_ALARM_VOLUME;
+ public static int OP_AUDIO_BLUETOOTH_VOLUME;
+ public static int OP_AUDIO_MASTER_VOLUME;
+ public static int OP_AUDIO_MEDIA_VOLUME;
+ public static int OP_AUDIO_NOTIFICATION_VOLUME;
+ public static int OP_AUDIO_RING_VOLUME;
+ public static int OP_AUDIO_VOICE_VOLUME;
+ public static int OP_BIND_ACCESSIBILITY_SERVICE;
+ public static int OP_BLUETOOTH_SCAN;
+ public static int OP_BODY_SENSORS;
+ public static int OP_CALL_PHONE;
+ public static int OP_CAMERA;
+ public static int OP_CHANGE_WIFI_STATE;
+ public static int OP_COARSE_LOCATION;
+ public static int OP_FINE_LOCATION;
+ public static int OP_GET_ACCOUNTS;
+ public static int OP_GET_USAGE_STATS;
+ public static int OP_GPS;
+ public static int OP_INSTANT_APP_START_FOREGROUND;
+ public static int OP_MANAGE_IPSEC_TUNNELS;
+ public static int OP_MOCK_LOCATION;
+ public static int OP_MONITOR_HIGH_POWER_LOCATION;
+ public static int OP_MONITOR_LOCATION;
+ public static int OP_MUTE_MICROPHONE;
+ public static int OP_NEIGHBORING_CELLS;
+ public static int OP_NONE;
+ public static int OP_PICTURE_IN_PICTURE;
+ public static int OP_PLAY_AUDIO;
+ public static int OP_POST_NOTIFICATION;
+ public static int OP_PROCESS_OUTGOING_CALLS;
+ public static int OP_PROJECT_MEDIA;
+ public static int OP_READ_CALENDAR;
+ public static int OP_READ_CALL_LOG;
+ public static int OP_READ_CELL_BROADCASTS;
+ public static int OP_READ_CLIPBOARD;
+ public static int OP_READ_CONTACTS;
+ public static int OP_READ_EXTERNAL_STORAGE;
+ public static int OP_READ_ICC_SMS;
+ public static int OP_READ_PHONE_NUMBERS;
+ public static int OP_READ_PHONE_STATE;
+ public static int OP_READ_SMS;
+ public static int OP_RECEIVE_EMERGECY_SMS;
+ public static int OP_RECEIVE_MMS;
+ public static int OP_RECEIVE_SMS;
+ public static int OP_RECEIVE_WAP_PUSH;
+ public static int OP_RECORD_AUDIO;
+ public static int OP_REQUEST_DELETE_PACKAGES;
+ public static int OP_REQUEST_INSTALL_PACKAGES;
+ public static int OP_RUN_ANY_IN_BACKGROUND;
+ public static int OP_RUN_IN_BACKGROUND;
+ public static int OP_SEND_SMS;
+ public static int OP_START_FOREGROUND;
+ public static int OP_SYSTEM_ALERT_WINDOW;
+ public static int OP_TAKE_AUDIO_FOCUS;
+ public static int OP_TAKE_MEDIA_BUTTONS;
+ public static int OP_TOAST_WINDOW;
+ public static int OP_TURN_SCREEN_ON;
+ public static int OP_USE_FINGERPRINT;
+ public static int OP_USE_SIP;
+ public static int OP_VIBRATE;
+ public static int OP_WAKE_LOCK;
+ public static int OP_WIFI_SCAN;
+ public static int OP_WRITE_CALENDAR;
+ public static int OP_WRITE_CALL_LOG;
+ public static int OP_WRITE_CLIPBOARD;
+ public static int OP_WRITE_CONTACTS;
+ public static int OP_WRITE_EXTERNAL_STORAGE;
+ public static int OP_WRITE_ICC_SMS;
+ public static int OP_WRITE_SETTINGS;
+ public static int OP_WRITE_SMS;
+ public static int OP_WRITE_WALLPAPER;
+ public static int UID_STATE_BACKGROUND;
+ public static int UID_STATE_CACHED;
+ public static int UID_STATE_FOREGROUND;
+ public static int UID_STATE_FOREGROUND_SERVICE;
+ public static int UID_STATE_LAST_NON_RESTRICTED;
+ public static int UID_STATE_PERSISTENT;
+ public static int UID_STATE_TOP;
+ public static int WATCH_FOREGROUND_CHANGES;
+ public static int _NUM_OP;
+ public static int _NUM_UID_STATE;
+}
+
+-keep class android.app.AppOpsManager$OnOpActiveChangedListener {
+
+ public abstract void onOpActiveChanged(int, int, java.lang.String, boolean);
+
+
+}
+
+-keep class android.app.AppOpsManager$OnOpChangedListener {
+
+ public abstract void onOpChanged(java.lang.String, java.lang.String);
+
+
+}
+
+-keep class android.app.AppOpsManager$OpEntry {
+ <init>(int, int, long, long, int, int, java.lang.String);
+ <init>(int, int, long[], long[], int, boolean, int, java.lang.String);
+ <init>(int, int, long[], long[], int, int, java.lang.String);
+
+ public int describeContents();
+ public int getDuration();
+ public long getLastAccessBackgroundTime();
+ public long getLastAccessForegroundTime();
+ public long getLastAccessTime();
+ public long getLastRejectBackgroundTime();
+ public long getLastRejectForegroundTime();
+ public long getLastRejectTime();
+ public long getLastRejectTimeFor(int);
+ public long getLastTimeFor(int);
+ public int getMode();
+ public int getOp();
+ public java.lang.String getProxyPackageName();
+ public int getProxyUid();
+ public long getRejectTime();
+ public long getTime();
+ public boolean isRunning();
+ public void writeToParcel(android.os.Parcel, int);
+
+
+ public static android.os.Parcelable$Creator CREATOR;
+}
+
+-keep class android.app.AppOpsManager$PackageOps {
+ <init>(java.lang.String, int, java.util.List);
+
+ public int describeContents();
+ public java.util.List getOps();
+ public java.lang.String getPackageName();
+ public int getUid();
+ public void writeToParcel(android.os.Parcel, int);
+
+
+ public static android.os.Parcelable$Creator CREATOR;
+}
+
+-keep class android.app.Application {
+ <init>();
+
+ public android.view.autofill.AutofillManager$AutofillClient getAutofillClient();
+ public static java.lang.String getProcessName();
+ public void onConfigurationChanged(android.content.res.Configuration);
+ public void onCreate();
+ public void onLowMemory();
+ public void onTerminate();
+ public void onTrimMemory(int);
+ public void registerActivityLifecycleCallbacks(android.app.Application$ActivityLifecycleCallbacks);
+ public void registerComponentCallbacks(android.content.ComponentCallbacks);
+ public void registerOnProvideAssistDataListener(android.app.Application$OnProvideAssistDataListener);
+ public void unregisterActivityLifecycleCallbacks(android.app.Application$ActivityLifecycleCallbacks);
+ public void unregisterComponentCallbacks(android.content.ComponentCallbacks);
+ public void unregisterOnProvideAssistDataListener(android.app.Application$OnProvideAssistDataListener);
+
+
+ public android.app.LoadedApk mLoadedApk;
+}
+
+-keep class android.app.Application$ActivityLifecycleCallbacks {
+
+ public abstract void onActivityCreated(android.app.Activity, android.os.Bundle);
+ public abstract void onActivityDestroyed(android.app.Activity);
+ public abstract void onActivityPaused(android.app.Activity);
+ public abstract void onActivityResumed(android.app.Activity);
+ public abstract void onActivitySaveInstanceState(android.app.Activity, android.os.Bundle);
+ public abstract void onActivityStarted(android.app.Activity);
+ public abstract void onActivityStopped(android.app.Activity);
+
+
+}
+
+-keep class android.app.Application$OnProvideAssistDataListener {
+
+ public abstract void onProvideAssistData(android.app.Activity, android.os.Bundle);
+
+
+}
+
+-keep class android.app.ApplicationErrorReport {
+ <init>();
+
+ public int describeContents();
+ public void dump(android.util.Printer, java.lang.String);
+ public static android.content.ComponentName getErrorReportReceiver(android.content.Context, java.lang.String, int);
+ public void readFromParcel(android.os.Parcel);
+ public void writeToParcel(android.os.Parcel, int);
+
+
+ public static android.os.Parcelable$Creator CREATOR;
+ public static int TYPE_ANR;
+ public static int TYPE_BATTERY;
+ public static int TYPE_CRASH;
+ public static int TYPE_NONE;
+ public static int TYPE_RUNNING_SERVICE;
+ public android.app.ApplicationErrorReport$AnrInfo anrInfo;
+ public android.app.ApplicationErrorReport$BatteryInfo batteryInfo;
+ public android.app.ApplicationErrorReport$CrashInfo crashInfo;
+ public java.lang.String installerPackageName;
+ public java.lang.String packageName;
+ public java.lang.String processName;
+ public android.app.ApplicationErrorReport$RunningServiceInfo runningServiceInfo;
+ public boolean systemApp;
+ public long time;
+ public int type;
+}
+
+-keep class android.app.ApplicationErrorReport$AnrInfo {
+ <init>();
+ <init>(android.os.Parcel);
+
+ public void dump(android.util.Printer, java.lang.String);
+ public void writeToParcel(android.os.Parcel, int);
+
+
+ public java.lang.String activity;
+ public java.lang.String cause;
+ public java.lang.String info;
+}
+
+-keep class android.app.ApplicationErrorReport$BatteryInfo {
+ <init>();
+ <init>(android.os.Parcel);
+
+ public void dump(android.util.Printer, java.lang.String);
+ public void writeToParcel(android.os.Parcel, int);
+
+
+ public java.lang.String checkinDetails;
+ public long durationMicros;
+ public java.lang.String usageDetails;
+ public int usagePercent;
+}
+
+-keep class android.app.ApplicationErrorReport$CrashInfo {
+ <init>();
+ <init>(java.lang.Throwable);
+ <init>(android.os.Parcel);
+
+ public void appendStackTrace(java.lang.String);
+ public void dump(android.util.Printer, java.lang.String);
+ public void writeToParcel(android.os.Parcel, int);
+
+
+ public java.lang.String exceptionClassName;
+ public java.lang.String exceptionMessage;
+ public java.lang.String stackTrace;
+ public java.lang.String throwClassName;
+ public java.lang.String throwFileName;
+ public int throwLineNumber;
+ public java.lang.String throwMethodName;
+}
+
+-keep class android.app.ApplicationErrorReport$ParcelableCrashInfo {
+ <init>();
+ <init>(java.lang.Throwable);
+ <init>(android.os.Parcel);
+
+ public int describeContents();
+
+
+ public static android.os.Parcelable$Creator CREATOR;
+}
+
+-keep class android.app.ApplicationErrorReport$RunningServiceInfo {
+ <init>();
+ <init>(android.os.Parcel);
+
+ public void dump(android.util.Printer, java.lang.String);
+ public void writeToParcel(android.os.Parcel, int);
+
+
+ public long durationMillis;
+ public java.lang.String serviceDetails;
+}
+
+-keep class android.app.ClientTransactionHandler {
+ <init>();
+
+ public void executeTransaction(android.app.servertransaction.ClientTransaction);
+ public abstract android.app.ActivityThread$ActivityClientRecord getActivityClient(android.os.IBinder);
+ public abstract android.app.LoadedApk getPackageInfoNoCheck(android.content.pm.ApplicationInfo, android.content.res.CompatibilityInfo);
+ public abstract void handleActivityConfigurationChanged(android.os.IBinder, android.content.res.Configuration, int);
+ public abstract void handleConfigurationChanged(android.content.res.Configuration);
+ public abstract void handleDestroyActivity(android.os.IBinder, boolean, int, boolean, java.lang.String);
+ public abstract android.app.Activity handleLaunchActivity(android.app.ActivityThread$ActivityClientRecord, android.app.servertransaction.PendingTransactionActions, android.content.Intent);
+ public abstract void handleMultiWindowModeChanged(android.os.IBinder, boolean, android.content.res.Configuration);
+ public abstract void handleNewIntent(android.os.IBinder, java.util.List, boolean);
+ public abstract void handlePauseActivity(android.os.IBinder, boolean, boolean, int, android.app.servertransaction.PendingTransactionActions, java.lang.String);
+ public abstract void handlePictureInPictureModeChanged(android.os.IBinder, boolean, android.content.res.Configuration);
+ public abstract void handleRelaunchActivity(android.app.ActivityThread$ActivityClientRecord, android.app.servertransaction.PendingTransactionActions);
+ public abstract void handleResumeActivity(android.os.IBinder, boolean, boolean, java.lang.String);
+ public abstract void handleSendResult(android.os.IBinder, java.util.List, java.lang.String);
+ public abstract void handleStartActivity(android.app.ActivityThread$ActivityClientRecord, android.app.servertransaction.PendingTransactionActions);
+ public abstract void handleStopActivity(android.os.IBinder, boolean, int, android.app.servertransaction.PendingTransactionActions, boolean, java.lang.String);
+ public abstract void handleWindowVisibility(android.os.IBinder, boolean);
+ public abstract void performRestartActivity(android.os.IBinder, boolean);
+ public abstract android.app.ActivityThread$ActivityClientRecord prepareRelaunchActivity(android.os.IBinder, java.util.List, java.util.List, int, android.util.MergedConfiguration, boolean);
+ public abstract void reportRelaunch(android.os.IBinder, android.app.servertransaction.PendingTransactionActions);
+ public abstract void reportStop(android.app.servertransaction.PendingTransactionActions);
+ public abstract void updatePendingConfiguration(android.content.res.Configuration);
+ public abstract void updateProcessState(int, boolean);
+
+
+}
+
+-keep class android.app.ContentProviderHolder {
+ <init>(android.content.pm.ProviderInfo);
+
+ public int describeContents();
+ public void writeToParcel(android.os.Parcel, int);
+
+
+ public static android.os.Parcelable$Creator CREATOR;
+ public android.os.IBinder connection;
+ public android.content.pm.ProviderInfo info;
+ public boolean noReleaseNeeded;
+ public android.content.IContentProvider provider;
+}
+
+-keep class android.app.ContextImpl {
+
+ public boolean bindService(android.content.Intent, android.content.ServiceConnection, int);
+ public boolean bindServiceAsUser(android.content.Intent, android.content.ServiceConnection, int, android.os.UserHandle);
+ public boolean bindServiceAsUser(android.content.Intent, android.content.ServiceConnection, int, android.os.Handler, android.os.UserHandle);
+ public boolean canLoadUnsafeResources();
+ public int checkCallingOrSelfPermission(java.lang.String);
+ public int checkCallingOrSelfUriPermission(android.net.Uri, int);
+ public int checkCallingPermission(java.lang.String);
+ public int checkCallingUriPermission(android.net.Uri, int);
+ public int checkPermission(java.lang.String, int, int);
+ public int checkPermission(java.lang.String, int, int, android.os.IBinder);
+ public int checkSelfPermission(java.lang.String);
+ public int checkUriPermission(android.net.Uri, int, int, int);
+ public int checkUriPermission(android.net.Uri, int, int, int, android.os.IBinder);
+ public int checkUriPermission(android.net.Uri, java.lang.String, java.lang.String, int, int, int);
+ public void clearWallpaper();
+ public android.content.Context createApplicationContext(android.content.pm.ApplicationInfo, int);
+ public android.content.Context createConfigurationContext(android.content.res.Configuration);
+ public android.content.Context createContextForSplit(java.lang.String);
+ public android.content.Context createCredentialProtectedStorageContext();
+ public android.content.Context createDeviceProtectedStorageContext();
+ public android.content.Context createDisplayContext(android.view.Display);
+ public android.content.Context createPackageContext(java.lang.String, int);
+ public android.content.Context createPackageContextAsUser(java.lang.String, int, android.os.UserHandle);
+ public java.lang.String[] databaseList();
+ public boolean deleteDatabase(java.lang.String);
+ public boolean deleteFile(java.lang.String);
+ public boolean deleteSharedPreferences(java.lang.String);
+ public void enforceCallingOrSelfPermission(java.lang.String, java.lang.String);
+ public void enforceCallingOrSelfUriPermission(android.net.Uri, int, java.lang.String);
+ public void enforceCallingPermission(java.lang.String, java.lang.String);
+ public void enforceCallingUriPermission(android.net.Uri, int, java.lang.String);
+ public void enforcePermission(java.lang.String, int, int, java.lang.String);
+ public void enforceUriPermission(android.net.Uri, int, int, int, java.lang.String);
+ public void enforceUriPermission(android.net.Uri, java.lang.String, java.lang.String, int, int, int, java.lang.String);
+ public java.lang.String[] fileList();
+ public android.os.IBinder getActivityToken();
+ public android.content.Context getApplicationContext();
+ public android.content.pm.ApplicationInfo getApplicationInfo();
+ public android.content.res.AssetManager getAssets();
+ public android.view.autofill.AutofillManager$AutofillClient getAutofillClient();
+ public java.lang.String getBasePackageName();
+ public java.io.File getCacheDir();
+ public java.lang.ClassLoader getClassLoader();
+ public java.io.File getCodeCacheDir();
+ public android.content.ContentResolver getContentResolver();
+ public java.io.File getDataDir();
+ public java.io.File getDatabasePath(java.lang.String);
+ public java.io.File getDir(java.lang.String, int);
+ public android.view.Display getDisplay();
+ public android.view.DisplayAdjustments getDisplayAdjustments(int);
+ public java.io.File getExternalCacheDir();
+ public java.io.File[] getExternalCacheDirs();
+ public java.io.File getExternalFilesDir(java.lang.String);
+ public java.io.File[] getExternalFilesDirs(java.lang.String);
+ public java.io.File[] getExternalMediaDirs();
+ public java.io.File getFileStreamPath(java.lang.String);
+ public java.io.File getFilesDir();
+ public android.app.IApplicationThread getIApplicationThread();
+ public java.util.concurrent.Executor getMainExecutor();
+ public android.os.Looper getMainLooper();
+ public android.os.Handler getMainThreadHandler();
+ public java.io.File getNoBackupFilesDir();
+ public java.io.File getObbDir();
+ public java.io.File[] getObbDirs();
+ public java.lang.String getOpPackageName();
+ public java.lang.String getPackageCodePath();
+ public android.content.pm.PackageManager getPackageManager();
+ public java.lang.String getPackageName();
+ public java.lang.String getPackageResourcePath();
+ public java.io.File getPreloadsFileCache();
+ public android.content.res.Resources getResources();
+ public android.app.IServiceConnection getServiceDispatcher(android.content.ServiceConnection, android.os.Handler, int);
+ public android.content.SharedPreferences getSharedPreferences(java.lang.String, int);
+ public android.content.SharedPreferences getSharedPreferences(java.io.File, int);
+ public java.io.File getSharedPreferencesPath(java.lang.String);
+ public java.lang.Object getSystemService(java.lang.String);
+ public java.lang.String getSystemServiceName(java.lang.Class);
+ public android.content.res.Resources$Theme getTheme();
+ public int getThemeResId();
+ public android.os.UserHandle getUser();
+ public int getUserId();
+ public android.graphics.drawable.Drawable getWallpaper();
+ public int getWallpaperDesiredMinimumHeight();
+ public int getWallpaperDesiredMinimumWidth();
+ public void grantUriPermission(java.lang.String, android.net.Uri, int);
+ public boolean isAutofillCompatibilityEnabled();
+ public boolean isCredentialProtectedStorage();
+ public boolean isDeviceProtectedStorage();
+ public boolean isRestricted();
+ public boolean moveDatabaseFrom(android.content.Context, java.lang.String);
+ public boolean moveSharedPreferencesFrom(android.content.Context, java.lang.String);
+ public java.io.FileInputStream openFileInput(java.lang.String);
+ public java.io.FileOutputStream openFileOutput(java.lang.String, int);
+ public android.database.sqlite.SQLiteDatabase openOrCreateDatabase(java.lang.String, int, android.database.sqlite.SQLiteDatabase$CursorFactory);
+ public android.database.sqlite.SQLiteDatabase openOrCreateDatabase(java.lang.String, int, android.database.sqlite.SQLiteDatabase$CursorFactory, android.database.DatabaseErrorHandler);
+ public android.graphics.drawable.Drawable peekWallpaper();
+ public android.content.Intent registerReceiver(android.content.BroadcastReceiver, android.content.IntentFilter);
+ public android.content.Intent registerReceiver(android.content.BroadcastReceiver, android.content.IntentFilter, int);
+ public android.content.Intent registerReceiver(android.content.BroadcastReceiver, android.content.IntentFilter, java.lang.String, android.os.Handler);
+ public android.content.Intent registerReceiver(android.content.BroadcastReceiver, android.content.IntentFilter, java.lang.String, android.os.Handler, int);
+ public android.content.Intent registerReceiverAsUser(android.content.BroadcastReceiver, android.os.UserHandle, android.content.IntentFilter, java.lang.String, android.os.Handler);
+ public void reloadSharedPreferences();
+ public void removeStickyBroadcast(android.content.Intent);
+ public void removeStickyBroadcastAsUser(android.content.Intent, android.os.UserHandle);
+ public void revokeUriPermission(android.net.Uri, int);
+ public void revokeUriPermission(java.lang.String, android.net.Uri, int);
+ public void sendBroadcast(android.content.Intent);
+ public void sendBroadcast(android.content.Intent, java.lang.String);
+ public void sendBroadcast(android.content.Intent, java.lang.String, android.os.Bundle);
+ public void sendBroadcast(android.content.Intent, java.lang.String, int);
+ public void sendBroadcastAsUser(android.content.Intent, android.os.UserHandle);
+ public void sendBroadcastAsUser(android.content.Intent, android.os.UserHandle, java.lang.String);
+ public void sendBroadcastAsUser(android.content.Intent, android.os.UserHandle, java.lang.String, android.os.Bundle);
+ public void sendBroadcastAsUser(android.content.Intent, android.os.UserHandle, java.lang.String, int);
+ public void sendBroadcastAsUserMultiplePermissions(android.content.Intent, android.os.UserHandle, java.lang.String[]);
+ public void sendBroadcastMultiplePermissions(android.content.Intent, java.lang.String[]);
+ public void sendOrderedBroadcast(android.content.Intent, java.lang.String);
+ public void sendOrderedBroadcast(android.content.Intent, java.lang.String, android.content.BroadcastReceiver, android.os.Handler, int, java.lang.String, android.os.Bundle);
+ public void sendOrderedBroadcast(android.content.Intent, java.lang.String, android.os.Bundle, android.content.BroadcastReceiver, android.os.Handler, int, java.lang.String, android.os.Bundle);
+ public void sendOrderedBroadcast(android.content.Intent, java.lang.String, int, android.content.BroadcastReceiver, android.os.Handler, int, java.lang.String, android.os.Bundle);
+ public void sendOrderedBroadcastAsUser(android.content.Intent, android.os.UserHandle, java.lang.String, android.content.BroadcastReceiver, android.os.Handler, int, java.lang.String, android.os.Bundle);
+ public void sendOrderedBroadcastAsUser(android.content.Intent, android.os.UserHandle, java.lang.String, int, android.content.BroadcastReceiver, android.os.Handler, int, java.lang.String, android.os.Bundle);
+ public void sendOrderedBroadcastAsUser(android.content.Intent, android.os.UserHandle, java.lang.String, int, android.os.Bundle, android.content.BroadcastReceiver, android.os.Handler, int, java.lang.String, android.os.Bundle);
+ public void sendStickyBroadcast(android.content.Intent);
+ public void sendStickyBroadcastAsUser(android.content.Intent, android.os.UserHandle);
+ public void sendStickyBroadcastAsUser(android.content.Intent, android.os.UserHandle, android.os.Bundle);
+ public void sendStickyOrderedBroadcast(android.content.Intent, android.content.BroadcastReceiver, android.os.Handler, int, java.lang.String, android.os.Bundle);
+ public void sendStickyOrderedBroadcastAsUser(android.content.Intent, android.os.UserHandle, android.content.BroadcastReceiver, android.os.Handler, int, java.lang.String, android.os.Bundle);
+ public void setAutofillClient(android.view.autofill.AutofillManager$AutofillClient);
+ public void setAutofillCompatibilityEnabled(boolean);
+ public void setTheme(int);
+ public void setWallpaper(android.graphics.Bitmap);
+ public void setWallpaper(java.io.InputStream);
+ public void startActivities(android.content.Intent[]);
+ public void startActivities(android.content.Intent[], android.os.Bundle);
+ public int startActivitiesAsUser(android.content.Intent[], android.os.Bundle, android.os.UserHandle);
+ public void startActivity(android.content.Intent);
+ public void startActivity(android.content.Intent, android.os.Bundle);
+ public void startActivityAsUser(android.content.Intent, android.os.UserHandle);
+ public void startActivityAsUser(android.content.Intent, android.os.Bundle, android.os.UserHandle);
+ public android.content.ComponentName startForegroundService(android.content.Intent);
+ public android.content.ComponentName startForegroundServiceAsUser(android.content.Intent, android.os.UserHandle);
+ public boolean startInstrumentation(android.content.ComponentName, java.lang.String, android.os.Bundle);
+ public void startIntentSender(android.content.IntentSender, android.content.Intent, int, int, int);
+ public void startIntentSender(android.content.IntentSender, android.content.Intent, int, int, int, android.os.Bundle);
+ public android.content.ComponentName startService(android.content.Intent);
+ public android.content.ComponentName startServiceAsUser(android.content.Intent, android.os.UserHandle);
+ public boolean stopService(android.content.Intent);
+ public boolean stopServiceAsUser(android.content.Intent, android.os.UserHandle);
+ public void unbindService(android.content.ServiceConnection);
+ public void unregisterReceiver(android.content.BroadcastReceiver);
+ public void updateDisplay(int);
+
+
+}
+
+-keep class android.app.Dialog {
+ <init>(android.content.Context);
+ <init>(android.content.Context, int);
+ <init>(android.content.Context, boolean, android.os.Message);
+ <init>(android.content.Context, boolean, android.content.DialogInterface$OnCancelListener);
+
+ public void addContentView(android.view.View, android.view.ViewGroup$LayoutParams);
+ public void cancel();
+ public void closeOptionsMenu();
+ public void create();
+ public void dismiss();
+ public boolean dispatchGenericMotionEvent(android.view.MotionEvent);
+ public boolean dispatchKeyEvent(android.view.KeyEvent);
+ public boolean dispatchKeyShortcutEvent(android.view.KeyEvent);
+ public boolean dispatchPopulateAccessibilityEvent(android.view.accessibility.AccessibilityEvent);
+ public boolean dispatchTouchEvent(android.view.MotionEvent);
+ public boolean dispatchTrackballEvent(android.view.MotionEvent);
+ public android.view.View findViewById(int);
+ public android.app.ActionBar getActionBar();
+ public android.content.Context getContext();
+ public android.view.View getCurrentFocus();
+ public android.view.LayoutInflater getLayoutInflater();
+ public android.app.Activity getOwnerActivity();
+ public android.view.SearchEvent getSearchEvent();
+ public int getVolumeControlStream();
+ public android.view.Window getWindow();
+ public void hide();
+ public void invalidateOptionsMenu();
+ public boolean isShowing();
+ public void onActionModeFinished(android.view.ActionMode);
+ public void onActionModeStarted(android.view.ActionMode);
+ public void onAttachedToWindow();
+ public void onBackPressed();
+ public void onContentChanged();
+ public boolean onContextItemSelected(android.view.MenuItem);
+ public void onContextMenuClosed(android.view.Menu);
+ protected void onCreate(android.os.Bundle);
+ public void onCreateContextMenu(android.view.ContextMenu, android.view.View, android.view.ContextMenu$ContextMenuInfo);
+ public boolean onCreateOptionsMenu(android.view.Menu);
+ public boolean onCreatePanelMenu(int, android.view.Menu);
+ public android.view.View onCreatePanelView(int);
+ public void onDetachedFromWindow();
+ public boolean onGenericMotionEvent(android.view.MotionEvent);
+ public boolean onKeyDown(int, android.view.KeyEvent);
+ public boolean onKeyLongPress(int, android.view.KeyEvent);
+ public boolean onKeyMultiple(int, int, android.view.KeyEvent);
+ public boolean onKeyShortcut(int, android.view.KeyEvent);
+ public boolean onKeyUp(int, android.view.KeyEvent);
+ public boolean onMenuItemSelected(int, android.view.MenuItem);
+ public boolean onMenuOpened(int, android.view.Menu);
+ public boolean onOptionsItemSelected(android.view.MenuItem);
+ public void onOptionsMenuClosed(android.view.Menu);
+ public void onPanelClosed(int, android.view.Menu);
+ public boolean onPrepareOptionsMenu(android.view.Menu);
+ public boolean onPreparePanel(int, android.view.View, android.view.Menu);
+ public void onRestoreInstanceState(android.os.Bundle);
+ public android.os.Bundle onSaveInstanceState();
+ public boolean onSearchRequested(android.view.SearchEvent);
+ public boolean onSearchRequested();
+ protected void onStart();
+ protected void onStop();
+ public boolean onTouchEvent(android.view.MotionEvent);
+ public boolean onTrackballEvent(android.view.MotionEvent);
+ public void onWindowAttributesChanged(android.view.WindowManager$LayoutParams);
+ public void onWindowDismissed(boolean, boolean);
+ public void onWindowFocusChanged(boolean);
+ public android.view.ActionMode onWindowStartingActionMode(android.view.ActionMode$Callback);
+ public android.view.ActionMode onWindowStartingActionMode(android.view.ActionMode$Callback, int);
+ public void openContextMenu(android.view.View);
+ public void openOptionsMenu();
+ public void registerForContextMenu(android.view.View);
+ public boolean requestWindowFeature(int);
+ public android.view.View requireViewById(int);
+ public void setCancelMessage(android.os.Message);
+ public void setCancelable(boolean);
+ public void setCanceledOnTouchOutside(boolean);
+ public void setContentView(int);
+ public void setContentView(android.view.View);
+ public void setContentView(android.view.View, android.view.ViewGroup$LayoutParams);
+ public void setDismissMessage(android.os.Message);
+ public void setFeatureDrawable(int, android.graphics.drawable.Drawable);
+ public void setFeatureDrawableAlpha(int, int);
+ public void setFeatureDrawableResource(int, int);
+ public void setFeatureDrawableUri(int, android.net.Uri);
+ public void setOnCancelListener(android.content.DialogInterface$OnCancelListener);
+ public void setOnDismissListener(android.content.DialogInterface$OnDismissListener);
+ public void setOnKeyListener(android.content.DialogInterface$OnKeyListener);
+ public void setOnShowListener(android.content.DialogInterface$OnShowListener);
+ public void setOwnerActivity(android.app.Activity);
+ public void setTitle(java.lang.CharSequence);
+ public void setTitle(int);
+ public void setVolumeControlStream(int);
+ public void show();
+ public boolean takeCancelAndDismissListeners(java.lang.String, android.content.DialogInterface$OnCancelListener, android.content.DialogInterface$OnDismissListener);
+ public void takeKeyEvents(boolean);
+ public void unregisterForContextMenu(android.view.View);
+
+
+ protected boolean mCancelable;
+}
+
+-keep class android.app.Fragment {
+ <init>();
+
+ public void dump(java.lang.String, java.io.FileDescriptor, java.io.PrintWriter, java.lang.String[]);
+ public boolean equals(java.lang.Object);
+ public android.app.Activity getActivity();
+ public boolean getAllowEnterTransitionOverlap();
+ public boolean getAllowReturnTransitionOverlap();
+ public android.os.Bundle getArguments();
+ public android.app.FragmentManager getChildFragmentManager();
+ public android.content.Context getContext();
+ public android.transition.Transition getEnterTransition();
+ public android.transition.Transition getExitTransition();
+ public android.app.FragmentManager getFragmentManager();
+ public java.lang.Object getHost();
+ public int getId();
+ public android.view.LayoutInflater getLayoutInflater();
+ public android.app.LoaderManager getLoaderManager();
+ public android.app.Fragment getParentFragment();
+ public android.transition.Transition getReenterTransition();
+ public android.content.res.Resources getResources();
+ public boolean getRetainInstance();
+ public android.transition.Transition getReturnTransition();
+ public android.transition.Transition getSharedElementEnterTransition();
+ public android.transition.Transition getSharedElementReturnTransition();
+ public java.lang.String getString(int);
+ public java.lang.String getString(int, java.lang.Object[]);
+ public java.lang.String getTag();
+ public android.app.Fragment getTargetFragment();
+ public int getTargetRequestCode();
+ public java.lang.CharSequence getText(int);
+ public boolean getUserVisibleHint();
+ public android.view.View getView();
+ public int hashCode();
+ public static android.app.Fragment instantiate(android.content.Context, java.lang.String);
+ public static android.app.Fragment instantiate(android.content.Context, java.lang.String, android.os.Bundle);
+ public boolean isAdded();
+ public boolean isDetached();
+ public boolean isHidden();
+ public boolean isInLayout();
+ public boolean isRemoving();
+ public boolean isResumed();
+ public boolean isStateSaved();
+ public boolean isVisible();
+ public void onActivityCreated(android.os.Bundle);
+ public void onActivityResult(int, int, android.content.Intent);
+ public void onAttach(android.content.Context);
+ public void onAttach(android.app.Activity);
+ public void onAttachFragment(android.app.Fragment);
+ public void onConfigurationChanged(android.content.res.Configuration);
+ public boolean onContextItemSelected(android.view.MenuItem);
+ public void onCreate(android.os.Bundle);
+ public android.animation.Animator onCreateAnimator(int, boolean, int);
+ public void onCreateContextMenu(android.view.ContextMenu, android.view.View, android.view.ContextMenu$ContextMenuInfo);
+ public void onCreateOptionsMenu(android.view.Menu, android.view.MenuInflater);
+ public android.view.View onCreateView(android.view.LayoutInflater, android.view.ViewGroup, android.os.Bundle);
+ public void onDestroy();
+ public void onDestroyOptionsMenu();
+ public void onDestroyView();
+ public void onDetach();
+ public android.view.LayoutInflater onGetLayoutInflater(android.os.Bundle);
+ public void onHiddenChanged(boolean);
+ public void onInflate(android.util.AttributeSet, android.os.Bundle);
+ public void onInflate(android.content.Context, android.util.AttributeSet, android.os.Bundle);
+ public void onInflate(android.app.Activity, android.util.AttributeSet, android.os.Bundle);
+ public void onLowMemory();
+ public void onMultiWindowModeChanged(boolean, android.content.res.Configuration);
+ public void onMultiWindowModeChanged(boolean);
+ public boolean onOptionsItemSelected(android.view.MenuItem);
+ public void onOptionsMenuClosed(android.view.Menu);
+ public void onPause();
+ public void onPictureInPictureModeChanged(boolean, android.content.res.Configuration);
+ public void onPictureInPictureModeChanged(boolean);
+ public void onPrepareOptionsMenu(android.view.Menu);
+ public void onRequestPermissionsResult(int, java.lang.String[], int[]);
+ public void onResume();
+ public void onSaveInstanceState(android.os.Bundle);
+ public void onStart();
+ public void onStop();
+ public void onTrimMemory(int);
+ public void onViewCreated(android.view.View, android.os.Bundle);
+ public void onViewStateRestored(android.os.Bundle);
+ public void postponeEnterTransition();
+ public void registerForContextMenu(android.view.View);
+ public void requestPermissions(java.lang.String[], int);
+ public void setAllowEnterTransitionOverlap(boolean);
+ public void setAllowReturnTransitionOverlap(boolean);
+ public void setArguments(android.os.Bundle);
+ public void setEnterSharedElementCallback(android.app.SharedElementCallback);
+ public void setEnterTransition(android.transition.Transition);
+ public void setExitSharedElementCallback(android.app.SharedElementCallback);
+ public void setExitTransition(android.transition.Transition);
+ public void setHasOptionsMenu(boolean);
+ public void setInitialSavedState(android.app.Fragment$SavedState);
+ public void setMenuVisibility(boolean);
+ public void setReenterTransition(android.transition.Transition);
+ public void setRetainInstance(boolean);
+ public void setReturnTransition(android.transition.Transition);
+ public void setSharedElementEnterTransition(android.transition.Transition);
+ public void setSharedElementReturnTransition(android.transition.Transition);
+ public void setTargetFragment(android.app.Fragment, int);
+ public void setUserVisibleHint(boolean);
+ public boolean shouldShowRequestPermissionRationale(java.lang.String);
+ public void startActivity(android.content.Intent);
+ public void startActivity(android.content.Intent, android.os.Bundle);
+ public void startActivityForResult(android.content.Intent, int);
+ public void startActivityForResult(android.content.Intent, int, android.os.Bundle);
+ public void startActivityForResultAsUser(android.content.Intent, int, android.os.Bundle, android.os.UserHandle);
+ public void startIntentSenderForResult(android.content.IntentSender, int, android.content.Intent, int, int, int, android.os.Bundle);
+ public void startPostponedEnterTransition();
+ public java.lang.String toString();
+ public void unregisterForContextMenu(android.view.View);
+
+
+}
+
+-keep class android.app.Fragment$SavedState {
+
+ public int describeContents();
+ public void writeToParcel(android.os.Parcel, int);
+
+
+ public static android.os.Parcelable$ClassLoaderCreator CREATOR;
+}
+
+-keep class android.app.FragmentContainer {
+ <init>();
+
+ public android.app.Fragment instantiate(android.content.Context, java.lang.String, android.os.Bundle);
+ public abstract android.view.View onFindViewById(int);
+ public abstract boolean onHasView();
+
+
+}
+
+-keep class android.app.FragmentHostCallback {
+ <init>(android.content.Context, android.os.Handler, int);
+
+ public void onAttachFragment(android.app.Fragment);
+ public void onDump(java.lang.String, java.io.FileDescriptor, java.io.PrintWriter, java.lang.String[]);
+ public android.view.View onFindViewById(int);
+ public abstract java.lang.Object onGetHost();
+ public android.view.LayoutInflater onGetLayoutInflater();
+ public int onGetWindowAnimations();
+ public boolean onHasView();
+ public boolean onHasWindowAnimations();
+ public void onInvalidateOptionsMenu();
+ public void onRequestPermissionsFromFragment(android.app.Fragment, java.lang.String[], int);
+ public boolean onShouldSaveFragmentState(android.app.Fragment);
+ public void onStartActivityAsUserFromFragment(android.app.Fragment, android.content.Intent, int, android.os.Bundle, android.os.UserHandle);
+ public void onStartActivityFromFragment(android.app.Fragment, android.content.Intent, int, android.os.Bundle);
+ public void onStartIntentSenderFromFragment(android.app.Fragment, android.content.IntentSender, int, android.content.Intent, int, int, int, android.os.Bundle);
+ public boolean onUseFragmentManagerInflaterFactory();
+
+
+}
+
+-keep class android.app.FragmentManager {
+ <init>();
+
+ public abstract void addOnBackStackChangedListener(android.app.FragmentManager$OnBackStackChangedListener);
+ public abstract android.app.FragmentTransaction beginTransaction();
+ public abstract void dump(java.lang.String, java.io.FileDescriptor, java.io.PrintWriter, java.lang.String[]);
+ public static void enableDebugLogging(boolean);
+ public abstract boolean executePendingTransactions();
+ public abstract android.app.Fragment findFragmentById(int);
+ public abstract android.app.Fragment findFragmentByTag(java.lang.String);
+ public abstract android.app.FragmentManager$BackStackEntry getBackStackEntryAt(int);
+ public abstract int getBackStackEntryCount();
+ public abstract android.app.Fragment getFragment(android.os.Bundle, java.lang.String);
+ public abstract java.util.List getFragments();
+ public abstract android.app.Fragment getPrimaryNavigationFragment();
+ public void invalidateOptionsMenu();
+ public abstract boolean isDestroyed();
+ public abstract boolean isStateSaved();
+ public android.app.FragmentTransaction openTransaction();
+ public abstract void popBackStack();
+ public abstract void popBackStack(java.lang.String, int);
+ public abstract void popBackStack(int, int);
+ public abstract boolean popBackStackImmediate();
+ public abstract boolean popBackStackImmediate(java.lang.String, int);
+ public abstract boolean popBackStackImmediate(int, int);
+ public abstract void putFragment(android.os.Bundle, java.lang.String, android.app.Fragment);
+ public abstract void registerFragmentLifecycleCallbacks(android.app.FragmentManager$FragmentLifecycleCallbacks, boolean);
+ public abstract void removeOnBackStackChangedListener(android.app.FragmentManager$OnBackStackChangedListener);
+ public abstract android.app.Fragment$SavedState saveFragmentInstanceState(android.app.Fragment);
+ public abstract void unregisterFragmentLifecycleCallbacks(android.app.FragmentManager$FragmentLifecycleCallbacks);
+
+
+ public static int POP_BACK_STACK_INCLUSIVE;
+}
+
+-keep class android.app.FragmentManager$BackStackEntry {
+
+ public abstract java.lang.CharSequence getBreadCrumbShortTitle();
+ public abstract int getBreadCrumbShortTitleRes();
+ public abstract java.lang.CharSequence getBreadCrumbTitle();
+ public abstract int getBreadCrumbTitleRes();
+ public abstract int getId();
+ public abstract java.lang.String getName();
+
+
+}
+
+-keep class android.app.FragmentManager$FragmentLifecycleCallbacks {
+ <init>();
+
+ public void onFragmentActivityCreated(android.app.FragmentManager, android.app.Fragment, android.os.Bundle);
+ public void onFragmentAttached(android.app.FragmentManager, android.app.Fragment, android.content.Context);
+ public void onFragmentCreated(android.app.FragmentManager, android.app.Fragment, android.os.Bundle);
+ public void onFragmentDestroyed(android.app.FragmentManager, android.app.Fragment);
+ public void onFragmentDetached(android.app.FragmentManager, android.app.Fragment);
+ public void onFragmentPaused(android.app.FragmentManager, android.app.Fragment);
+ public void onFragmentPreAttached(android.app.FragmentManager, android.app.Fragment, android.content.Context);
+ public void onFragmentPreCreated(android.app.FragmentManager, android.app.Fragment, android.os.Bundle);
+ public void onFragmentResumed(android.app.FragmentManager, android.app.Fragment);
+ public void onFragmentSaveInstanceState(android.app.FragmentManager, android.app.Fragment, android.os.Bundle);
+ public void onFragmentStarted(android.app.FragmentManager, android.app.Fragment);
+ public void onFragmentStopped(android.app.FragmentManager, android.app.Fragment);
+ public void onFragmentViewCreated(android.app.FragmentManager, android.app.Fragment, android.view.View, android.os.Bundle);
+ public void onFragmentViewDestroyed(android.app.FragmentManager, android.app.Fragment);
+
+
+}
+
+-keep class android.app.FragmentManager$OnBackStackChangedListener {
+
+ public abstract void onBackStackChanged();
+
+
+}
+
+-keep class android.app.FragmentTransaction {
+ <init>();
+
+ public abstract android.app.FragmentTransaction add(android.app.Fragment, java.lang.String);
+ public abstract android.app.FragmentTransaction add(int, android.app.Fragment);
+ public abstract android.app.FragmentTransaction add(int, android.app.Fragment, java.lang.String);
+ public abstract android.app.FragmentTransaction addSharedElement(android.view.View, java.lang.String);
+ public abstract android.app.FragmentTransaction addToBackStack(java.lang.String);
+ public abstract android.app.FragmentTransaction attach(android.app.Fragment);
+ public abstract int commit();
+ public abstract int commitAllowingStateLoss();
+ public abstract void commitNow();
+ public abstract void commitNowAllowingStateLoss();
+ public abstract android.app.FragmentTransaction detach(android.app.Fragment);
+ public abstract android.app.FragmentTransaction disallowAddToBackStack();
+ public abstract android.app.FragmentTransaction hide(android.app.Fragment);
+ public abstract boolean isAddToBackStackAllowed();
+ public abstract boolean isEmpty();
+ public abstract android.app.FragmentTransaction remove(android.app.Fragment);
+ public abstract android.app.FragmentTransaction replace(int, android.app.Fragment);
+ public abstract android.app.FragmentTransaction replace(int, android.app.Fragment, java.lang.String);
+ public abstract android.app.FragmentTransaction runOnCommit(java.lang.Runnable);
+ public abstract android.app.FragmentTransaction setBreadCrumbShortTitle(int);
+ public abstract android.app.FragmentTransaction setBreadCrumbShortTitle(java.lang.CharSequence);
+ public abstract android.app.FragmentTransaction setBreadCrumbTitle(int);
+ public abstract android.app.FragmentTransaction setBreadCrumbTitle(java.lang.CharSequence);
+ public abstract android.app.FragmentTransaction setCustomAnimations(int, int);
+ public abstract android.app.FragmentTransaction setCustomAnimations(int, int, int, int);
+ public abstract android.app.FragmentTransaction setPrimaryNavigationFragment(android.app.Fragment);
+ public abstract android.app.FragmentTransaction setReorderingAllowed(boolean);
+ public abstract android.app.FragmentTransaction setTransition(int);
+ public abstract android.app.FragmentTransaction setTransitionStyle(int);
+ public abstract android.app.FragmentTransaction show(android.app.Fragment);
+
+
+ public static int TRANSIT_ENTER_MASK;
+ public static int TRANSIT_EXIT_MASK;
+ public static int TRANSIT_FRAGMENT_CLOSE;
+ public static int TRANSIT_FRAGMENT_FADE;
+ public static int TRANSIT_FRAGMENT_OPEN;
+ public static int TRANSIT_NONE;
+ public static int TRANSIT_UNSET;
+}
+
+-keep class android.app.GrantedUriPermission {
+ <init>(android.net.Uri, java.lang.String);
+
+ public int describeContents();
+ public java.lang.String toString();
+ public void writeToParcel(android.os.Parcel, int);
+
+
+ public static android.os.Parcelable$Creator CREATOR;
+ public java.lang.String packageName;
+ public android.net.Uri uri;
+}
+
+-keep class android.app.IActivityController {
+
+ public abstract boolean activityResuming(java.lang.String);
+ public abstract boolean activityStarting(android.content.Intent, java.lang.String);
+ public abstract boolean appCrashed(java.lang.String, int, java.lang.String, java.lang.String, long, java.lang.String);
+ public abstract int appEarlyNotResponding(java.lang.String, int, java.lang.String);
+ public abstract int appNotResponding(java.lang.String, int, java.lang.String);
+ public abstract int systemNotResponding(java.lang.String);
+
+
+}
+
+-keep class android.app.IActivityManager {
+
+ public abstract void activityDestroyed(android.os.IBinder);
+ public abstract void activityIdle(android.os.IBinder, android.content.res.Configuration, boolean);
+ public abstract void activityPaused(android.os.IBinder);
+ public abstract void activityRelaunched(android.os.IBinder);
+ public abstract void activityResumed(android.os.IBinder);
+ public abstract void activitySlept(android.os.IBinder);
+ public abstract void activityStopped(android.os.IBinder, android.os.Bundle, android.os.PersistableBundle, java.lang.CharSequence);
+ public abstract int addAppTask(android.os.IBinder, android.content.Intent, android.app.ActivityManager$TaskDescription, android.graphics.Bitmap);
+ public abstract void addInstrumentationResults(android.app.IApplicationThread, android.os.Bundle);
+ public abstract void addPackageDependency(java.lang.String);
+ public abstract void alwaysShowUnsupportedCompileSdkWarning(android.content.ComponentName);
+ public abstract void appNotRespondingViaProvider(android.os.IBinder);
+ public abstract void attachApplication(android.app.IApplicationThread, long);
+ public abstract void backgroundWhitelistUid(int);
+ public abstract void backupAgentCreated(java.lang.String, android.os.IBinder);
+ public abstract boolean bindBackupAgent(java.lang.String, int, int);
+ public abstract int bindService(android.app.IApplicationThread, android.os.IBinder, android.content.Intent, java.lang.String, android.app.IServiceConnection, int, java.lang.String, int);
+ public abstract void bootAnimationComplete();
+ public abstract int broadcastIntent(android.app.IApplicationThread, android.content.Intent, java.lang.String, android.content.IIntentReceiver, int, java.lang.String, android.os.Bundle, java.lang.String[], int, android.os.Bundle, boolean, boolean, int);
+ public abstract void cancelIntentSender(android.content.IIntentSender);
+ public abstract void cancelRecentsAnimation(boolean);
+ public abstract void cancelTaskWindowTransition(int);
+ public abstract int checkGrantUriPermission(int, java.lang.String, android.net.Uri, int, int);
+ public abstract int checkPermission(java.lang.String, int, int);
+ public abstract int checkPermissionWithToken(java.lang.String, int, int, android.os.IBinder);
+ public abstract int checkUriPermission(android.net.Uri, int, int, int, int, android.os.IBinder);
+ public abstract boolean clearApplicationUserData(java.lang.String, boolean, android.content.pm.IPackageDataObserver, int);
+ public abstract void clearGrantedUriPermissions(java.lang.String, int);
+ public abstract void clearPendingBackup();
+ public abstract void closeSystemDialogs(java.lang.String);
+ public abstract boolean convertFromTranslucent(android.os.IBinder);
+ public abstract boolean convertToTranslucent(android.os.IBinder, android.os.Bundle);
+ public abstract void crashApplication(int, int, java.lang.String, int, java.lang.String);
+ public abstract int createStackOnDisplay(int);
+ public abstract void dismissKeyguard(android.os.IBinder, com.android.internal.policy.IKeyguardDismissCallback, java.lang.CharSequence);
+ public abstract void dismissPip(boolean, int);
+ public abstract void dismissSplitScreenMode(boolean);
+ public abstract boolean dumpHeap(java.lang.String, int, boolean, boolean, boolean, java.lang.String, android.os.ParcelFileDescriptor);
+ public abstract void dumpHeapFinished(java.lang.String);
+ public abstract boolean enterPictureInPictureMode(android.os.IBinder, android.app.PictureInPictureParams);
+ public abstract void enterSafeMode();
+ public abstract void exitFreeformMode(android.os.IBinder);
+ public abstract boolean finishActivity(android.os.IBinder, int, android.content.Intent, int);
+ public abstract boolean finishActivityAffinity(android.os.IBinder);
+ public abstract void finishHeavyWeightApp();
+ public abstract void finishInstrumentation(android.app.IApplicationThread, int, android.os.Bundle);
+ public abstract void finishReceiver(android.os.IBinder, int, java.lang.String, android.os.Bundle, boolean, int);
+ public abstract void finishSubActivity(android.os.IBinder, java.lang.String, int);
+ public abstract void finishVoiceTask(android.service.voice.IVoiceInteractionSession);
+ public abstract void forceStopPackage(java.lang.String, int);
+ public abstract android.content.ComponentName getActivityClassForToken(android.os.IBinder);
+ public abstract int getActivityDisplayId(android.os.IBinder);
+ public abstract android.os.Bundle getActivityOptions(android.os.IBinder);
+ public abstract java.util.List getAllStackInfos();
+ public abstract android.graphics.Point getAppTaskThumbnailSize();
+ public abstract java.util.List getAppTasks(java.lang.String);
+ public abstract android.os.Bundle getAssistContextExtras(int);
+ public abstract android.content.ComponentName getCallingActivity(android.os.IBinder);
+ public abstract java.lang.String getCallingPackage(android.os.IBinder);
+ public abstract android.content.res.Configuration getConfiguration();
+ public abstract android.app.ContentProviderHolder getContentProvider(android.app.IApplicationThread, java.lang.String, int, boolean);
+ public abstract android.app.ContentProviderHolder getContentProviderExternal(java.lang.String, int, android.os.IBinder);
+ public abstract android.content.pm.UserInfo getCurrentUser();
+ public abstract android.content.pm.ConfigurationInfo getDeviceConfigurationInfo();
+ public abstract java.util.List getFilteredTasks(int, int, int);
+ public abstract android.app.ActivityManager$StackInfo getFocusedStackInfo();
+ public abstract int getFrontActivityScreenCompatMode();
+ public abstract android.content.pm.ParceledListSlice getGrantedUriPermissions(java.lang.String, int);
+ public abstract android.content.Intent getIntentForIntentSender(android.content.IIntentSender);
+ public abstract android.content.IIntentSender getIntentSender(int, java.lang.String, android.os.IBinder, java.lang.String, int, android.content.Intent[], java.lang.String[], int, android.os.Bundle, int);
+ public abstract int getLastResumedActivityUserId();
+ public abstract java.lang.String getLaunchedFromPackage(android.os.IBinder);
+ public abstract int getLaunchedFromUid(android.os.IBinder);
+ public abstract int getLockTaskModeState();
+ public abstract int getMaxNumPictureInPictureActions(android.os.IBinder);
+ public abstract void getMemoryInfo(android.app.ActivityManager$MemoryInfo);
+ public abstract int getMemoryTrimLevel();
+ public abstract void getMyMemoryState(android.app.ActivityManager$RunningAppProcessInfo);
+ public abstract boolean getPackageAskScreenCompat(java.lang.String);
+ public abstract java.lang.String getPackageForIntentSender(android.content.IIntentSender);
+ public abstract java.lang.String getPackageForToken(android.os.IBinder);
+ public abstract int getPackageProcessState(java.lang.String, java.lang.String);
+ public abstract int getPackageScreenCompatMode(java.lang.String);
+ public abstract android.content.pm.ParceledListSlice getPersistedUriPermissions(java.lang.String, boolean);
+ public abstract int getProcessLimit();
+ public abstract android.os.Debug$MemoryInfo[] getProcessMemoryInfo(int[]);
+ public abstract long[] getProcessPss(int[]);
+ public abstract java.util.List getProcessesInErrorState();
+ public abstract java.lang.String getProviderMimeType(android.net.Uri, int);
+ public abstract android.content.pm.ParceledListSlice getRecentTasks(int, int, int);
+ public abstract int getRequestedOrientation(android.os.IBinder);
+ public abstract java.util.List getRunningAppProcesses();
+ public abstract java.util.List getRunningExternalApplications();
+ public abstract android.app.PendingIntent getRunningServiceControlPanel(android.content.ComponentName);
+ public abstract int[] getRunningUserIds();
+ public abstract java.util.List getServices(int, int);
+ public abstract android.app.ActivityManager$StackInfo getStackInfo(int, int);
+ public abstract java.lang.String getTagForIntentSender(android.content.IIntentSender, java.lang.String);
+ public abstract android.graphics.Rect getTaskBounds(int);
+ public abstract android.app.ActivityManager$TaskDescription getTaskDescription(int);
+ public abstract android.graphics.Bitmap getTaskDescriptionIcon(java.lang.String, int);
+ public abstract int getTaskForActivity(android.os.IBinder, boolean);
+ public abstract android.app.ActivityManager$TaskSnapshot getTaskSnapshot(int, boolean);
+ public abstract java.util.List getTasks(int);
+ public abstract int getUidForIntentSender(android.content.IIntentSender);
+ public abstract int getUidProcessState(int, java.lang.String);
+ public abstract android.os.IBinder getUriPermissionOwnerForActivity(android.os.IBinder);
+ public abstract void grantUriPermission(android.app.IApplicationThread, java.lang.String, android.net.Uri, int, int);
+ public abstract void grantUriPermissionFromOwner(android.os.IBinder, int, java.lang.String, android.net.Uri, int, int, int);
+ public abstract void handleApplicationCrash(android.os.IBinder, android.app.ApplicationErrorReport$ParcelableCrashInfo);
+ public abstract void handleApplicationStrictModeViolation(android.os.IBinder, int, android.os.StrictMode$ViolationInfo);
+ public abstract boolean handleApplicationWtf(android.os.IBinder, java.lang.String, boolean, android.app.ApplicationErrorReport$ParcelableCrashInfo);
+ public abstract int handleIncomingUser(int, int, int, boolean, boolean, java.lang.String, java.lang.String);
+ public abstract void hang(android.os.IBinder, boolean);
+ public abstract long inputDispatchingTimedOut(int, boolean, java.lang.String);
+ public abstract boolean isAppForeground(int);
+ public abstract boolean isAppStartModeDisabled(int, java.lang.String);
+ public abstract boolean isAssistDataAllowedOnCurrentActivity();
+ public abstract boolean isBackgroundRestricted(java.lang.String);
+ public abstract boolean isImmersive(android.os.IBinder);
+ public abstract boolean isInLockTaskMode();
+ public abstract boolean isInMultiWindowMode(android.os.IBinder);
+ public abstract boolean isInPictureInPictureMode(android.os.IBinder);
+ public abstract boolean isIntentSenderAForegroundService(android.content.IIntentSender);
+ public abstract boolean isIntentSenderAnActivity(android.content.IIntentSender);
+ public abstract boolean isIntentSenderTargetedToPackage(android.content.IIntentSender);
+ public abstract boolean isRootVoiceInteraction(android.os.IBinder);
+ public abstract boolean isTopActivityImmersive();
+ public abstract boolean isTopOfTask(android.os.IBinder);
+ public abstract boolean isUidActive(int, java.lang.String);
+ public abstract boolean isUserAMonkey();
+ public abstract boolean isUserRunning(int, int);
+ public abstract boolean isVrModePackageEnabled(android.content.ComponentName);
+ public abstract void keyguardGoingAway(int);
+ public abstract void killAllBackgroundProcesses();
+ public abstract void killApplication(java.lang.String, int, int, java.lang.String);
+ public abstract void killApplicationProcess(java.lang.String, int);
+ public abstract void killBackgroundProcesses(java.lang.String, int);
+ public abstract void killPackageDependents(java.lang.String, int);
+ public abstract boolean killPids(int[], java.lang.String, boolean);
+ public abstract boolean killProcessesBelowForeground(java.lang.String);
+ public abstract void killUid(int, int, java.lang.String);
+ public abstract boolean launchAssistIntent(android.content.Intent, int, java.lang.String, int, android.os.Bundle);
+ public abstract void makePackageIdle(java.lang.String, int);
+ public abstract boolean moveActivityTaskToBack(android.os.IBinder, boolean);
+ public abstract void moveStackToDisplay(int, int);
+ public abstract void moveTaskBackwards(int);
+ public abstract void moveTaskToFront(int, int, android.os.Bundle);
+ public abstract void moveTaskToStack(int, int, boolean);
+ public abstract void moveTasksToFullscreenStack(int, boolean);
+ public abstract boolean moveTopActivityToPinnedStack(int, android.graphics.Rect);
+ public abstract boolean navigateUpTo(android.os.IBinder, android.content.Intent, int, android.content.Intent);
+ public abstract android.os.IBinder newUriPermissionOwner(java.lang.String);
+ public abstract void noteAlarmFinish(android.content.IIntentSender, android.os.WorkSource, int, java.lang.String);
+ public abstract void noteAlarmStart(android.content.IIntentSender, android.os.WorkSource, int, java.lang.String);
+ public abstract void noteWakeupAlarm(android.content.IIntentSender, android.os.WorkSource, int, java.lang.String, java.lang.String);
+ public abstract void notifyActivityDrawn(android.os.IBinder);
+ public abstract void notifyCleartextNetwork(int, byte[]);
+ public abstract void notifyEnterAnimationComplete(android.os.IBinder);
+ public abstract void notifyLaunchTaskBehindComplete(android.os.IBinder);
+ public abstract void notifyLockedProfile(int);
+ public abstract void notifyPinnedStackAnimationEnded();
+ public abstract void notifyPinnedStackAnimationStarted();
+ public abstract android.os.ParcelFileDescriptor openContentUri(java.lang.String);
+ public abstract void overridePendingTransition(android.os.IBinder, java.lang.String, int, int);
+ public abstract android.os.IBinder peekService(android.content.Intent, java.lang.String, java.lang.String);
+ public abstract void performIdleMaintenance();
+ public abstract void positionTaskInStack(int, int, int);
+ public abstract boolean profileControl(java.lang.String, int, boolean, android.app.ProfilerInfo, int);
+ public abstract void publishContentProviders(android.app.IApplicationThread, java.util.List);
+ public abstract void publishService(android.os.IBinder, android.content.Intent, android.os.IBinder);
+ public abstract boolean refContentProvider(android.os.IBinder, int, int);
+ public abstract void registerIntentSenderCancelListener(android.content.IIntentSender, com.android.internal.os.IResultReceiver);
+ public abstract void registerProcessObserver(android.app.IProcessObserver);
+ public abstract android.content.Intent registerReceiver(android.app.IApplicationThread, java.lang.String, android.content.IIntentReceiver, android.content.IntentFilter, java.lang.String, int, int);
+ public abstract void registerRemoteAnimationForNextActivityStart(java.lang.String, android.view.RemoteAnimationAdapter);
+ public abstract void registerRemoteAnimations(android.os.IBinder, android.view.RemoteAnimationDefinition);
+ public abstract void registerTaskStackListener(android.app.ITaskStackListener);
+ public abstract void registerUidObserver(android.app.IUidObserver, int, int, java.lang.String);
+ public abstract void registerUserSwitchObserver(android.app.IUserSwitchObserver, java.lang.String);
+ public abstract boolean releaseActivityInstance(android.os.IBinder);
+ public abstract void releasePersistableUriPermission(android.net.Uri, int, java.lang.String, int);
+ public abstract void releaseSomeActivities(android.app.IApplicationThread);
+ public abstract void removeContentProvider(android.os.IBinder, boolean);
+ public abstract void removeContentProviderExternal(java.lang.String, android.os.IBinder);
+ public abstract void removeStack(int);
+ public abstract void removeStacksInWindowingModes(int[]);
+ public abstract void removeStacksWithActivityTypes(int[]);
+ public abstract boolean removeTask(int);
+ public abstract void reportActivityFullyDrawn(android.os.IBinder, boolean);
+ public abstract void reportAssistContextExtras(android.os.IBinder, android.os.Bundle, android.app.assist.AssistStructure, android.app.assist.AssistContent, android.net.Uri);
+ public abstract void reportSizeConfigurations(android.os.IBinder, int[], int[], int[]);
+ public abstract boolean requestAssistContextExtras(int, android.app.IAssistDataReceiver, android.os.Bundle, android.os.IBinder, boolean, boolean);
+ public abstract boolean requestAutofillData(android.app.IAssistDataReceiver, android.os.Bundle, android.os.IBinder, int);
+ public abstract void requestBugReport(int);
+ public abstract void requestTelephonyBugReport(java.lang.String, java.lang.String);
+ public abstract void requestWifiBugReport(java.lang.String, java.lang.String);
+ public abstract void resizeDockedStack(android.graphics.Rect, android.graphics.Rect, android.graphics.Rect, android.graphics.Rect, android.graphics.Rect);
+ public abstract void resizePinnedStack(android.graphics.Rect, android.graphics.Rect);
+ public abstract void resizeStack(int, android.graphics.Rect, boolean, boolean, boolean, int);
+ public abstract void resizeTask(int, android.graphics.Rect, int);
+ public abstract void restart();
+ public abstract int restartUserInBackground(int);
+ public abstract void resumeAppSwitches();
+ public abstract void revokeUriPermission(android.app.IApplicationThread, java.lang.String, android.net.Uri, int, int);
+ public abstract void revokeUriPermissionFromOwner(android.os.IBinder, android.net.Uri, int, int);
+ public abstract void scheduleApplicationInfoChanged(java.util.List, int);
+ public abstract void sendIdleJobTrigger();
+ public abstract int sendIntentSender(android.content.IIntentSender, android.os.IBinder, int, android.content.Intent, java.lang.String, android.content.IIntentReceiver, java.lang.String, android.os.Bundle);
+ public abstract void serviceDoneExecuting(android.os.IBinder, int, int, int);
+ public abstract void setActivityController(android.app.IActivityController, boolean);
+ public abstract void setAgentApp(java.lang.String, java.lang.String);
+ public abstract void setAlwaysFinish(boolean);
+ public abstract void setDebugApp(java.lang.String, boolean, boolean);
+ public abstract void setDisablePreviewScreenshots(android.os.IBinder, boolean);
+ public abstract void setDumpHeapDebugLimit(java.lang.String, int, long, java.lang.String);
+ public abstract void setFocusedStack(int);
+ public abstract void setFocusedTask(int);
+ public abstract void setFrontActivityScreenCompatMode(int);
+ public abstract void setHasTopUi(boolean);
+ public abstract void setImmersive(android.os.IBinder, boolean);
+ public abstract void setLockScreenShown(boolean, boolean, int);
+ public abstract void setPackageAskScreenCompat(java.lang.String, boolean);
+ public abstract void setPackageScreenCompatMode(java.lang.String, int);
+ public abstract void setPersistentVrThread(int);
+ public abstract void setPictureInPictureParams(android.os.IBinder, android.app.PictureInPictureParams);
+ public abstract void setProcessImportant(android.os.IBinder, int, boolean, java.lang.String);
+ public abstract void setProcessLimit(int);
+ public abstract boolean setProcessMemoryTrimLevel(java.lang.String, int, int);
+ public abstract void setRenderThread(int);
+ public abstract void setRequestedOrientation(android.os.IBinder, int);
+ public abstract void setServiceForeground(android.content.ComponentName, android.os.IBinder, int, android.app.Notification, int);
+ public abstract void setShowWhenLocked(android.os.IBinder, boolean);
+ public abstract void setSplitScreenResizing(boolean);
+ public abstract void setTaskDescription(android.os.IBinder, android.app.ActivityManager$TaskDescription);
+ public abstract void setTaskResizeable(int, int);
+ public abstract void setTaskWindowingMode(int, int, boolean);
+ public abstract boolean setTaskWindowingModeSplitScreenPrimary(int, int, boolean, boolean, android.graphics.Rect, boolean);
+ public abstract void setTurnScreenOn(android.os.IBinder, boolean);
+ public abstract void setUserIsMonkey(boolean);
+ public abstract void setVoiceKeepAwake(android.service.voice.IVoiceInteractionSession, boolean);
+ public abstract int setVrMode(android.os.IBinder, boolean, android.content.ComponentName);
+ public abstract void setVrThread(int);
+ public abstract boolean shouldUpRecreateTask(android.os.IBinder, java.lang.String);
+ public abstract boolean showAssistFromActivity(android.os.IBinder, android.os.Bundle);
+ public abstract void showBootMessage(java.lang.CharSequence, boolean);
+ public abstract void showLockTaskEscapeMessage(android.os.IBinder);
+ public abstract void showWaitingForDebugger(android.app.IApplicationThread, boolean);
+ public abstract boolean shutdown(int);
+ public abstract void signalPersistentProcesses(int);
+ public abstract int startActivities(android.app.IApplicationThread, java.lang.String, android.content.Intent[], java.lang.String[], android.os.IBinder, android.os.Bundle, int);
+ public abstract int startActivity(android.app.IApplicationThread, java.lang.String, android.content.Intent, java.lang.String, android.os.IBinder, java.lang.String, int, int, android.app.ProfilerInfo, android.os.Bundle);
+ public abstract android.app.WaitResult startActivityAndWait(android.app.IApplicationThread, java.lang.String, android.content.Intent, java.lang.String, android.os.IBinder, java.lang.String, int, int, android.app.ProfilerInfo, android.os.Bundle, int);
+ public abstract int startActivityAsCaller(android.app.IApplicationThread, java.lang.String, android.content.Intent, java.lang.String, android.os.IBinder, java.lang.String, int, int, android.app.ProfilerInfo, android.os.Bundle, boolean, int);
+ public abstract int startActivityAsUser(android.app.IApplicationThread, java.lang.String, android.content.Intent, java.lang.String, android.os.IBinder, java.lang.String, int, int, android.app.ProfilerInfo, android.os.Bundle, int);
+ public abstract int startActivityFromRecents(int, android.os.Bundle);
+ public abstract int startActivityIntentSender(android.app.IApplicationThread, android.content.IIntentSender, android.os.IBinder, android.content.Intent, java.lang.String, android.os.IBinder, java.lang.String, int, int, int, android.os.Bundle);
+ public abstract int startActivityWithConfig(android.app.IApplicationThread, java.lang.String, android.content.Intent, java.lang.String, android.os.IBinder, java.lang.String, int, int, android.content.res.Configuration, android.os.Bundle, int);
+ public abstract int startAssistantActivity(java.lang.String, int, int, android.content.Intent, java.lang.String, android.os.Bundle, int);
+ public abstract boolean startBinderTracking();
+ public abstract void startConfirmDeviceCredentialIntent(android.content.Intent, android.os.Bundle);
+ public abstract void startInPlaceAnimationOnFrontMostApplication(android.os.Bundle);
+ public abstract boolean startInstrumentation(android.content.ComponentName, java.lang.String, int, android.os.Bundle, android.app.IInstrumentationWatcher, android.app.IUiAutomationConnection, int, java.lang.String);
+ public abstract void startLocalVoiceInteraction(android.os.IBinder, android.os.Bundle);
+ public abstract void startLockTaskModeByToken(android.os.IBinder);
+ public abstract boolean startNextMatchingActivity(android.os.IBinder, android.content.Intent, android.os.Bundle);
+ public abstract void startRecentsActivity(android.content.Intent, android.app.IAssistDataReceiver, android.view.IRecentsAnimationRunner);
+ public abstract android.content.ComponentName startService(android.app.IApplicationThread, android.content.Intent, java.lang.String, boolean, java.lang.String, int);
+ public abstract void startSystemLockTaskMode(int);
+ public abstract boolean startUserInBackground(int);
+ public abstract boolean startUserInBackgroundWithListener(int, android.os.IProgressListener);
+ public abstract int startVoiceActivity(java.lang.String, int, int, android.content.Intent, java.lang.String, android.service.voice.IVoiceInteractionSession, com.android.internal.app.IVoiceInteractor, int, android.app.ProfilerInfo, android.os.Bundle, int);
+ public abstract void stopAppSwitches();
+ public abstract boolean stopBinderTrackingAndDump(android.os.ParcelFileDescriptor);
+ public abstract void stopLocalVoiceInteraction(android.os.IBinder);
+ public abstract void stopLockTaskModeByToken(android.os.IBinder);
+ public abstract int stopService(android.app.IApplicationThread, android.content.Intent, java.lang.String, int);
+ public abstract boolean stopServiceToken(android.content.ComponentName, android.os.IBinder, int);
+ public abstract void stopSystemLockTaskMode();
+ public abstract int stopUser(int, boolean, android.app.IStopUserCallback);
+ public abstract boolean supportsLocalVoiceInteraction();
+ public abstract void suppressResizeConfigChanges(boolean);
+ public abstract boolean switchUser(int);
+ public abstract void takePersistableUriPermission(android.net.Uri, int, java.lang.String, int);
+ public abstract void unbindBackupAgent(android.content.pm.ApplicationInfo);
+ public abstract void unbindFinished(android.os.IBinder, android.content.Intent, boolean);
+ public abstract boolean unbindService(android.app.IServiceConnection);
+ public abstract void unbroadcastIntent(android.app.IApplicationThread, android.content.Intent, int);
+ public abstract void unhandledBack();
+ public abstract boolean unlockUser(int, byte[], byte[], android.os.IProgressListener);
+ public abstract void unregisterIntentSenderCancelListener(android.content.IIntentSender, com.android.internal.os.IResultReceiver);
+ public abstract void unregisterProcessObserver(android.app.IProcessObserver);
+ public abstract void unregisterReceiver(android.content.IIntentReceiver);
+ public abstract void unregisterTaskStackListener(android.app.ITaskStackListener);
+ public abstract void unregisterUidObserver(android.app.IUidObserver);
+ public abstract void unregisterUserSwitchObserver(android.app.IUserSwitchObserver);
+ public abstract void unstableProviderDied(android.os.IBinder);
+ public abstract boolean updateConfiguration(android.content.res.Configuration);
+ public abstract void updateDeviceOwner(java.lang.String);
+ public abstract boolean updateDisplayOverrideConfiguration(android.content.res.Configuration, int);
+ public abstract void updateLockTaskFeatures(int, int);
+ public abstract void updateLockTaskPackages(int, java.lang.String[]);
+ public abstract void updatePersistentConfiguration(android.content.res.Configuration);
+ public abstract void waitForNetworkStateUpdate(long);
+ public abstract boolean willActivityBeVisible(android.os.IBinder);
+
+
+}
+
+-keep class android.app.IAppTask {
+
+ public abstract void finishAndRemoveTask();
+ public abstract android.app.ActivityManager$RecentTaskInfo getTaskInfo();
+ public abstract void moveToFront();
+ public abstract void setExcludeFromRecents(boolean);
+ public abstract int startActivity(android.os.IBinder, java.lang.String, android.content.Intent, java.lang.String, android.os.Bundle);
+
+
+}
+
+-keep class android.app.IApplicationThread {
+
+ public abstract void attachAgent(java.lang.String);
+ public abstract void bindApplication(java.lang.String, android.content.pm.ApplicationInfo, java.util.List, android.content.ComponentName, android.app.ProfilerInfo, android.os.Bundle, android.app.IInstrumentationWatcher, android.app.IUiAutomationConnection, int, boolean, boolean, boolean, boolean, android.content.res.Configuration, android.content.res.CompatibilityInfo, java.util.Map, android.os.Bundle, java.lang.String, boolean);
+ public abstract void clearDnsCache();
+ public abstract void dispatchPackageBroadcast(int, java.lang.String[]);
+ public abstract void dumpActivity(android.os.ParcelFileDescriptor, android.os.IBinder, java.lang.String, java.lang.String[]);
+ public abstract void dumpDbInfo(android.os.ParcelFileDescriptor, java.lang.String[]);
+ public abstract void dumpGfxInfo(android.os.ParcelFileDescriptor, java.lang.String[]);
+ public abstract void dumpHeap(boolean, boolean, boolean, java.lang.String, android.os.ParcelFileDescriptor);
+ public abstract void dumpMemInfo(android.os.ParcelFileDescriptor, android.os.Debug$MemoryInfo, boolean, boolean, boolean, boolean, boolean, java.lang.String[]);
+ public abstract void dumpMemInfoProto(android.os.ParcelFileDescriptor, android.os.Debug$MemoryInfo, boolean, boolean, boolean, boolean, java.lang.String[]);
+ public abstract void dumpProvider(android.os.ParcelFileDescriptor, android.os.IBinder, java.lang.String[]);
+ public abstract void dumpService(android.os.ParcelFileDescriptor, android.os.IBinder, java.lang.String[]);
+ public abstract void handleTrustStorageUpdate();
+ public abstract void notifyCleartextNetwork(byte[]);
+ public abstract void processInBackground();
+ public abstract void profilerControl(boolean, android.app.ProfilerInfo, int);
+ public abstract void requestAssistContextExtras(android.os.IBinder, android.os.IBinder, int, int, int);
+ public abstract void runIsolatedEntryPoint(java.lang.String, java.lang.String[]);
+ public abstract void scheduleApplicationInfoChanged(android.content.pm.ApplicationInfo);
+ public abstract void scheduleBindService(android.os.IBinder, android.content.Intent, boolean, int);
+ public abstract void scheduleCrash(java.lang.String);
+ public abstract void scheduleCreateBackupAgent(android.content.pm.ApplicationInfo, android.content.res.CompatibilityInfo, int);
+ public abstract void scheduleCreateService(android.os.IBinder, android.content.pm.ServiceInfo, android.content.res.CompatibilityInfo, int);
+ public abstract void scheduleDestroyBackupAgent(android.content.pm.ApplicationInfo, android.content.res.CompatibilityInfo);
+ public abstract void scheduleEnterAnimationComplete(android.os.IBinder);
+ public abstract void scheduleExit();
+ public abstract void scheduleInstallProvider(android.content.pm.ProviderInfo);
+ public abstract void scheduleLocalVoiceInteractionStarted(android.os.IBinder, com.android.internal.app.IVoiceInteractor);
+ public abstract void scheduleLowMemory();
+ public abstract void scheduleOnNewActivityOptions(android.os.IBinder, android.os.Bundle);
+ public abstract void scheduleReceiver(android.content.Intent, android.content.pm.ActivityInfo, android.content.res.CompatibilityInfo, int, java.lang.String, android.os.Bundle, boolean, int, int);
+ public abstract void scheduleRegisteredReceiver(android.content.IIntentReceiver, android.content.Intent, int, java.lang.String, android.os.Bundle, boolean, boolean, int, int);
+ public abstract void scheduleServiceArgs(android.os.IBinder, android.content.pm.ParceledListSlice);
+ public abstract void scheduleSleeping(android.os.IBinder, boolean);
+ public abstract void scheduleStopService(android.os.IBinder);
+ public abstract void scheduleSuicide();
+ public abstract void scheduleTransaction(android.app.servertransaction.ClientTransaction);
+ public abstract void scheduleTranslucentConversionComplete(android.os.IBinder, boolean);
+ public abstract void scheduleTrimMemory(int);
+ public abstract void scheduleUnbindService(android.os.IBinder, android.content.Intent);
+ public abstract void setCoreSettings(android.os.Bundle);
+ public abstract void setHttpProxy(java.lang.String, java.lang.String, java.lang.String, android.net.Uri);
+ public abstract void setNetworkBlockSeq(long);
+ public abstract void setProcessState(int);
+ public abstract void setSchedulingGroup(int);
+ public abstract void startBinderTracking();
+ public abstract void stopBinderTrackingAndDump(android.os.ParcelFileDescriptor);
+ public abstract void unstableProviderDied(android.os.IBinder);
+ public abstract void updatePackageCompatibilityInfo(java.lang.String, android.content.res.CompatibilityInfo);
+ public abstract void updateTimePrefs(int);
+ public abstract void updateTimeZone();
+
+
+}
+
+-keep class android.app.IApplicationThread$Stub {
+ <init>();
+
+ public android.os.IBinder asBinder();
+ public static android.app.IApplicationThread asInterface(android.os.IBinder);
+ public boolean onTransact(int, android.os.Parcel, android.os.Parcel, int);
+
+
+}
+
+-keep class android.app.IAssistDataReceiver {
+
+ public abstract void onHandleAssistData(android.os.Bundle);
+ public abstract void onHandleAssistScreenshot(android.graphics.Bitmap);
+
+
+}
+
+-keep class android.app.IInstrumentationWatcher {
+
+ public abstract void instrumentationFinished(android.content.ComponentName, int, android.os.Bundle);
+ public abstract void instrumentationStatus(android.content.ComponentName, int, android.os.Bundle);
+
+
+}
+
+-keep class android.app.IProcessObserver {
+
+ public abstract void onForegroundActivitiesChanged(int, int, boolean);
+ public abstract void onProcessDied(int, int);
+
+
+}
+
+-keep class android.app.IServiceConnection {
+
+ public abstract void connected(android.content.ComponentName, android.os.IBinder, boolean);
+
+
+}
+
+-keep class android.app.IStopUserCallback {
+
+ public abstract void userStopAborted(int);
+ public abstract void userStopped(int);
+
+
+}
+
+-keep class android.app.ITaskStackListener {
+
+ public abstract void onActivityDismissingDockedStack();
+ public abstract void onActivityForcedResizable(java.lang.String, int, int);
+ public abstract void onActivityLaunchOnSecondaryDisplayFailed();
+ public abstract void onActivityPinned(java.lang.String, int, int, int);
+ public abstract void onActivityRequestedOrientationChanged(int, int);
+ public abstract void onActivityUnpinned();
+ public abstract void onPinnedActivityRestartAttempt(boolean);
+ public abstract void onPinnedStackAnimationEnded();
+ public abstract void onPinnedStackAnimationStarted();
+ public abstract void onTaskCreated(int, android.content.ComponentName);
+ public abstract void onTaskDescriptionChanged(int, android.app.ActivityManager$TaskDescription);
+ public abstract void onTaskMovedToFront(int);
+ public abstract void onTaskProfileLocked(int, int);
+ public abstract void onTaskRemovalStarted(int);
+ public abstract void onTaskRemoved(int);
+ public abstract void onTaskSnapshotChanged(int, android.app.ActivityManager$TaskSnapshot);
+ public abstract void onTaskStackChanged();
+
+
+ public static int FORCED_RESIZEABLE_REASON_SECONDARY_DISPLAY;
+ public static int FORCED_RESIZEABLE_REASON_SPLIT_SCREEN;
+}
+
+-keep class android.app.IUiAutomationConnection {
+
+ public abstract void clearWindowAnimationFrameStats();
+ public abstract boolean clearWindowContentFrameStats(int);
+ public abstract void connect(android.accessibilityservice.IAccessibilityServiceClient, int);
+ public abstract void disconnect();
+ public abstract void executeShellCommand(java.lang.String, android.os.ParcelFileDescriptor, android.os.ParcelFileDescriptor);
+ public abstract android.view.WindowAnimationFrameStats getWindowAnimationFrameStats();
+ public abstract android.view.WindowContentFrameStats getWindowContentFrameStats(int);
+ public abstract void grantRuntimePermission(java.lang.String, java.lang.String, int);
+ public abstract boolean injectInputEvent(android.view.InputEvent, boolean);
+ public abstract void revokeRuntimePermission(java.lang.String, java.lang.String, int);
+ public abstract boolean setRotation(int);
+ public abstract void shutdown();
+ public abstract android.graphics.Bitmap takeScreenshot(android.graphics.Rect, int);
+
+
+}
+
+-keep class android.app.IUidObserver {
+
+ public abstract void onUidActive(int);
+ public abstract void onUidCachedChanged(int, boolean);
+ public abstract void onUidGone(int, boolean);
+ public abstract void onUidIdle(int, boolean);
+ public abstract void onUidStateChanged(int, int, long);
+
+
+}
+
+-keep class android.app.IUserSwitchObserver {
+
+ public abstract void onForegroundProfileSwitch(int);
+ public abstract void onLockedBootComplete(int);
+ public abstract void onUserSwitchComplete(int);
+ public abstract void onUserSwitching(int, android.os.IRemoteCallback);
+
+
+}
+
+-keep class android.app.Instrumentation {
+ <init>();
+
+ public android.os.TestLooperManager acquireLooperManager(android.os.Looper);
+ public void addMonitor(android.app.Instrumentation$ActivityMonitor);
+ public android.app.Instrumentation$ActivityMonitor addMonitor(android.content.IntentFilter, android.app.Instrumentation$ActivityResult, boolean);
+ public android.app.Instrumentation$ActivityMonitor addMonitor(java.lang.String, android.app.Instrumentation$ActivityResult, boolean);
+ public void addResults(android.os.Bundle);
+ public void callActivityOnCreate(android.app.Activity, android.os.Bundle);
+ public void callActivityOnCreate(android.app.Activity, android.os.Bundle, android.os.PersistableBundle);
+ public void callActivityOnDestroy(android.app.Activity);
+ public void callActivityOnNewIntent(android.app.Activity, android.content.Intent);
+ public void callActivityOnNewIntent(android.app.Activity, com.android.internal.content.ReferrerIntent);
+ public void callActivityOnPause(android.app.Activity);
+ public void callActivityOnPostCreate(android.app.Activity, android.os.Bundle);
+ public void callActivityOnPostCreate(android.app.Activity, android.os.Bundle, android.os.PersistableBundle);
+ public void callActivityOnRestart(android.app.Activity);
+ public void callActivityOnRestoreInstanceState(android.app.Activity, android.os.Bundle);
+ public void callActivityOnRestoreInstanceState(android.app.Activity, android.os.Bundle, android.os.PersistableBundle);
+ public void callActivityOnResume(android.app.Activity);
+ public void callActivityOnSaveInstanceState(android.app.Activity, android.os.Bundle);
+ public void callActivityOnSaveInstanceState(android.app.Activity, android.os.Bundle, android.os.PersistableBundle);
+ public void callActivityOnStart(android.app.Activity);
+ public void callActivityOnStop(android.app.Activity);
+ public void callActivityOnUserLeaving(android.app.Activity);
+ public void callApplicationOnCreate(android.app.Application);
+ public boolean checkMonitorHit(android.app.Instrumentation$ActivityMonitor, int);
+ public static void checkStartActivityResult(int, java.lang.Object);
+ public void endPerformanceSnapshot();
+ public void execStartActivities(android.content.Context, android.os.IBinder, android.os.IBinder, android.app.Activity, android.content.Intent[], android.os.Bundle);
+ public int execStartActivitiesAsUser(android.content.Context, android.os.IBinder, android.os.IBinder, android.app.Activity, android.content.Intent[], android.os.Bundle, int);
+ public android.app.Instrumentation$ActivityResult execStartActivity(android.content.Context, android.os.IBinder, android.os.IBinder, android.app.Activity, android.content.Intent, int, android.os.Bundle);
+ public android.app.Instrumentation$ActivityResult execStartActivity(android.content.Context, android.os.IBinder, android.os.IBinder, java.lang.String, android.content.Intent, int, android.os.Bundle);
+ public android.app.Instrumentation$ActivityResult execStartActivity(android.content.Context, android.os.IBinder, android.os.IBinder, java.lang.String, android.content.Intent, int, android.os.Bundle, android.os.UserHandle);
+ public android.app.Instrumentation$ActivityResult execStartActivityAsCaller(android.content.Context, android.os.IBinder, android.os.IBinder, android.app.Activity, android.content.Intent, int, android.os.Bundle, boolean, int);
+ public void execStartActivityFromAppTask(android.content.Context, android.os.IBinder, android.app.IAppTask, android.content.Intent, android.os.Bundle);
+ public void finish(int, android.os.Bundle);
+ public android.os.Bundle getAllocCounts();
+ public android.os.Bundle getBinderCounts();
+ public android.content.ComponentName getComponentName();
+ public android.content.Context getContext();
+ public java.lang.String getProcessName();
+ public android.content.Context getTargetContext();
+ public android.app.UiAutomation getUiAutomation();
+ public android.app.UiAutomation getUiAutomation(int);
+ public boolean invokeContextMenuAction(android.app.Activity, int, int);
+ public boolean invokeMenuActionSync(android.app.Activity, int, int);
+ public boolean isProfiling();
+ public android.app.Activity newActivity(java.lang.Class, android.content.Context, android.os.IBinder, android.app.Application, android.content.Intent, android.content.pm.ActivityInfo, java.lang.CharSequence, android.app.Activity, java.lang.String, java.lang.Object);
+ public android.app.Activity newActivity(java.lang.ClassLoader, java.lang.String, android.content.Intent);
+ public android.app.Application newApplication(java.lang.ClassLoader, java.lang.String, android.content.Context);
+ public static android.app.Application newApplication(java.lang.Class, android.content.Context);
+ public void onCreate(android.os.Bundle);
+ public void onDestroy();
+ public boolean onException(java.lang.Object, java.lang.Throwable);
+ public void onStart();
+ public void removeMonitor(android.app.Instrumentation$ActivityMonitor);
+ public void runOnMainSync(java.lang.Runnable);
+ public void sendCharacterSync(int);
+ public void sendKeyDownUpSync(int);
+ public void sendKeySync(android.view.KeyEvent);
+ public void sendPointerSync(android.view.MotionEvent);
+ public void sendStatus(int, android.os.Bundle);
+ public void sendStringSync(java.lang.String);
+ public void sendTrackballEventSync(android.view.MotionEvent);
+ public void setAutomaticPerformanceSnapshots();
+ public void setInTouchMode(boolean);
+ public void start();
+ public android.app.Activity startActivitySync(android.content.Intent);
+ public android.app.Activity startActivitySync(android.content.Intent, android.os.Bundle);
+ public void startAllocCounting();
+ public void startPerformanceSnapshot();
+ public void startProfiling();
+ public void stopAllocCounting();
+ public void stopProfiling();
+ public void waitForIdle(java.lang.Runnable);
+ public void waitForIdleSync();
+ public android.app.Activity waitForMonitor(android.app.Instrumentation$ActivityMonitor);
+ public android.app.Activity waitForMonitorWithTimeout(android.app.Instrumentation$ActivityMonitor, long);
+
+
+ public static java.lang.String REPORT_KEY_IDENTIFIER;
+ public static java.lang.String REPORT_KEY_STREAMRESULT;
+}
+
+-keep class android.app.Instrumentation$ActivityMonitor {
+ <init>(android.content.IntentFilter, android.app.Instrumentation$ActivityResult, boolean);
+ <init>(java.lang.String, android.app.Instrumentation$ActivityResult, boolean);
+ <init>();
+
+ public android.content.IntentFilter getFilter();
+ public int getHits();
+ public android.app.Activity getLastActivity();
+ public android.app.Instrumentation$ActivityResult getResult();
+ public boolean isBlocking();
+ public android.app.Instrumentation$ActivityResult onStartActivity(android.content.Intent);
+ public android.app.Activity waitForActivity();
+ public android.app.Activity waitForActivityWithTimeout(long);
+
+
+}
+
+-keep class android.app.Instrumentation$ActivityResult {
+ <init>(int, android.content.Intent);
+
+ public int getResultCode();
+ public android.content.Intent getResultData();
+
+
+}
+
+-keep class android.app.LoadedApk {
+ <init>(android.app.ActivityThread, android.content.pm.ApplicationInfo, android.content.res.CompatibilityInfo, java.lang.ClassLoader, boolean, boolean, boolean);
+
+ public android.content.IIntentReceiver forgetReceiverDispatcher(android.content.Context, android.content.BroadcastReceiver);
+ public android.app.IServiceConnection forgetServiceDispatcher(android.content.Context, android.content.ServiceConnection);
+ public java.lang.String getAppDir();
+ public android.app.AppComponentFactory getAppFactory();
+ public android.content.pm.ApplicationInfo getApplicationInfo();
+ public android.content.res.AssetManager getAssets();
+ public java.lang.ClassLoader getClassLoader();
+ public android.content.res.CompatibilityInfo getCompatibilityInfo();
+ public java.io.File getCredentialProtectedDataDirFile();
+ public java.lang.String getDataDir();
+ public java.io.File getDataDirFile();
+ public java.io.File getDeviceProtectedDataDirFile();
+ public java.lang.String getLibDir();
+ public java.lang.String[] getOverlayDirs();
+ public java.lang.String getPackageName();
+ public android.content.IIntentReceiver getReceiverDispatcher(android.content.BroadcastReceiver, android.content.Context, android.os.Handler, android.app.Instrumentation, boolean);
+ public java.lang.String getResDir();
+ public android.content.res.Resources getResources();
+ public android.app.IServiceConnection getServiceDispatcher(android.content.ServiceConnection, android.content.Context, android.os.Handler, int);
+ public java.lang.String[] getSplitAppDirs();
+ public java.lang.String[] getSplitResDirs();
+ public int getTargetSdkVersion();
+ public boolean isSecurityViolation();
+ public android.app.Application makeApplication(boolean, android.app.Instrumentation);
+ public static void makePaths(android.app.ActivityThread, android.content.pm.ApplicationInfo, java.util.List);
+ public static void makePaths(android.app.ActivityThread, boolean, android.content.pm.ApplicationInfo, java.util.List, java.util.List);
+ public void removeContextRegistrations(android.content.Context, java.lang.String, java.lang.String);
+ public void setCompatibilityInfo(android.content.res.CompatibilityInfo);
+ public void updateApplicationInfo(android.content.pm.ApplicationInfo, java.util.List);
+
+
+}
+
+-keep class android.app.LoaderManager {
+ <init>();
+
+ public abstract void destroyLoader(int);
+ public abstract void dump(java.lang.String, java.io.FileDescriptor, java.io.PrintWriter, java.lang.String[]);
+ public static void enableDebugLogging(boolean);
+ public android.app.FragmentHostCallback getFragmentHostCallback();
+ public abstract android.content.Loader getLoader(int);
+ public abstract android.content.Loader initLoader(int, android.os.Bundle, android.app.LoaderManager$LoaderCallbacks);
+ public abstract android.content.Loader restartLoader(int, android.os.Bundle, android.app.LoaderManager$LoaderCallbacks);
+
+
+}
+
+-keep class android.app.LoaderManager$LoaderCallbacks {
+
+ public abstract android.content.Loader onCreateLoader(int, android.os.Bundle);
+ public abstract void onLoadFinished(android.content.Loader, java.lang.Object);
+ public abstract void onLoaderReset(android.content.Loader);
+
+
+}
+
+-keep class android.app.Notification {
+ <init>();
+ <init>(android.content.Context, int, java.lang.CharSequence, long, java.lang.CharSequence, java.lang.CharSequence, android.content.Intent);
+ <init>(int, java.lang.CharSequence, long);
+ <init>(android.os.Parcel);
+
+ public static void addFieldsFromContext(android.content.Context, android.app.Notification);
+ public static void addFieldsFromContext(android.content.pm.ApplicationInfo, android.app.Notification);
+ public static boolean areActionsVisiblyDifferent(android.app.Notification, android.app.Notification);
+ public static boolean areRemoteViewsChanged(android.app.Notification$Builder, android.app.Notification$Builder);
+ public static boolean areStyledNotificationsVisiblyDifferent(android.app.Notification$Builder, android.app.Notification$Builder);
+ public android.app.Notification clone();
+ public java.lang.Object clone();
+ public void cloneInto(android.app.Notification, boolean);
+ public int describeContents();
+ public int getBadgeIconType();
+ public java.lang.String getChannel();
+ public java.lang.String getChannelId();
+ public java.lang.String getGroup();
+ public int getGroupAlertBehavior();
+ public android.graphics.drawable.Icon getLargeIcon();
+ public java.lang.Class getNotificationStyle();
+ public static java.lang.Class getNotificationStyleClass(java.lang.String);
+ public java.lang.CharSequence getSettingsText();
+ public java.lang.String getShortcutId();
+ public android.graphics.drawable.Icon getSmallIcon();
+ public java.lang.String getSortKey();
+ public long getTimeout();
+ public long getTimeoutAfter();
+ public boolean hasCompletedProgress();
+ public boolean hasMediaSession();
+ public boolean isColorized();
+ public boolean isColorizedMedia();
+ public boolean isGroupChild();
+ public boolean isGroupSummary();
+ public boolean isMediaNotification();
+ public void lightenPayload();
+ public static java.lang.String priorityToString(int);
+ public static java.lang.CharSequence safeCharSequence(java.lang.CharSequence);
+ public void setLatestEventInfo(android.content.Context, java.lang.CharSequence, java.lang.CharSequence, android.app.PendingIntent);
+ public void setSmallIcon(android.graphics.drawable.Icon);
+ public boolean showsChronometer();
+ public boolean showsTime();
+ public boolean suppressAlertingDueToGrouping();
+ public java.lang.String toString();
+ public static java.lang.String visibilityToString(int);
+ public void visitUris(java.util.function.Consumer);
+ public void writeToParcel(android.os.Parcel, int);
+ public void writeToProto(android.util.proto.ProtoOutputStream, long);
+
+
+ public static android.media.AudioAttributes AUDIO_ATTRIBUTES_DEFAULT;
+ public static int BADGE_ICON_LARGE;
+ public static int BADGE_ICON_NONE;
+ public static int BADGE_ICON_SMALL;
+ public static java.lang.String CATEGORY_ALARM;
+ public static java.lang.String CATEGORY_CALL;
+ public static java.lang.String CATEGORY_CAR_EMERGENCY;
+ public static java.lang.String CATEGORY_CAR_INFORMATION;
+ public static java.lang.String CATEGORY_CAR_WARNING;
+ public static java.lang.String CATEGORY_EMAIL;
+ public static java.lang.String CATEGORY_ERROR;
+ public static java.lang.String CATEGORY_EVENT;
+ public static java.lang.String CATEGORY_MESSAGE;
+ public static java.lang.String CATEGORY_NAVIGATION;
+ public static java.lang.String CATEGORY_PROGRESS;
+ public static java.lang.String CATEGORY_PROMO;
+ public static java.lang.String CATEGORY_RECOMMENDATION;
+ public static java.lang.String CATEGORY_REMINDER;
+ public static java.lang.String CATEGORY_SERVICE;
+ public static java.lang.String CATEGORY_SOCIAL;
+ public static java.lang.String CATEGORY_STATUS;
+ public static java.lang.String CATEGORY_SYSTEM;
+ public static java.lang.String CATEGORY_TRANSPORT;
+ public static int COLOR_DEFAULT;
+ public static int COLOR_INVALID;
+ public static android.os.Parcelable$Creator CREATOR;
+ public static int DEFAULT_ALL;
+ public static int DEFAULT_LIGHTS;
+ public static int DEFAULT_SOUND;
+ public static int DEFAULT_VIBRATE;
+ public static java.lang.String EXTRA_ALLOW_DURING_SETUP;
+ public static java.lang.String EXTRA_AUDIO_CONTENTS_URI;
+ public static java.lang.String EXTRA_BACKGROUND_IMAGE_URI;
+ public static java.lang.String EXTRA_BIG_TEXT;
+ public static java.lang.String EXTRA_BUILDER_APPLICATION_INFO;
+ public static java.lang.String EXTRA_CHANNEL_GROUP_ID;
+ public static java.lang.String EXTRA_CHANNEL_ID;
+ public static java.lang.String EXTRA_CHRONOMETER_COUNT_DOWN;
+ public static java.lang.String EXTRA_COLORIZED;
+ public static java.lang.String EXTRA_COMPACT_ACTIONS;
+ public static java.lang.String EXTRA_CONTAINS_CUSTOM_VIEW;
+ public static java.lang.String EXTRA_CONVERSATION_TITLE;
+ public static java.lang.String EXTRA_FOREGROUND_APPS;
+ public static java.lang.String EXTRA_HIDE_SMART_REPLIES;
+ public static java.lang.String EXTRA_HISTORIC_MESSAGES;
+ public static java.lang.String EXTRA_INFO_TEXT;
+ public static java.lang.String EXTRA_IS_GROUP_CONVERSATION;
+ public static java.lang.String EXTRA_LARGE_ICON;
+ public static java.lang.String EXTRA_LARGE_ICON_BIG;
+ public static java.lang.String EXTRA_MEDIA_SESSION;
+ public static java.lang.String EXTRA_MESSAGES;
+ public static java.lang.String EXTRA_MESSAGING_PERSON;
+ public static java.lang.String EXTRA_NOTIFICATION_ID;
+ public static java.lang.String EXTRA_NOTIFICATION_TAG;
+ public static java.lang.String EXTRA_PEOPLE;
+ public static java.lang.String EXTRA_PEOPLE_LIST;
+ public static java.lang.String EXTRA_PICTURE;
+ public static java.lang.String EXTRA_PROGRESS;
+ public static java.lang.String EXTRA_PROGRESS_INDETERMINATE;
+ public static java.lang.String EXTRA_PROGRESS_MAX;
+ public static java.lang.String EXTRA_REDUCED_IMAGES;
+ public static java.lang.String EXTRA_REMOTE_INPUT_DRAFT;
+ public static java.lang.String EXTRA_REMOTE_INPUT_HISTORY;
+ public static java.lang.String EXTRA_SELF_DISPLAY_NAME;
+ public static java.lang.String EXTRA_SHOW_CHRONOMETER;
+ public static java.lang.String EXTRA_SHOW_REMOTE_INPUT_SPINNER;
+ public static java.lang.String EXTRA_SHOW_WHEN;
+ public static java.lang.String EXTRA_SMALL_ICON;
+ public static java.lang.String EXTRA_SUBSTITUTE_APP_NAME;
+ public static java.lang.String EXTRA_SUB_TEXT;
+ public static java.lang.String EXTRA_SUMMARY_TEXT;
+ public static java.lang.String EXTRA_TEMPLATE;
+ public static java.lang.String EXTRA_TEXT;
+ public static java.lang.String EXTRA_TEXT_LINES;
+ public static java.lang.String EXTRA_TITLE;
+ public static java.lang.String EXTRA_TITLE_BIG;
+ public static int FLAG_AUTOGROUP_SUMMARY;
+ public static int FLAG_AUTO_CANCEL;
+ public static int FLAG_CAN_COLORIZE;
+ public static int FLAG_FOREGROUND_SERVICE;
+ public static int FLAG_GROUP_SUMMARY;
+ public static int FLAG_HIGH_PRIORITY;
+ public static int FLAG_INSISTENT;
+ public static int FLAG_LOCAL_ONLY;
+ public static int FLAG_NO_CLEAR;
+ public static int FLAG_ONGOING_EVENT;
+ public static int FLAG_ONLY_ALERT_ONCE;
+ public static int FLAG_SHOW_LIGHTS;
+ public static int GROUP_ALERT_ALL;
+ public static int GROUP_ALERT_CHILDREN;
+ public static int GROUP_ALERT_SUMMARY;
+ public static java.lang.String INTENT_CATEGORY_NOTIFICATION_PREFERENCES;
+ public static int PRIORITY_DEFAULT;
+ public static int PRIORITY_HIGH;
+ public static int PRIORITY_LOW;
+ public static int PRIORITY_MAX;
+ public static int PRIORITY_MIN;
+ public static int STREAM_DEFAULT;
+ public static int VISIBILITY_PRIVATE;
+ public static int VISIBILITY_PUBLIC;
+ public static int VISIBILITY_SECRET;
+ public android.app.Notification$Action[] actions;
+ public android.util.ArraySet allPendingIntents;
+ public android.media.AudioAttributes audioAttributes;
+ public int audioStreamType;
+ public android.widget.RemoteViews bigContentView;
+ public java.lang.String category;
+ public int color;
+ public android.app.PendingIntent contentIntent;
+ public android.widget.RemoteViews contentView;
+ public int defaults;
+ public android.app.PendingIntent deleteIntent;
+ public android.os.Bundle extras;
+ public int flags;
+ public android.app.PendingIntent fullScreenIntent;
+ public android.widget.RemoteViews headsUpContentView;
+ public int icon;
+ public int iconLevel;
+ public android.graphics.Bitmap largeIcon;
+ public int ledARGB;
+ public int ledOffMS;
+ public int ledOnMS;
+ public int number;
+ public int priority;
+ public static android.os.IBinder processWhitelistToken;
+ public android.app.Notification publicVersion;
+ public android.net.Uri sound;
+ public java.lang.CharSequence tickerText;
+ public android.widget.RemoteViews tickerView;
+ public long[] vibrate;
+ public int visibility;
+ public long when;
+}
+
+-keep class android.app.Notification$Action {
+ <init>(int, java.lang.CharSequence, android.app.PendingIntent);
+
+ public android.app.Notification$Action clone();
+ public java.lang.Object clone();
+ public int describeContents();
+ public boolean getAllowGeneratedReplies();
+ public android.app.RemoteInput[] getDataOnlyRemoteInputs();
+ public android.os.Bundle getExtras();
+ public android.graphics.drawable.Icon getIcon();
+ public android.app.RemoteInput[] getRemoteInputs();
+ public int getSemanticAction();
+ public void writeToParcel(android.os.Parcel, int);
+
+
+ public static android.os.Parcelable$Creator CREATOR;
+ public static int SEMANTIC_ACTION_ARCHIVE;
+ public static int SEMANTIC_ACTION_CALL;
+ public static int SEMANTIC_ACTION_DELETE;
+ public static int SEMANTIC_ACTION_MARK_AS_READ;
+ public static int SEMANTIC_ACTION_MARK_AS_UNREAD;
+ public static int SEMANTIC_ACTION_MUTE;
+ public static int SEMANTIC_ACTION_NONE;
+ public static int SEMANTIC_ACTION_REPLY;
+ public static int SEMANTIC_ACTION_THUMBS_DOWN;
+ public static int SEMANTIC_ACTION_THUMBS_UP;
+ public static int SEMANTIC_ACTION_UNMUTE;
+ public android.app.PendingIntent actionIntent;
+ public int icon;
+ public java.lang.CharSequence title;
+}
+
+-keep class android.app.Notification$Builder {
+ <init>(android.content.Context, java.lang.String);
+ <init>(android.content.Context);
+ <init>(android.content.Context, android.app.Notification);
+
+ public android.app.Notification$Builder addAction(int, java.lang.CharSequence, android.app.PendingIntent);
+ public android.app.Notification$Builder addAction(android.app.Notification$Action);
+ public android.app.Notification$Builder addExtras(android.os.Bundle);
+ public android.app.Notification$Builder addPerson(java.lang.String);
+ public android.app.Notification$Builder addPerson(android.app.Person);
+ public android.app.Notification build();
+ public android.app.Notification buildInto(android.app.Notification);
+ public android.app.Notification buildUnstyled();
+ public android.widget.RemoteViews createBigContentView();
+ public android.widget.RemoteViews createContentView();
+ public android.widget.RemoteViews createContentView(boolean);
+ public android.widget.RemoteViews createHeadsUpContentView(boolean);
+ public android.widget.RemoteViews createHeadsUpContentView();
+ public android.app.Notification$Builder extend(android.app.Notification$Extender);
+ public android.os.Bundle getExtras();
+ public java.lang.CharSequence getHeadsUpStatusBarText(boolean);
+ public android.app.Notification getNotification();
+ public int getPrimaryTextColor();
+ public int getSecondaryTextColor();
+ public android.app.Notification$Style getStyle();
+ public java.lang.String loadHeaderAppName();
+ public android.widget.RemoteViews makeAmbientNotification();
+ public static void makeHeaderExpanded(android.widget.RemoteViews);
+ public android.widget.RemoteViews makeLowPriorityContentView(boolean);
+ public android.widget.RemoteViews makeNotificationHeader(boolean);
+ public android.widget.RemoteViews makePublicAmbientNotification();
+ public android.widget.RemoteViews makePublicContentView();
+ public static android.app.Notification maybeCloneStrippedForDelivery(android.app.Notification, boolean, android.content.Context);
+ public static android.app.Notification$Builder recoverBuilder(android.content.Context, android.app.Notification);
+ public android.app.Notification$Builder setActions(android.app.Notification$Action[]);
+ public android.app.Notification$Builder setAutoCancel(boolean);
+ public android.app.Notification$Builder setBadgeIconType(int);
+ public android.app.Notification$Builder setCategory(java.lang.String);
+ public android.app.Notification$Builder setChannel(java.lang.String);
+ public android.app.Notification$Builder setChannelId(java.lang.String);
+ public android.app.Notification$Builder setChronometerCountDown(boolean);
+ public android.app.Notification$Builder setColor(int);
+ public void setColorPalette(int, int);
+ public android.app.Notification$Builder setColorized(boolean);
+ public android.app.Notification$Builder setContent(android.widget.RemoteViews);
+ public android.app.Notification$Builder setContentInfo(java.lang.CharSequence);
+ public android.app.Notification$Builder setContentIntent(android.app.PendingIntent);
+ public android.app.Notification$Builder setContentText(java.lang.CharSequence);
+ public android.app.Notification$Builder setContentTitle(java.lang.CharSequence);
+ public android.app.Notification$Builder setCustomBigContentView(android.widget.RemoteViews);
+ public android.app.Notification$Builder setCustomContentView(android.widget.RemoteViews);
+ public android.app.Notification$Builder setCustomHeadsUpContentView(android.widget.RemoteViews);
+ public android.app.Notification$Builder setDefaults(int);
+ public android.app.Notification$Builder setDeleteIntent(android.app.PendingIntent);
+ public android.app.Notification$Builder setExtras(android.os.Bundle);
+ public android.app.Notification$Builder setFlag(int, boolean);
+ public android.app.Notification$Builder setFullScreenIntent(android.app.PendingIntent, boolean);
+ public android.app.Notification$Builder setGroup(java.lang.String);
+ public android.app.Notification$Builder setGroupAlertBehavior(int);
+ public android.app.Notification$Builder setGroupSummary(boolean);
+ public android.app.Notification$Builder setHideSmartReplies(boolean);
+ public android.app.Notification$Builder setLargeIcon(android.graphics.Bitmap);
+ public android.app.Notification$Builder setLargeIcon(android.graphics.drawable.Icon);
+ public android.app.Notification$Builder setLights(int, int, int);
+ public android.app.Notification$Builder setLocalOnly(boolean);
+ public android.app.Notification$Builder setNumber(int);
+ public android.app.Notification$Builder setOngoing(boolean);
+ public android.app.Notification$Builder setOnlyAlertOnce(boolean);
+ public android.app.Notification$Builder setPriority(int);
+ public android.app.Notification$Builder setProgress(int, int, boolean);
+ public android.app.Notification$Builder setPublicVersion(android.app.Notification);
+ public void setRebuildStyledRemoteViews(boolean);
+ public android.app.Notification$Builder setRemoteInputHistory(java.lang.CharSequence[]);
+ public android.app.Notification$Builder setSettingsText(java.lang.CharSequence);
+ public android.app.Notification$Builder setShortcutId(java.lang.String);
+ public android.app.Notification$Builder setShowRemoteInputSpinner(boolean);
+ public android.app.Notification$Builder setShowWhen(boolean);
+ public android.app.Notification$Builder setSmallIcon(int);
+ public android.app.Notification$Builder setSmallIcon(int, int);
+ public android.app.Notification$Builder setSmallIcon(android.graphics.drawable.Icon);
+ public android.app.Notification$Builder setSortKey(java.lang.String);
+ public android.app.Notification$Builder setSound(android.net.Uri);
+ public android.app.Notification$Builder setSound(android.net.Uri, int);
+ public android.app.Notification$Builder setSound(android.net.Uri, android.media.AudioAttributes);
+ public android.app.Notification$Builder setStyle(android.app.Notification$Style);
+ public android.app.Notification$Builder setSubText(java.lang.CharSequence);
+ public android.app.Notification$Builder setTicker(java.lang.CharSequence);
+ public android.app.Notification$Builder setTicker(java.lang.CharSequence, android.widget.RemoteViews);
+ public android.app.Notification$Builder setTimeout(long);
+ public android.app.Notification$Builder setTimeoutAfter(long);
+ public android.app.Notification$Builder setUsesChronometer(boolean);
+ public android.app.Notification$Builder setVibrate(long[]);
+ public android.app.Notification$Builder setVisibility(int);
+ public android.app.Notification$Builder setWhen(long);
+ public boolean usesStandardHeader();
+
+
+ public static java.lang.String EXTRA_REBUILD_BIG_CONTENT_VIEW_ACTION_COUNT;
+ public static java.lang.String EXTRA_REBUILD_CONTENT_VIEW_ACTION_COUNT;
+ public static java.lang.String EXTRA_REBUILD_HEADS_UP_CONTENT_VIEW_ACTION_COUNT;
+}
+
+-keep class android.app.Notification$Extender {
+
+ public abstract android.app.Notification$Builder extend(android.app.Notification$Builder);
+
+
+}
+
+-keep class android.app.Notification$Style {
+ <init>();
+
+ public void addExtras(android.os.Bundle);
+ public abstract boolean areNotificationsVisiblyDifferent(android.app.Notification$Style);
+ public android.app.Notification build();
+ public android.app.Notification buildStyled(android.app.Notification);
+ protected void checkBuilder();
+ public boolean displayCustomViewInline();
+ public java.lang.CharSequence getHeadsUpStatusBarText();
+ protected android.widget.RemoteViews getStandardView(int);
+ protected android.widget.RemoteViews getStandardView(int, android.app.Notification$TemplateBindResult);
+ protected boolean hasProgress();
+ public boolean hasSummaryInHeader();
+ protected void internalSetBigContentTitle(java.lang.CharSequence);
+ protected void internalSetSummaryText(java.lang.CharSequence);
+ public android.widget.RemoteViews makeBigContentView();
+ public android.widget.RemoteViews makeContentView(boolean);
+ public android.widget.RemoteViews makeHeadsUpContentView(boolean);
+ public void purgeResources();
+ public void reduceImageSizes(android.content.Context);
+ protected void restoreFromExtras(android.os.Bundle);
+ public void setBuilder(android.app.Notification$Builder);
+ public void validate(android.content.Context);
+
+
+ protected android.app.Notification$Builder mBuilder;
+ protected java.lang.CharSequence mSummaryText;
+ protected boolean mSummaryTextSet;
+}
+
+-keep class android.app.Notification$TemplateBindResult {
+
+ public int getIconMarginEnd();
+ public void setIconMarginEnd(int);
+
+
+}
+
+-keep class android.app.OnActivityPausedListener {
+
+ public abstract void onPaused(android.app.Activity);
+
+
+}
+
-keep class android.app.PendingIntent {
public void cancel();
@@ -21,17 +3890,29 @@
public boolean equals(java.lang.Object);
public static android.app.PendingIntent getActivities(android.content.Context, int, android.content.Intent[], int);
public static android.app.PendingIntent getActivities(android.content.Context, int, android.content.Intent[], int, android.os.Bundle);
+ public static android.app.PendingIntent getActivitiesAsUser(android.content.Context, int, android.content.Intent[], int, android.os.Bundle, android.os.UserHandle);
public static android.app.PendingIntent getActivity(android.content.Context, int, android.content.Intent, int);
public static android.app.PendingIntent getActivity(android.content.Context, int, android.content.Intent, int, android.os.Bundle);
+ public static android.app.PendingIntent getActivityAsUser(android.content.Context, int, android.content.Intent, int, android.os.Bundle, android.os.UserHandle);
public static android.app.PendingIntent getBroadcast(android.content.Context, int, android.content.Intent, int);
+ public static android.app.PendingIntent getBroadcastAsUser(android.content.Context, int, android.content.Intent, int, android.os.UserHandle);
public java.lang.String getCreatorPackage();
public int getCreatorUid();
public android.os.UserHandle getCreatorUserHandle();
+ public static android.app.PendingIntent getForegroundService(android.content.Context, int, android.content.Intent, int);
+ public android.content.Intent getIntent();
public android.content.IntentSender getIntentSender();
public static android.app.PendingIntent getService(android.content.Context, int, android.content.Intent, int);
+ public java.lang.String getTag(java.lang.String);
+ public android.content.IIntentSender getTarget();
public java.lang.String getTargetPackage();
+ public android.os.IBinder getWhitelistToken();
public int hashCode();
+ public boolean isActivity();
+ public boolean isForegroundService();
+ public boolean isTargetedToPackage();
public static android.app.PendingIntent readPendingIntentOrNullFromParcel(android.os.Parcel);
+ public void registerCancelListener(android.app.PendingIntent$CancelListener);
public void send();
public void send(int);
public void send(android.content.Context, int, android.content.Intent);
@@ -39,9 +3920,13 @@
public void send(android.content.Context, int, android.content.Intent, android.app.PendingIntent$OnFinished, android.os.Handler);
public void send(android.content.Context, int, android.content.Intent, android.app.PendingIntent$OnFinished, android.os.Handler, java.lang.String);
public void send(android.content.Context, int, android.content.Intent, android.app.PendingIntent$OnFinished, android.os.Handler, java.lang.String, android.os.Bundle);
+ public int sendAndReturnResult(android.content.Context, int, android.content.Intent, android.app.PendingIntent$OnFinished, android.os.Handler, java.lang.String, android.os.Bundle);
+ public static void setOnMarshaledListener(android.app.PendingIntent$OnMarshaledListener);
public java.lang.String toString();
+ public void unregisterCancelListener(android.app.PendingIntent$CancelListener);
public static void writePendingIntentOrNullToParcel(android.app.PendingIntent, android.os.Parcel);
public void writeToParcel(android.os.Parcel, int);
+ public void writeToProto(android.util.proto.ProtoOutputStream, long);
public static android.os.Parcelable$Creator CREATOR;
@@ -52,6 +3937,13 @@
public static int FLAG_UPDATE_CURRENT;
}
+-keep class android.app.PendingIntent$CancelListener {
+
+ public abstract void onCancelled(android.app.PendingIntent);
+
+
+}
+
-keep class android.app.PendingIntent$CanceledException {
<init>();
<init>(java.lang.String);
@@ -68,6 +3960,687 @@
}
+-keep class android.app.PendingIntent$OnMarshaledListener {
+
+ public abstract void onMarshaled(android.app.PendingIntent, android.os.Parcel, int);
+
+
+}
+
+-keep class android.app.Person {
+
+ public int describeContents();
+ public android.graphics.drawable.Icon getIcon();
+ public java.lang.String getKey();
+ public java.lang.CharSequence getName();
+ public java.lang.String getUri();
+ public boolean isBot();
+ public boolean isImportant();
+ public java.lang.String resolveToLegacyUri();
+ public android.app.Person$Builder toBuilder();
+ public void writeToParcel(android.os.Parcel, int);
+
+
+ public static android.os.Parcelable$Creator CREATOR;
+}
+
+-keep class android.app.Person$Builder {
+ <init>();
+
+ public android.app.Person build();
+ public android.app.Person$Builder setBot(boolean);
+ public android.app.Person$Builder setIcon(android.graphics.drawable.Icon);
+ public android.app.Person$Builder setImportant(boolean);
+ public android.app.Person$Builder setKey(java.lang.String);
+ public android.app.Person$Builder setName(java.lang.CharSequence);
+ public android.app.Person$Builder setUri(java.lang.String);
+
+
+}
+
+-keep class android.app.PictureInPictureArgs {
+ <init>();
+ <init>(float, java.util.List);
+
+ public static android.app.PictureInPictureArgs convert(android.app.PictureInPictureParams);
+ public static android.app.PictureInPictureParams convert(android.app.PictureInPictureArgs);
+ public void copyOnlySet(android.app.PictureInPictureArgs);
+ public int describeContents();
+ public java.util.List getActions();
+ public float getAspectRatio();
+ public android.util.Rational getAspectRatioRational();
+ public android.graphics.Rect getSourceRectHint();
+ public android.graphics.Rect getSourceRectHintInsets();
+ public boolean hasSetActions();
+ public boolean hasSetAspectRatio();
+ public boolean hasSourceBoundsHint();
+ public boolean hasSourceBoundsHintInsets();
+ public void setActions(java.util.List);
+ public void setAspectRatio(float);
+ public void setSourceRectHint(android.graphics.Rect);
+ public void setSourceRectHintInsets(android.graphics.Rect);
+ public void truncateActions(int);
+ public void writeToParcel(android.os.Parcel, int);
+
+
+ public static android.os.Parcelable$Creator CREATOR;
+}
+
+-keep class android.app.PictureInPictureParams {
+
+ public void copyOnlySet(android.app.PictureInPictureParams);
+ public int describeContents();
+ public java.util.List getActions();
+ public float getAspectRatio();
+ public android.util.Rational getAspectRatioRational();
+ public android.graphics.Rect getSourceRectHint();
+ public boolean hasSetActions();
+ public boolean hasSetAspectRatio();
+ public boolean hasSourceBoundsHint();
+ public void truncateActions(int);
+ public void writeToParcel(android.os.Parcel, int);
+
+
+ public static android.os.Parcelable$Creator CREATOR;
+}
+
+-keep class android.app.ProfilerInfo {
+ <init>(java.lang.String, android.os.ParcelFileDescriptor, int, boolean, boolean, java.lang.String, boolean);
+ <init>(android.app.ProfilerInfo);
+
+ public void closeFd();
+ public int describeContents();
+ public boolean equals(java.lang.Object);
+ public int hashCode();
+ public android.app.ProfilerInfo setAgent(java.lang.String, boolean);
+ public void writeToParcel(android.os.Parcel, int);
+ public void writeToProto(android.util.proto.ProtoOutputStream, long);
+
+
+ public static android.os.Parcelable$Creator CREATOR;
+ public java.lang.String agent;
+ public boolean attachAgentDuringBind;
+ public boolean autoStopProfiler;
+ public android.os.ParcelFileDescriptor profileFd;
+ public java.lang.String profileFile;
+ public int samplingInterval;
+ public boolean streamingOutput;
+}
+
+-keep class android.app.RemoteAction {
+ <init>(android.graphics.drawable.Icon, java.lang.CharSequence, java.lang.CharSequence, android.app.PendingIntent);
+
+ public android.app.RemoteAction clone();
+ public java.lang.Object clone();
+ public int describeContents();
+ public void dump(java.lang.String, java.io.PrintWriter);
+ public android.app.PendingIntent getActionIntent();
+ public java.lang.CharSequence getContentDescription();
+ public android.graphics.drawable.Icon getIcon();
+ public java.lang.CharSequence getTitle();
+ public boolean isEnabled();
+ public void setEnabled(boolean);
+ public void setShouldShowIcon(boolean);
+ public boolean shouldShowIcon();
+ public void writeToParcel(android.os.Parcel, int);
+
+
+ public static android.os.Parcelable$Creator CREATOR;
+}
+
+-keep class android.app.RemoteInput {
+
+ public static void addDataResultToIntent(android.app.RemoteInput, android.content.Intent, java.util.Map);
+ public static void addResultsToIntent(android.app.RemoteInput[], android.content.Intent, android.os.Bundle);
+ public int describeContents();
+ public boolean getAllowFreeFormInput();
+ public java.util.Set getAllowedDataTypes();
+ public java.lang.CharSequence[] getChoices();
+ public static java.util.Map getDataResultsFromIntent(android.content.Intent, java.lang.String);
+ public android.os.Bundle getExtras();
+ public java.lang.CharSequence getLabel();
+ public java.lang.String getResultKey();
+ public static android.os.Bundle getResultsFromIntent(android.content.Intent);
+ public static int getResultsSource(android.content.Intent);
+ public boolean isDataOnly();
+ public static void setResultsSource(android.content.Intent, int);
+ public void writeToParcel(android.os.Parcel, int);
+
+
+ public static android.os.Parcelable$Creator CREATOR;
+ public static java.lang.String EXTRA_RESULTS_DATA;
+ public static java.lang.String RESULTS_CLIP_LABEL;
+ public static int SOURCE_CHOICE;
+ public static int SOURCE_FREE_FORM_INPUT;
+}
+
+-keep class android.app.ResultInfo {
+ <init>(java.lang.String, int, int, android.content.Intent);
+ <init>(android.os.Parcel);
+
+ public int describeContents();
+ public boolean equals(java.lang.Object);
+ public int hashCode();
+ public java.lang.String toString();
+ public void writeToParcel(android.os.Parcel, int);
+
+
+ public static android.os.Parcelable$Creator CREATOR;
+ public android.content.Intent mData;
+ public int mRequestCode;
+ public int mResultCode;
+ public java.lang.String mResultWho;
+}
+
+-keep class android.app.Service {
+ <init>();
+
+ public void attach(android.content.Context, android.app.ActivityThread, java.lang.String, android.os.IBinder, android.app.Application, java.lang.Object);
+ public void detachAndCleanUp();
+ protected void dump(java.io.FileDescriptor, java.io.PrintWriter, java.lang.String[]);
+ public android.app.Application getApplication();
+ public abstract android.os.IBinder onBind(android.content.Intent);
+ public void onConfigurationChanged(android.content.res.Configuration);
+ public void onCreate();
+ public void onDestroy();
+ public void onLowMemory();
+ public void onRebind(android.content.Intent);
+ public void onStart(android.content.Intent, int);
+ public int onStartCommand(android.content.Intent, int, int);
+ public void onTaskRemoved(android.content.Intent);
+ public void onTrimMemory(int);
+ public boolean onUnbind(android.content.Intent);
+ public void setForeground(boolean);
+ public void startForeground(int, android.app.Notification);
+ public void stopForeground(boolean);
+ public void stopForeground(int);
+ public void stopSelf();
+ public void stopSelf(int);
+ public boolean stopSelfResult(int);
+
+
+ public static int START_CONTINUATION_MASK;
+ public static int START_FLAG_REDELIVERY;
+ public static int START_FLAG_RETRY;
+ public static int START_NOT_STICKY;
+ public static int START_REDELIVER_INTENT;
+ public static int START_STICKY;
+ public static int START_STICKY_COMPATIBILITY;
+ public static int START_TASK_REMOVED_COMPLETE;
+ public static int STOP_FOREGROUND_DETACH;
+ public static int STOP_FOREGROUND_REMOVE;
+}
+
+-keep class android.app.SharedElementCallback {
+ <init>();
+
+ public android.os.Parcelable onCaptureSharedElementSnapshot(android.view.View, android.graphics.Matrix, android.graphics.RectF);
+ public android.view.View onCreateSnapshotView(android.content.Context, android.os.Parcelable);
+ public void onMapSharedElements(java.util.List, java.util.Map);
+ public void onRejectSharedElements(java.util.List);
+ public void onSharedElementEnd(java.util.List, java.util.List, java.util.List);
+ public void onSharedElementStart(java.util.List, java.util.List, java.util.List);
+ public void onSharedElementsArrived(java.util.List, java.util.List, android.app.SharedElementCallback$OnSharedElementsReadyListener);
+
+
+}
+
+-keep class android.app.SharedElementCallback$OnSharedElementsReadyListener {
+
+ public abstract void onSharedElementsReady();
+
+
+}
+
+-keep class android.app.TaskStackBuilder {
+
+ public android.app.TaskStackBuilder addNextIntent(android.content.Intent);
+ public android.app.TaskStackBuilder addNextIntentWithParentStack(android.content.Intent);
+ public android.app.TaskStackBuilder addParentStack(android.app.Activity);
+ public android.app.TaskStackBuilder addParentStack(java.lang.Class);
+ public android.app.TaskStackBuilder addParentStack(android.content.ComponentName);
+ public static android.app.TaskStackBuilder create(android.content.Context);
+ public android.content.Intent editIntentAt(int);
+ public int getIntentCount();
+ public android.content.Intent[] getIntents();
+ public android.app.PendingIntent getPendingIntent(int, int);
+ public android.app.PendingIntent getPendingIntent(int, int, android.os.Bundle);
+ public android.app.PendingIntent getPendingIntent(int, int, android.os.Bundle, android.os.UserHandle);
+ public void startActivities();
+ public int startActivities(android.os.Bundle, android.os.UserHandle);
+ public void startActivities(android.os.Bundle);
+
+
+}
+
+-keep class android.app.UiAutomation {
+ <init>(android.os.Looper, android.app.IUiAutomationConnection);
+
+ public void clearWindowAnimationFrameStats();
+ public boolean clearWindowContentFrameStats(int);
+ public void connect();
+ public void connect(int);
+ public void destroy();
+ public void disconnect();
+ public android.view.accessibility.AccessibilityEvent executeAndWaitForEvent(java.lang.Runnable, android.app.UiAutomation$AccessibilityEventFilter, long);
+ public android.os.ParcelFileDescriptor executeShellCommand(java.lang.String);
+ public android.os.ParcelFileDescriptor[] executeShellCommandRw(java.lang.String);
+ public android.view.accessibility.AccessibilityNodeInfo findFocus(int);
+ public int getConnectionId();
+ public int getFlags();
+ public android.view.accessibility.AccessibilityNodeInfo getRootInActiveWindow();
+ public android.accessibilityservice.AccessibilityServiceInfo getServiceInfo();
+ public android.view.WindowAnimationFrameStats getWindowAnimationFrameStats();
+ public android.view.WindowContentFrameStats getWindowContentFrameStats(int);
+ public java.util.List getWindows();
+ public void grantRuntimePermission(java.lang.String, java.lang.String);
+ public boolean grantRuntimePermission(java.lang.String, java.lang.String, android.os.UserHandle);
+ public void grantRuntimePermissionAsUser(java.lang.String, java.lang.String, android.os.UserHandle);
+ public boolean injectInputEvent(android.view.InputEvent, boolean);
+ public boolean isDestroyed();
+ public boolean performGlobalAction(int);
+ public void revokeRuntimePermission(java.lang.String, java.lang.String);
+ public boolean revokeRuntimePermission(java.lang.String, java.lang.String, android.os.UserHandle);
+ public void revokeRuntimePermissionAsUser(java.lang.String, java.lang.String, android.os.UserHandle);
+ public void setOnAccessibilityEventListener(android.app.UiAutomation$OnAccessibilityEventListener);
+ public boolean setRotation(int);
+ public void setRunAsMonkey(boolean);
+ public void setServiceInfo(android.accessibilityservice.AccessibilityServiceInfo);
+ public android.graphics.Bitmap takeScreenshot();
+ public void waitForIdle(long, long);
+
+
+ public static int FLAG_DONT_SUPPRESS_ACCESSIBILITY_SERVICES;
+ public static int ROTATION_FREEZE_0;
+ public static int ROTATION_FREEZE_180;
+ public static int ROTATION_FREEZE_270;
+ public static int ROTATION_FREEZE_90;
+ public static int ROTATION_FREEZE_CURRENT;
+ public static int ROTATION_UNFREEZE;
+}
+
+-keep class android.app.UiAutomation$AccessibilityEventFilter {
+
+ public abstract boolean accept(android.view.accessibility.AccessibilityEvent);
+
+
+}
+
+-keep class android.app.UiAutomation$OnAccessibilityEventListener {
+
+ public abstract void onAccessibilityEvent(android.view.accessibility.AccessibilityEvent);
+
+
+}
+
+-keep class android.app.VoiceInteractor {
+
+ public android.app.VoiceInteractor$Request getActiveRequest(java.lang.String);
+ public android.app.VoiceInteractor$Request[] getActiveRequests();
+ public boolean submitRequest(android.app.VoiceInteractor$Request);
+ public boolean submitRequest(android.app.VoiceInteractor$Request, java.lang.String);
+ public boolean[] supportsCommands(java.lang.String[]);
+
+
+}
+
+-keep class android.app.VoiceInteractor$PickOptionRequest {
+ <init>(android.app.VoiceInteractor$Prompt, android.app.VoiceInteractor$PickOptionRequest$Option[], android.os.Bundle);
+ <init>(java.lang.CharSequence, android.app.VoiceInteractor$PickOptionRequest$Option[], android.os.Bundle);
+
+ public void onPickOptionResult(boolean, android.app.VoiceInteractor$PickOptionRequest$Option[], android.os.Bundle);
+
+
+}
+
+-keep class android.app.VoiceInteractor$PickOptionRequest$Option {
+ <init>(java.lang.CharSequence);
+ <init>(java.lang.CharSequence, int);
+
+ public android.app.VoiceInteractor$PickOptionRequest$Option addSynonym(java.lang.CharSequence);
+ public int countSynonyms();
+ public int describeContents();
+ public android.os.Bundle getExtras();
+ public int getIndex();
+ public java.lang.CharSequence getLabel();
+ public java.lang.CharSequence getSynonymAt(int);
+ public void setExtras(android.os.Bundle);
+ public void writeToParcel(android.os.Parcel, int);
+
+
+ public static android.os.Parcelable$Creator CREATOR;
+}
+
+-keep class android.app.VoiceInteractor$Prompt {
+ <init>(java.lang.CharSequence[], java.lang.CharSequence);
+ <init>(java.lang.CharSequence);
+
+ public int countVoicePrompts();
+ public int describeContents();
+ public java.lang.CharSequence getVisualPrompt();
+ public java.lang.CharSequence getVoicePromptAt(int);
+ public java.lang.String toString();
+ public void writeToParcel(android.os.Parcel, int);
+
+
+ public static android.os.Parcelable$Creator CREATOR;
+}
+
+-keep class android.app.VoiceInteractor$Request {
+
+ public void cancel();
+ public android.app.Activity getActivity();
+ public android.content.Context getContext();
+ public java.lang.String getName();
+ public void onAttached(android.app.Activity);
+ public void onCancel();
+ public void onDetached();
+ public java.lang.String toString();
+
+
+}
+
+-keep class android.app.WaitResult {
+ <init>();
+
+ public int describeContents();
+ public void dump(java.io.PrintWriter, java.lang.String);
+ public void writeToParcel(android.os.Parcel, int);
+
+
+ public static android.os.Parcelable$Creator CREATOR;
+ public int result;
+ public long thisTime;
+ public boolean timeout;
+ public long totalTime;
+ public android.content.ComponentName who;
+}
+
+-keep class android.app.WindowConfiguration {
+ <init>();
+ <init>(android.app.WindowConfiguration);
+
+ public static java.lang.String activityTypeToString(int);
+ public boolean canReceiveKeys();
+ public boolean canResizeTask();
+ public int compareTo(android.app.WindowConfiguration);
+ public int compareTo(java.lang.Object);
+ public int describeContents();
+ public long diff(android.app.WindowConfiguration, boolean);
+ public boolean equals(java.lang.Object);
+ public int getActivityType();
+ public android.graphics.Rect getAppBounds();
+ public android.graphics.Rect getBounds();
+ public int getWindowingMode();
+ public boolean hasMovementAnimations();
+ public boolean hasWindowDecorCaption();
+ public boolean hasWindowShadow();
+ public int hashCode();
+ public boolean isAlwaysOnTop();
+ public static boolean isFloating(int);
+ public boolean keepVisibleDeadAppWindowOnScreen();
+ public boolean persistTaskBounds();
+ public void setActivityType(int);
+ public void setAppBounds(android.graphics.Rect);
+ public void setAppBounds(int, int, int, int);
+ public void setBounds(android.graphics.Rect);
+ public void setTo(android.app.WindowConfiguration);
+ public void setToDefaults();
+ public void setWindowingMode(int);
+ public boolean supportSplitScreenWindowingMode();
+ public static boolean supportSplitScreenWindowingMode(int);
+ public boolean tasksAreFloating();
+ public java.lang.String toString();
+ public void unset();
+ public int updateFrom(android.app.WindowConfiguration);
+ public boolean useWindowFrameForBackdrop();
+ public static java.lang.String windowingModeToString(int);
+ public boolean windowsAreScaleable();
+ public void writeToParcel(android.os.Parcel, int);
+ public void writeToProto(android.util.proto.ProtoOutputStream, long);
+
+
+ public static int ACTIVITY_TYPE_ASSISTANT;
+ public static int ACTIVITY_TYPE_HOME;
+ public static int ACTIVITY_TYPE_RECENTS;
+ public static int ACTIVITY_TYPE_STANDARD;
+ public static int ACTIVITY_TYPE_UNDEFINED;
+ public static android.os.Parcelable$Creator CREATOR;
+ public static int PINNED_WINDOWING_MODE_ELEVATION_IN_DIP;
+ public static int WINDOWING_MODE_FREEFORM;
+ public static int WINDOWING_MODE_FULLSCREEN;
+ public static int WINDOWING_MODE_FULLSCREEN_OR_SPLIT_SCREEN_SECONDARY;
+ public static int WINDOWING_MODE_PINNED;
+ public static int WINDOWING_MODE_SPLIT_SCREEN_PRIMARY;
+ public static int WINDOWING_MODE_SPLIT_SCREEN_SECONDARY;
+ public static int WINDOWING_MODE_UNDEFINED;
+ public static int WINDOW_CONFIG_ACTIVITY_TYPE;
+ public static int WINDOW_CONFIG_APP_BOUNDS;
+ public static int WINDOW_CONFIG_BOUNDS;
+ public static int WINDOW_CONFIG_WINDOWING_MODE;
+}
+
+-keep class android.app.assist.AssistContent {
+ <init>();
+
+ public int describeContents();
+ public android.content.ClipData getClipData();
+ public android.os.Bundle getExtras();
+ public android.content.Intent getIntent();
+ public java.lang.String getStructuredData();
+ public android.net.Uri getWebUri();
+ public boolean isAppProvidedIntent();
+ public boolean isAppProvidedWebUri();
+ public void setClipData(android.content.ClipData);
+ public void setDefaultIntent(android.content.Intent);
+ public void setIntent(android.content.Intent);
+ public void setStructuredData(java.lang.String);
+ public void setWebUri(android.net.Uri);
+ public void writeToParcel(android.os.Parcel, int);
+
+
+ public static android.os.Parcelable$Creator CREATOR;
+}
+
+-keep class android.app.assist.AssistStructure {
+ <init>(android.app.Activity, boolean, int);
+ <init>();
+ <init>(android.os.Parcel);
+
+ public void clearSendChannel();
+ public int describeContents();
+ public void dump(boolean);
+ public void ensureData();
+ public void ensureDataForAutofill();
+ public long getAcquisitionEndTime();
+ public long getAcquisitionStartTime();
+ public android.content.ComponentName getActivityComponent();
+ public int getFlags();
+ public android.app.assist.AssistStructure$WindowNode getWindowNodeAt(int);
+ public int getWindowNodeCount();
+ public boolean isHomeActivity();
+ public void sanitizeForParceling(boolean);
+ public void setAcquisitionEndTime(long);
+ public void setAcquisitionStartTime(long);
+ public void setActivityComponent(android.content.ComponentName);
+ public void setHomeActivity(boolean);
+ public void writeToParcel(android.os.Parcel, int);
+
+
+ public static android.os.Parcelable$Creator CREATOR;
+}
+
+-keep class android.app.assist.AssistStructure$AutofillOverlay {
+ <init>();
+
+
+
+ public boolean focused;
+ public android.view.autofill.AutofillValue value;
+}
+
+-keep class android.app.assist.AssistStructure$ViewNode {
+
+ public float getAlpha();
+ public java.lang.String[] getAutofillHints();
+ public android.view.autofill.AutofillId getAutofillId();
+ public java.lang.CharSequence[] getAutofillOptions();
+ public int getAutofillType();
+ public android.view.autofill.AutofillValue getAutofillValue();
+ public android.app.assist.AssistStructure$ViewNode getChildAt(int);
+ public int getChildCount();
+ public java.lang.String getClassName();
+ public java.lang.CharSequence getContentDescription();
+ public float getElevation();
+ public android.os.Bundle getExtras();
+ public int getHeight();
+ public java.lang.String getHint();
+ public android.view.ViewStructure$HtmlInfo getHtmlInfo();
+ public int getId();
+ public java.lang.String getIdEntry();
+ public java.lang.String getIdPackage();
+ public java.lang.String getIdType();
+ public int getImportantForAutofill();
+ public int getInputType();
+ public int getLeft();
+ public android.os.LocaleList getLocaleList();
+ public int getMaxTextEms();
+ public int getMaxTextLength();
+ public int getMinTextEms();
+ public int getScrollX();
+ public int getScrollY();
+ public java.lang.CharSequence getText();
+ public int getTextBackgroundColor();
+ public int getTextColor();
+ public java.lang.String getTextIdEntry();
+ public int[] getTextLineBaselines();
+ public int[] getTextLineCharOffsets();
+ public int getTextSelectionEnd();
+ public int getTextSelectionStart();
+ public float getTextSize();
+ public int getTextStyle();
+ public int getTop();
+ public android.graphics.Matrix getTransformation();
+ public int getVisibility();
+ public java.lang.String getWebDomain();
+ public java.lang.String getWebScheme();
+ public int getWidth();
+ public boolean isAccessibilityFocused();
+ public boolean isActivated();
+ public boolean isAssistBlocked();
+ public boolean isCheckable();
+ public boolean isChecked();
+ public boolean isClickable();
+ public boolean isContextClickable();
+ public boolean isEnabled();
+ public boolean isFocusable();
+ public boolean isFocused();
+ public boolean isLongClickable();
+ public boolean isOpaque();
+ public boolean isSanitized();
+ public boolean isSelected();
+ public void setAutofillOverlay(android.app.assist.AssistStructure$AutofillOverlay);
+ public void setWebDomain(java.lang.String);
+ public void updateAutofillValue(android.view.autofill.AutofillValue);
+
+
+ public static int TEXT_COLOR_UNDEFINED;
+ public static int TEXT_STYLE_BOLD;
+ public static int TEXT_STYLE_ITALIC;
+ public static int TEXT_STYLE_STRIKE_THRU;
+ public static int TEXT_STYLE_UNDERLINE;
+}
+
+-keep class android.app.assist.AssistStructure$WindowNode {
+
+ public int getDisplayId();
+ public int getHeight();
+ public int getLeft();
+ public android.app.assist.AssistStructure$ViewNode getRootViewNode();
+ public java.lang.CharSequence getTitle();
+ public int getTop();
+ public int getWidth();
+
+
+}
+
+-keep class android.app.servertransaction.ActivityLifecycleItem {
+ <init>();
+
+ public abstract int getTargetState();
+ public void recycle();
+
+
+ public static int ON_CREATE;
+ public static int ON_DESTROY;
+ public static int ON_PAUSE;
+ public static int ON_RESTART;
+ public static int ON_RESUME;
+ public static int ON_START;
+ public static int ON_STOP;
+ public static int PRE_ON_CREATE;
+ public static int UNDEFINED;
+}
+
+-keep class android.app.servertransaction.ClientTransaction {
+
+ public void addCallback(android.app.servertransaction.ClientTransactionItem);
+ public int describeContents();
+ public boolean equals(java.lang.Object);
+ public android.os.IBinder getActivityToken();
+ public android.app.IApplicationThread getClient();
+ public android.app.servertransaction.ActivityLifecycleItem getLifecycleStateRequest();
+ public int hashCode();
+ public static android.app.servertransaction.ClientTransaction obtain(android.app.IApplicationThread, android.os.IBinder);
+ public void preExecute(android.app.ClientTransactionHandler);
+ public void recycle();
+ public void schedule();
+ public void setLifecycleStateRequest(android.app.servertransaction.ActivityLifecycleItem);
+ public void writeToParcel(android.os.Parcel, int);
+
+
+ public static android.os.Parcelable$Creator CREATOR;
+}
+
+-keep class android.app.servertransaction.ClientTransactionItem {
+ <init>();
+
+ public int describeContents();
+ public int getPostExecutionState();
+
+
+}
+
+-keep class android.app.servertransaction.PendingTransactionActions {
+ <init>();
+
+ public void clear();
+ public android.os.Bundle getOldState();
+ public android.app.servertransaction.PendingTransactionActions$StopInfo getStopInfo();
+ public void setCallOnPostCreate(boolean);
+ public void setOldState(android.os.Bundle);
+ public void setReportRelaunchToWindowManager(boolean);
+ public void setRestoreInstanceState(boolean);
+ public void setStopInfo(android.app.servertransaction.PendingTransactionActions$StopInfo);
+ public boolean shouldCallOnPostCreate();
+ public boolean shouldReportRelaunchToWindowManager();
+ public boolean shouldRestoreInstanceState();
+
+
+}
+
+-keep class android.app.servertransaction.PendingTransactionActions$StopInfo {
+ <init>();
+
+ public void run();
+ public void setActivity(android.app.ActivityThread$ActivityClientRecord);
+ public void setDescription(java.lang.CharSequence);
+ public void setPersistentState(android.os.PersistableBundle);
+ public void setState(android.os.Bundle);
+
+
+}
+
-keep class android.content.BroadcastReceiver {
<init>();
@@ -75,9 +4648,11 @@
public void clearAbortBroadcast();
public boolean getAbortBroadcast();
public boolean getDebugUnregister();
+ public android.content.BroadcastReceiver$PendingResult getPendingResult();
public int getResultCode();
public java.lang.String getResultData();
public android.os.Bundle getResultExtras(boolean);
+ public int getSendingUserId();
public android.content.BroadcastReceiver$PendingResult goAsync();
public boolean isInitialStickyBroadcast();
public boolean isOrderedBroadcast();
@@ -85,6 +4660,7 @@
public android.os.IBinder peekService(android.content.Context, android.content.Intent);
public void setDebugUnregister(boolean);
public void setOrderedHint(boolean);
+ public void setPendingResult(android.content.BroadcastReceiver$PendingResult);
public void setResult(int, java.lang.String, android.os.Bundle);
public void setResultCode(int);
public void setResultData(java.lang.String);
@@ -94,6 +4670,7 @@
}
-keep class android.content.BroadcastReceiver$PendingResult {
+ <init>(int, java.lang.String, android.os.Bundle, int, boolean, boolean, android.os.IBinder, int, int);
public void abortBroadcast();
public void clearAbortBroadcast();
@@ -102,22 +4679,35 @@
public int getResultCode();
public java.lang.String getResultData();
public android.os.Bundle getResultExtras(boolean);
+ public int getSendingUserId();
+ public void sendFinished(android.app.IActivityManager);
+ public void setExtrasClassLoader(java.lang.ClassLoader);
public void setResult(int, java.lang.String, android.os.Bundle);
public void setResultCode(int);
public void setResultData(java.lang.String);
public void setResultExtras(android.os.Bundle);
+ public static int TYPE_COMPONENT;
+ public static int TYPE_REGISTERED;
+ public static int TYPE_UNREGISTERED;
}
-keep class android.content.ClipData {
<init>(java.lang.CharSequence, java.lang.String[], android.content.ClipData$Item);
<init>(android.content.ClipDescription, android.content.ClipData$Item);
+ <init>(android.content.ClipDescription, java.util.ArrayList);
<init>(android.content.ClipData);
public void addItem(android.content.ClipData$Item);
+ public void addItem(android.content.ClipData$Item, android.content.ContentResolver);
+ public void addItem(android.content.ContentResolver, android.content.ClipData$Item);
+ public void collectUris(java.util.List);
public int describeContents();
+ public void fixUris(int);
+ public void fixUrisLight(int);
public android.content.ClipDescription getDescription();
+ public android.graphics.Bitmap getIcon();
public android.content.ClipData$Item getItemAt(int);
public int getItemCount();
public static android.content.ClipData newHtmlText(java.lang.CharSequence, java.lang.CharSequence, java.lang.String);
@@ -125,14 +4715,22 @@
public static android.content.ClipData newPlainText(java.lang.CharSequence, java.lang.CharSequence);
public static android.content.ClipData newRawUri(java.lang.CharSequence, android.net.Uri);
public static android.content.ClipData newUri(android.content.ContentResolver, java.lang.CharSequence, android.net.Uri);
+ public void prepareToEnterProcess();
+ public void prepareToLeaveProcess(boolean);
+ public void prepareToLeaveProcess(boolean, int);
+ public void setItemAt(int, android.content.ClipData$Item);
+ public void toShortString(java.lang.StringBuilder);
+ public void toShortStringShortItems(java.lang.StringBuilder, boolean);
public java.lang.String toString();
public void writeToParcel(android.os.Parcel, int);
+ public void writeToProto(android.util.proto.ProtoOutputStream, long);
public static android.os.Parcelable$Creator CREATOR;
}
-keep class android.content.ClipData$Item {
+ <init>(android.content.ClipData$Item);
<init>(java.lang.CharSequence);
<init>(java.lang.CharSequence, java.lang.String);
<init>(android.content.Intent);
@@ -147,7 +4745,10 @@
public android.content.Intent getIntent();
public java.lang.CharSequence getText();
public android.net.Uri getUri();
+ public void toShortString(java.lang.StringBuilder);
+ public void toShortSummaryString(java.lang.StringBuilder);
public java.lang.String toString();
+ public void writeToProto(android.util.proto.ProtoOutputStream, long);
}
@@ -159,15 +4760,25 @@
public static boolean compareMimeTypes(java.lang.String, java.lang.String);
public int describeContents();
public java.lang.String[] filterMimeTypes(java.lang.String);
+ public android.os.PersistableBundle getExtras();
public java.lang.CharSequence getLabel();
public java.lang.String getMimeType(int);
public int getMimeTypeCount();
+ public long getTimestamp();
public boolean hasMimeType(java.lang.String);
+ public void setExtras(android.os.PersistableBundle);
+ public void setTimestamp(long);
+ public boolean toShortString(java.lang.StringBuilder);
+ public boolean toShortStringTypesOnly(java.lang.StringBuilder);
public java.lang.String toString();
+ public void validate();
public void writeToParcel(android.os.Parcel, int);
+ public void writeToProto(android.util.proto.ProtoOutputStream, long);
public static android.os.Parcelable$Creator CREATOR;
+ public static java.lang.String EXTRA_TARGET_COMPONENT_NAME;
+ public static java.lang.String EXTRA_USER_SERIAL_NUMBER;
public static java.lang.String MIMETYPE_TEXT_HTML;
public static java.lang.String MIMETYPE_TEXT_INTENT;
public static java.lang.String MIMETYPE_TEXT_PLAIN;
@@ -188,6 +4799,8 @@
<init>(android.content.Context, java.lang.Class);
<init>(android.os.Parcel);
+ public void appendShortString(java.lang.StringBuilder);
+ public static void appendShortString(java.lang.StringBuilder, java.lang.String, java.lang.String);
public android.content.ComponentName clone();
public java.lang.Object clone();
public int compareTo(android.content.ComponentName);
@@ -202,12 +4815,14 @@
public java.lang.String getPackageName();
public java.lang.String getShortClassName();
public int hashCode();
+ public static void printShortString(java.io.PrintWriter, java.lang.String, java.lang.String);
public static android.content.ComponentName readFromParcel(android.os.Parcel);
public java.lang.String toShortString();
public java.lang.String toString();
public static android.content.ComponentName unflattenFromString(java.lang.String);
public void writeToParcel(android.os.Parcel, int);
public static void writeToParcel(android.content.ComponentName, android.os.Parcel);
+ public void writeToProto(android.util.proto.ProtoOutputStream, long);
public static android.os.Parcelable$Creator CREATOR;
@@ -215,23 +4830,38 @@
-keep class android.content.ContentProvider {
<init>();
+ <init>(android.content.Context, java.lang.String, java.lang.String, android.content.pm.PathPermission[]);
public android.content.ContentProviderResult[] applyBatch(java.util.ArrayList);
public void attachInfo(android.content.Context, android.content.pm.ProviderInfo);
+ public void attachInfoForTesting(android.content.Context, android.content.pm.ProviderInfo);
public int bulkInsert(android.net.Uri, android.content.ContentValues[]);
public android.os.Bundle call(java.lang.String, java.lang.String, android.os.Bundle);
public android.net.Uri canonicalize(android.net.Uri);
+ public static android.content.ContentProvider coerceToLocalContentProvider(android.content.IContentProvider);
public abstract int delete(android.net.Uri, java.lang.String, java.lang.String[]);
public void dump(java.io.FileDescriptor, java.io.PrintWriter, java.lang.String[]);
+ protected int enforceReadPermissionInner(android.net.Uri, java.lang.String, android.os.IBinder);
+ protected int enforceWritePermissionInner(android.net.Uri, java.lang.String, android.os.IBinder);
+ public android.app.AppOpsManager getAppOpsManager();
+ public static java.lang.String getAuthorityWithoutUserId(java.lang.String);
public java.lang.String getCallingPackage();
public android.content.Context getContext();
+ public android.content.IContentProvider getIContentProvider();
public android.content.pm.PathPermission[] getPathPermissions();
public java.lang.String getReadPermission();
public java.lang.String[] getStreamTypes(android.net.Uri, java.lang.String);
public abstract java.lang.String getType(android.net.Uri);
+ public static android.net.Uri getUriWithoutUserId(android.net.Uri);
+ public static int getUserIdFromAuthority(java.lang.String, int);
+ public static int getUserIdFromAuthority(java.lang.String);
+ public static int getUserIdFromUri(android.net.Uri, int);
+ public static int getUserIdFromUri(android.net.Uri);
public java.lang.String getWritePermission();
public abstract android.net.Uri insert(android.net.Uri, android.content.ContentValues);
protected boolean isTemporary();
+ protected boolean matchesOurAuthorities(java.lang.String);
+ public static android.net.Uri maybeAddUserId(android.net.Uri, int);
public void onConfigurationChanged(android.content.res.Configuration);
public abstract boolean onCreate();
public void onLowMemory();
@@ -246,12 +4876,18 @@
public android.content.res.AssetFileDescriptor openTypedAssetFile(android.net.Uri, java.lang.String, android.os.Bundle, android.os.CancellationSignal);
public abstract android.database.Cursor query(android.net.Uri, java.lang.String[], java.lang.String, java.lang.String[], java.lang.String);
public android.database.Cursor query(android.net.Uri, java.lang.String[], java.lang.String, java.lang.String[], java.lang.String, android.os.CancellationSignal);
+ public android.database.Cursor query(android.net.Uri, java.lang.String[], android.os.Bundle, android.os.CancellationSignal);
+ public boolean refresh(android.net.Uri, android.os.Bundle, android.os.CancellationSignal);
+ public android.net.Uri rejectInsert(android.net.Uri, android.content.ContentValues);
+ public void setAppOps(int, int);
+ protected void setAuthorities(java.lang.String);
protected void setPathPermissions(android.content.pm.PathPermission[]);
protected void setReadPermission(java.lang.String);
protected void setWritePermission(java.lang.String);
public void shutdown();
public android.net.Uri uncanonicalize(android.net.Uri);
public abstract int update(android.net.Uri, android.content.ContentValues, java.lang.String, java.lang.String[]);
+ public static boolean uriHasUserId(android.net.Uri);
}
@@ -264,11 +4900,13 @@
}
-keep class android.content.ContentProviderClient {
+ <init>(android.content.ContentResolver, android.content.IContentProvider, boolean);
public android.content.ContentProviderResult[] applyBatch(java.util.ArrayList);
public int bulkInsert(android.net.Uri, android.content.ContentValues[]);
public android.os.Bundle call(java.lang.String, java.lang.String, android.os.Bundle);
public android.net.Uri canonicalize(android.net.Uri);
+ public void close();
public int delete(android.net.Uri, java.lang.String, java.lang.String[]);
protected void finalize();
public android.content.ContentProvider getLocalContentProvider();
@@ -283,7 +4921,11 @@
public android.content.res.AssetFileDescriptor openTypedAssetFileDescriptor(android.net.Uri, java.lang.String, android.os.Bundle, android.os.CancellationSignal);
public android.database.Cursor query(android.net.Uri, java.lang.String[], java.lang.String, java.lang.String[], java.lang.String);
public android.database.Cursor query(android.net.Uri, java.lang.String[], java.lang.String, java.lang.String[], java.lang.String, android.os.CancellationSignal);
+ public android.database.Cursor query(android.net.Uri, java.lang.String[], android.os.Bundle, android.os.CancellationSignal);
+ public boolean refresh(android.net.Uri, android.os.Bundle, android.os.CancellationSignal);
public boolean release();
+ public static void releaseQuietly(android.content.ContentProviderClient);
+ public void setDetectNotResponding(long);
public android.net.Uri uncanonicalize(android.net.Uri);
public int update(android.net.Uri, android.content.ContentValues, java.lang.String, java.lang.String[]);
@@ -291,10 +4933,13 @@
}
-keep class android.content.ContentProviderOperation {
+ <init>(android.content.ContentProviderOperation, boolean);
public android.content.ContentProviderResult apply(android.content.ContentProvider, android.content.ContentProviderResult[], int);
public int describeContents();
+ public int getType();
public android.net.Uri getUri();
+ public android.content.ContentProviderOperation getWithoutUserIdInUri();
public boolean isAssertQuery();
public boolean isDelete();
public boolean isInsert();
@@ -313,6 +4958,10 @@
public static android.os.Parcelable$Creator CREATOR;
+ public static int TYPE_ASSERT;
+ public static int TYPE_DELETE;
+ public static int TYPE_INSERT;
+ public static int TYPE_UPDATE;
}
-keep class android.content.ContentProviderOperation$Builder {
@@ -334,6 +4983,7 @@
<init>(android.net.Uri);
<init>(int);
<init>(android.os.Parcel);
+ <init>(android.content.ContentProviderResult, int);
public int describeContents();
public java.lang.String toString();
@@ -350,34 +5000,66 @@
public android.content.ContentProviderClient acquireContentProviderClient(android.net.Uri);
public android.content.ContentProviderClient acquireContentProviderClient(java.lang.String);
+ protected android.content.IContentProvider acquireExistingProvider(android.content.Context, java.lang.String);
+ public android.content.IContentProvider acquireExistingProvider(android.net.Uri);
+ protected abstract android.content.IContentProvider acquireProvider(android.content.Context, java.lang.String);
+ public android.content.IContentProvider acquireProvider(android.net.Uri);
+ public android.content.IContentProvider acquireProvider(java.lang.String);
public android.content.ContentProviderClient acquireUnstableContentProviderClient(android.net.Uri);
public android.content.ContentProviderClient acquireUnstableContentProviderClient(java.lang.String);
+ protected abstract android.content.IContentProvider acquireUnstableProvider(android.content.Context, java.lang.String);
+ public android.content.IContentProvider acquireUnstableProvider(android.net.Uri);
+ public android.content.IContentProvider acquireUnstableProvider(java.lang.String);
public static void addPeriodicSync(android.accounts.Account, java.lang.String, android.os.Bundle, long);
public static java.lang.Object addStatusChangeListener(int, android.content.SyncStatusObserver);
+ public void appNotRespondingViaProvider(android.content.IContentProvider);
public android.content.ContentProviderResult[] applyBatch(java.lang.String, java.util.ArrayList);
public int bulkInsert(android.net.Uri, android.content.ContentValues[]);
public android.os.Bundle call(android.net.Uri, java.lang.String, java.lang.String, android.os.Bundle);
public void cancelSync(android.net.Uri);
public static void cancelSync(android.accounts.Account, java.lang.String);
public static void cancelSync(android.content.SyncRequest);
+ public static void cancelSyncAsUser(android.accounts.Account, java.lang.String, int);
public android.net.Uri canonicalize(android.net.Uri);
+ public static android.os.Bundle createSqlQueryBundle(java.lang.String, java.lang.String[], java.lang.String);
+ public static java.lang.String createSqlSortClause(android.os.Bundle);
public int delete(android.net.Uri, java.lang.String, java.lang.String[]);
+ public android.os.Bundle getCache(android.net.Uri);
+ public static android.content.IContentService getContentService();
public static android.content.SyncInfo getCurrentSync();
public static java.util.List getCurrentSyncs();
+ public static java.util.List getCurrentSyncsAsUser(int);
public static int getIsSyncable(android.accounts.Account, java.lang.String);
+ public static int getIsSyncableAsUser(android.accounts.Account, java.lang.String, int);
public static boolean getMasterSyncAutomatically();
+ public static boolean getMasterSyncAutomaticallyAsUser(int);
public java.util.List getOutgoingPersistedUriPermissions();
+ public java.lang.String getPackageName();
public static java.util.List getPeriodicSyncs(android.accounts.Account, java.lang.String);
public java.util.List getPersistedUriPermissions();
+ public android.content.ContentResolver$OpenResourceIdResult getResourceId(android.net.Uri);
public java.lang.String[] getStreamTypes(android.net.Uri, java.lang.String);
+ public static java.lang.String[] getSyncAdapterPackagesForAuthorityAsUser(java.lang.String, int);
public static android.content.SyncAdapterType[] getSyncAdapterTypes();
+ public static android.content.SyncAdapterType[] getSyncAdapterTypesAsUser(int);
public static boolean getSyncAutomatically(android.accounts.Account, java.lang.String);
+ public static boolean getSyncAutomaticallyAsUser(android.accounts.Account, java.lang.String, int);
+ public static android.content.SyncStatusInfo getSyncStatus(android.accounts.Account, java.lang.String);
+ public static android.content.SyncStatusInfo getSyncStatusAsUser(android.accounts.Account, java.lang.String, int);
+ public int getTargetSdkVersion();
public java.lang.String getType(android.net.Uri);
+ public android.graphics.drawable.Drawable getTypeDrawable(java.lang.String);
+ public int getUserId();
public android.net.Uri insert(android.net.Uri, android.content.ContentValues);
+ public static boolean invalidPeriodicExtras(android.os.Bundle);
public static boolean isSyncActive(android.accounts.Account, java.lang.String);
public static boolean isSyncPending(android.accounts.Account, java.lang.String);
+ public static boolean isSyncPendingAsUser(android.accounts.Account, java.lang.String, int);
public void notifyChange(android.net.Uri, android.database.ContentObserver);
public void notifyChange(android.net.Uri, android.database.ContentObserver, boolean);
+ public void notifyChange(android.net.Uri, android.database.ContentObserver, int);
+ public void notifyChange(android.net.Uri, android.database.ContentObserver, boolean, int);
+ public void notifyChange(android.net.Uri, android.database.ContentObserver, int, int);
public android.content.res.AssetFileDescriptor openAssetFileDescriptor(android.net.Uri, java.lang.String);
public android.content.res.AssetFileDescriptor openAssetFileDescriptor(android.net.Uri, java.lang.String, android.os.CancellationSignal);
public android.os.ParcelFileDescriptor openFileDescriptor(android.net.Uri, java.lang.String);
@@ -387,35 +5069,80 @@
public java.io.OutputStream openOutputStream(android.net.Uri, java.lang.String);
public android.content.res.AssetFileDescriptor openTypedAssetFileDescriptor(android.net.Uri, java.lang.String, android.os.Bundle);
public android.content.res.AssetFileDescriptor openTypedAssetFileDescriptor(android.net.Uri, java.lang.String, android.os.Bundle, android.os.CancellationSignal);
+ public void putCache(android.net.Uri, android.os.Bundle);
public android.database.Cursor query(android.net.Uri, java.lang.String[], java.lang.String, java.lang.String[], java.lang.String);
public android.database.Cursor query(android.net.Uri, java.lang.String[], java.lang.String, java.lang.String[], java.lang.String, android.os.CancellationSignal);
+ public android.database.Cursor query(android.net.Uri, java.lang.String[], android.os.Bundle, android.os.CancellationSignal);
+ public boolean refresh(android.net.Uri, android.os.Bundle, android.os.CancellationSignal);
public void registerContentObserver(android.net.Uri, boolean, android.database.ContentObserver);
+ public void registerContentObserver(android.net.Uri, boolean, android.database.ContentObserver, int);
public void releasePersistableUriPermission(android.net.Uri, int);
+ public abstract boolean releaseProvider(android.content.IContentProvider);
+ public abstract boolean releaseUnstableProvider(android.content.IContentProvider);
public static void removePeriodicSync(android.accounts.Account, java.lang.String, android.os.Bundle);
public static void removeStatusChangeListener(java.lang.Object);
public static void requestSync(android.accounts.Account, java.lang.String, android.os.Bundle);
public static void requestSync(android.content.SyncRequest);
+ public static void requestSyncAsUser(android.accounts.Account, java.lang.String, int, android.os.Bundle);
+ public int resolveUserId(android.net.Uri);
public static void setIsSyncable(android.accounts.Account, java.lang.String, int);
public static void setMasterSyncAutomatically(boolean);
+ public static void setMasterSyncAutomaticallyAsUser(boolean, int);
public static void setSyncAutomatically(android.accounts.Account, java.lang.String, boolean);
+ public static void setSyncAutomaticallyAsUser(android.accounts.Account, java.lang.String, boolean, int);
public void startSync(android.net.Uri, android.os.Bundle);
+ public static int syncErrorStringToInt(java.lang.String);
+ public static java.lang.String syncErrorToString(int);
public void takePersistableUriPermission(android.net.Uri, int);
+ public void takePersistableUriPermission(java.lang.String, android.net.Uri, int);
public android.net.Uri uncanonicalize(android.net.Uri);
public void unregisterContentObserver(android.database.ContentObserver);
+ public abstract void unstableProviderDied(android.content.IContentProvider);
public int update(android.net.Uri, android.content.ContentValues, java.lang.String, java.lang.String[]);
public static void validateSyncExtrasBundle(android.os.Bundle);
+ public static android.content.Intent ACTION_SYNC_CONN_STATUS_CHANGED;
public static java.lang.String ANY_CURSOR_ITEM_TYPE;
+ public static java.lang.String CONTENT_SERVICE_NAME;
public static java.lang.String CURSOR_DIR_BASE_TYPE;
public static java.lang.String CURSOR_ITEM_BASE_TYPE;
+ public static java.lang.String EXTRA_HONORED_ARGS;
+ public static java.lang.String EXTRA_REFRESH_SUPPORTED;
public static java.lang.String EXTRA_SIZE;
+ public static java.lang.String EXTRA_TOTAL_COUNT;
+ public static int NOTIFY_SKIP_NOTIFY_FOR_DESCENDANTS;
+ public static int NOTIFY_SYNC_TO_NETWORK;
+ public static java.lang.String QUERY_ARG_LIMIT;
+ public static java.lang.String QUERY_ARG_OFFSET;
+ public static java.lang.String QUERY_ARG_SORT_COLLATION;
+ public static java.lang.String QUERY_ARG_SORT_COLUMNS;
+ public static java.lang.String QUERY_ARG_SORT_DIRECTION;
+ public static java.lang.String QUERY_ARG_SQL_SELECTION;
+ public static java.lang.String QUERY_ARG_SQL_SELECTION_ARGS;
+ public static java.lang.String QUERY_ARG_SQL_SORT_ORDER;
+ public static int QUERY_SORT_DIRECTION_ASCENDING;
+ public static int QUERY_SORT_DIRECTION_DESCENDING;
public static java.lang.String SCHEME_ANDROID_RESOURCE;
public static java.lang.String SCHEME_CONTENT;
public static java.lang.String SCHEME_FILE;
+ public static int SYNC_ERROR_AUTHENTICATION;
+ public static int SYNC_ERROR_CONFLICT;
+ public static int SYNC_ERROR_INTERNAL;
+ public static int SYNC_ERROR_IO;
+ public static int SYNC_ERROR_PARSE;
+ public static int SYNC_ERROR_SYNC_ALREADY_IN_PROGRESS;
+ public static int SYNC_ERROR_TOO_MANY_DELETIONS;
+ public static int SYNC_ERROR_TOO_MANY_RETRIES;
+ public static int SYNC_EXEMPTION_NONE;
+ public static int SYNC_EXEMPTION_PROMOTE_BUCKET;
+ public static int SYNC_EXEMPTION_PROMOTE_BUCKET_WITH_TEMP;
public static java.lang.String SYNC_EXTRAS_ACCOUNT;
+ public static java.lang.String SYNC_EXTRAS_DISALLOW_METERED;
public static java.lang.String SYNC_EXTRAS_DISCARD_LOCAL_DELETIONS;
public static java.lang.String SYNC_EXTRAS_DO_NOT_RETRY;
+ public static java.lang.String SYNC_EXTRAS_EXPECTED_DOWNLOAD;
+ public static java.lang.String SYNC_EXTRAS_EXPECTED_UPLOAD;
public static java.lang.String SYNC_EXTRAS_EXPEDITED;
public static java.lang.String SYNC_EXTRAS_FORCE;
public static java.lang.String SYNC_EXTRAS_IGNORE_BACKOFF;
@@ -423,10 +5150,24 @@
public static java.lang.String SYNC_EXTRAS_INITIALIZE;
public static java.lang.String SYNC_EXTRAS_MANUAL;
public static java.lang.String SYNC_EXTRAS_OVERRIDE_TOO_MANY_DELETIONS;
+ public static java.lang.String SYNC_EXTRAS_PRIORITY;
+ public static java.lang.String SYNC_EXTRAS_REQUIRE_CHARGING;
public static java.lang.String SYNC_EXTRAS_UPLOAD;
public static int SYNC_OBSERVER_TYPE_ACTIVE;
+ public static int SYNC_OBSERVER_TYPE_ALL;
public static int SYNC_OBSERVER_TYPE_PENDING;
public static int SYNC_OBSERVER_TYPE_SETTINGS;
+ public static int SYNC_OBSERVER_TYPE_STATUS;
+ public static java.lang.String SYNC_VIRTUAL_EXTRAS_EXEMPTION_FLAG;
+}
+
+-keep class android.content.ContentResolver$OpenResourceIdResult {
+ <init>();
+
+
+
+ public int id;
+ public android.content.res.Resources r;
}
-keep class android.content.ContentValues {
@@ -448,7 +5189,9 @@
public java.lang.Long getAsLong(java.lang.String);
public java.lang.Short getAsShort(java.lang.String);
public java.lang.String getAsString(java.lang.String);
+ public java.util.ArrayList getStringArrayList(java.lang.String);
public int hashCode();
+ public boolean isEmpty();
public java.util.Set keySet();
public void put(java.lang.String, java.lang.String);
public void put(java.lang.String, java.lang.Byte);
@@ -461,6 +5204,7 @@
public void put(java.lang.String, byte[]);
public void putAll(android.content.ContentValues);
public void putNull(java.lang.String);
+ public void putStringArrayList(java.lang.String, java.util.ArrayList);
public void remove(java.lang.String);
public int size();
public java.lang.String toString();
@@ -475,22 +5219,35 @@
-keep class android.content.Context {
<init>();
+ public void assertRuntimeOverlayThemable();
public abstract boolean bindService(android.content.Intent, android.content.ServiceConnection, int);
+ public boolean bindServiceAsUser(android.content.Intent, android.content.ServiceConnection, int, android.os.UserHandle);
+ public boolean bindServiceAsUser(android.content.Intent, android.content.ServiceConnection, int, android.os.Handler, android.os.UserHandle);
+ public abstract boolean canLoadUnsafeResources();
+ public boolean canStartActivityForResult();
public abstract int checkCallingOrSelfPermission(java.lang.String);
public abstract int checkCallingOrSelfUriPermission(android.net.Uri, int);
public abstract int checkCallingPermission(java.lang.String);
public abstract int checkCallingUriPermission(android.net.Uri, int);
public abstract int checkPermission(java.lang.String, int, int);
+ public abstract int checkPermission(java.lang.String, int, int, android.os.IBinder);
public abstract int checkSelfPermission(java.lang.String);
public abstract int checkUriPermission(android.net.Uri, int, int, int);
+ public abstract int checkUriPermission(android.net.Uri, int, int, int, android.os.IBinder);
public abstract int checkUriPermission(android.net.Uri, java.lang.String, java.lang.String, int, int, int);
public abstract void clearWallpaper();
+ public abstract android.content.Context createApplicationContext(android.content.pm.ApplicationInfo, int);
public abstract android.content.Context createConfigurationContext(android.content.res.Configuration);
+ public abstract android.content.Context createContextForSplit(java.lang.String);
+ public abstract android.content.Context createCredentialProtectedStorageContext();
+ public abstract android.content.Context createDeviceProtectedStorageContext();
public abstract android.content.Context createDisplayContext(android.view.Display);
public abstract android.content.Context createPackageContext(java.lang.String, int);
+ public android.content.Context createPackageContextAsUser(java.lang.String, int, android.os.UserHandle);
public abstract java.lang.String[] databaseList();
public abstract boolean deleteDatabase(java.lang.String);
public abstract boolean deleteFile(java.lang.String);
+ public abstract boolean deleteSharedPreferences(java.lang.String);
public abstract void enforceCallingOrSelfPermission(java.lang.String, java.lang.String);
public abstract void enforceCallingOrSelfUriPermission(android.net.Uri, int, java.lang.String);
public abstract void enforceCallingPermission(java.lang.String, java.lang.String);
@@ -499,17 +5256,23 @@
public abstract void enforceUriPermission(android.net.Uri, int, int, int, java.lang.String);
public abstract void enforceUriPermission(android.net.Uri, java.lang.String, java.lang.String, int, int, int, java.lang.String);
public abstract java.lang.String[] fileList();
+ public android.os.IBinder getActivityToken();
public abstract android.content.Context getApplicationContext();
public abstract android.content.pm.ApplicationInfo getApplicationInfo();
public abstract android.content.res.AssetManager getAssets();
+ public android.view.autofill.AutofillManager$AutofillClient getAutofillClient();
+ public abstract java.lang.String getBasePackageName();
public abstract java.io.File getCacheDir();
public abstract java.lang.ClassLoader getClassLoader();
public abstract java.io.File getCodeCacheDir();
public int getColor(int);
public android.content.res.ColorStateList getColorStateList(int);
public abstract android.content.ContentResolver getContentResolver();
+ public abstract java.io.File getDataDir();
public abstract java.io.File getDatabasePath(java.lang.String);
public abstract java.io.File getDir(java.lang.String, int);
+ public abstract android.view.Display getDisplay();
+ public abstract android.view.DisplayAdjustments getDisplayAdjustments(int);
public android.graphics.drawable.Drawable getDrawable(int);
public abstract java.io.File getExternalCacheDir();
public abstract java.io.File[] getExternalCacheDirs();
@@ -518,16 +5281,26 @@
public abstract java.io.File[] getExternalMediaDirs();
public abstract java.io.File getFileStreamPath(java.lang.String);
public abstract java.io.File getFilesDir();
+ public android.app.IApplicationThread getIApplicationThread();
+ public java.util.concurrent.Executor getMainExecutor();
public abstract android.os.Looper getMainLooper();
+ public android.os.Handler getMainThreadHandler();
+ public int getNextAutofillId();
public abstract java.io.File getNoBackupFilesDir();
public abstract java.io.File getObbDir();
public abstract java.io.File[] getObbDirs();
+ public abstract java.lang.String getOpPackageName();
public abstract java.lang.String getPackageCodePath();
public abstract android.content.pm.PackageManager getPackageManager();
public abstract java.lang.String getPackageName();
public abstract java.lang.String getPackageResourcePath();
+ public abstract java.io.File getPreloadsFileCache();
public abstract android.content.res.Resources getResources();
+ public android.app.IServiceConnection getServiceDispatcher(android.content.ServiceConnection, android.os.Handler, int);
public abstract android.content.SharedPreferences getSharedPreferences(java.lang.String, int);
+ public abstract android.content.SharedPreferences getSharedPreferences(java.io.File, int);
+ public abstract java.io.File getSharedPreferencesPath(java.lang.String);
+ public java.io.File getSharedPrefsFile(java.lang.String);
public java.lang.String getString(int);
public java.lang.String getString(int, java.lang.Object[]);
public abstract java.lang.Object getSystemService(java.lang.String);
@@ -535,11 +5308,19 @@
public abstract java.lang.String getSystemServiceName(java.lang.Class);
public java.lang.CharSequence getText(int);
public abstract android.content.res.Resources$Theme getTheme();
+ public int getThemeResId();
+ public android.os.UserHandle getUser();
+ public int getUserId();
public abstract android.graphics.drawable.Drawable getWallpaper();
public abstract int getWallpaperDesiredMinimumHeight();
public abstract int getWallpaperDesiredMinimumWidth();
public abstract void grantUriPermission(java.lang.String, android.net.Uri, int);
+ public boolean isAutofillCompatibilityEnabled();
+ public abstract boolean isCredentialProtectedStorage();
+ public abstract boolean isDeviceProtectedStorage();
public boolean isRestricted();
+ public abstract boolean moveDatabaseFrom(android.content.Context, java.lang.String);
+ public abstract boolean moveSharedPreferencesFrom(android.content.Context, java.lang.String);
public android.content.res.TypedArray obtainStyledAttributes(int[]);
public android.content.res.TypedArray obtainStyledAttributes(int, int[]);
public android.content.res.TypedArray obtainStyledAttributes(android.util.AttributeSet, int[]);
@@ -551,36 +5332,63 @@
public abstract android.graphics.drawable.Drawable peekWallpaper();
public void registerComponentCallbacks(android.content.ComponentCallbacks);
public abstract android.content.Intent registerReceiver(android.content.BroadcastReceiver, android.content.IntentFilter);
+ public abstract android.content.Intent registerReceiver(android.content.BroadcastReceiver, android.content.IntentFilter, int);
public abstract android.content.Intent registerReceiver(android.content.BroadcastReceiver, android.content.IntentFilter, java.lang.String, android.os.Handler);
+ public abstract android.content.Intent registerReceiver(android.content.BroadcastReceiver, android.content.IntentFilter, java.lang.String, android.os.Handler, int);
+ public abstract android.content.Intent registerReceiverAsUser(android.content.BroadcastReceiver, android.os.UserHandle, android.content.IntentFilter, java.lang.String, android.os.Handler);
+ public abstract void reloadSharedPreferences();
public abstract void removeStickyBroadcast(android.content.Intent);
public abstract void removeStickyBroadcastAsUser(android.content.Intent, android.os.UserHandle);
public abstract void revokeUriPermission(android.net.Uri, int);
+ public abstract void revokeUriPermission(java.lang.String, android.net.Uri, int);
public abstract void sendBroadcast(android.content.Intent);
public abstract void sendBroadcast(android.content.Intent, java.lang.String);
+ public abstract void sendBroadcast(android.content.Intent, java.lang.String, android.os.Bundle);
+ public abstract void sendBroadcast(android.content.Intent, java.lang.String, int);
public abstract void sendBroadcastAsUser(android.content.Intent, android.os.UserHandle);
public abstract void sendBroadcastAsUser(android.content.Intent, android.os.UserHandle, java.lang.String);
+ public abstract void sendBroadcastAsUser(android.content.Intent, android.os.UserHandle, java.lang.String, android.os.Bundle);
+ public abstract void sendBroadcastAsUser(android.content.Intent, android.os.UserHandle, java.lang.String, int);
+ public abstract void sendBroadcastAsUserMultiplePermissions(android.content.Intent, android.os.UserHandle, java.lang.String[]);
+ public abstract void sendBroadcastMultiplePermissions(android.content.Intent, java.lang.String[]);
public abstract void sendOrderedBroadcast(android.content.Intent, java.lang.String);
public abstract void sendOrderedBroadcast(android.content.Intent, java.lang.String, android.content.BroadcastReceiver, android.os.Handler, int, java.lang.String, android.os.Bundle);
+ public abstract void sendOrderedBroadcast(android.content.Intent, java.lang.String, android.os.Bundle, android.content.BroadcastReceiver, android.os.Handler, int, java.lang.String, android.os.Bundle);
+ public abstract void sendOrderedBroadcast(android.content.Intent, java.lang.String, int, android.content.BroadcastReceiver, android.os.Handler, int, java.lang.String, android.os.Bundle);
public abstract void sendOrderedBroadcastAsUser(android.content.Intent, android.os.UserHandle, java.lang.String, android.content.BroadcastReceiver, android.os.Handler, int, java.lang.String, android.os.Bundle);
+ public abstract void sendOrderedBroadcastAsUser(android.content.Intent, android.os.UserHandle, java.lang.String, int, android.content.BroadcastReceiver, android.os.Handler, int, java.lang.String, android.os.Bundle);
+ public abstract void sendOrderedBroadcastAsUser(android.content.Intent, android.os.UserHandle, java.lang.String, int, android.os.Bundle, android.content.BroadcastReceiver, android.os.Handler, int, java.lang.String, android.os.Bundle);
public abstract void sendStickyBroadcast(android.content.Intent);
public abstract void sendStickyBroadcastAsUser(android.content.Intent, android.os.UserHandle);
+ public abstract void sendStickyBroadcastAsUser(android.content.Intent, android.os.UserHandle, android.os.Bundle);
public abstract void sendStickyOrderedBroadcast(android.content.Intent, android.content.BroadcastReceiver, android.os.Handler, int, java.lang.String, android.os.Bundle);
public abstract void sendStickyOrderedBroadcastAsUser(android.content.Intent, android.os.UserHandle, android.content.BroadcastReceiver, android.os.Handler, int, java.lang.String, android.os.Bundle);
+ public void setAutofillClient(android.view.autofill.AutofillManager$AutofillClient);
+ public void setAutofillCompatibilityEnabled(boolean);
public abstract void setTheme(int);
public abstract void setWallpaper(android.graphics.Bitmap);
public abstract void setWallpaper(java.io.InputStream);
public abstract void startActivities(android.content.Intent[]);
public abstract void startActivities(android.content.Intent[], android.os.Bundle);
+ public int startActivitiesAsUser(android.content.Intent[], android.os.Bundle, android.os.UserHandle);
public abstract void startActivity(android.content.Intent);
public abstract void startActivity(android.content.Intent, android.os.Bundle);
+ public void startActivityAsUser(android.content.Intent, android.os.UserHandle);
+ public void startActivityAsUser(android.content.Intent, android.os.Bundle, android.os.UserHandle);
+ public void startActivityForResult(java.lang.String, android.content.Intent, int, android.os.Bundle);
+ public abstract android.content.ComponentName startForegroundService(android.content.Intent);
+ public abstract android.content.ComponentName startForegroundServiceAsUser(android.content.Intent, android.os.UserHandle);
public abstract boolean startInstrumentation(android.content.ComponentName, java.lang.String, android.os.Bundle);
public abstract void startIntentSender(android.content.IntentSender, android.content.Intent, int, int, int);
public abstract void startIntentSender(android.content.IntentSender, android.content.Intent, int, int, int, android.os.Bundle);
public abstract android.content.ComponentName startService(android.content.Intent);
+ public abstract android.content.ComponentName startServiceAsUser(android.content.Intent, android.os.UserHandle);
public abstract boolean stopService(android.content.Intent);
+ public abstract boolean stopServiceAsUser(android.content.Intent, android.os.UserHandle);
public abstract void unbindService(android.content.ServiceConnection);
public void unregisterComponentCallbacks(android.content.ComponentCallbacks);
public abstract void unregisterReceiver(android.content.BroadcastReceiver);
+ public abstract void updateDisplay(int);
public static java.lang.String ACCESSIBILITY_SERVICE;
@@ -590,37 +5398,67 @@
public static java.lang.String APPWIDGET_SERVICE;
public static java.lang.String APP_OPS_SERVICE;
public static java.lang.String AUDIO_SERVICE;
+ public static java.lang.String AUTOFILL_MANAGER_SERVICE;
+ public static java.lang.String BACKUP_SERVICE;
public static java.lang.String BATTERY_SERVICE;
public static int BIND_ABOVE_CLIENT;
public static int BIND_ADJUST_WITH_ACTIVITY;
+ public static int BIND_ALLOW_INSTANT;
public static int BIND_ALLOW_OOM_MANAGEMENT;
+ public static int BIND_ALLOW_WHITELIST_MANAGEMENT;
public static int BIND_AUTO_CREATE;
public static int BIND_DEBUG_UNBIND;
+ public static int BIND_EXTERNAL_SERVICE;
+ public static int BIND_FOREGROUND_SERVICE;
+ public static int BIND_FOREGROUND_SERVICE_WHILE_AWAKE;
public static int BIND_IMPORTANT;
+ public static int BIND_IMPORTANT_BACKGROUND;
public static int BIND_NOT_FOREGROUND;
+ public static int BIND_NOT_VISIBLE;
+ public static int BIND_SHOWING_UI;
+ public static int BIND_TREAT_LIKE_ACTIVITY;
+ public static int BIND_VISIBLE;
public static int BIND_WAIVE_PRIORITY;
public static java.lang.String BLUETOOTH_SERVICE;
public static java.lang.String CAMERA_SERVICE;
public static java.lang.String CAPTIONING_SERVICE;
public static java.lang.String CARRIER_CONFIG_SERVICE;
public static java.lang.String CLIPBOARD_SERVICE;
+ public static java.lang.String COMPANION_DEVICE_SERVICE;
public static java.lang.String CONNECTIVITY_SERVICE;
public static java.lang.String CONSUMER_IR_SERVICE;
+ public static java.lang.String CONTEXTHUB_SERVICE;
+ public static int CONTEXT_CREDENTIAL_PROTECTED_STORAGE;
+ public static int CONTEXT_DEVICE_PROTECTED_STORAGE;
public static int CONTEXT_IGNORE_SECURITY;
public static int CONTEXT_INCLUDE_CODE;
+ public static int CONTEXT_REGISTER_PACKAGE;
public static int CONTEXT_RESTRICTED;
+ public static java.lang.String COUNTRY_DETECTOR;
+ public static java.lang.String CROSS_PROFILE_APPS_SERVICE;
+ public static java.lang.String DEVICE_IDENTIFIERS_SERVICE;
+ public static java.lang.String DEVICE_IDLE_CONTROLLER;
public static java.lang.String DEVICE_POLICY_SERVICE;
public static java.lang.String DISPLAY_SERVICE;
public static java.lang.String DOWNLOAD_SERVICE;
public static java.lang.String DROPBOX_SERVICE;
+ public static java.lang.String ETHERNET_SERVICE;
+ public static java.lang.String EUICC_CARD_SERVICE;
+ public static java.lang.String EUICC_SERVICE;
public static java.lang.String FINGERPRINT_SERVICE;
+ public static java.lang.String GATEKEEPER_SERVICE;
+ public static java.lang.String HARDWARE_PROPERTIES_SERVICE;
+ public static java.lang.String HDMI_CONTROL_SERVICE;
+ public static java.lang.String INCIDENT_SERVICE;
public static java.lang.String INPUT_METHOD_SERVICE;
public static java.lang.String INPUT_SERVICE;
+ public static java.lang.String IPSEC_SERVICE;
public static java.lang.String JOB_SCHEDULER_SERVICE;
public static java.lang.String KEYGUARD_SERVICE;
public static java.lang.String LAUNCHER_APPS_SERVICE;
public static java.lang.String LAYOUT_INFLATER_SERVICE;
public static java.lang.String LOCATION_SERVICE;
+ public static java.lang.String LOWPAN_SERVICE;
public static java.lang.String MEDIA_PROJECTION_SERVICE;
public static java.lang.String MEDIA_ROUTER_SERVICE;
public static java.lang.String MEDIA_SESSION_SERVICE;
@@ -628,35 +5466,377 @@
public static int MODE_APPEND;
public static int MODE_ENABLE_WRITE_AHEAD_LOGGING;
public static int MODE_MULTI_PROCESS;
+ public static int MODE_NO_LOCALIZED_COLLATORS;
public static int MODE_PRIVATE;
public static int MODE_WORLD_READABLE;
public static int MODE_WORLD_WRITEABLE;
+ public static java.lang.String NETWORKMANAGEMENT_SERVICE;
+ public static java.lang.String NETWORK_POLICY_SERVICE;
+ public static java.lang.String NETWORK_SCORE_SERVICE;
public static java.lang.String NETWORK_STATS_SERVICE;
+ public static java.lang.String NETWORK_WATCHLIST_SERVICE;
public static java.lang.String NFC_SERVICE;
public static java.lang.String NOTIFICATION_SERVICE;
public static java.lang.String NSD_SERVICE;
+ public static java.lang.String OEM_LOCK_SERVICE;
+ public static java.lang.String OVERLAY_SERVICE;
+ public static java.lang.String PERSISTENT_DATA_BLOCK_SERVICE;
public static java.lang.String POWER_SERVICE;
public static java.lang.String PRINT_SERVICE;
+ public static java.lang.String RADIO_SERVICE;
+ public static int RECEIVER_VISIBLE_TO_INSTANT_APPS;
+ public static java.lang.String RECOVERY_SERVICE;
public static java.lang.String RESTRICTIONS_SERVICE;
public static java.lang.String SEARCH_SERVICE;
+ public static java.lang.String SECURE_ELEMENT_SERVICE;
public static java.lang.String SENSOR_SERVICE;
+ public static java.lang.String SERIAL_SERVICE;
+ public static java.lang.String SHORTCUT_SERVICE;
+ public static java.lang.String SIP_SERVICE;
+ public static java.lang.String SLICE_SERVICE;
+ public static java.lang.String SOUND_TRIGGER_SERVICE;
+ public static java.lang.String STATS_COMPANION_SERVICE;
+ public static java.lang.String STATS_MANAGER;
+ public static java.lang.String STATUS_BAR_SERVICE;
public static java.lang.String STORAGE_SERVICE;
+ public static java.lang.String STORAGE_STATS_SERVICE;
+ public static java.lang.String SYSTEM_HEALTH_SERVICE;
+ public static java.lang.String SYSTEM_UPDATE_SERVICE;
public static java.lang.String TELECOM_SERVICE;
public static java.lang.String TELEPHONY_SERVICE;
public static java.lang.String TELEPHONY_SUBSCRIPTION_SERVICE;
+ public static java.lang.String TEXT_CLASSIFICATION_SERVICE;
public static java.lang.String TEXT_SERVICES_MANAGER_SERVICE;
+ public static java.lang.String TIME_ZONE_RULES_MANAGER_SERVICE;
+ public static java.lang.String TRUST_SERVICE;
public static java.lang.String TV_INPUT_SERVICE;
public static java.lang.String UI_MODE_SERVICE;
+ public static java.lang.String UPDATE_LOCK_SERVICE;
public static java.lang.String USAGE_STATS_SERVICE;
public static java.lang.String USB_SERVICE;
public static java.lang.String USER_SERVICE;
public static java.lang.String VIBRATOR_SERVICE;
+ public static java.lang.String VOICE_INTERACTION_MANAGER_SERVICE;
+ public static java.lang.String VR_SERVICE;
public static java.lang.String WALLPAPER_SERVICE;
+ public static java.lang.String WIFI_AWARE_SERVICE;
public static java.lang.String WIFI_P2P_SERVICE;
+ public static java.lang.String WIFI_RTT_RANGING_SERVICE;
+ public static java.lang.String WIFI_RTT_SERVICE;
+ public static java.lang.String WIFI_SCANNING_SERVICE;
public static java.lang.String WIFI_SERVICE;
public static java.lang.String WINDOW_SERVICE;
}
+-keep class android.content.ContextWrapper {
+ <init>(android.content.Context);
+
+ protected void attachBaseContext(android.content.Context);
+ public boolean bindService(android.content.Intent, android.content.ServiceConnection, int);
+ public boolean bindServiceAsUser(android.content.Intent, android.content.ServiceConnection, int, android.os.UserHandle);
+ public boolean bindServiceAsUser(android.content.Intent, android.content.ServiceConnection, int, android.os.Handler, android.os.UserHandle);
+ public boolean canLoadUnsafeResources();
+ public boolean canStartActivityForResult();
+ public int checkCallingOrSelfPermission(java.lang.String);
+ public int checkCallingOrSelfUriPermission(android.net.Uri, int);
+ public int checkCallingPermission(java.lang.String);
+ public int checkCallingUriPermission(android.net.Uri, int);
+ public int checkPermission(java.lang.String, int, int);
+ public int checkPermission(java.lang.String, int, int, android.os.IBinder);
+ public int checkSelfPermission(java.lang.String);
+ public int checkUriPermission(android.net.Uri, int, int, int);
+ public int checkUriPermission(android.net.Uri, int, int, int, android.os.IBinder);
+ public int checkUriPermission(android.net.Uri, java.lang.String, java.lang.String, int, int, int);
+ public void clearWallpaper();
+ public android.content.Context createApplicationContext(android.content.pm.ApplicationInfo, int);
+ public android.content.Context createConfigurationContext(android.content.res.Configuration);
+ public android.content.Context createContextForSplit(java.lang.String);
+ public android.content.Context createCredentialProtectedStorageContext();
+ public android.content.Context createDeviceProtectedStorageContext();
+ public android.content.Context createDisplayContext(android.view.Display);
+ public android.content.Context createPackageContext(java.lang.String, int);
+ public android.content.Context createPackageContextAsUser(java.lang.String, int, android.os.UserHandle);
+ public java.lang.String[] databaseList();
+ public boolean deleteDatabase(java.lang.String);
+ public boolean deleteFile(java.lang.String);
+ public boolean deleteSharedPreferences(java.lang.String);
+ public void enforceCallingOrSelfPermission(java.lang.String, java.lang.String);
+ public void enforceCallingOrSelfUriPermission(android.net.Uri, int, java.lang.String);
+ public void enforceCallingPermission(java.lang.String, java.lang.String);
+ public void enforceCallingUriPermission(android.net.Uri, int, java.lang.String);
+ public void enforcePermission(java.lang.String, int, int, java.lang.String);
+ public void enforceUriPermission(android.net.Uri, int, int, int, java.lang.String);
+ public void enforceUriPermission(android.net.Uri, java.lang.String, java.lang.String, int, int, int, java.lang.String);
+ public java.lang.String[] fileList();
+ public android.os.IBinder getActivityToken();
+ public android.content.Context getApplicationContext();
+ public android.content.pm.ApplicationInfo getApplicationInfo();
+ public android.content.res.AssetManager getAssets();
+ public android.view.autofill.AutofillManager$AutofillClient getAutofillClient();
+ public android.content.Context getBaseContext();
+ public java.lang.String getBasePackageName();
+ public java.io.File getCacheDir();
+ public java.lang.ClassLoader getClassLoader();
+ public java.io.File getCodeCacheDir();
+ public android.content.ContentResolver getContentResolver();
+ public java.io.File getDataDir();
+ public java.io.File getDatabasePath(java.lang.String);
+ public java.io.File getDir(java.lang.String, int);
+ public android.view.Display getDisplay();
+ public android.view.DisplayAdjustments getDisplayAdjustments(int);
+ public java.io.File getExternalCacheDir();
+ public java.io.File[] getExternalCacheDirs();
+ public java.io.File getExternalFilesDir(java.lang.String);
+ public java.io.File[] getExternalFilesDirs(java.lang.String);
+ public java.io.File[] getExternalMediaDirs();
+ public java.io.File getFileStreamPath(java.lang.String);
+ public java.io.File getFilesDir();
+ public android.app.IApplicationThread getIApplicationThread();
+ public java.util.concurrent.Executor getMainExecutor();
+ public android.os.Looper getMainLooper();
+ public android.os.Handler getMainThreadHandler();
+ public int getNextAutofillId();
+ public java.io.File getNoBackupFilesDir();
+ public java.io.File getObbDir();
+ public java.io.File[] getObbDirs();
+ public java.lang.String getOpPackageName();
+ public java.lang.String getPackageCodePath();
+ public android.content.pm.PackageManager getPackageManager();
+ public java.lang.String getPackageName();
+ public java.lang.String getPackageResourcePath();
+ public java.io.File getPreloadsFileCache();
+ public android.content.res.Resources getResources();
+ public android.app.IServiceConnection getServiceDispatcher(android.content.ServiceConnection, android.os.Handler, int);
+ public android.content.SharedPreferences getSharedPreferences(java.lang.String, int);
+ public android.content.SharedPreferences getSharedPreferences(java.io.File, int);
+ public java.io.File getSharedPreferencesPath(java.lang.String);
+ public java.lang.Object getSystemService(java.lang.String);
+ public java.lang.String getSystemServiceName(java.lang.Class);
+ public android.content.res.Resources$Theme getTheme();
+ public int getThemeResId();
+ public int getUserId();
+ public android.graphics.drawable.Drawable getWallpaper();
+ public int getWallpaperDesiredMinimumHeight();
+ public int getWallpaperDesiredMinimumWidth();
+ public void grantUriPermission(java.lang.String, android.net.Uri, int);
+ public boolean isAutofillCompatibilityEnabled();
+ public boolean isCredentialProtectedStorage();
+ public boolean isDeviceProtectedStorage();
+ public boolean isRestricted();
+ public boolean moveDatabaseFrom(android.content.Context, java.lang.String);
+ public boolean moveSharedPreferencesFrom(android.content.Context, java.lang.String);
+ public java.io.FileInputStream openFileInput(java.lang.String);
+ public java.io.FileOutputStream openFileOutput(java.lang.String, int);
+ public android.database.sqlite.SQLiteDatabase openOrCreateDatabase(java.lang.String, int, android.database.sqlite.SQLiteDatabase$CursorFactory);
+ public android.database.sqlite.SQLiteDatabase openOrCreateDatabase(java.lang.String, int, android.database.sqlite.SQLiteDatabase$CursorFactory, android.database.DatabaseErrorHandler);
+ public android.graphics.drawable.Drawable peekWallpaper();
+ public android.content.Intent registerReceiver(android.content.BroadcastReceiver, android.content.IntentFilter);
+ public android.content.Intent registerReceiver(android.content.BroadcastReceiver, android.content.IntentFilter, int);
+ public android.content.Intent registerReceiver(android.content.BroadcastReceiver, android.content.IntentFilter, java.lang.String, android.os.Handler);
+ public android.content.Intent registerReceiver(android.content.BroadcastReceiver, android.content.IntentFilter, java.lang.String, android.os.Handler, int);
+ public android.content.Intent registerReceiverAsUser(android.content.BroadcastReceiver, android.os.UserHandle, android.content.IntentFilter, java.lang.String, android.os.Handler);
+ public void reloadSharedPreferences();
+ public void removeStickyBroadcast(android.content.Intent);
+ public void removeStickyBroadcastAsUser(android.content.Intent, android.os.UserHandle);
+ public void revokeUriPermission(android.net.Uri, int);
+ public void revokeUriPermission(java.lang.String, android.net.Uri, int);
+ public void sendBroadcast(android.content.Intent);
+ public void sendBroadcast(android.content.Intent, java.lang.String);
+ public void sendBroadcast(android.content.Intent, java.lang.String, android.os.Bundle);
+ public void sendBroadcast(android.content.Intent, java.lang.String, int);
+ public void sendBroadcastAsUser(android.content.Intent, android.os.UserHandle);
+ public void sendBroadcastAsUser(android.content.Intent, android.os.UserHandle, java.lang.String);
+ public void sendBroadcastAsUser(android.content.Intent, android.os.UserHandle, java.lang.String, android.os.Bundle);
+ public void sendBroadcastAsUser(android.content.Intent, android.os.UserHandle, java.lang.String, int);
+ public void sendBroadcastAsUserMultiplePermissions(android.content.Intent, android.os.UserHandle, java.lang.String[]);
+ public void sendBroadcastMultiplePermissions(android.content.Intent, java.lang.String[]);
+ public void sendOrderedBroadcast(android.content.Intent, java.lang.String);
+ public void sendOrderedBroadcast(android.content.Intent, java.lang.String, android.content.BroadcastReceiver, android.os.Handler, int, java.lang.String, android.os.Bundle);
+ public void sendOrderedBroadcast(android.content.Intent, java.lang.String, android.os.Bundle, android.content.BroadcastReceiver, android.os.Handler, int, java.lang.String, android.os.Bundle);
+ public void sendOrderedBroadcast(android.content.Intent, java.lang.String, int, android.content.BroadcastReceiver, android.os.Handler, int, java.lang.String, android.os.Bundle);
+ public void sendOrderedBroadcastAsUser(android.content.Intent, android.os.UserHandle, java.lang.String, android.content.BroadcastReceiver, android.os.Handler, int, java.lang.String, android.os.Bundle);
+ public void sendOrderedBroadcastAsUser(android.content.Intent, android.os.UserHandle, java.lang.String, int, android.content.BroadcastReceiver, android.os.Handler, int, java.lang.String, android.os.Bundle);
+ public void sendOrderedBroadcastAsUser(android.content.Intent, android.os.UserHandle, java.lang.String, int, android.os.Bundle, android.content.BroadcastReceiver, android.os.Handler, int, java.lang.String, android.os.Bundle);
+ public void sendStickyBroadcast(android.content.Intent);
+ public void sendStickyBroadcastAsUser(android.content.Intent, android.os.UserHandle);
+ public void sendStickyBroadcastAsUser(android.content.Intent, android.os.UserHandle, android.os.Bundle);
+ public void sendStickyOrderedBroadcast(android.content.Intent, android.content.BroadcastReceiver, android.os.Handler, int, java.lang.String, android.os.Bundle);
+ public void sendStickyOrderedBroadcastAsUser(android.content.Intent, android.os.UserHandle, android.content.BroadcastReceiver, android.os.Handler, int, java.lang.String, android.os.Bundle);
+ public void setAutofillClient(android.view.autofill.AutofillManager$AutofillClient);
+ public void setAutofillCompatibilityEnabled(boolean);
+ public void setTheme(int);
+ public void setWallpaper(android.graphics.Bitmap);
+ public void setWallpaper(java.io.InputStream);
+ public void startActivities(android.content.Intent[]);
+ public void startActivities(android.content.Intent[], android.os.Bundle);
+ public int startActivitiesAsUser(android.content.Intent[], android.os.Bundle, android.os.UserHandle);
+ public void startActivity(android.content.Intent);
+ public void startActivity(android.content.Intent, android.os.Bundle);
+ public void startActivityAsUser(android.content.Intent, android.os.UserHandle);
+ public void startActivityAsUser(android.content.Intent, android.os.Bundle, android.os.UserHandle);
+ public void startActivityForResult(java.lang.String, android.content.Intent, int, android.os.Bundle);
+ public android.content.ComponentName startForegroundService(android.content.Intent);
+ public android.content.ComponentName startForegroundServiceAsUser(android.content.Intent, android.os.UserHandle);
+ public boolean startInstrumentation(android.content.ComponentName, java.lang.String, android.os.Bundle);
+ public void startIntentSender(android.content.IntentSender, android.content.Intent, int, int, int);
+ public void startIntentSender(android.content.IntentSender, android.content.Intent, int, int, int, android.os.Bundle);
+ public android.content.ComponentName startService(android.content.Intent);
+ public android.content.ComponentName startServiceAsUser(android.content.Intent, android.os.UserHandle);
+ public boolean stopService(android.content.Intent);
+ public boolean stopServiceAsUser(android.content.Intent, android.os.UserHandle);
+ public void unbindService(android.content.ServiceConnection);
+ public void unregisterReceiver(android.content.BroadcastReceiver);
+ public void updateDisplay(int);
+
+
+}
+
+-keep class android.content.DialogInterface {
+
+ public abstract void cancel();
+ public abstract void dismiss();
+
+
+ public static int BUTTON1;
+ public static int BUTTON2;
+ public static int BUTTON3;
+ public static int BUTTON_NEGATIVE;
+ public static int BUTTON_NEUTRAL;
+ public static int BUTTON_POSITIVE;
+}
+
+-keep class android.content.DialogInterface$OnCancelListener {
+
+ public abstract void onCancel(android.content.DialogInterface);
+
+
+}
+
+-keep class android.content.DialogInterface$OnDismissListener {
+
+ public abstract void onDismiss(android.content.DialogInterface);
+
+
+}
+
+-keep class android.content.DialogInterface$OnKeyListener {
+
+ public abstract boolean onKey(android.content.DialogInterface, int, android.view.KeyEvent);
+
+
+}
+
+-keep class android.content.DialogInterface$OnShowListener {
+
+ public abstract void onShow(android.content.DialogInterface);
+
+
+}
+
+-keep class android.content.IContentProvider {
+
+ public abstract android.content.ContentProviderResult[] applyBatch(java.lang.String, java.util.ArrayList);
+ public abstract int bulkInsert(java.lang.String, android.net.Uri, android.content.ContentValues[]);
+ public abstract android.os.Bundle call(java.lang.String, java.lang.String, java.lang.String, android.os.Bundle);
+ public abstract android.net.Uri canonicalize(java.lang.String, android.net.Uri);
+ public abstract android.os.ICancellationSignal createCancellationSignal();
+ public abstract int delete(java.lang.String, android.net.Uri, java.lang.String, java.lang.String[]);
+ public abstract java.lang.String[] getStreamTypes(android.net.Uri, java.lang.String);
+ public abstract java.lang.String getType(android.net.Uri);
+ public abstract android.net.Uri insert(java.lang.String, android.net.Uri, android.content.ContentValues);
+ public abstract android.content.res.AssetFileDescriptor openAssetFile(java.lang.String, android.net.Uri, java.lang.String, android.os.ICancellationSignal);
+ public abstract android.os.ParcelFileDescriptor openFile(java.lang.String, android.net.Uri, java.lang.String, android.os.ICancellationSignal, android.os.IBinder);
+ public abstract android.content.res.AssetFileDescriptor openTypedAssetFile(java.lang.String, android.net.Uri, java.lang.String, android.os.Bundle, android.os.ICancellationSignal);
+ public abstract android.database.Cursor query(java.lang.String, android.net.Uri, java.lang.String[], android.os.Bundle, android.os.ICancellationSignal);
+ public abstract boolean refresh(java.lang.String, android.net.Uri, android.os.Bundle, android.os.ICancellationSignal);
+ public abstract android.net.Uri uncanonicalize(java.lang.String, android.net.Uri);
+ public abstract int update(java.lang.String, android.net.Uri, android.content.ContentValues, java.lang.String, java.lang.String[]);
+
+
+ public static int APPLY_BATCH_TRANSACTION;
+ public static int BULK_INSERT_TRANSACTION;
+ public static int CALL_TRANSACTION;
+ public static int CANONICALIZE_TRANSACTION;
+ public static int CREATE_CANCELATION_SIGNAL_TRANSACTION;
+ public static int DELETE_TRANSACTION;
+ public static int GET_STREAM_TYPES_TRANSACTION;
+ public static int GET_TYPE_TRANSACTION;
+ public static int INSERT_TRANSACTION;
+ public static int OPEN_ASSET_FILE_TRANSACTION;
+ public static int OPEN_FILE_TRANSACTION;
+ public static int OPEN_TYPED_ASSET_FILE_TRANSACTION;
+ public static int QUERY_TRANSACTION;
+ public static int REFRESH_TRANSACTION;
+ public static int UNCANONICALIZE_TRANSACTION;
+ public static int UPDATE_TRANSACTION;
+ public static java.lang.String descriptor;
+}
+
+-keep class android.content.IContentService {
+
+ public abstract void addPeriodicSync(android.accounts.Account, java.lang.String, android.os.Bundle, long);
+ public abstract void addStatusChangeListener(int, android.content.ISyncStatusObserver);
+ public abstract void cancelRequest(android.content.SyncRequest);
+ public abstract void cancelSync(android.accounts.Account, java.lang.String, android.content.ComponentName);
+ public abstract void cancelSyncAsUser(android.accounts.Account, java.lang.String, android.content.ComponentName, int);
+ public abstract android.os.Bundle getCache(java.lang.String, android.net.Uri, int);
+ public abstract java.util.List getCurrentSyncs();
+ public abstract java.util.List getCurrentSyncsAsUser(int);
+ public abstract int getIsSyncable(android.accounts.Account, java.lang.String);
+ public abstract int getIsSyncableAsUser(android.accounts.Account, java.lang.String, int);
+ public abstract boolean getMasterSyncAutomatically();
+ public abstract boolean getMasterSyncAutomaticallyAsUser(int);
+ public abstract java.util.List getPeriodicSyncs(android.accounts.Account, java.lang.String, android.content.ComponentName);
+ public abstract java.lang.String[] getSyncAdapterPackagesForAuthorityAsUser(java.lang.String, int);
+ public abstract android.content.SyncAdapterType[] getSyncAdapterTypes();
+ public abstract android.content.SyncAdapterType[] getSyncAdapterTypesAsUser(int);
+ public abstract boolean getSyncAutomatically(android.accounts.Account, java.lang.String);
+ public abstract boolean getSyncAutomaticallyAsUser(android.accounts.Account, java.lang.String, int);
+ public abstract android.content.SyncStatusInfo getSyncStatus(android.accounts.Account, java.lang.String, android.content.ComponentName);
+ public abstract android.content.SyncStatusInfo getSyncStatusAsUser(android.accounts.Account, java.lang.String, android.content.ComponentName, int);
+ public abstract boolean isSyncActive(android.accounts.Account, java.lang.String, android.content.ComponentName);
+ public abstract boolean isSyncPending(android.accounts.Account, java.lang.String, android.content.ComponentName);
+ public abstract boolean isSyncPendingAsUser(android.accounts.Account, java.lang.String, android.content.ComponentName, int);
+ public abstract void notifyChange(android.net.Uri, android.database.IContentObserver, boolean, int, int, int);
+ public abstract void putCache(java.lang.String, android.net.Uri, android.os.Bundle, int);
+ public abstract void registerContentObserver(android.net.Uri, boolean, android.database.IContentObserver, int, int);
+ public abstract void removePeriodicSync(android.accounts.Account, java.lang.String, android.os.Bundle);
+ public abstract void removeStatusChangeListener(android.content.ISyncStatusObserver);
+ public abstract void requestSync(android.accounts.Account, java.lang.String, android.os.Bundle);
+ public abstract void resetTodayStats();
+ public abstract void setIsSyncable(android.accounts.Account, java.lang.String, int);
+ public abstract void setMasterSyncAutomatically(boolean);
+ public abstract void setMasterSyncAutomaticallyAsUser(boolean, int);
+ public abstract void setSyncAutomatically(android.accounts.Account, java.lang.String, boolean);
+ public abstract void setSyncAutomaticallyAsUser(android.accounts.Account, java.lang.String, boolean, int);
+ public abstract void sync(android.content.SyncRequest);
+ public abstract void syncAsUser(android.content.SyncRequest, int);
+ public abstract void unregisterContentObserver(android.database.IContentObserver);
+
+
+}
+
+-keep class android.content.IIntentReceiver {
+
+ public abstract void performReceive(android.content.Intent, int, java.lang.String, android.os.Bundle, boolean, boolean, int);
+
+
+}
+
+-keep class android.content.IIntentSender {
+
+ public abstract void send(int, android.content.Intent, java.lang.String, android.os.IBinder, android.content.IIntentReceiver, java.lang.String, android.os.Bundle);
+
+
+}
+
+-keep class android.content.ISyncStatusObserver {
+
+ public abstract void onStatusChanged(int);
+
+
+}
+
-keep class android.content.Intent {
<init>();
<init>(android.content.Intent);
@@ -664,17 +5844,21 @@
<init>(java.lang.String, android.net.Uri);
<init>(android.content.Context, java.lang.Class);
<init>(java.lang.String, android.net.Uri, android.content.Context, java.lang.Class);
+ <init>(android.os.Parcel);
public android.content.Intent addCategory(java.lang.String);
public android.content.Intent addFlags(int);
+ public boolean canStripForHistory();
public java.lang.Object clone();
public android.content.Intent cloneFilter();
public static android.content.Intent createChooser(android.content.Intent, java.lang.CharSequence);
public static android.content.Intent createChooser(android.content.Intent, java.lang.CharSequence, android.content.IntentSender);
public int describeContents();
+ public static java.lang.String dockStateToString(int);
public int fillIn(android.content.Intent, int);
public boolean filterEquals(android.content.Intent);
public int filterHashCode();
+ public void fixUris(int);
public java.lang.String getAction();
public boolean[] getBooleanArrayExtra(java.lang.String);
public boolean getBooleanExtra(java.lang.String, boolean);
@@ -689,19 +5873,24 @@
public java.lang.CharSequence getCharSequenceExtra(java.lang.String);
public android.content.ClipData getClipData();
public android.content.ComponentName getComponent();
+ public int getContentUserHint();
public android.net.Uri getData();
public java.lang.String getDataString();
public double[] getDoubleArrayExtra(java.lang.String);
public double getDoubleExtra(java.lang.String, double);
+ public java.lang.Object getExtra(java.lang.String);
+ public java.lang.Object getExtra(java.lang.String, java.lang.Object);
public android.os.Bundle getExtras();
public int getFlags();
public float[] getFloatArrayExtra(java.lang.String);
public float getFloatExtra(java.lang.String, float);
+ public android.os.IBinder getIBinderExtra(java.lang.String);
public int[] getIntArrayExtra(java.lang.String);
public int getIntExtra(java.lang.String, int);
public java.util.ArrayList getIntegerArrayListExtra(java.lang.String);
public static android.content.Intent getIntent(java.lang.String);
public static android.content.Intent getIntentOld(java.lang.String);
+ public java.lang.String getLaunchToken();
public long[] getLongArrayExtra(java.lang.String);
public long getLongExtra(java.lang.String, long);
public java.lang.String getPackage();
@@ -721,12 +5910,25 @@
public boolean hasCategory(java.lang.String);
public boolean hasExtra(java.lang.String);
public boolean hasFileDescriptors();
+ public boolean hasWebURI();
+ public static boolean isAccessUriMode(int);
+ public boolean isDocument();
+ public boolean isExcludingStopped();
+ public boolean isWebIntent();
public static android.content.Intent makeMainActivity(android.content.ComponentName);
public static android.content.Intent makeMainSelectorActivity(java.lang.String, java.lang.String);
public static android.content.Intent makeRestartActivityTask(android.content.ComponentName);
+ public android.content.Intent maybeStripForHistory();
+ public boolean migrateExtraStreamToClipData();
public static java.lang.String normalizeMimeType(java.lang.String);
+ public static android.content.Intent parseCommandArgs(android.os.ShellCommand, android.content.Intent$CommandOptionHandler);
public static android.content.Intent parseIntent(android.content.res.Resources, org.xmlpull.v1.XmlPullParser, android.util.AttributeSet);
public static android.content.Intent parseUri(java.lang.String, int);
+ public void prepareToEnterProcess();
+ public void prepareToLeaveProcess(android.content.Context);
+ public void prepareToLeaveProcess(boolean);
+ public void prepareToLeaveUser(int);
+ public static void printIntentArgsHelp(java.io.PrintWriter, java.lang.String);
public android.content.Intent putCharSequenceArrayListExtra(java.lang.String, java.util.ArrayList);
public android.content.Intent putExtra(java.lang.String, boolean);
public android.content.Intent putExtra(java.lang.String, byte);
@@ -752,6 +5954,7 @@
public android.content.Intent putExtra(java.lang.String, java.lang.String[]);
public android.content.Intent putExtra(java.lang.String, java.lang.CharSequence[]);
public android.content.Intent putExtra(java.lang.String, android.os.Bundle);
+ public android.content.Intent putExtra(java.lang.String, android.os.IBinder);
public android.content.Intent putExtras(android.content.Intent);
public android.content.Intent putExtras(android.os.Bundle);
public android.content.Intent putIntegerArrayListExtra(java.lang.String, java.util.ArrayList);
@@ -760,14 +5963,20 @@
public void readFromParcel(android.os.Parcel);
public void removeCategory(java.lang.String);
public void removeExtra(java.lang.String);
+ public void removeFlags(int);
+ public void removeUnsafeExtras();
public android.content.Intent replaceExtras(android.content.Intent);
public android.content.Intent replaceExtras(android.os.Bundle);
public android.content.ComponentName resolveActivity(android.content.pm.PackageManager);
public android.content.pm.ActivityInfo resolveActivityInfo(android.content.pm.PackageManager, int);
+ public android.content.ComponentName resolveSystemService(android.content.pm.PackageManager, int);
public java.lang.String resolveType(android.content.Context);
public java.lang.String resolveType(android.content.ContentResolver);
public java.lang.String resolveTypeIfNeeded(android.content.ContentResolver);
+ public static android.content.Intent restoreFromXml(org.xmlpull.v1.XmlPullParser);
+ public void saveToXml(org.xmlpull.v1.XmlSerializer);
public android.content.Intent setAction(java.lang.String);
+ public void setAllowFds(boolean);
public android.content.Intent setClass(android.content.Context, java.lang.Class);
public android.content.Intent setClassName(android.content.Context, java.lang.String);
public android.content.Intent setClassName(java.lang.String, java.lang.String);
@@ -777,35 +5986,51 @@
public android.content.Intent setDataAndNormalize(android.net.Uri);
public android.content.Intent setDataAndType(android.net.Uri, java.lang.String);
public android.content.Intent setDataAndTypeAndNormalize(android.net.Uri, java.lang.String);
+ public void setDefusable(boolean);
public void setExtrasClassLoader(java.lang.ClassLoader);
public android.content.Intent setFlags(int);
+ public void setLaunchToken(java.lang.String);
public android.content.Intent setPackage(java.lang.String);
public void setSelector(android.content.Intent);
public void setSourceBounds(android.graphics.Rect);
public android.content.Intent setType(java.lang.String);
public android.content.Intent setTypeAndNormalize(java.lang.String);
+ public java.lang.String toInsecureString();
+ public java.lang.String toInsecureStringWithClip();
+ public java.lang.String toShortString(boolean, boolean, boolean, boolean);
+ public void toShortString(java.lang.StringBuilder, boolean, boolean, boolean, boolean);
public java.lang.String toString();
public java.lang.String toURI();
public java.lang.String toUri(int);
public void writeToParcel(android.os.Parcel, int);
+ public void writeToProto(android.util.proto.ProtoOutputStream, long);
+ public void writeToProto(android.util.proto.ProtoOutputStream, long, boolean, boolean, boolean, boolean);
+ public static java.lang.String ACTION_ADVANCED_SETTINGS_CHANGED;
public static java.lang.String ACTION_AIRPLANE_MODE_CHANGED;
+ public static java.lang.String ACTION_ALARM_CHANGED;
public static java.lang.String ACTION_ALL_APPS;
public static java.lang.String ACTION_ANSWER;
+ public static java.lang.String ACTION_APPLICATION_PREFERENCES;
public static java.lang.String ACTION_APPLICATION_RESTRICTIONS_CHANGED;
public static java.lang.String ACTION_APP_ERROR;
public static java.lang.String ACTION_ASSIST;
public static java.lang.String ACTION_ATTACH_DATA;
public static java.lang.String ACTION_BATTERY_CHANGED;
+ public static java.lang.String ACTION_BATTERY_LEVEL_CHANGED;
public static java.lang.String ACTION_BATTERY_LOW;
public static java.lang.String ACTION_BATTERY_OKAY;
public static java.lang.String ACTION_BOOT_COMPLETED;
public static java.lang.String ACTION_BUG_REPORT;
public static java.lang.String ACTION_CALL;
public static java.lang.String ACTION_CALL_BUTTON;
+ public static java.lang.String ACTION_CALL_EMERGENCY;
+ public static java.lang.String ACTION_CALL_PRIVILEGED;
public static java.lang.String ACTION_CAMERA_BUTTON;
+ public static java.lang.String ACTION_CARRIER_SETUP;
public static java.lang.String ACTION_CHOOSER;
+ public static java.lang.String ACTION_CLEAR_DNS_CACHE;
public static java.lang.String ACTION_CLOSE_SYSTEM_DIALOGS;
public static java.lang.String ACTION_CONFIGURATION_CHANGED;
public static java.lang.String ACTION_CREATE_DOCUMENT;
@@ -813,31 +6038,56 @@
public static java.lang.String ACTION_DATE_CHANGED;
public static java.lang.String ACTION_DEFAULT;
public static java.lang.String ACTION_DELETE;
+ public static java.lang.String ACTION_DEVICE_INITIALIZATION_WIZARD;
+ public static java.lang.String ACTION_DEVICE_LOCKED_CHANGED;
+ public static java.lang.String ACTION_DEVICE_STORAGE_FULL;
public static java.lang.String ACTION_DEVICE_STORAGE_LOW;
+ public static java.lang.String ACTION_DEVICE_STORAGE_NOT_FULL;
public static java.lang.String ACTION_DEVICE_STORAGE_OK;
public static java.lang.String ACTION_DIAL;
+ public static java.lang.String ACTION_DISMISS_KEYBOARD_SHORTCUTS;
+ public static java.lang.String ACTION_DOCK_ACTIVE;
public static java.lang.String ACTION_DOCK_EVENT;
+ public static java.lang.String ACTION_DOCK_IDLE;
public static java.lang.String ACTION_DREAMING_STARTED;
public static java.lang.String ACTION_DREAMING_STOPPED;
+ public static java.lang.String ACTION_DYNAMIC_SENSOR_CHANGED;
public static java.lang.String ACTION_EDIT;
public static java.lang.String ACTION_EXTERNAL_APPLICATIONS_AVAILABLE;
public static java.lang.String ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE;
+ public static java.lang.String ACTION_FACTORY_RESET;
public static java.lang.String ACTION_FACTORY_TEST;
public static java.lang.String ACTION_GET_CONTENT;
public static java.lang.String ACTION_GET_RESTRICTION_ENTRIES;
+ public static java.lang.String ACTION_GLOBAL_BUTTON;
public static java.lang.String ACTION_GTALK_SERVICE_CONNECTED;
public static java.lang.String ACTION_GTALK_SERVICE_DISCONNECTED;
public static java.lang.String ACTION_HEADSET_PLUG;
+ public static java.lang.String ACTION_IDLE_MAINTENANCE_END;
+ public static java.lang.String ACTION_IDLE_MAINTENANCE_START;
public static java.lang.String ACTION_INPUT_METHOD_CHANGED;
public static java.lang.String ACTION_INSERT;
public static java.lang.String ACTION_INSERT_OR_EDIT;
+ public static java.lang.String ACTION_INSTALL_FAILURE;
+ public static java.lang.String ACTION_INSTALL_INSTANT_APP_PACKAGE;
public static java.lang.String ACTION_INSTALL_PACKAGE;
+ public static java.lang.String ACTION_INSTANT_APP_RESOLVER_SETTINGS;
+ public static java.lang.String ACTION_INTENT_FILTER_NEEDS_VERIFICATION;
public static java.lang.String ACTION_LOCALE_CHANGED;
+ public static java.lang.String ACTION_LOCKED_BOOT_COMPLETED;
public static java.lang.String ACTION_MAIN;
public static java.lang.String ACTION_MANAGED_PROFILE_ADDED;
+ public static java.lang.String ACTION_MANAGED_PROFILE_AVAILABLE;
public static java.lang.String ACTION_MANAGED_PROFILE_REMOVED;
+ public static java.lang.String ACTION_MANAGED_PROFILE_UNAVAILABLE;
+ public static java.lang.String ACTION_MANAGED_PROFILE_UNLOCKED;
+ public static java.lang.String ACTION_MANAGE_APP_PERMISSIONS;
public static java.lang.String ACTION_MANAGE_NETWORK_USAGE;
public static java.lang.String ACTION_MANAGE_PACKAGE_STORAGE;
+ public static java.lang.String ACTION_MANAGE_PERMISSIONS;
+ public static java.lang.String ACTION_MANAGE_PERMISSION_APPS;
+ public static java.lang.String ACTION_MASTER_CLEAR;
+ public static java.lang.String ACTION_MASTER_CLEAR_NOTIFICATION;
public static java.lang.String ACTION_MEDIA_BAD_REMOVAL;
public static java.lang.String ACTION_MEDIA_BUTTON;
public static java.lang.String ACTION_MEDIA_CHECKING;
@@ -845,16 +6095,23 @@
public static java.lang.String ACTION_MEDIA_MOUNTED;
public static java.lang.String ACTION_MEDIA_NOFS;
public static java.lang.String ACTION_MEDIA_REMOVED;
+ public static java.lang.String ACTION_MEDIA_RESOURCE_GRANTED;
public static java.lang.String ACTION_MEDIA_SCANNER_FINISHED;
public static java.lang.String ACTION_MEDIA_SCANNER_SCAN_FILE;
public static java.lang.String ACTION_MEDIA_SCANNER_STARTED;
public static java.lang.String ACTION_MEDIA_SHARED;
public static java.lang.String ACTION_MEDIA_UNMOUNTABLE;
public static java.lang.String ACTION_MEDIA_UNMOUNTED;
+ public static java.lang.String ACTION_MEDIA_UNSHARED;
public static java.lang.String ACTION_MY_PACKAGE_REPLACED;
+ public static java.lang.String ACTION_MY_PACKAGE_SUSPENDED;
+ public static java.lang.String ACTION_MY_PACKAGE_UNSUSPENDED;
public static java.lang.String ACTION_NEW_OUTGOING_CALL;
public static java.lang.String ACTION_OPEN_DOCUMENT;
public static java.lang.String ACTION_OPEN_DOCUMENT_TREE;
+ public static java.lang.String ACTION_OVERLAY_CHANGED;
+ public static java.lang.String ACTION_PACKAGES_SUSPENDED;
+ public static java.lang.String ACTION_PACKAGES_UNSUSPENDED;
public static java.lang.String ACTION_PACKAGE_ADDED;
public static java.lang.String ACTION_PACKAGE_CHANGED;
public static java.lang.String ACTION_PACKAGE_DATA_CLEARED;
@@ -872,10 +6129,18 @@
public static java.lang.String ACTION_POWER_CONNECTED;
public static java.lang.String ACTION_POWER_DISCONNECTED;
public static java.lang.String ACTION_POWER_USAGE_SUMMARY;
+ public static java.lang.String ACTION_PREFERRED_ACTIVITY_CHANGED;
+ public static java.lang.String ACTION_PRE_BOOT_COMPLETED;
public static java.lang.String ACTION_PROCESS_TEXT;
public static java.lang.String ACTION_PROVIDER_CHANGED;
+ public static java.lang.String ACTION_QUERY_PACKAGE_RESTART;
public static java.lang.String ACTION_QUICK_CLOCK;
+ public static java.lang.String ACTION_QUICK_VIEW;
public static java.lang.String ACTION_REBOOT;
+ public static java.lang.String ACTION_REMOTE_INTENT;
+ public static java.lang.String ACTION_REQUEST_SHUTDOWN;
+ public static java.lang.String ACTION_RESOLVE_INSTANT_APP_PACKAGE;
+ public static java.lang.String ACTION_REVIEW_PERMISSIONS;
public static java.lang.String ACTION_RUN;
public static java.lang.String ACTION_SCREEN_OFF;
public static java.lang.String ACTION_SCREEN_ON;
@@ -884,10 +6149,19 @@
public static java.lang.String ACTION_SEND;
public static java.lang.String ACTION_SENDTO;
public static java.lang.String ACTION_SEND_MULTIPLE;
+ public static java.lang.String ACTION_SERVICE_STATE;
+ public static java.lang.String ACTION_SETTING_RESTORED;
public static java.lang.String ACTION_SET_WALLPAPER;
+ public static java.lang.String ACTION_SHOW_APP_INFO;
+ public static java.lang.String ACTION_SHOW_BRIGHTNESS_DIALOG;
+ public static java.lang.String ACTION_SHOW_KEYBOARD_SHORTCUTS;
+ public static java.lang.String ACTION_SHOW_SUSPENDED_APP_DETAILS;
public static java.lang.String ACTION_SHUTDOWN;
+ public static java.lang.String ACTION_SIM_STATE_CHANGED;
+ public static java.lang.String ACTION_SPLIT_CONFIGURATION_CHANGED;
public static java.lang.String ACTION_SYNC;
public static java.lang.String ACTION_SYSTEM_TUTORIAL;
+ public static java.lang.String ACTION_THERMAL_EVENT;
public static java.lang.String ACTION_TIMEZONE_CHANGED;
public static java.lang.String ACTION_TIME_CHANGED;
public static java.lang.String ACTION_TIME_TICK;
@@ -895,11 +6169,22 @@
public static java.lang.String ACTION_UMS_CONNECTED;
public static java.lang.String ACTION_UMS_DISCONNECTED;
public static java.lang.String ACTION_UNINSTALL_PACKAGE;
+ public static java.lang.String ACTION_UPGRADE_SETUP;
+ public static java.lang.String ACTION_USER_ADDED;
public static java.lang.String ACTION_USER_BACKGROUND;
public static java.lang.String ACTION_USER_FOREGROUND;
+ public static java.lang.String ACTION_USER_INFO_CHANGED;
public static java.lang.String ACTION_USER_INITIALIZE;
public static java.lang.String ACTION_USER_PRESENT;
+ public static java.lang.String ACTION_USER_REMOVED;
+ public static java.lang.String ACTION_USER_STARTED;
+ public static java.lang.String ACTION_USER_STARTING;
+ public static java.lang.String ACTION_USER_STOPPED;
+ public static java.lang.String ACTION_USER_STOPPING;
+ public static java.lang.String ACTION_USER_SWITCHED;
+ public static java.lang.String ACTION_USER_UNLOCKED;
public static java.lang.String ACTION_VIEW;
+ public static java.lang.String ACTION_VOICE_ASSIST;
public static java.lang.String ACTION_VOICE_COMMAND;
public static java.lang.String ACTION_WALLPAPER_CHANGED;
public static java.lang.String ACTION_WEB_SEARCH;
@@ -916,6 +6201,7 @@
public static java.lang.String CATEGORY_APP_MUSIC;
public static java.lang.String CATEGORY_BROWSABLE;
public static java.lang.String CATEGORY_CAR_DOCK;
+ public static java.lang.String CATEGORY_CAR_LAUNCHER;
public static java.lang.String CATEGORY_CAR_MODE;
public static java.lang.String CATEGORY_DEFAULT;
public static java.lang.String CATEGORY_DESK_DOCK;
@@ -924,19 +6210,25 @@
public static java.lang.String CATEGORY_FRAMEWORK_INSTRUMENTATION_TEST;
public static java.lang.String CATEGORY_HE_DESK_DOCK;
public static java.lang.String CATEGORY_HOME;
+ public static java.lang.String CATEGORY_HOME_MAIN;
public static java.lang.String CATEGORY_INFO;
public static java.lang.String CATEGORY_LAUNCHER;
+ public static java.lang.String CATEGORY_LAUNCHER_APP;
public static java.lang.String CATEGORY_LEANBACK_LAUNCHER;
+ public static java.lang.String CATEGORY_LEANBACK_SETTINGS;
public static java.lang.String CATEGORY_LE_DESK_DOCK;
public static java.lang.String CATEGORY_MONKEY;
public static java.lang.String CATEGORY_OPENABLE;
public static java.lang.String CATEGORY_PREFERENCE;
public static java.lang.String CATEGORY_SAMPLE_CODE;
public static java.lang.String CATEGORY_SELECTED_ALTERNATIVE;
+ public static java.lang.String CATEGORY_SETUP_WIZARD;
public static java.lang.String CATEGORY_TAB;
public static java.lang.String CATEGORY_TEST;
+ public static java.lang.String CATEGORY_TYPED_OPENABLE;
public static java.lang.String CATEGORY_UNIT_TEST;
public static java.lang.String CATEGORY_VOICE;
+ public static java.lang.String CATEGORY_VR_HOME;
public static android.os.Parcelable$Creator CREATOR;
public static java.lang.String EXTRA_ALARM_COUNT;
public static java.lang.String EXTRA_ALLOW_MULTIPLE;
@@ -947,17 +6239,33 @@
public static java.lang.String EXTRA_ASSIST_INPUT_HINT_KEYBOARD;
public static java.lang.String EXTRA_ASSIST_PACKAGE;
public static java.lang.String EXTRA_ASSIST_UID;
+ public static java.lang.String EXTRA_AUTO_LAUNCH_SINGLE_CHOICE;
public static java.lang.String EXTRA_BCC;
public static java.lang.String EXTRA_BUG_REPORT;
+ public static java.lang.String EXTRA_CALLING_PACKAGE;
public static java.lang.String EXTRA_CC;
+ public static java.lang.String EXTRA_CDMA_DEFAULT_ROAMING_INDICATOR;
+ public static java.lang.String EXTRA_CDMA_ROAMING_INDICATOR;
public static java.lang.String EXTRA_CHANGED_COMPONENT_NAME;
public static java.lang.String EXTRA_CHANGED_COMPONENT_NAME_LIST;
public static java.lang.String EXTRA_CHANGED_PACKAGE_LIST;
public static java.lang.String EXTRA_CHANGED_UID_LIST;
public static java.lang.String EXTRA_CHOOSER_REFINEMENT_INTENT_SENDER;
+ public static java.lang.String EXTRA_CHOOSER_TARGETS;
public static java.lang.String EXTRA_CHOSEN_COMPONENT;
public static java.lang.String EXTRA_CHOSEN_COMPONENT_INTENT_SENDER;
+ public static java.lang.String EXTRA_CLIENT_INTENT;
+ public static java.lang.String EXTRA_CLIENT_LABEL;
+ public static java.lang.String EXTRA_COMPONENT_NAME;
+ public static java.lang.String EXTRA_CONTENT_ANNOTATIONS;
+ public static java.lang.String EXTRA_CSS_INDICATOR;
+ public static java.lang.String EXTRA_DATA_OPERATOR_ALPHA_LONG;
+ public static java.lang.String EXTRA_DATA_OPERATOR_ALPHA_SHORT;
+ public static java.lang.String EXTRA_DATA_OPERATOR_NUMERIC;
+ public static java.lang.String EXTRA_DATA_RADIO_TECH;
+ public static java.lang.String EXTRA_DATA_REG_STATE;
public static java.lang.String EXTRA_DATA_REMOVED;
+ public static java.lang.String EXTRA_DATA_ROAMING_TYPE;
public static java.lang.String EXTRA_DOCK_STATE;
public static int EXTRA_DOCK_STATE_CAR;
public static int EXTRA_DOCK_STATE_DESK;
@@ -966,40 +6274,112 @@
public static int EXTRA_DOCK_STATE_UNDOCKED;
public static java.lang.String EXTRA_DONT_KILL_APP;
public static java.lang.String EXTRA_EMAIL;
+ public static java.lang.String EXTRA_EMERGENCY_ONLY;
+ public static java.lang.String EXTRA_EPHEMERAL_FAILURE;
+ public static java.lang.String EXTRA_EPHEMERAL_HOSTNAME;
+ public static java.lang.String EXTRA_EPHEMERAL_SUCCESS;
+ public static java.lang.String EXTRA_EPHEMERAL_TOKEN;
+ public static java.lang.String EXTRA_EXCLUDE_COMPONENTS;
+ public static java.lang.String EXTRA_FORCE_FACTORY_RESET;
+ public static java.lang.String EXTRA_FORCE_MASTER_CLEAR;
+ public static java.lang.String EXTRA_FROM_STORAGE;
public static java.lang.String EXTRA_HTML_TEXT;
+ public static java.lang.String EXTRA_INDEX;
public static java.lang.String EXTRA_INITIAL_INTENTS;
public static java.lang.String EXTRA_INSTALLER_PACKAGE_NAME;
+ public static java.lang.String EXTRA_INSTALL_RESULT;
+ public static java.lang.String EXTRA_INSTANT_APP_ACTION;
+ public static java.lang.String EXTRA_INSTANT_APP_BUNDLES;
+ public static java.lang.String EXTRA_INSTANT_APP_EXTRAS;
+ public static java.lang.String EXTRA_INSTANT_APP_FAILURE;
+ public static java.lang.String EXTRA_INSTANT_APP_HOSTNAME;
+ public static java.lang.String EXTRA_INSTANT_APP_SUCCESS;
+ public static java.lang.String EXTRA_INSTANT_APP_TOKEN;
public static java.lang.String EXTRA_INTENT;
+ public static java.lang.String EXTRA_IS_DATA_ROAMING_FROM_REGISTRATION;
+ public static java.lang.String EXTRA_IS_USING_CARRIER_AGGREGATION;
+ public static java.lang.String EXTRA_KEY_CONFIRM;
public static java.lang.String EXTRA_KEY_EVENT;
+ public static java.lang.String EXTRA_LAUNCHER_EXTRAS;
public static java.lang.String EXTRA_LOCAL_ONLY;
+ public static java.lang.String EXTRA_LONG_VERSION_CODE;
+ public static java.lang.String EXTRA_LTE_EARFCN_RSRP_BOOST;
+ public static java.lang.String EXTRA_MANUAL;
+ public static java.lang.String EXTRA_MEDIA_RESOURCE_TYPE;
+ public static int EXTRA_MEDIA_RESOURCE_TYPE_AUDIO_CODEC;
+ public static int EXTRA_MEDIA_RESOURCE_TYPE_VIDEO_CODEC;
public static java.lang.String EXTRA_MIME_TYPES;
+ public static java.lang.String EXTRA_NETWORK_ID;
public static java.lang.String EXTRA_NOT_UNKNOWN_SOURCE;
+ public static java.lang.String EXTRA_OPERATOR_ALPHA_LONG;
+ public static java.lang.String EXTRA_OPERATOR_ALPHA_SHORT;
+ public static java.lang.String EXTRA_OPERATOR_NUMERIC;
+ public static java.lang.String EXTRA_ORIGINATING_UID;
public static java.lang.String EXTRA_ORIGINATING_URI;
+ public static java.lang.String EXTRA_PACKAGES;
+ public static java.lang.String EXTRA_PACKAGE_NAME;
+ public static java.lang.String EXTRA_PERMISSION_NAME;
public static java.lang.String EXTRA_PHONE_NUMBER;
public static java.lang.String EXTRA_PROCESS_TEXT;
public static java.lang.String EXTRA_PROCESS_TEXT_READONLY;
+ public static java.lang.String EXTRA_QUICK_VIEW_ADVANCED;
+ public static java.lang.String EXTRA_QUICK_VIEW_FEATURES;
+ public static java.lang.String EXTRA_QUIET_MODE;
+ public static java.lang.String EXTRA_REASON;
public static java.lang.String EXTRA_REFERRER;
public static java.lang.String EXTRA_REFERRER_NAME;
+ public static java.lang.String EXTRA_REMOTE_CALLBACK;
public static java.lang.String EXTRA_REMOTE_INTENT_TOKEN;
+ public static java.lang.String EXTRA_REMOVED_FOR_ALL_USERS;
public static java.lang.String EXTRA_REPLACEMENT_EXTRAS;
public static java.lang.String EXTRA_REPLACING;
public static java.lang.String EXTRA_RESTRICTIONS_BUNDLE;
public static java.lang.String EXTRA_RESTRICTIONS_INTENT;
public static java.lang.String EXTRA_RESTRICTIONS_LIST;
+ public static java.lang.String EXTRA_RESULT_NEEDED;
public static java.lang.String EXTRA_RESULT_RECEIVER;
public static java.lang.String EXTRA_RETURN_RESULT;
+ public static java.lang.String EXTRA_SETTING_NAME;
+ public static java.lang.String EXTRA_SETTING_NEW_VALUE;
+ public static java.lang.String EXTRA_SETTING_PREVIOUS_VALUE;
+ public static java.lang.String EXTRA_SETTING_RESTORED_FROM_SDK_INT;
public static java.lang.String EXTRA_SHORTCUT_ICON;
public static java.lang.String EXTRA_SHORTCUT_ICON_RESOURCE;
public static java.lang.String EXTRA_SHORTCUT_INTENT;
public static java.lang.String EXTRA_SHORTCUT_NAME;
public static java.lang.String EXTRA_SHUTDOWN_USERSPACE_ONLY;
+ public static java.lang.String EXTRA_SIM_ACTIVATION_RESPONSE;
+ public static java.lang.String EXTRA_SPLIT_NAME;
public static java.lang.String EXTRA_STREAM;
public static java.lang.String EXTRA_SUBJECT;
+ public static java.lang.String EXTRA_SUSPENDED_PACKAGE_EXTRAS;
+ public static java.lang.String EXTRA_SYSTEM_ID;
+ public static java.lang.String EXTRA_TASK_ID;
public static java.lang.String EXTRA_TEMPLATE;
public static java.lang.String EXTRA_TEXT;
+ public static java.lang.String EXTRA_THERMAL_STATE;
+ public static int EXTRA_THERMAL_STATE_EXCEEDED;
+ public static int EXTRA_THERMAL_STATE_NORMAL;
+ public static int EXTRA_THERMAL_STATE_WARNING;
+ public static java.lang.String EXTRA_TIME_PREF_24_HOUR_FORMAT;
+ public static int EXTRA_TIME_PREF_VALUE_USE_12_HOUR;
+ public static int EXTRA_TIME_PREF_VALUE_USE_24_HOUR;
+ public static int EXTRA_TIME_PREF_VALUE_USE_LOCALE_DEFAULT;
public static java.lang.String EXTRA_TITLE;
public static java.lang.String EXTRA_UID;
+ public static java.lang.String EXTRA_UNINSTALL_ALL_USERS;
+ public static java.lang.String EXTRA_UNKNOWN_INSTANT_APP;
public static java.lang.String EXTRA_USER;
+ public static java.lang.String EXTRA_USER_HANDLE;
+ public static java.lang.String EXTRA_USER_ID;
+ public static java.lang.String EXTRA_USER_REQUESTED_SHUTDOWN;
+ public static java.lang.String EXTRA_VERIFICATION_BUNDLE;
+ public static java.lang.String EXTRA_VERSION_CODE;
+ public static java.lang.String EXTRA_VOICE_RADIO_TECH;
+ public static java.lang.String EXTRA_VOICE_REG_STATE;
+ public static java.lang.String EXTRA_VOICE_ROAMING_TYPE;
+ public static java.lang.String EXTRA_WIPE_ESIMS;
+ public static java.lang.String EXTRA_WIPE_EXTERNAL_STORAGE;
public static int FILL_IN_ACTION;
public static int FILL_IN_CATEGORIES;
public static int FILL_IN_CLIP_DATA;
@@ -1015,6 +6395,8 @@
public static int FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS;
public static int FLAG_ACTIVITY_FORWARD_RESULT;
public static int FLAG_ACTIVITY_LAUNCHED_FROM_HISTORY;
+ public static int FLAG_ACTIVITY_LAUNCH_ADJACENT;
+ public static int FLAG_ACTIVITY_MATCH_EXTERNAL;
public static int FLAG_ACTIVITY_MULTIPLE_TASK;
public static int FLAG_ACTIVITY_NEW_DOCUMENT;
public static int FLAG_ACTIVITY_NEW_TASK;
@@ -1028,36 +6410,57 @@
public static int FLAG_ACTIVITY_SINGLE_TOP;
public static int FLAG_ACTIVITY_TASK_ON_HOME;
public static int FLAG_DEBUG_LOG_RESOLUTION;
+ public static int FLAG_DEBUG_TRIAGED_MISSING;
public static int FLAG_EXCLUDE_STOPPED_PACKAGES;
public static int FLAG_FROM_BACKGROUND;
public static int FLAG_GRANT_PERSISTABLE_URI_PERMISSION;
public static int FLAG_GRANT_PREFIX_URI_PERMISSION;
public static int FLAG_GRANT_READ_URI_PERMISSION;
public static int FLAG_GRANT_WRITE_URI_PERMISSION;
+ public static int FLAG_IGNORE_EPHEMERAL;
public static int FLAG_INCLUDE_STOPPED_PACKAGES;
+ public static int FLAG_RECEIVER_BOOT_UPGRADE;
+ public static int FLAG_RECEIVER_EXCLUDE_BACKGROUND;
public static int FLAG_RECEIVER_FOREGROUND;
+ public static int FLAG_RECEIVER_FROM_SHELL;
+ public static int FLAG_RECEIVER_INCLUDE_BACKGROUND;
public static int FLAG_RECEIVER_NO_ABORT;
public static int FLAG_RECEIVER_REGISTERED_ONLY;
+ public static int FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT;
public static int FLAG_RECEIVER_REPLACE_PENDING;
+ public static int FLAG_RECEIVER_VISIBLE_TO_INSTANT_APPS;
+ public static int IMMUTABLE_FLAGS;
public static java.lang.String METADATA_DOCK_HOME;
+ public static java.lang.String METADATA_SETUP_VERSION;
public static int URI_ALLOW_UNSAFE;
public static int URI_ANDROID_APP_SCHEME;
public static int URI_INTENT_SCHEME;
}
+-keep class android.content.Intent$CommandOptionHandler {
+
+ public abstract boolean handleOption(java.lang.String, android.os.ShellCommand);
+
+
+}
+
-keep class android.content.IntentFilter {
<init>();
<init>(java.lang.String);
<init>(java.lang.String, java.lang.String);
<init>(android.content.IntentFilter);
+ <init>(android.os.Parcel);
public java.util.Iterator actionsIterator();
public void addAction(java.lang.String);
public void addCategory(java.lang.String);
public void addDataAuthority(java.lang.String, java.lang.String);
+ public void addDataAuthority(android.content.IntentFilter$AuthorityEntry);
public void addDataPath(java.lang.String, int);
+ public void addDataPath(android.os.PatternMatcher);
public void addDataScheme(java.lang.String);
public void addDataSchemeSpecificPart(java.lang.String, int);
+ public void addDataSchemeSpecificPart(android.os.PatternMatcher);
public void addDataType(java.lang.String);
public java.util.Iterator authoritiesIterator();
public java.util.Iterator categoriesIterator();
@@ -1069,36 +6472,58 @@
public int countDataSchemes();
public int countDataTypes();
public static android.content.IntentFilter create(java.lang.String, java.lang.String);
+ public boolean debugCheck();
public int describeContents();
public void dump(android.util.Printer, java.lang.String);
public java.lang.String getAction(int);
+ public boolean getAutoVerify();
public java.lang.String getCategory(int);
public android.content.IntentFilter$AuthorityEntry getDataAuthority(int);
public android.os.PatternMatcher getDataPath(int);
public java.lang.String getDataScheme(int);
public android.os.PatternMatcher getDataSchemeSpecificPart(int);
public java.lang.String getDataType(int);
+ public java.lang.String[] getHosts();
+ public java.util.ArrayList getHostsList();
+ public int getOrder();
public int getPriority();
+ public int getVisibilityToInstantApp();
+ public boolean handleAllWebDataURI();
+ public boolean handlesWebUris(boolean);
public boolean hasAction(java.lang.String);
public boolean hasCategory(java.lang.String);
public boolean hasDataAuthority(android.net.Uri);
+ public boolean hasDataAuthority(android.content.IntentFilter$AuthorityEntry);
public boolean hasDataPath(java.lang.String);
+ public boolean hasDataPath(android.os.PatternMatcher);
public boolean hasDataScheme(java.lang.String);
public boolean hasDataSchemeSpecificPart(java.lang.String);
+ public boolean hasDataSchemeSpecificPart(android.os.PatternMatcher);
public boolean hasDataType(java.lang.String);
+ public boolean hasExactDataType(java.lang.String);
+ public boolean isExplicitlyVisibleToInstantApp();
+ public boolean isImplicitlyVisibleToInstantApp();
+ public boolean isVerified();
+ public boolean isVisibleToInstantApp();
public int match(android.content.ContentResolver, android.content.Intent, boolean, java.lang.String);
public int match(java.lang.String, java.lang.String, java.lang.String, android.net.Uri, java.util.Set, java.lang.String);
public boolean matchAction(java.lang.String);
public java.lang.String matchCategories(java.util.Set);
public int matchData(java.lang.String, java.lang.String, android.net.Uri);
public int matchDataAuthority(android.net.Uri);
+ public boolean needsVerification();
public java.util.Iterator pathsIterator();
public void readFromXml(org.xmlpull.v1.XmlPullParser);
public java.util.Iterator schemeSpecificPartsIterator();
public java.util.Iterator schemesIterator();
+ public void setAutoVerify(boolean);
+ public void setOrder(int);
public void setPriority(int);
+ public void setVerified(boolean);
+ public void setVisibilityToInstantApp(int);
public java.util.Iterator typesIterator();
public void writeToParcel(android.os.Parcel, int);
+ public void writeToProto(android.util.proto.ProtoOutputStream, long);
public void writeToXml(org.xmlpull.v1.XmlSerializer);
@@ -1117,15 +6542,22 @@
public static int NO_MATCH_CATEGORY;
public static int NO_MATCH_DATA;
public static int NO_MATCH_TYPE;
+ public static java.lang.String SCHEME_HTTP;
+ public static java.lang.String SCHEME_HTTPS;
public static int SYSTEM_HIGH_PRIORITY;
public static int SYSTEM_LOW_PRIORITY;
+ public static int VISIBILITY_EXPLICIT;
+ public static int VISIBILITY_IMPLICIT;
+ public static int VISIBILITY_NONE;
}
-keep class android.content.IntentFilter$AuthorityEntry {
<init>(java.lang.String, java.lang.String);
+ public boolean equals(java.lang.Object);
public java.lang.String getHost();
public int getPort();
+ public boolean match(android.content.IntentFilter$AuthorityEntry);
public int match(android.net.Uri);
@@ -1140,13 +6572,18 @@
}
-keep class android.content.IntentSender {
+ <init>(android.content.IIntentSender);
+ <init>(android.content.IIntentSender, android.os.IBinder);
+ <init>(android.os.IBinder);
public int describeContents();
public boolean equals(java.lang.Object);
public java.lang.String getCreatorPackage();
public int getCreatorUid();
public android.os.UserHandle getCreatorUserHandle();
+ public android.content.IIntentSender getTarget();
public java.lang.String getTargetPackage();
+ public android.os.IBinder getWhitelistToken();
public int hashCode();
public static android.content.IntentSender readIntentSenderOrNullFromParcel(android.os.Parcel);
public void sendIntent(android.content.Context, int, android.content.Intent, android.content.IntentSender$OnFinished, android.os.Handler);
@@ -1175,6 +6612,57 @@
}
+-keep class android.content.Loader {
+ <init>(android.content.Context);
+
+ public void abandon();
+ public boolean cancelLoad();
+ public void commitContentChanged();
+ public java.lang.String dataToString(java.lang.Object);
+ public void deliverCancellation();
+ public void deliverResult(java.lang.Object);
+ public void dump(java.lang.String, java.io.FileDescriptor, java.io.PrintWriter, java.lang.String[]);
+ public void forceLoad();
+ public android.content.Context getContext();
+ public int getId();
+ public boolean isAbandoned();
+ public boolean isReset();
+ public boolean isStarted();
+ protected void onAbandon();
+ protected boolean onCancelLoad();
+ public void onContentChanged();
+ protected void onForceLoad();
+ protected void onReset();
+ protected void onStartLoading();
+ protected void onStopLoading();
+ public void registerListener(int, android.content.Loader$OnLoadCompleteListener);
+ public void registerOnLoadCanceledListener(android.content.Loader$OnLoadCanceledListener);
+ public void reset();
+ public void rollbackContentChanged();
+ public void startLoading();
+ public void stopLoading();
+ public boolean takeContentChanged();
+ public java.lang.String toString();
+ public void unregisterListener(android.content.Loader$OnLoadCompleteListener);
+ public void unregisterOnLoadCanceledListener(android.content.Loader$OnLoadCanceledListener);
+
+
+}
+
+-keep class android.content.Loader$OnLoadCanceledListener {
+
+ public abstract void onLoadCanceled(android.content.Loader);
+
+
+}
+
+-keep class android.content.Loader$OnLoadCompleteListener {
+
+ public abstract void onLoadComplete(android.content.Loader, java.lang.Object);
+
+
+}
+
-keep class android.content.OperationApplicationException {
<init>();
<init>(java.lang.String);
@@ -1190,9 +6678,12 @@
-keep class android.content.PeriodicSync {
<init>(android.accounts.Account, java.lang.String, android.os.Bundle, long);
+ <init>(android.content.PeriodicSync);
+ <init>(android.accounts.Account, java.lang.String, android.os.Bundle, long, long);
public int describeContents();
public boolean equals(java.lang.Object);
+ public static boolean syncExtrasEquals(android.os.Bundle, android.os.Bundle);
public java.lang.String toString();
public void writeToParcel(android.os.Parcel, int);
@@ -1201,11 +6692,14 @@
public android.accounts.Account account;
public java.lang.String authority;
public android.os.Bundle extras;
+ public long flexTime;
public long period;
}
-keep class android.content.ServiceConnection {
+ public void onBindingDied(android.content.ComponentName);
+ public void onNullBinding(android.content.ComponentName);
public abstract void onServiceConnected(android.content.ComponentName, android.os.IBinder);
public abstract void onServiceDisconnected(android.content.ComponentName);
@@ -1254,11 +6748,13 @@
-keep class android.content.SyncAdapterType {
<init>(java.lang.String, java.lang.String, boolean, boolean);
+ <init>(java.lang.String, java.lang.String, boolean, boolean, boolean, boolean, java.lang.String, java.lang.String);
<init>(android.os.Parcel);
public boolean allowParallelSyncs();
public int describeContents();
public boolean equals(java.lang.Object);
+ public java.lang.String getPackageName();
public java.lang.String getSettingsActivity();
public int hashCode();
public boolean isAlwaysSyncable();
@@ -1276,23 +6772,114 @@
}
-keep class android.content.SyncInfo {
+ <init>(int, android.accounts.Account, java.lang.String, long);
+ <init>(android.content.SyncInfo);
- public int describeContents();
- public void writeToParcel(android.os.Parcel, int);
-
-
- public android.accounts.Account account;
- public java.lang.String authority;
- public long startTime;
-}
-
--keep class android.content.SyncRequest {
-
+ public static android.content.SyncInfo createAccountRedacted(int, java.lang.String, long);
public int describeContents();
public void writeToParcel(android.os.Parcel, int);
public static android.os.Parcelable$Creator CREATOR;
+ public android.accounts.Account account;
+ public java.lang.String authority;
+ public int authorityId;
+ public long startTime;
+}
+
+-keep class android.content.SyncRequest {
+ <init>(android.content.SyncRequest$Builder);
+
+ public int describeContents();
+ public android.accounts.Account getAccount();
+ public android.os.Bundle getBundle();
+ public java.lang.String getProvider();
+ public long getSyncFlexTime();
+ public long getSyncRunTime();
+ public boolean isExpedited();
+ public boolean isPeriodic();
+ public void writeToParcel(android.os.Parcel, int);
+
+
+ public static android.os.Parcelable$Creator CREATOR;
+}
+
+-keep class android.content.SyncRequest$Builder {
+ <init>();
+
+ public android.content.SyncRequest build();
+ public android.content.SyncRequest$Builder setDisallowMetered(boolean);
+ public android.content.SyncRequest$Builder setExpedited(boolean);
+ public android.content.SyncRequest$Builder setExtras(android.os.Bundle);
+ public android.content.SyncRequest$Builder setIgnoreBackoff(boolean);
+ public android.content.SyncRequest$Builder setIgnoreSettings(boolean);
+ public android.content.SyncRequest$Builder setManual(boolean);
+ public android.content.SyncRequest$Builder setNoRetry(boolean);
+ public android.content.SyncRequest$Builder setRequiresCharging(boolean);
+ public android.content.SyncRequest$Builder setSyncAdapter(android.accounts.Account, java.lang.String);
+ public android.content.SyncRequest$Builder syncOnce();
+ public android.content.SyncRequest$Builder syncPeriodic(long, long);
+
+
+}
+
+-keep class android.content.SyncStatusInfo {
+ <init>(int);
+ <init>(android.os.Parcel);
+ <init>(android.content.SyncStatusInfo);
+
+ public void addEvent(java.lang.String);
+ public int describeContents();
+ public java.lang.String getEvent(int);
+ public int getEventCount();
+ public long getEventTime(int);
+ public int getLastFailureMesgAsInt(int);
+ public long getPeriodicSyncTime(int);
+ public void maybeResetTodayStats(boolean, boolean);
+ public void removePeriodicSyncTime(int);
+ public void setLastFailure(int, long, java.lang.String);
+ public void setLastSuccess(int, long);
+ public void setPeriodicSyncTime(int, long);
+ public void writeToParcel(android.os.Parcel, int);
+
+
+ public static android.os.Parcelable$Creator CREATOR;
+ public int authorityId;
+ public long initialFailureTime;
+ public boolean initialize;
+ public java.lang.String lastFailureMesg;
+ public int lastFailureSource;
+ public long lastFailureTime;
+ public int lastSuccessSource;
+ public long lastSuccessTime;
+ public long lastTodayResetTime;
+ public boolean pending;
+ public long[] perSourceLastFailureTimes;
+ public long[] perSourceLastSuccessTimes;
+ public android.content.SyncStatusInfo$Stats todayStats;
+ public android.content.SyncStatusInfo$Stats totalStats;
+ public android.content.SyncStatusInfo$Stats yesterdayStats;
+}
+
+-keep class android.content.SyncStatusInfo$Stats {
+ <init>();
+
+ public void clear();
+ public void copyTo(android.content.SyncStatusInfo$Stats);
+ public void readFromParcel(android.os.Parcel);
+ public void writeToParcel(android.os.Parcel);
+
+
+ public int numCancels;
+ public int numFailures;
+ public int numSourceFeed;
+ public int numSourceLocal;
+ public int numSourceOther;
+ public int numSourcePeriodic;
+ public int numSourcePoll;
+ public int numSourceUser;
+ public int numSyncs;
+ public long totalElapsedTime;
}
-keep class android.content.SyncStatusObserver {
@@ -1303,6 +6890,8 @@
}
-keep class android.content.UriPermission {
+ <init>(android.net.Uri, int, long);
+ <init>(android.os.Parcel);
public int describeContents();
public long getPersistedTime();
@@ -1321,13 +6910,32 @@
<init>();
<init>(android.content.pm.ActivityInfo);
+ public static int activityInfoConfigJavaToNative(int);
+ public static int activityInfoConfigNativeToJava(int);
+ public static java.lang.String colorModeToString(int);
public int describeContents();
public void dump(android.util.Printer, java.lang.String);
+ public void dump(android.util.Printer, java.lang.String, int);
+ public int getRealConfigChanged();
public int getThemeResource();
+ public static boolean isFixedOrientationLandscape(int);
+ public static boolean isFixedOrientationPortrait(int);
+ public static boolean isPreserveOrientationMode(int);
+ public static boolean isResizeableMode(int);
+ public static boolean isTranslucentOrFloating(android.content.res.TypedArray);
+ public static java.lang.String lockTaskLaunchModeToString(int);
+ public static java.lang.String resizeModeToString(int);
+ public static java.lang.String screenOrientationToString(int);
+ public boolean supportsPictureInPicture();
public java.lang.String toString();
public void writeToParcel(android.os.Parcel, int);
+ public static int COLOR_MODE_DEFAULT;
+ public static int COLOR_MODE_HDR;
+ public static int COLOR_MODE_WIDE_COLOR_GAMUT;
+ public static int CONFIG_ASSETS_PATHS;
+ public static int CONFIG_COLOR_MODE;
public static int CONFIG_DENSITY;
public static int CONFIG_FONT_SCALE;
public static int CONFIG_KEYBOARD;
@@ -1336,6 +6944,7 @@
public static int CONFIG_LOCALE;
public static int CONFIG_MCC;
public static int CONFIG_MNC;
+ public static int[] CONFIG_NATIVE_BITS;
public static int CONFIG_NAVIGATION;
public static int CONFIG_ORIENTATION;
public static int CONFIG_SCREEN_LAYOUT;
@@ -1343,33 +6952,56 @@
public static int CONFIG_SMALLEST_SCREEN_SIZE;
public static int CONFIG_TOUCHSCREEN;
public static int CONFIG_UI_MODE;
+ public static int CONFIG_WINDOW_CONFIGURATION;
public static android.os.Parcelable$Creator CREATOR;
public static int DOCUMENT_LAUNCH_ALWAYS;
public static int DOCUMENT_LAUNCH_INTO_EXISTING;
public static int DOCUMENT_LAUNCH_NEVER;
public static int DOCUMENT_LAUNCH_NONE;
+ public static int FLAG_ALLOW_EMBEDDED;
public static int FLAG_ALLOW_TASK_REPARENTING;
+ public static int FLAG_ALWAYS_FOCUSABLE;
public static int FLAG_ALWAYS_RETAIN_TASK_STATE;
public static int FLAG_AUTO_REMOVE_FROM_RECENTS;
public static int FLAG_CLEAR_TASK_ON_LAUNCH;
+ public static int FLAG_ENABLE_VR_MODE;
public static int FLAG_EXCLUDE_FROM_RECENTS;
public static int FLAG_FINISH_ON_CLOSE_SYSTEM_DIALOGS;
public static int FLAG_FINISH_ON_TASK_LAUNCH;
public static int FLAG_HARDWARE_ACCELERATED;
public static int FLAG_IMMERSIVE;
+ public static int FLAG_IMPLICITLY_VISIBLE_TO_INSTANT_APP;
public static int FLAG_MULTIPROCESS;
public static int FLAG_NO_HISTORY;
public static int FLAG_RELINQUISH_TASK_IDENTITY;
public static int FLAG_RESUME_WHILE_PAUSING;
+ public static int FLAG_SHOW_FOR_ALL_USERS;
+ public static int FLAG_SHOW_WHEN_LOCKED;
public static int FLAG_SINGLE_USER;
public static int FLAG_STATE_NOT_NEEDED;
+ public static int FLAG_SUPPORTS_PICTURE_IN_PICTURE;
+ public static int FLAG_SYSTEM_USER_ONLY;
+ public static int FLAG_TURN_SCREEN_ON;
+ public static int FLAG_VISIBLE_TO_INSTANT_APP;
public static int LAUNCH_MULTIPLE;
public static int LAUNCH_SINGLE_INSTANCE;
public static int LAUNCH_SINGLE_TASK;
public static int LAUNCH_SINGLE_TOP;
+ public static int LOCK_TASK_LAUNCH_MODE_ALWAYS;
+ public static int LOCK_TASK_LAUNCH_MODE_DEFAULT;
+ public static int LOCK_TASK_LAUNCH_MODE_IF_WHITELISTED;
+ public static int LOCK_TASK_LAUNCH_MODE_NEVER;
public static int PERSIST_ACROSS_REBOOTS;
public static int PERSIST_NEVER;
public static int PERSIST_ROOT_ONLY;
+ public static int RESIZE_MODE_FORCE_RESIZABLE_LANDSCAPE_ONLY;
+ public static int RESIZE_MODE_FORCE_RESIZABLE_PORTRAIT_ONLY;
+ public static int RESIZE_MODE_FORCE_RESIZABLE_PRESERVE_ORIENTATION;
+ public static int RESIZE_MODE_FORCE_RESIZEABLE;
+ public static int RESIZE_MODE_RESIZEABLE;
+ public static int RESIZE_MODE_RESIZEABLE_AND_PIPABLE_DEPRECATED;
+ public static int RESIZE_MODE_RESIZEABLE_VIA_SDK_VERSION;
+ public static int RESIZE_MODE_UNRESIZEABLE;
public static int SCREEN_ORIENTATION_BEHIND;
public static int SCREEN_ORIENTATION_FULL_SENSOR;
public static int SCREEN_ORIENTATION_FULL_USER;
@@ -1382,25 +7014,48 @@
public static int SCREEN_ORIENTATION_SENSOR;
public static int SCREEN_ORIENTATION_SENSOR_LANDSCAPE;
public static int SCREEN_ORIENTATION_SENSOR_PORTRAIT;
+ public static int SCREEN_ORIENTATION_UNSET;
public static int SCREEN_ORIENTATION_UNSPECIFIED;
public static int SCREEN_ORIENTATION_USER;
public static int SCREEN_ORIENTATION_USER_LANDSCAPE;
public static int SCREEN_ORIENTATION_USER_PORTRAIT;
public static int UIOPTION_SPLIT_ACTION_BAR_WHEN_NARROW;
+ public int colorMode;
public int configChanges;
public int documentLaunchMode;
public int flags;
public int launchMode;
+ public java.lang.String launchToken;
+ public int lockTaskLaunchMode;
+ public float maxAspectRatio;
public int maxRecents;
public java.lang.String parentActivityName;
public java.lang.String permission;
public int persistableMode;
+ public java.lang.String requestedVrComponent;
+ public int resizeMode;
+ public int rotationAnimation;
public int screenOrientation;
public int softInputMode;
public java.lang.String targetActivity;
public java.lang.String taskAffinity;
public int theme;
public int uiOptions;
+ public android.content.pm.ActivityInfo$WindowLayout windowLayout;
+}
+
+-keep class android.content.pm.ActivityInfo$WindowLayout {
+ <init>(int, float, int, float, int, int, int);
+
+
+
+ public int gravity;
+ public int height;
+ public float heightFraction;
+ public int minHeight;
+ public int minWidth;
+ public int width;
+ public float widthFraction;
}
-keep class android.content.pm.ApplicationInfo {
@@ -1408,12 +7063,68 @@
<init>(android.content.pm.ApplicationInfo);
public int describeContents();
+ public void disableCompatibilityMode();
public void dump(android.util.Printer, java.lang.String);
+ public void dump(android.util.Printer, java.lang.String, int);
+ protected android.content.pm.ApplicationInfo getApplicationInfo();
+ public java.lang.String getBaseCodePath();
+ public java.lang.String getBaseResourcePath();
+ public static java.lang.CharSequence getCategoryTitle(android.content.Context, int);
+ public java.lang.String getCodePath();
+ public int getHiddenApiEnforcementPolicy();
+ public java.lang.String getResourcePath();
+ public java.lang.String[] getSplitCodePaths();
+ public java.lang.String[] getSplitResourcePaths();
+ public boolean hasCode();
+ public boolean hasRtlSupport();
+ public void initForUser(int);
+ public boolean isDefaultToDeviceProtectedStorage();
+ public boolean isDirectBootAware();
+ public boolean isEncryptionAware();
+ public boolean isExternal();
+ public boolean isExternalAsec();
+ public boolean isForwardLocked();
+ public boolean isInstantApp();
+ public boolean isInternal();
+ public boolean isOem();
+ public boolean isPartiallyDirectBootAware();
+ public boolean isPrivilegedApp();
+ public boolean isProduct();
+ public boolean isRequiredForSystemUser();
+ public boolean isSignedWithPlatformKey();
+ public boolean isStaticSharedLibrary();
+ public boolean isSystemApp();
+ public boolean isUpdatedSystemApp();
+ public static boolean isValidHiddenApiEnforcementPolicy(int);
+ public boolean isVendor();
+ public boolean isVirtualPreload();
+ public android.graphics.drawable.Drawable loadDefaultIcon(android.content.pm.PackageManager);
public java.lang.CharSequence loadDescription(android.content.pm.PackageManager);
+ public void maybeUpdateHiddenApiEnforcementPolicy(int, int);
+ public boolean requestsIsolatedSplitLoading();
+ public void setBaseCodePath(java.lang.String);
+ public void setBaseResourcePath(java.lang.String);
+ public void setCodePath(java.lang.String);
+ public void setHiddenApiEnforcementPolicy(int);
+ public void setResourcePath(java.lang.String);
+ public void setSplitCodePaths(java.lang.String[]);
+ public void setSplitResourcePaths(java.lang.String[]);
+ public void setVersionCode(long);
public java.lang.String toString();
+ public boolean usesCompatibilityMode();
public void writeToParcel(android.os.Parcel, int);
+ public void writeToProto(android.util.proto.ProtoOutputStream, long, int);
+ public static int CATEGORY_AUDIO;
+ public static int CATEGORY_GAME;
+ public static int CATEGORY_IMAGE;
+ public static int CATEGORY_MAPS;
+ public static int CATEGORY_NEWS;
+ public static int CATEGORY_PRODUCTIVITY;
+ public static int CATEGORY_SOCIAL;
+ public static int CATEGORY_UNDEFINED;
+ public static int CATEGORY_VIDEO;
public static android.os.Parcelable$Creator CREATOR;
public static int FLAG_ALLOW_BACKUP;
public static int FLAG_ALLOW_CLEAR_USER_DATA;
@@ -1441,34 +7152,149 @@
public static int FLAG_SUPPORTS_SCREEN_DENSITIES;
public static int FLAG_SUPPORTS_SMALL_SCREENS;
public static int FLAG_SUPPORTS_XLARGE_SCREENS;
+ public static int FLAG_SUSPENDED;
public static int FLAG_SYSTEM;
public static int FLAG_TEST_ONLY;
public static int FLAG_UPDATED_SYSTEM_APP;
public static int FLAG_USES_CLEARTEXT_TRAFFIC;
public static int FLAG_VM_SAFE_MODE;
+ public static int HIDDEN_API_ENFORCEMENT_BLACK;
+ public static int HIDDEN_API_ENFORCEMENT_DARK_GREY_AND_BLACK;
+ public static int HIDDEN_API_ENFORCEMENT_DEFAULT;
+ public static int HIDDEN_API_ENFORCEMENT_JUST_WARN;
+ public static int HIDDEN_API_ENFORCEMENT_NONE;
+ public static java.lang.String METADATA_PRELOADED_FONTS;
+ public static int PRIVATE_FLAG_ACTIVITIES_RESIZE_MODE_RESIZEABLE;
+ public static int PRIVATE_FLAG_ACTIVITIES_RESIZE_MODE_RESIZEABLE_VIA_SDK_VERSION;
+ public static int PRIVATE_FLAG_ACTIVITIES_RESIZE_MODE_UNRESIZEABLE;
+ public static int PRIVATE_FLAG_BACKUP_IN_FOREGROUND;
+ public static int PRIVATE_FLAG_CANT_SAVE_STATE;
+ public static int PRIVATE_FLAG_DEFAULT_TO_DEVICE_PROTECTED_STORAGE;
+ public static int PRIVATE_FLAG_DIRECT_BOOT_AWARE;
+ public static int PRIVATE_FLAG_FORWARD_LOCK;
+ public static int PRIVATE_FLAG_HAS_DOMAIN_URLS;
+ public static int PRIVATE_FLAG_HIDDEN;
+ public static int PRIVATE_FLAG_INSTANT;
+ public static int PRIVATE_FLAG_ISOLATED_SPLIT_LOADING;
+ public static int PRIVATE_FLAG_OEM;
+ public static int PRIVATE_FLAG_PARTIALLY_DIRECT_BOOT_AWARE;
+ public static int PRIVATE_FLAG_PRIVILEGED;
+ public static int PRIVATE_FLAG_PRODUCT;
+ public static int PRIVATE_FLAG_REQUIRED_FOR_SYSTEM_USER;
+ public static int PRIVATE_FLAG_SIGNED_WITH_PLATFORM_KEY;
+ public static int PRIVATE_FLAG_STATIC_SHARED_LIBRARY;
+ public static int PRIVATE_FLAG_VENDOR;
+ public static int PRIVATE_FLAG_VIRTUAL_PRELOAD;
+ public java.lang.String appComponentFactory;
public java.lang.String backupAgentName;
+ public int category;
+ public java.lang.String classLoaderName;
public java.lang.String className;
public int compatibleWidthLimitDp;
+ public int compileSdkVersion;
+ public java.lang.String compileSdkVersionCodename;
+ public java.lang.String credentialProtectedDataDir;
public java.lang.String dataDir;
public int descriptionRes;
+ public java.lang.String deviceProtectedDataDir;
public boolean enabled;
+ public int enabledSetting;
public int flags;
+ public int fullBackupContent;
+ public int installLocation;
public int largestWidthLimitDp;
+ public long longVersionCode;
public java.lang.String manageSpaceActivityName;
+ public float maxAspectRatio;
+ public int minSdkVersion;
public java.lang.String nativeLibraryDir;
+ public java.lang.String nativeLibraryRootDir;
+ public boolean nativeLibraryRootRequiresIsa;
+ public int networkSecurityConfigRes;
public java.lang.String permission;
+ public java.lang.String primaryCpuAbi;
+ public int privateFlags;
public java.lang.String processName;
public java.lang.String publicSourceDir;
public int requiresSmallestWidthDp;
+ public java.lang.String[] resourceDirs;
+ public java.lang.String scanPublicSourceDir;
+ public java.lang.String scanSourceDir;
+ public java.lang.String seInfo;
+ public java.lang.String seInfoUser;
+ public java.lang.String secondaryCpuAbi;
+ public java.lang.String secondaryNativeLibraryDir;
public java.lang.String[] sharedLibraryFiles;
public java.lang.String sourceDir;
+ public java.lang.String[] splitClassLoaderNames;
+ public android.util.SparseArray splitDependencies;
+ public java.lang.String[] splitNames;
public java.lang.String[] splitPublicSourceDirs;
public java.lang.String[] splitSourceDirs;
+ public java.util.UUID storageUuid;
+ public int targetSandboxVersion;
public int targetSdkVersion;
public java.lang.String taskAffinity;
public int theme;
public int uiOptions;
public int uid;
+ public int versionCode;
+ public java.lang.String volumeUuid;
+}
+
+-keep class android.content.pm.AuxiliaryResolveInfo {
+ <init>(java.lang.String, boolean, android.content.Intent, java.util.List);
+ <init>(android.content.ComponentName, android.content.Intent, java.util.List);
+ <init>(android.content.ComponentName, java.lang.String, long, java.lang.String);
+
+
+
+ public android.content.Intent failureIntent;
+ public java.util.List filters;
+ public android.content.ComponentName installFailureActivity;
+ public boolean needsPhaseTwo;
+ public java.lang.String token;
+}
+
+-keep class android.content.pm.AuxiliaryResolveInfo$AuxiliaryFilter {
+ <init>(android.content.IntentFilter, android.content.pm.InstantAppResolveInfo, java.lang.String, android.os.Bundle);
+ <init>(android.content.pm.InstantAppResolveInfo, java.lang.String, android.os.Bundle);
+ <init>(java.lang.String, long, java.lang.String);
+
+ public java.lang.String toString();
+
+
+ public android.os.Bundle extras;
+ public java.lang.String packageName;
+ public android.content.pm.InstantAppResolveInfo resolveInfo;
+ public java.lang.String splitName;
+ public long versionCode;
+}
+
+-keep class android.content.pm.BaseParceledListSlice {
+ <init>(java.util.List);
+
+ public java.util.List getList();
+ protected abstract android.os.Parcelable$Creator readParcelableCreator(android.os.Parcel, java.lang.ClassLoader);
+ public void setInlineCountLimit(int);
+ protected abstract void writeElement(java.lang.Object, android.os.Parcel, int);
+ protected abstract void writeParcelableCreator(java.lang.Object, android.os.Parcel);
+ public void writeToParcel(android.os.Parcel, int);
+
+
+}
+
+-keep class android.content.pm.ChangedPackages {
+ <init>(int, java.util.List);
+ <init>(android.os.Parcel);
+
+ public int describeContents();
+ public java.util.List getPackageNames();
+ public int getSequenceNumber();
+ public void writeToParcel(android.os.Parcel, int);
+
+
+ public static android.os.Parcelable$Creator CREATOR;
}
-keep class android.content.pm.ComponentInfo {
@@ -1478,19 +7304,27 @@
protected void dumpBack(android.util.Printer, java.lang.String);
protected void dumpFront(android.util.Printer, java.lang.String);
+ protected android.content.pm.ApplicationInfo getApplicationInfo();
public int getBannerResource();
+ public android.content.ComponentName getComponentName();
public int getIconResource();
public int getLogoResource();
public boolean isEnabled();
- public java.lang.CharSequence loadLabel(android.content.pm.PackageManager);
+ protected android.graphics.drawable.Drawable loadDefaultBanner(android.content.pm.PackageManager);
+ public android.graphics.drawable.Drawable loadDefaultIcon(android.content.pm.PackageManager);
+ protected android.graphics.drawable.Drawable loadDefaultLogo(android.content.pm.PackageManager);
+ public java.lang.CharSequence loadUnsafeLabel(android.content.pm.PackageManager);
public void writeToParcel(android.os.Parcel, int);
public android.content.pm.ApplicationInfo applicationInfo;
public int descriptionRes;
+ public boolean directBootAware;
public boolean enabled;
+ public boolean encryptionAware;
public boolean exported;
public java.lang.String processName;
+ public java.lang.String splitName;
}
-keep class android.content.pm.ConfigurationInfo {
@@ -1534,6 +7368,7 @@
public java.lang.String getGlEsVersion();
public java.lang.String toString();
public void writeToParcel(android.os.Parcel, int);
+ public void writeToProto(android.util.proto.ProtoOutputStream, long);
public static android.os.Parcelable$Creator CREATOR;
@@ -1542,32 +7377,459 @@
public int flags;
public java.lang.String name;
public int reqGlEsVersion;
+ public int version;
+}
+
+-keep class android.content.pm.IDexModuleRegisterCallback {
+
+ public abstract void onDexModuleRegistered(java.lang.String, boolean, java.lang.String);
+
+
+}
+
+-keep class android.content.pm.IOnPermissionsChangeListener {
+
+ public abstract void onPermissionsChanged(int);
+
+
+}
+
+-keep class android.content.pm.IPackageDataObserver {
+
+ public abstract void onRemoveCompleted(java.lang.String, boolean);
+
+
+}
+
+-keep class android.content.pm.IPackageDeleteObserver {
+
+ public abstract void packageDeleted(java.lang.String, int);
+
+
+}
+
+-keep class android.content.pm.IPackageDeleteObserver2 {
+
+ public abstract void onPackageDeleted(java.lang.String, int, java.lang.String);
+ public abstract void onUserActionRequired(android.content.Intent);
+
+
+}
+
+-keep class android.content.pm.IPackageInstaller {
+
+ public abstract void abandonSession(int);
+ public abstract int createSession(android.content.pm.PackageInstaller$SessionParams, java.lang.String, int);
+ public abstract android.content.pm.ParceledListSlice getAllSessions(int);
+ public abstract android.content.pm.ParceledListSlice getMySessions(java.lang.String, int);
+ public abstract android.content.pm.PackageInstaller$SessionInfo getSessionInfo(int);
+ public abstract android.content.pm.IPackageInstallerSession openSession(int);
+ public abstract void registerCallback(android.content.pm.IPackageInstallerCallback, int);
+ public abstract void setPermissionsResult(int, boolean);
+ public abstract void uninstall(android.content.pm.VersionedPackage, java.lang.String, int, android.content.IntentSender, int);
+ public abstract void unregisterCallback(android.content.pm.IPackageInstallerCallback);
+ public abstract void updateSessionAppIcon(int, android.graphics.Bitmap);
+ public abstract void updateSessionAppLabel(int, java.lang.String);
+
+
+}
+
+-keep class android.content.pm.IPackageInstallerCallback {
+
+ public abstract void onSessionActiveChanged(int, boolean);
+ public abstract void onSessionBadgingChanged(int);
+ public abstract void onSessionCreated(int);
+ public abstract void onSessionFinished(int, boolean);
+ public abstract void onSessionProgressChanged(int, float);
+
+
+}
+
+-keep class android.content.pm.IPackageInstallerSession {
+
+ public abstract void abandon();
+ public abstract void addClientProgress(float);
+ public abstract void close();
+ public abstract void commit(android.content.IntentSender, boolean);
+ public abstract java.lang.String[] getNames();
+ public abstract android.os.ParcelFileDescriptor openRead(java.lang.String);
+ public abstract android.os.ParcelFileDescriptor openWrite(java.lang.String, long, long);
+ public abstract void removeSplit(java.lang.String);
+ public abstract void setClientProgress(float);
+ public abstract void transfer(java.lang.String);
+ public abstract void write(java.lang.String, long, long, android.os.ParcelFileDescriptor);
+
+
+}
+
+-keep class android.content.pm.IPackageManager {
+
+ public abstract boolean activitySupportsIntent(android.content.ComponentName, android.content.Intent, java.lang.String);
+ public abstract void addCrossProfileIntentFilter(android.content.IntentFilter, java.lang.String, int, int, int);
+ public abstract void addOnPermissionsChangeListener(android.content.pm.IOnPermissionsChangeListener);
+ public abstract boolean addPermission(android.content.pm.PermissionInfo);
+ public abstract boolean addPermissionAsync(android.content.pm.PermissionInfo);
+ public abstract void addPersistentPreferredActivity(android.content.IntentFilter, android.content.ComponentName, int);
+ public abstract void addPreferredActivity(android.content.IntentFilter, int, android.content.ComponentName[], android.content.ComponentName, int);
+ public abstract boolean canForwardTo(android.content.Intent, java.lang.String, int, int);
+ public abstract boolean canRequestPackageInstalls(java.lang.String, int);
+ public abstract java.lang.String[] canonicalToCurrentPackageNames(java.lang.String[]);
+ public abstract void checkPackageStartable(java.lang.String, int);
+ public abstract int checkPermission(java.lang.String, java.lang.String, int);
+ public abstract int checkSignatures(java.lang.String, java.lang.String);
+ public abstract int checkUidPermission(java.lang.String, int);
+ public abstract int checkUidSignatures(int, int);
+ public abstract void clearApplicationProfileData(java.lang.String);
+ public abstract void clearApplicationUserData(java.lang.String, android.content.pm.IPackageDataObserver, int);
+ public abstract void clearCrossProfileIntentFilters(int, java.lang.String);
+ public abstract void clearPackagePersistentPreferredActivities(java.lang.String, int);
+ public abstract void clearPackagePreferredActivities(java.lang.String);
+ public abstract java.lang.String[] currentToCanonicalPackageNames(java.lang.String[]);
+ public abstract void deleteApplicationCacheFiles(java.lang.String, android.content.pm.IPackageDataObserver);
+ public abstract void deleteApplicationCacheFilesAsUser(java.lang.String, int, android.content.pm.IPackageDataObserver);
+ public abstract void deletePackageAsUser(java.lang.String, int, android.content.pm.IPackageDeleteObserver, int, int);
+ public abstract void deletePackageVersioned(android.content.pm.VersionedPackage, android.content.pm.IPackageDeleteObserver2, int, int);
+ public abstract void deletePreloadsFileCache();
+ public abstract void dumpProfiles(java.lang.String);
+ public abstract void enterSafeMode();
+ public abstract void extendVerificationTimeout(int, int, long);
+ public abstract android.content.pm.ResolveInfo findPersistentPreferredActivity(android.content.Intent, int);
+ public abstract void finishPackageInstall(int, boolean);
+ public abstract void flushPackageRestrictionsAsUser(int);
+ public abstract void forceDexOpt(java.lang.String);
+ public abstract void freeStorage(java.lang.String, long, int, android.content.IntentSender);
+ public abstract void freeStorageAndNotify(java.lang.String, long, int, android.content.pm.IPackageDataObserver);
+ public abstract android.content.pm.ActivityInfo getActivityInfo(android.content.ComponentName, int, int);
+ public abstract android.content.pm.ParceledListSlice getAllIntentFilters(java.lang.String);
+ public abstract java.util.List getAllPackages();
+ public abstract android.content.pm.ParceledListSlice getAllPermissionGroups(int);
+ public abstract java.lang.String[] getAppOpPermissionPackages(java.lang.String);
+ public abstract int getApplicationEnabledSetting(java.lang.String, int);
+ public abstract boolean getApplicationHiddenSettingAsUser(java.lang.String, int);
+ public abstract android.content.pm.ApplicationInfo getApplicationInfo(java.lang.String, int, int);
+ public abstract android.content.pm.dex.IArtManager getArtManager();
+ public abstract boolean getBlockUninstallForUser(java.lang.String, int);
+ public abstract android.content.pm.ChangedPackages getChangedPackages(int, int);
+ public abstract int getComponentEnabledSetting(android.content.ComponentName, int);
+ public abstract byte[] getDefaultAppsBackup(int);
+ public abstract java.lang.String getDefaultBrowserPackageName(int);
+ public abstract int getFlagsForUid(int);
+ public abstract java.lang.CharSequence getHarmfulAppWarning(java.lang.String, int);
+ public abstract android.content.ComponentName getHomeActivities(java.util.List);
+ public abstract int getInstallLocation();
+ public abstract int getInstallReason(java.lang.String, int);
+ public abstract android.content.pm.ParceledListSlice getInstalledApplications(int, int);
+ public abstract android.content.pm.ParceledListSlice getInstalledPackages(int, int);
+ public abstract java.lang.String getInstallerPackageName(java.lang.String);
+ public abstract java.lang.String getInstantAppAndroidId(java.lang.String, int);
+ public abstract byte[] getInstantAppCookie(java.lang.String, int);
+ public abstract android.graphics.Bitmap getInstantAppIcon(java.lang.String, int);
+ public abstract android.content.ComponentName getInstantAppInstallerComponent();
+ public abstract android.content.ComponentName getInstantAppResolverComponent();
+ public abstract android.content.ComponentName getInstantAppResolverSettingsComponent();
+ public abstract android.content.pm.ParceledListSlice getInstantApps(int);
+ public abstract android.content.pm.InstrumentationInfo getInstrumentationInfo(android.content.ComponentName, int);
+ public abstract byte[] getIntentFilterVerificationBackup(int);
+ public abstract android.content.pm.ParceledListSlice getIntentFilterVerifications(java.lang.String);
+ public abstract int getIntentVerificationStatus(java.lang.String, int);
+ public abstract android.content.pm.KeySet getKeySetByAlias(java.lang.String, java.lang.String);
+ public abstract android.content.pm.ResolveInfo getLastChosenActivity(android.content.Intent, java.lang.String, int);
+ public abstract int getMoveStatus(int);
+ public abstract java.lang.String getNameForUid(int);
+ public abstract java.lang.String[] getNamesForUids(int[]);
+ public abstract int[] getPackageGids(java.lang.String, int, int);
+ public abstract android.content.pm.PackageInfo getPackageInfo(java.lang.String, int, int);
+ public abstract android.content.pm.PackageInfo getPackageInfoVersioned(android.content.pm.VersionedPackage, int, int);
+ public abstract android.content.pm.IPackageInstaller getPackageInstaller();
+ public abstract void getPackageSizeInfo(java.lang.String, int, android.content.pm.IPackageStatsObserver);
+ public abstract int getPackageUid(java.lang.String, int, int);
+ public abstract java.lang.String[] getPackagesForUid(int);
+ public abstract android.content.pm.ParceledListSlice getPackagesHoldingPermissions(java.lang.String[], int, int);
+ public abstract java.lang.String getPermissionControllerPackageName();
+ public abstract int getPermissionFlags(java.lang.String, java.lang.String, int);
+ public abstract byte[] getPermissionGrantBackup(int);
+ public abstract android.content.pm.PermissionGroupInfo getPermissionGroupInfo(java.lang.String, int);
+ public abstract android.content.pm.PermissionInfo getPermissionInfo(java.lang.String, java.lang.String, int);
+ public abstract android.content.pm.ParceledListSlice getPersistentApplications(int);
+ public abstract int getPreferredActivities(java.util.List, java.util.List, java.lang.String);
+ public abstract byte[] getPreferredActivityBackup(int);
+ public abstract int getPrivateFlagsForUid(int);
+ public abstract android.content.pm.ProviderInfo getProviderInfo(android.content.ComponentName, int, int);
+ public abstract android.content.pm.ActivityInfo getReceiverInfo(android.content.ComponentName, int, int);
+ public abstract android.content.pm.ServiceInfo getServiceInfo(android.content.ComponentName, int, int);
+ public abstract java.lang.String getServicesSystemSharedLibraryPackageName();
+ public abstract android.content.pm.ParceledListSlice getSharedLibraries(java.lang.String, int, int);
+ public abstract java.lang.String getSharedSystemSharedLibraryPackageName();
+ public abstract android.content.pm.KeySet getSigningKeySet(java.lang.String);
+ public abstract android.os.PersistableBundle getSuspendedPackageAppExtras(java.lang.String, int);
+ public abstract android.content.pm.ParceledListSlice getSystemAvailableFeatures();
+ public abstract java.lang.String[] getSystemSharedLibraryNames();
+ public abstract java.lang.String getSystemTextClassifierPackageName();
+ public abstract int getUidForSharedUser(java.lang.String);
+ public abstract android.content.pm.VerifierDeviceIdentity getVerifierDeviceIdentity();
+ public abstract void grantDefaultPermissionsToActiveLuiApp(java.lang.String, int);
+ public abstract void grantDefaultPermissionsToEnabledCarrierApps(java.lang.String[], int);
+ public abstract void grantDefaultPermissionsToEnabledImsServices(java.lang.String[], int);
+ public abstract void grantDefaultPermissionsToEnabledTelephonyDataServices(java.lang.String[], int);
+ public abstract void grantRuntimePermission(java.lang.String, java.lang.String, int);
+ public abstract boolean hasSigningCertificate(java.lang.String, byte[], int);
+ public abstract boolean hasSystemFeature(java.lang.String, int);
+ public abstract boolean hasSystemUidErrors();
+ public abstract boolean hasUidSigningCertificate(int, byte[], int);
+ public abstract int installExistingPackageAsUser(java.lang.String, int, int, int);
+ public abstract boolean isFirstBoot();
+ public abstract boolean isInstantApp(java.lang.String, int);
+ public abstract boolean isOnlyCoreApps();
+ public abstract boolean isPackageAvailable(java.lang.String, int);
+ public abstract boolean isPackageDeviceAdminOnAnyUser(java.lang.String);
+ public abstract boolean isPackageSignedByKeySet(java.lang.String, android.content.pm.KeySet);
+ public abstract boolean isPackageSignedByKeySetExactly(java.lang.String, android.content.pm.KeySet);
+ public abstract boolean isPackageStateProtected(java.lang.String, int);
+ public abstract boolean isPackageSuspendedForUser(java.lang.String, int);
+ public abstract boolean isPermissionEnforced(java.lang.String);
+ public abstract boolean isPermissionRevokedByPolicy(java.lang.String, java.lang.String, int);
+ public abstract boolean isProtectedBroadcast(java.lang.String);
+ public abstract boolean isSafeMode();
+ public abstract boolean isStorageLow();
+ public abstract boolean isUidPrivileged(int);
+ public abstract boolean isUpgrade();
+ public abstract void logAppProcessStartIfNeeded(java.lang.String, int, java.lang.String, java.lang.String, int);
+ public abstract int movePackage(java.lang.String, java.lang.String);
+ public abstract int movePrimaryStorage(java.lang.String);
+ public abstract android.content.pm.PackageCleanItem nextPackageToClean(android.content.pm.PackageCleanItem);
+ public abstract void notifyDexLoad(java.lang.String, java.util.List, java.util.List, java.lang.String);
+ public abstract void notifyPackageUse(java.lang.String, int);
+ public abstract boolean performDexOptMode(java.lang.String, boolean, java.lang.String, boolean, boolean, java.lang.String);
+ public abstract boolean performDexOptSecondary(java.lang.String, java.lang.String, boolean);
+ public abstract void performFstrimIfNeeded();
+ public abstract android.content.pm.ParceledListSlice queryContentProviders(java.lang.String, int, int, java.lang.String);
+ public abstract android.content.pm.ParceledListSlice queryInstrumentation(java.lang.String, int);
+ public abstract android.content.pm.ParceledListSlice queryIntentActivities(android.content.Intent, java.lang.String, int, int);
+ public abstract android.content.pm.ParceledListSlice queryIntentActivityOptions(android.content.ComponentName, android.content.Intent[], java.lang.String[], android.content.Intent, java.lang.String, int, int);
+ public abstract android.content.pm.ParceledListSlice queryIntentContentProviders(android.content.Intent, java.lang.String, int, int);
+ public abstract android.content.pm.ParceledListSlice queryIntentReceivers(android.content.Intent, java.lang.String, int, int);
+ public abstract android.content.pm.ParceledListSlice queryIntentServices(android.content.Intent, java.lang.String, int, int);
+ public abstract android.content.pm.ParceledListSlice queryPermissionsByGroup(java.lang.String, int);
+ public abstract void querySyncProviders(java.util.List, java.util.List);
+ public abstract void reconcileSecondaryDexFiles(java.lang.String);
+ public abstract void registerDexModule(java.lang.String, java.lang.String, boolean, android.content.pm.IDexModuleRegisterCallback);
+ public abstract void registerMoveCallback(android.content.pm.IPackageMoveObserver);
+ public abstract void removeOnPermissionsChangeListener(android.content.pm.IOnPermissionsChangeListener);
+ public abstract void removePermission(java.lang.String);
+ public abstract void replacePreferredActivity(android.content.IntentFilter, int, android.content.ComponentName[], android.content.ComponentName, int);
+ public abstract void resetApplicationPreferences(int);
+ public abstract void resetRuntimePermissions();
+ public abstract android.content.pm.ProviderInfo resolveContentProvider(java.lang.String, int, int);
+ public abstract android.content.pm.ResolveInfo resolveIntent(android.content.Intent, java.lang.String, int, int);
+ public abstract android.content.pm.ResolveInfo resolveService(android.content.Intent, java.lang.String, int, int);
+ public abstract void restoreDefaultApps(byte[], int);
+ public abstract void restoreIntentFilterVerification(byte[], int);
+ public abstract void restorePermissionGrants(byte[], int);
+ public abstract void restorePreferredActivities(byte[], int);
+ public abstract void revokeDefaultPermissionsFromDisabledTelephonyDataServices(java.lang.String[], int);
+ public abstract void revokeDefaultPermissionsFromLuiApps(java.lang.String[], int);
+ public abstract void revokeRuntimePermission(java.lang.String, java.lang.String, int);
+ public abstract boolean runBackgroundDexoptJob(java.util.List);
+ public abstract void setApplicationCategoryHint(java.lang.String, int, java.lang.String);
+ public abstract void setApplicationEnabledSetting(java.lang.String, int, int, int, java.lang.String);
+ public abstract boolean setApplicationHiddenSettingAsUser(java.lang.String, boolean, int);
+ public abstract boolean setBlockUninstallForUser(java.lang.String, boolean, int);
+ public abstract void setComponentEnabledSetting(android.content.ComponentName, int, int, int);
+ public abstract boolean setDefaultBrowserPackageName(java.lang.String, int);
+ public abstract void setHarmfulAppWarning(java.lang.String, java.lang.CharSequence, int);
+ public abstract void setHomeActivity(android.content.ComponentName, int);
+ public abstract boolean setInstallLocation(int);
+ public abstract void setInstallerPackageName(java.lang.String, java.lang.String);
+ public abstract boolean setInstantAppCookie(java.lang.String, byte[], int);
+ public abstract void setLastChosenActivity(android.content.Intent, java.lang.String, int, android.content.IntentFilter, int, android.content.ComponentName);
+ public abstract void setPackageStoppedState(java.lang.String, boolean, int);
+ public abstract java.lang.String[] setPackagesSuspendedAsUser(java.lang.String[], boolean, android.os.PersistableBundle, android.os.PersistableBundle, java.lang.String, java.lang.String, int);
+ public abstract void setPermissionEnforced(java.lang.String, boolean);
+ public abstract boolean setRequiredForSystemUser(java.lang.String, boolean);
+ public abstract void setUpdateAvailable(java.lang.String, boolean);
+ public abstract boolean shouldShowRequestPermissionRationale(java.lang.String, java.lang.String, int);
+ public abstract void systemReady();
+ public abstract void unregisterMoveCallback(android.content.pm.IPackageMoveObserver);
+ public abstract boolean updateIntentVerificationStatus(java.lang.String, int, int);
+ public abstract void updatePackagesIfNeeded();
+ public abstract void updatePermissionFlags(java.lang.String, java.lang.String, int, int, int);
+ public abstract void updatePermissionFlagsForAllApps(int, int, int);
+ public abstract void verifyIntentFilter(int, int, java.util.List);
+ public abstract void verifyPendingInstall(int, int);
+
+
+}
+
+-keep class android.content.pm.IPackageMoveObserver {
+
+ public abstract void onCreated(int, android.os.Bundle);
+ public abstract void onStatusChanged(int, int, long);
+
+
+}
+
+-keep class android.content.pm.IPackageStatsObserver {
+
+ public abstract void onGetStatsCompleted(android.content.pm.PackageStats, boolean);
+
+
+}
+
+-keep class android.content.pm.InstantAppInfo {
+ <init>(android.content.pm.ApplicationInfo, java.lang.String[], java.lang.String[]);
+ <init>(java.lang.String, java.lang.CharSequence, java.lang.String[], java.lang.String[]);
+
+ public int describeContents();
+ public android.content.pm.ApplicationInfo getApplicationInfo();
+ public java.lang.String[] getGrantedPermissions();
+ public java.lang.String getPackageName();
+ public java.lang.String[] getRequestedPermissions();
+ public android.graphics.drawable.Drawable loadIcon(android.content.pm.PackageManager);
+ public java.lang.CharSequence loadLabel(android.content.pm.PackageManager);
+ public void writeToParcel(android.os.Parcel, int);
+
+
+ public static android.os.Parcelable$Creator CREATOR;
+}
+
+-keep class android.content.pm.InstantAppIntentFilter {
+ <init>(java.lang.String, java.util.List);
+
+ public int describeContents();
+ public java.util.List getFilters();
+ public java.lang.String getSplitName();
+ public void writeToParcel(android.os.Parcel, int);
+
+
+ public static android.os.Parcelable$Creator CREATOR;
+}
+
+-keep class android.content.pm.InstantAppResolveInfo {
+ <init>(android.content.pm.InstantAppResolveInfo$InstantAppDigest, java.lang.String, java.util.List, int);
+ <init>(android.content.pm.InstantAppResolveInfo$InstantAppDigest, java.lang.String, java.util.List, long, android.os.Bundle);
+ <init>(java.lang.String, java.lang.String, java.util.List);
+ <init>(android.os.Bundle);
+
+ public int describeContents();
+ public byte[] getDigestBytes();
+ public int getDigestPrefix();
+ public android.os.Bundle getExtras();
+ public java.util.List getIntentFilters();
+ public long getLongVersionCode();
+ public java.lang.String getPackageName();
+ public int getVersionCode();
+ public boolean shouldLetInstallerDecide();
+ public void writeToParcel(android.os.Parcel, int);
+
+
+ public static android.os.Parcelable$Creator CREATOR;
+}
+
+-keep class android.content.pm.InstantAppResolveInfo$InstantAppDigest {
+ <init>(java.lang.String);
+ <init>(java.lang.String, int);
+
+ public int describeContents();
+ public byte[][] getDigestBytes();
+ public int[] getDigestPrefix();
+ public int[] getDigestPrefixSecure();
+ public void writeToParcel(android.os.Parcel, int);
+
+
+ public static android.os.Parcelable$Creator CREATOR;
+ public static android.content.pm.InstantAppResolveInfo$InstantAppDigest UNDEFINED;
}
-keep class android.content.pm.InstrumentationInfo {
<init>();
<init>(android.content.pm.InstrumentationInfo);
+ public void copyTo(android.content.pm.ApplicationInfo);
public int describeContents();
public java.lang.String toString();
public void writeToParcel(android.os.Parcel, int);
public static android.os.Parcelable$Creator CREATOR;
+ public java.lang.String credentialProtectedDataDir;
public java.lang.String dataDir;
+ public java.lang.String deviceProtectedDataDir;
public boolean functionalTest;
public boolean handleProfiling;
+ public java.lang.String nativeLibraryDir;
+ public java.lang.String primaryCpuAbi;
public java.lang.String publicSourceDir;
+ public java.lang.String secondaryCpuAbi;
+ public java.lang.String secondaryNativeLibraryDir;
public java.lang.String sourceDir;
+ public android.util.SparseArray splitDependencies;
+ public java.lang.String[] splitNames;
public java.lang.String[] splitPublicSourceDirs;
public java.lang.String[] splitSourceDirs;
public java.lang.String targetPackage;
+ public java.lang.String targetProcesses;
+}
+
+-keep class android.content.pm.IntentFilterVerificationInfo {
+ <init>();
+ <init>(java.lang.String, android.util.ArraySet);
+ <init>(org.xmlpull.v1.XmlPullParser);
+ <init>(android.os.Parcel);
+
+ public int describeContents();
+ public java.util.Set getDomains();
+ public java.lang.String getDomainsString();
+ public java.lang.String getPackageName();
+ public int getStatus();
+ public java.lang.String getStatusString();
+ public static java.lang.String getStatusStringFromValue(long);
+ public void readFromXml(org.xmlpull.v1.XmlPullParser);
+ public void setDomains(android.util.ArraySet);
+ public void setStatus(int);
+ public void writeToParcel(android.os.Parcel, int);
+ public void writeToXml(org.xmlpull.v1.XmlSerializer);
+
+
+ public static android.os.Parcelable$Creator CREATOR;
+}
+
+-keep class android.content.pm.KeySet {
+ <init>(android.os.IBinder);
+
+ public int describeContents();
+ public boolean equals(java.lang.Object);
+ public android.os.IBinder getToken();
+ public int hashCode();
+ public void writeToParcel(android.os.Parcel, int);
+
+
+ public static android.os.Parcelable$Creator CREATOR;
+}
+
+-keep class android.content.pm.PackageCleanItem {
+ <init>(int, java.lang.String, boolean);
+
+ public int describeContents();
+ public boolean equals(java.lang.Object);
+ public int hashCode();
+ public void writeToParcel(android.os.Parcel, int);
+
+
+ public static android.os.Parcelable$Creator CREATOR;
+ public boolean andCode;
+ public java.lang.String packageName;
+ public int userId;
}
-keep class android.content.pm.PackageInfo {
<init>();
+ public static long composeLongVersionCode(int, int);
public int describeContents();
+ public long getLongVersionCode();
+ public boolean isOverlayPackage();
+ public boolean isStaticOverlayPackage();
+ public void setLongVersionCode(long);
public java.lang.String toString();
public void writeToParcel(android.os.Parcel, int);
@@ -1576,17 +7838,26 @@
public static int INSTALL_LOCATION_AUTO;
public static int INSTALL_LOCATION_INTERNAL_ONLY;
public static int INSTALL_LOCATION_PREFER_EXTERNAL;
+ public static int INSTALL_LOCATION_UNSPECIFIED;
public static int REQUESTED_PERMISSION_GRANTED;
+ public static int REQUESTED_PERMISSION_REQUIRED;
public android.content.pm.ActivityInfo[] activities;
public android.content.pm.ApplicationInfo applicationInfo;
public int baseRevisionCode;
+ public int compileSdkVersion;
+ public java.lang.String compileSdkVersionCodename;
public android.content.pm.ConfigurationInfo[] configPreferences;
+ public boolean coreApp;
public android.content.pm.FeatureGroupInfo[] featureGroups;
public long firstInstallTime;
public int[] gids;
public int installLocation;
public android.content.pm.InstrumentationInfo[] instrumentation;
+ public boolean isStub;
public long lastUpdateTime;
+ public java.lang.String overlayCategory;
+ public int overlayPriority;
+ public java.lang.String overlayTarget;
public java.lang.String packageName;
public android.content.pm.PermissionInfo[] permissions;
public android.content.pm.ProviderInfo[] providers;
@@ -1594,19 +7865,27 @@
public android.content.pm.FeatureInfo[] reqFeatures;
public java.lang.String[] requestedPermissions;
public int[] requestedPermissionsFlags;
+ public java.lang.String requiredAccountType;
+ public boolean requiredForAllUsers;
+ public java.lang.String restrictedAccountType;
public android.content.pm.ServiceInfo[] services;
public java.lang.String sharedUserId;
public int sharedUserLabel;
public android.content.pm.Signature[] signatures;
+ public android.content.pm.SigningInfo signingInfo;
public java.lang.String[] splitNames;
public int[] splitRevisionCodes;
public int versionCode;
+ public int versionCodeMajor;
public java.lang.String versionName;
}
-keep class android.content.pm.PackageInstaller {
+ <init>(android.content.pm.IPackageInstaller, java.lang.String, int);
public void abandonSession(int);
+ public void addSessionCallback(android.content.pm.PackageInstaller$SessionCallback);
+ public void addSessionCallback(android.content.pm.PackageInstaller$SessionCallback, android.os.Handler);
public int createSession(android.content.pm.PackageInstaller$SessionParams);
public java.util.List getAllSessions();
public java.util.List getMySessions();
@@ -1614,15 +7893,28 @@
public android.content.pm.PackageInstaller$Session openSession(int);
public void registerSessionCallback(android.content.pm.PackageInstaller$SessionCallback);
public void registerSessionCallback(android.content.pm.PackageInstaller$SessionCallback, android.os.Handler);
+ public void removeSessionCallback(android.content.pm.PackageInstaller$SessionCallback);
+ public void setPermissionsResult(int, boolean);
public void uninstall(java.lang.String, android.content.IntentSender);
+ public void uninstall(java.lang.String, int, android.content.IntentSender);
+ public void uninstall(android.content.pm.VersionedPackage, android.content.IntentSender);
+ public void uninstall(android.content.pm.VersionedPackage, int, android.content.IntentSender);
public void unregisterSessionCallback(android.content.pm.PackageInstaller$SessionCallback);
public void updateSessionAppIcon(int, android.graphics.Bitmap);
public void updateSessionAppLabel(int, java.lang.CharSequence);
+ public static java.lang.String ACTION_CONFIRM_PERMISSIONS;
+ public static java.lang.String ACTION_SESSION_COMMITTED;
public static java.lang.String ACTION_SESSION_DETAILS;
+ public static boolean ENABLE_REVOCABLE_FD;
+ public static java.lang.String EXTRA_CALLBACK;
+ public static java.lang.String EXTRA_LEGACY_BUNDLE;
+ public static java.lang.String EXTRA_LEGACY_STATUS;
public static java.lang.String EXTRA_OTHER_PACKAGE_NAME;
public static java.lang.String EXTRA_PACKAGE_NAME;
+ public static java.lang.String EXTRA_PACKAGE_NAMES;
+ public static java.lang.String EXTRA_SESSION;
public static java.lang.String EXTRA_SESSION_ID;
public static java.lang.String EXTRA_STATUS;
public static java.lang.String EXTRA_STATUS_MESSAGE;
@@ -1639,15 +7931,22 @@
}
-keep class android.content.pm.PackageInstaller$Session {
+ <init>(android.content.pm.IPackageInstallerSession);
public void abandon();
+ public void addProgress(float);
public void close();
public void commit(android.content.IntentSender);
+ public void commitTransferred(android.content.IntentSender);
public void fsync(java.io.OutputStream);
public java.lang.String[] getNames();
public java.io.InputStream openRead(java.lang.String);
public java.io.OutputStream openWrite(java.lang.String, long, long);
+ public void removeSplit(java.lang.String);
+ public void setProgress(float);
public void setStagingProgress(float);
+ public void transfer(java.lang.String);
+ public void write(java.lang.String, long, long, android.os.ParcelFileDescriptor);
}
@@ -1665,30 +7964,82 @@
}
-keep class android.content.pm.PackageInstaller$SessionInfo {
+ <init>();
+ <init>(android.os.Parcel);
public android.content.Intent createDetailsIntent();
public int describeContents();
+ public boolean getAllocateAggressive();
+ public boolean getAllowDowngrade();
public android.graphics.Bitmap getAppIcon();
public java.lang.CharSequence getAppLabel();
public java.lang.String getAppPackageName();
+ public android.content.Intent getDetailsIntent();
+ public boolean getDontKillApp();
+ public java.lang.String[] getGrantedRuntimePermissions();
+ public boolean getInstallAsFullApp(boolean);
+ public boolean getInstallAsInstantApp(boolean);
+ public boolean getInstallAsVirtualPreload();
+ public int getInstallLocation();
+ public int getInstallReason();
public java.lang.String getInstallerPackageName();
+ public int getMode();
+ public int getOriginatingUid();
+ public android.net.Uri getOriginatingUri();
public float getProgress();
+ public android.net.Uri getReferrerUri();
public int getSessionId();
+ public long getSize();
public boolean isActive();
+ public boolean isOpen();
+ public boolean isSealed();
public void writeToParcel(android.os.Parcel, int);
public static android.os.Parcelable$Creator CREATOR;
+ public boolean active;
+ public android.graphics.Bitmap appIcon;
+ public java.lang.CharSequence appLabel;
+ public java.lang.String appPackageName;
+ public java.lang.String[] grantedRuntimePermissions;
+ public int installFlags;
+ public int installLocation;
+ public int installReason;
+ public java.lang.String installerPackageName;
+ public int mode;
+ public int originatingUid;
+ public android.net.Uri originatingUri;
+ public float progress;
+ public android.net.Uri referrerUri;
+ public java.lang.String resolvedBaseCodePath;
+ public boolean sealed;
+ public int sessionId;
+ public long sizeBytes;
}
-keep class android.content.pm.PackageInstaller$SessionParams {
<init>(int);
+ <init>(android.os.Parcel);
+ public boolean areHiddenOptionsSet();
public int describeContents();
+ public void dump(com.android.internal.util.IndentingPrintWriter);
+ public void setAllocateAggressive(boolean);
+ public void setAllowDowngrade(boolean);
public void setAppIcon(android.graphics.Bitmap);
public void setAppLabel(java.lang.CharSequence);
public void setAppPackageName(java.lang.String);
+ public void setDontKillApp(boolean);
+ public void setGrantedRuntimePermissions(java.lang.String[]);
+ public void setInstallAsInstantApp(boolean);
+ public void setInstallAsVirtualPreload();
+ public void setInstallFlagsExternal();
+ public void setInstallFlagsForcePermissionPrompt();
+ public void setInstallFlagsInternal();
public void setInstallLocation(int);
+ public void setInstallReason(int);
+ public void setInstallerPackageName(java.lang.String);
+ public void setOriginatingUid(int);
public void setOriginatingUri(android.net.Uri);
public void setReferrerUri(android.net.Uri);
public void setSize(long);
@@ -1698,6 +8049,24 @@
public static android.os.Parcelable$Creator CREATOR;
public static int MODE_FULL_INSTALL;
public static int MODE_INHERIT_EXISTING;
+ public static int MODE_INVALID;
+ public static int UID_UNKNOWN;
+ public java.lang.String abiOverride;
+ public android.graphics.Bitmap appIcon;
+ public long appIconLastModified;
+ public java.lang.String appLabel;
+ public java.lang.String appPackageName;
+ public java.lang.String[] grantedRuntimePermissions;
+ public int installFlags;
+ public int installLocation;
+ public int installReason;
+ public java.lang.String installerPackageName;
+ public int mode;
+ public int originatingUid;
+ public android.net.Uri originatingUri;
+ public android.net.Uri referrerUri;
+ public long sizeBytes;
+ public java.lang.String volumeUuid;
}
-keep class android.content.pm.PackageItemInfo {
@@ -1707,15 +8076,30 @@
protected void dumpBack(android.util.Printer, java.lang.String);
protected void dumpFront(android.util.Printer, java.lang.String);
+ protected android.content.pm.ApplicationInfo getApplicationInfo();
public android.graphics.drawable.Drawable loadBanner(android.content.pm.PackageManager);
+ protected android.graphics.drawable.Drawable loadDefaultBanner(android.content.pm.PackageManager);
+ public android.graphics.drawable.Drawable loadDefaultIcon(android.content.pm.PackageManager);
+ protected android.graphics.drawable.Drawable loadDefaultLogo(android.content.pm.PackageManager);
public android.graphics.drawable.Drawable loadIcon(android.content.pm.PackageManager);
public java.lang.CharSequence loadLabel(android.content.pm.PackageManager);
public android.graphics.drawable.Drawable loadLogo(android.content.pm.PackageManager);
+ public java.lang.CharSequence loadSafeLabel(android.content.pm.PackageManager);
+ public java.lang.CharSequence loadSafeLabel(android.content.pm.PackageManager, float, int);
public android.graphics.drawable.Drawable loadUnbadgedIcon(android.content.pm.PackageManager);
+ public java.lang.CharSequence loadUnsafeLabel(android.content.pm.PackageManager);
public android.content.res.XmlResourceParser loadXmlMetaData(android.content.pm.PackageManager, java.lang.String);
+ public static void setForceSafeLabels(boolean);
public void writeToParcel(android.os.Parcel, int);
+ public void writeToProto(android.util.proto.ProtoOutputStream, long);
+ public static int DUMP_FLAG_ALL;
+ public static int DUMP_FLAG_APPLICATION;
+ public static int DUMP_FLAG_DETAILS;
+ public static int SAFE_LABEL_FLAG_FIRST_LINE;
+ public static int SAFE_LABEL_FLAG_SINGLE_LINE;
+ public static int SAFE_LABEL_FLAG_TRIM;
public int banner;
public int icon;
public int labelRes;
@@ -1724,22 +8108,43 @@
public java.lang.String name;
public java.lang.CharSequence nonLocalizedLabel;
public java.lang.String packageName;
+ public int showUserIcon;
}
-keep class android.content.pm.PackageManager {
<init>();
+ public abstract void addCrossProfileIntentFilter(android.content.IntentFilter, int, int, int);
+ public abstract void addOnPermissionsChangeListener(android.content.pm.PackageManager$OnPermissionsChangedListener);
public abstract void addPackageToPreferred(java.lang.String);
public abstract boolean addPermission(android.content.pm.PermissionInfo);
public abstract boolean addPermissionAsync(android.content.pm.PermissionInfo);
public abstract void addPreferredActivity(android.content.IntentFilter, int, android.content.ComponentName[], android.content.ComponentName);
+ public void addPreferredActivityAsUser(android.content.IntentFilter, int, android.content.ComponentName[], android.content.ComponentName, int);
+ public android.content.Intent buildRequestPermissionsIntent(java.lang.String[]);
+ public abstract boolean canRequestPackageInstalls();
public abstract java.lang.String[] canonicalToCurrentPackageNames(java.lang.String[]);
public abstract int checkPermission(java.lang.String, java.lang.String);
public abstract int checkSignatures(java.lang.String, java.lang.String);
public abstract int checkSignatures(int, int);
+ public abstract void clearApplicationUserData(java.lang.String, android.content.pm.IPackageDataObserver);
+ public abstract void clearCrossProfileIntentFilters(int);
+ public abstract void clearInstantAppCookie();
public abstract void clearPackagePreferredActivities(java.lang.String);
public abstract java.lang.String[] currentToCanonicalPackageNames(java.lang.String[]);
+ public abstract void deleteApplicationCacheFiles(java.lang.String, android.content.pm.IPackageDataObserver);
+ public abstract void deleteApplicationCacheFilesAsUser(java.lang.String, int, android.content.pm.IPackageDataObserver);
+ public abstract void deletePackage(java.lang.String, android.content.pm.IPackageDeleteObserver, int);
+ public abstract void deletePackageAsUser(java.lang.String, android.content.pm.IPackageDeleteObserver, int, int);
+ public static int deleteStatusToPublicStatus(int);
+ public static java.lang.String deleteStatusToString(int, java.lang.String);
+ public static java.lang.String deleteStatusToString(int);
public abstract void extendVerificationTimeout(int, int, long);
+ public abstract void flushPackageRestrictionsAsUser(int);
+ public void freeStorage(long, android.content.IntentSender);
+ public abstract void freeStorage(java.lang.String, long, android.content.IntentSender);
+ public void freeStorageAndNotify(long, android.content.pm.IPackageDataObserver);
+ public abstract void freeStorageAndNotify(java.lang.String, long, android.content.pm.IPackageDataObserver);
public abstract android.graphics.drawable.Drawable getActivityBanner(android.content.ComponentName);
public abstract android.graphics.drawable.Drawable getActivityBanner(android.content.Intent);
public abstract android.graphics.drawable.Drawable getActivityIcon(android.content.ComponentName);
@@ -1747,89 +8152,236 @@
public abstract android.content.pm.ActivityInfo getActivityInfo(android.content.ComponentName, int);
public abstract android.graphics.drawable.Drawable getActivityLogo(android.content.ComponentName);
public abstract android.graphics.drawable.Drawable getActivityLogo(android.content.Intent);
+ public abstract java.util.List getAllIntentFilters(java.lang.String);
public abstract java.util.List getAllPermissionGroups(int);
public abstract android.graphics.drawable.Drawable getApplicationBanner(android.content.pm.ApplicationInfo);
public abstract android.graphics.drawable.Drawable getApplicationBanner(java.lang.String);
public abstract int getApplicationEnabledSetting(java.lang.String);
+ public abstract boolean getApplicationHiddenSettingAsUser(java.lang.String, android.os.UserHandle);
public abstract android.graphics.drawable.Drawable getApplicationIcon(android.content.pm.ApplicationInfo);
public abstract android.graphics.drawable.Drawable getApplicationIcon(java.lang.String);
public abstract android.content.pm.ApplicationInfo getApplicationInfo(java.lang.String, int);
+ public abstract android.content.pm.ApplicationInfo getApplicationInfoAsUser(java.lang.String, int, int);
public abstract java.lang.CharSequence getApplicationLabel(android.content.pm.ApplicationInfo);
public abstract android.graphics.drawable.Drawable getApplicationLogo(android.content.pm.ApplicationInfo);
public abstract android.graphics.drawable.Drawable getApplicationLogo(java.lang.String);
+ public android.content.pm.dex.ArtManager getArtManager();
+ public abstract android.content.Intent getCarLaunchIntentForPackage(java.lang.String);
+ public abstract android.content.pm.ChangedPackages getChangedPackages(int);
public abstract int getComponentEnabledSetting(android.content.ComponentName);
public abstract android.graphics.drawable.Drawable getDefaultActivityIcon();
+ public abstract java.lang.String getDefaultBrowserPackageNameAsUser(int);
public abstract android.graphics.drawable.Drawable getDrawable(java.lang.String, int, android.content.pm.ApplicationInfo);
+ public java.lang.CharSequence getHarmfulAppWarning(java.lang.String);
+ public abstract android.content.ComponentName getHomeActivities(java.util.List);
+ public abstract int getInstallReason(java.lang.String, android.os.UserHandle);
public abstract java.util.List getInstalledApplications(int);
+ public abstract java.util.List getInstalledApplicationsAsUser(int, int);
public abstract java.util.List getInstalledPackages(int);
+ public abstract java.util.List getInstalledPackagesAsUser(int, int);
public abstract java.lang.String getInstallerPackageName(java.lang.String);
+ public abstract java.lang.String getInstantAppAndroidId(java.lang.String, android.os.UserHandle);
+ public abstract byte[] getInstantAppCookie();
+ public abstract int getInstantAppCookieMaxBytes();
+ public abstract int getInstantAppCookieMaxSize();
+ public abstract android.graphics.drawable.Drawable getInstantAppIcon(java.lang.String);
+ public abstract android.content.ComponentName getInstantAppInstallerComponent();
+ public abstract android.content.ComponentName getInstantAppResolverSettingsComponent();
+ public abstract java.util.List getInstantApps();
public abstract android.content.pm.InstrumentationInfo getInstrumentationInfo(android.content.ComponentName, int);
+ public abstract java.util.List getIntentFilterVerifications(java.lang.String);
+ public abstract int getIntentVerificationStatusAsUser(java.lang.String, int);
+ public abstract android.content.pm.KeySet getKeySetByAlias(java.lang.String, java.lang.String);
public abstract android.content.Intent getLaunchIntentForPackage(java.lang.String);
public abstract android.content.Intent getLeanbackLaunchIntentForPackage(java.lang.String);
+ public abstract int getMoveStatus(int);
public abstract java.lang.String getNameForUid(int);
+ public abstract java.lang.String[] getNamesForUids(int[]);
public android.content.pm.PackageInfo getPackageArchiveInfo(java.lang.String, int);
+ public abstract java.util.List getPackageCandidateVolumes(android.content.pm.ApplicationInfo);
+ public abstract android.os.storage.VolumeInfo getPackageCurrentVolume(android.content.pm.ApplicationInfo);
public abstract int[] getPackageGids(java.lang.String);
+ public abstract int[] getPackageGids(java.lang.String, int);
public abstract android.content.pm.PackageInfo getPackageInfo(java.lang.String, int);
+ public abstract android.content.pm.PackageInfo getPackageInfo(android.content.pm.VersionedPackage, int);
+ public abstract android.content.pm.PackageInfo getPackageInfoAsUser(java.lang.String, int, int);
public abstract android.content.pm.PackageInstaller getPackageInstaller();
+ public void getPackageSizeInfo(java.lang.String, android.content.pm.IPackageStatsObserver);
+ public abstract void getPackageSizeInfoAsUser(java.lang.String, int, android.content.pm.IPackageStatsObserver);
+ public abstract int getPackageUid(java.lang.String, int);
+ public abstract int getPackageUidAsUser(java.lang.String, int);
+ public abstract int getPackageUidAsUser(java.lang.String, int, int);
public abstract java.lang.String[] getPackagesForUid(int);
public abstract java.util.List getPackagesHoldingPermissions(java.lang.String[], int);
+ public abstract java.lang.String getPermissionControllerPackageName();
+ public abstract int getPermissionFlags(java.lang.String, java.lang.String, android.os.UserHandle);
public abstract android.content.pm.PermissionGroupInfo getPermissionGroupInfo(java.lang.String, int);
public abstract android.content.pm.PermissionInfo getPermissionInfo(java.lang.String, int);
public abstract int getPreferredActivities(java.util.List, java.util.List, java.lang.String);
public abstract java.util.List getPreferredPackages(int);
+ public abstract java.util.List getPrimaryStorageCandidateVolumes();
+ public abstract android.os.storage.VolumeInfo getPrimaryStorageCurrentVolume();
public abstract android.content.pm.ProviderInfo getProviderInfo(android.content.ComponentName, int);
public abstract android.content.pm.ActivityInfo getReceiverInfo(android.content.ComponentName, int);
public abstract android.content.res.Resources getResourcesForActivity(android.content.ComponentName);
public abstract android.content.res.Resources getResourcesForApplication(android.content.pm.ApplicationInfo);
public abstract android.content.res.Resources getResourcesForApplication(java.lang.String);
+ public abstract android.content.res.Resources getResourcesForApplicationAsUser(java.lang.String, int);
public abstract android.content.pm.ServiceInfo getServiceInfo(android.content.ComponentName, int);
+ public abstract java.lang.String getServicesSystemSharedLibraryPackageName();
+ public abstract java.util.List getSharedLibraries(int);
+ public abstract java.util.List getSharedLibrariesAsUser(int, int);
+ public abstract java.lang.String getSharedSystemSharedLibraryPackageName();
+ public abstract android.content.pm.KeySet getSigningKeySet(java.lang.String);
+ public android.os.Bundle getSuspendedPackageAppExtras();
public abstract android.content.pm.FeatureInfo[] getSystemAvailableFeatures();
public abstract java.lang.String[] getSystemSharedLibraryNames();
+ public java.lang.String getSystemTextClassifierPackageName();
public abstract java.lang.CharSequence getText(java.lang.String, int, android.content.pm.ApplicationInfo);
+ public abstract int getUidForSharedUser(java.lang.String);
+ public abstract android.graphics.drawable.Drawable getUserBadgeForDensity(android.os.UserHandle, int);
+ public abstract android.graphics.drawable.Drawable getUserBadgeForDensityNoBackground(android.os.UserHandle, int);
public abstract android.graphics.drawable.Drawable getUserBadgedDrawableForDensity(android.graphics.drawable.Drawable, android.os.UserHandle, android.graphics.Rect, int);
public abstract android.graphics.drawable.Drawable getUserBadgedIcon(android.graphics.drawable.Drawable, android.os.UserHandle);
public abstract java.lang.CharSequence getUserBadgedLabel(java.lang.CharSequence, android.os.UserHandle);
+ public int getUserId();
+ public abstract android.content.pm.VerifierDeviceIdentity getVerifierDeviceIdentity();
public abstract android.content.res.XmlResourceParser getXml(java.lang.String, int, android.content.pm.ApplicationInfo);
+ public abstract void grantRuntimePermission(java.lang.String, java.lang.String, android.os.UserHandle);
+ public boolean hasSigningCertificate(java.lang.String, byte[], int);
+ public boolean hasSigningCertificate(int, byte[], int);
public abstract boolean hasSystemFeature(java.lang.String);
+ public abstract boolean hasSystemFeature(java.lang.String, int);
+ public abstract int installExistingPackage(java.lang.String);
+ public abstract int installExistingPackage(java.lang.String, int);
+ public abstract int installExistingPackageAsUser(java.lang.String, int);
+ public static int installStatusToPublicStatus(int);
+ public static java.lang.String installStatusToString(int, java.lang.String);
+ public static java.lang.String installStatusToString(int);
+ public abstract boolean isInstantApp();
+ public abstract boolean isInstantApp(java.lang.String);
+ public static boolean isMoveStatusFinished(int);
+ public abstract boolean isPackageAvailable(java.lang.String);
+ public boolean isPackageStateProtected(java.lang.String, int);
+ public boolean isPackageSuspended(java.lang.String);
+ public boolean isPackageSuspended();
+ public abstract boolean isPackageSuspendedForUser(java.lang.String, int);
+ public abstract boolean isPermissionReviewModeEnabled();
public abstract boolean isPermissionRevokedByPolicy(java.lang.String, java.lang.String);
public abstract boolean isSafeMode();
+ public abstract boolean isSignedBy(java.lang.String, android.content.pm.KeySet);
+ public abstract boolean isSignedByExactly(java.lang.String, android.content.pm.KeySet);
+ public abstract boolean isUpgrade();
+ public abstract android.graphics.drawable.Drawable loadItemIcon(android.content.pm.PackageItemInfo, android.content.pm.ApplicationInfo);
+ public abstract android.graphics.drawable.Drawable loadUnbadgedItemIcon(android.content.pm.PackageItemInfo, android.content.pm.ApplicationInfo);
+ public abstract int movePackage(java.lang.String, android.os.storage.VolumeInfo);
+ public abstract int movePrimaryStorage(android.os.storage.VolumeInfo);
+ public static java.lang.String permissionFlagToString(int);
public abstract java.util.List queryBroadcastReceivers(android.content.Intent, int);
+ public java.util.List queryBroadcastReceivers(android.content.Intent, int, int);
+ public java.util.List queryBroadcastReceiversAsUser(android.content.Intent, int, android.os.UserHandle);
+ public abstract java.util.List queryBroadcastReceiversAsUser(android.content.Intent, int, int);
public abstract java.util.List queryContentProviders(java.lang.String, int, int);
+ public java.util.List queryContentProviders(java.lang.String, int, int, java.lang.String);
public abstract java.util.List queryInstrumentation(java.lang.String, int);
public abstract java.util.List queryIntentActivities(android.content.Intent, int);
+ public abstract java.util.List queryIntentActivitiesAsUser(android.content.Intent, int, int);
public abstract java.util.List queryIntentActivityOptions(android.content.ComponentName, android.content.Intent[], android.content.Intent, int);
public abstract java.util.List queryIntentContentProviders(android.content.Intent, int);
+ public abstract java.util.List queryIntentContentProvidersAsUser(android.content.Intent, int, int);
public abstract java.util.List queryIntentServices(android.content.Intent, int);
+ public abstract java.util.List queryIntentServicesAsUser(android.content.Intent, int, int);
public abstract java.util.List queryPermissionsByGroup(java.lang.String, int);
+ public abstract void registerDexModule(java.lang.String, android.content.pm.PackageManager$DexModuleRegisterCallback);
+ public abstract void registerMoveCallback(android.content.pm.PackageManager$MoveCallback, android.os.Handler);
+ public abstract void removeOnPermissionsChangeListener(android.content.pm.PackageManager$OnPermissionsChangedListener);
public abstract void removePackageFromPreferred(java.lang.String);
public abstract void removePermission(java.lang.String);
+ public abstract void replacePreferredActivity(android.content.IntentFilter, int, android.content.ComponentName[], android.content.ComponentName);
+ public void replacePreferredActivityAsUser(android.content.IntentFilter, int, android.content.ComponentName[], android.content.ComponentName, int);
public abstract android.content.pm.ResolveInfo resolveActivity(android.content.Intent, int);
+ public abstract android.content.pm.ResolveInfo resolveActivityAsUser(android.content.Intent, int, int);
public abstract android.content.pm.ProviderInfo resolveContentProvider(java.lang.String, int);
+ public abstract android.content.pm.ProviderInfo resolveContentProviderAsUser(java.lang.String, int, int);
public abstract android.content.pm.ResolveInfo resolveService(android.content.Intent, int);
+ public abstract android.content.pm.ResolveInfo resolveServiceAsUser(android.content.Intent, int, int);
+ public abstract void revokeRuntimePermission(java.lang.String, java.lang.String, android.os.UserHandle);
+ public abstract void setApplicationCategoryHint(java.lang.String, int);
public abstract void setApplicationEnabledSetting(java.lang.String, int, int);
+ public abstract boolean setApplicationHiddenSettingAsUser(java.lang.String, boolean, android.os.UserHandle);
public abstract void setComponentEnabledSetting(android.content.ComponentName, int, int);
+ public abstract boolean setDefaultBrowserPackageNameAsUser(java.lang.String, int);
+ public void setHarmfulAppWarning(java.lang.String, java.lang.CharSequence);
public abstract void setInstallerPackageName(java.lang.String, java.lang.String);
+ public abstract boolean setInstantAppCookie(byte[]);
+ public java.lang.String[] setPackagesSuspended(java.lang.String[], boolean, android.os.PersistableBundle, android.os.PersistableBundle, java.lang.String);
+ public abstract void setUpdateAvailable(java.lang.String, boolean);
+ public abstract boolean shouldShowRequestPermissionRationale(java.lang.String);
+ public abstract void unregisterMoveCallback(android.content.pm.PackageManager$MoveCallback);
+ public abstract void updateInstantAppCookie(byte[]);
+ public abstract boolean updateIntentVerificationStatusAsUser(java.lang.String, int, int);
+ public abstract void updatePermissionFlags(java.lang.String, java.lang.String, int, int, android.os.UserHandle);
+ public abstract void verifyIntentFilter(int, int, java.util.List);
public abstract void verifyPendingInstall(int, int);
+ public static java.lang.String ACTION_CLEAN_EXTERNAL_STORAGE;
+ public static java.lang.String ACTION_REQUEST_PERMISSIONS;
+ public static boolean APPLY_DEFAULT_TO_DEVICE_PROTECTED_STORAGE;
+ public static int CERT_INPUT_RAW_X509;
+ public static int CERT_INPUT_SHA256;
public static int COMPONENT_ENABLED_STATE_DEFAULT;
public static int COMPONENT_ENABLED_STATE_DISABLED;
public static int COMPONENT_ENABLED_STATE_DISABLED_UNTIL_USED;
public static int COMPONENT_ENABLED_STATE_DISABLED_USER;
public static int COMPONENT_ENABLED_STATE_ENABLED;
+ public static int DELETE_ALL_USERS;
+ public static int DELETE_CHATTY;
+ public static int DELETE_DONT_KILL_APP;
+ public static int DELETE_FAILED_ABORTED;
+ public static int DELETE_FAILED_DEVICE_POLICY_MANAGER;
+ public static int DELETE_FAILED_INTERNAL_ERROR;
+ public static int DELETE_FAILED_OWNER_BLOCKED;
+ public static int DELETE_FAILED_USED_SHARED_LIBRARY;
+ public static int DELETE_FAILED_USER_RESTRICTED;
+ public static int DELETE_KEEP_DATA;
+ public static int DELETE_SUCCEEDED;
+ public static int DELETE_SYSTEM_APP;
public static int DONT_KILL_APP;
+ public static java.lang.String EXTRA_FAILURE_EXISTING_PACKAGE;
+ public static java.lang.String EXTRA_FAILURE_EXISTING_PERMISSION;
+ public static java.lang.String EXTRA_INTENT_FILTER_VERIFICATION_HOSTS;
+ public static java.lang.String EXTRA_INTENT_FILTER_VERIFICATION_ID;
+ public static java.lang.String EXTRA_INTENT_FILTER_VERIFICATION_PACKAGE_NAME;
+ public static java.lang.String EXTRA_INTENT_FILTER_VERIFICATION_URI_SCHEME;
+ public static java.lang.String EXTRA_MOVE_ID;
+ public static java.lang.String EXTRA_REQUEST_PERMISSIONS_NAMES;
+ public static java.lang.String EXTRA_REQUEST_PERMISSIONS_RESULTS;
public static java.lang.String EXTRA_VERIFICATION_ID;
+ public static java.lang.String EXTRA_VERIFICATION_INSTALLER_PACKAGE;
+ public static java.lang.String EXTRA_VERIFICATION_INSTALLER_UID;
+ public static java.lang.String EXTRA_VERIFICATION_INSTALL_FLAGS;
+ public static java.lang.String EXTRA_VERIFICATION_LONG_VERSION_CODE;
+ public static java.lang.String EXTRA_VERIFICATION_PACKAGE_NAME;
public static java.lang.String EXTRA_VERIFICATION_RESULT;
+ public static java.lang.String EXTRA_VERIFICATION_URI;
+ public static java.lang.String EXTRA_VERIFICATION_VERSION_CODE;
+ public static java.lang.String FEATURE_ACTIVITIES_ON_SECONDARY_DISPLAYS;
+ public static java.lang.String FEATURE_ADOPTABLE_STORAGE;
public static java.lang.String FEATURE_APP_WIDGETS;
+ public static java.lang.String FEATURE_ASSIST_GESTURE;
public static java.lang.String FEATURE_AUDIO_LOW_LATENCY;
public static java.lang.String FEATURE_AUDIO_OUTPUT;
public static java.lang.String FEATURE_AUDIO_PRO;
+ public static java.lang.String FEATURE_AUTOFILL;
public static java.lang.String FEATURE_AUTOMOTIVE;
public static java.lang.String FEATURE_BACKUP;
public static java.lang.String FEATURE_BLUETOOTH;
public static java.lang.String FEATURE_BLUETOOTH_LE;
+ public static java.lang.String FEATURE_BROADCAST_RADIO;
public static java.lang.String FEATURE_CAMERA;
public static java.lang.String FEATURE_CAMERA_ANY;
+ public static java.lang.String FEATURE_CAMERA_AR;
public static java.lang.String FEATURE_CAMERA_AUTOFOCUS;
public static java.lang.String FEATURE_CAMERA_CAPABILITY_MANUAL_POST_PROCESSING;
public static java.lang.String FEATURE_CAMERA_CAPABILITY_MANUAL_SENSOR;
@@ -1838,30 +8390,49 @@
public static java.lang.String FEATURE_CAMERA_FLASH;
public static java.lang.String FEATURE_CAMERA_FRONT;
public static java.lang.String FEATURE_CAMERA_LEVEL_FULL;
+ public static java.lang.String FEATURE_CANT_SAVE_STATE;
+ public static java.lang.String FEATURE_COMPANION_DEVICE_SETUP;
public static java.lang.String FEATURE_CONNECTION_SERVICE;
public static java.lang.String FEATURE_CONSUMER_IR;
+ public static java.lang.String FEATURE_CTS;
public static java.lang.String FEATURE_DEVICE_ADMIN;
+ public static java.lang.String FEATURE_DEVICE_ID_ATTESTATION;
+ public static java.lang.String FEATURE_EMBEDDED;
+ public static java.lang.String FEATURE_ETHERNET;
public static java.lang.String FEATURE_FAKETOUCH;
public static java.lang.String FEATURE_FAKETOUCH_MULTITOUCH_DISTINCT;
public static java.lang.String FEATURE_FAKETOUCH_MULTITOUCH_JAZZHAND;
+ public static java.lang.String FEATURE_FILE_BASED_ENCRYPTION;
public static java.lang.String FEATURE_FINGERPRINT;
+ public static java.lang.String FEATURE_FREEFORM_WINDOW_MANAGEMENT;
public static java.lang.String FEATURE_GAMEPAD;
+ public static java.lang.String FEATURE_HDMI_CEC;
public static java.lang.String FEATURE_HIFI_SENSORS;
public static java.lang.String FEATURE_HOME_SCREEN;
public static java.lang.String FEATURE_INPUT_METHODS;
public static java.lang.String FEATURE_LEANBACK;
+ public static java.lang.String FEATURE_LEANBACK_ONLY;
public static java.lang.String FEATURE_LIVE_TV;
public static java.lang.String FEATURE_LIVE_WALLPAPER;
public static java.lang.String FEATURE_LOCATION;
public static java.lang.String FEATURE_LOCATION_GPS;
public static java.lang.String FEATURE_LOCATION_NETWORK;
+ public static java.lang.String FEATURE_LOWPAN;
+ public static java.lang.String FEATURE_MANAGED_PROFILES;
public static java.lang.String FEATURE_MANAGED_USERS;
public static java.lang.String FEATURE_MICROPHONE;
public static java.lang.String FEATURE_MIDI;
public static java.lang.String FEATURE_NFC;
+ public static java.lang.String FEATURE_NFC_ANY;
+ public static java.lang.String FEATURE_NFC_HCE;
public static java.lang.String FEATURE_NFC_HOST_CARD_EMULATION;
+ public static java.lang.String FEATURE_NFC_HOST_CARD_EMULATION_NFCF;
public static java.lang.String FEATURE_OPENGLES_EXTENSION_PACK;
+ public static java.lang.String FEATURE_PC;
+ public static java.lang.String FEATURE_PICTURE_IN_PICTURE;
public static java.lang.String FEATURE_PRINTING;
+ public static java.lang.String FEATURE_RAM_LOW;
+ public static java.lang.String FEATURE_RAM_NORMAL;
public static java.lang.String FEATURE_SCREEN_LANDSCAPE;
public static java.lang.String FEATURE_SCREEN_PORTRAIT;
public static java.lang.String FEATURE_SECURELY_REMOVES_USERS;
@@ -1879,9 +8450,13 @@
public static java.lang.String FEATURE_SENSOR_STEP_DETECTOR;
public static java.lang.String FEATURE_SIP;
public static java.lang.String FEATURE_SIP_VOIP;
+ public static java.lang.String FEATURE_STRONGBOX_KEYSTORE;
public static java.lang.String FEATURE_TELEPHONY;
+ public static java.lang.String FEATURE_TELEPHONY_CARRIERLOCK;
public static java.lang.String FEATURE_TELEPHONY_CDMA;
+ public static java.lang.String FEATURE_TELEPHONY_EUICC;
public static java.lang.String FEATURE_TELEPHONY_GSM;
+ public static java.lang.String FEATURE_TELEPHONY_MBMS;
public static java.lang.String FEATURE_TELEVISION;
public static java.lang.String FEATURE_TOUCHSCREEN;
public static java.lang.String FEATURE_TOUCHSCREEN_MULTITOUCH;
@@ -1890,10 +8465,27 @@
public static java.lang.String FEATURE_USB_ACCESSORY;
public static java.lang.String FEATURE_USB_HOST;
public static java.lang.String FEATURE_VERIFIED_BOOT;
+ public static java.lang.String FEATURE_VOICE_RECOGNIZERS;
+ public static java.lang.String FEATURE_VR_HEADTRACKING;
+ public static java.lang.String FEATURE_VR_MODE;
+ public static java.lang.String FEATURE_VR_MODE_HIGH_PERFORMANCE;
+ public static java.lang.String FEATURE_VULKAN_HARDWARE_COMPUTE;
+ public static java.lang.String FEATURE_VULKAN_HARDWARE_LEVEL;
+ public static java.lang.String FEATURE_VULKAN_HARDWARE_VERSION;
public static java.lang.String FEATURE_WATCH;
public static java.lang.String FEATURE_WEBVIEW;
public static java.lang.String FEATURE_WIFI;
+ public static java.lang.String FEATURE_WIFI_AWARE;
public static java.lang.String FEATURE_WIFI_DIRECT;
+ public static java.lang.String FEATURE_WIFI_PASSPOINT;
+ public static java.lang.String FEATURE_WIFI_RTT;
+ public static int FLAG_PERMISSION_GRANTED_BY_DEFAULT;
+ public static int FLAG_PERMISSION_POLICY_FIXED;
+ public static int FLAG_PERMISSION_REVIEW_REQUIRED;
+ public static int FLAG_PERMISSION_REVOKE_ON_UPGRADE;
+ public static int FLAG_PERMISSION_SYSTEM_FIXED;
+ public static int FLAG_PERMISSION_USER_FIXED;
+ public static int FLAG_PERMISSION_USER_SET;
public static int GET_ACTIVITIES;
public static int GET_CONFIGURATIONS;
public static int GET_DISABLED_COMPONENTS;
@@ -1909,11 +8501,125 @@
public static int GET_SERVICES;
public static int GET_SHARED_LIBRARY_FILES;
public static int GET_SIGNATURES;
+ public static int GET_SIGNING_CERTIFICATES;
public static int GET_UNINSTALLED_PACKAGES;
public static int GET_URI_PERMISSION_PATTERNS;
+ public static int INSTALL_ALLOCATE_AGGRESSIVE;
+ public static int INSTALL_ALLOW_DOWNGRADE;
+ public static int INSTALL_ALLOW_TEST;
+ public static int INSTALL_ALL_USERS;
+ public static int INSTALL_DONT_KILL_APP;
+ public static int INSTALL_EXTERNAL;
+ public static int INSTALL_FAILED_ABORTED;
+ public static int INSTALL_FAILED_ALREADY_EXISTS;
+ public static int INSTALL_FAILED_BAD_DEX_METADATA;
+ public static int INSTALL_FAILED_CONFLICTING_PROVIDER;
+ public static int INSTALL_FAILED_CONTAINER_ERROR;
+ public static int INSTALL_FAILED_CPU_ABI_INCOMPATIBLE;
+ public static int INSTALL_FAILED_DEXOPT;
+ public static int INSTALL_FAILED_DUPLICATE_PACKAGE;
+ public static int INSTALL_FAILED_DUPLICATE_PERMISSION;
+ public static int INSTALL_FAILED_INSTANT_APP_INVALID;
+ public static int INSTALL_FAILED_INSUFFICIENT_STORAGE;
+ public static int INSTALL_FAILED_INTERNAL_ERROR;
+ public static int INSTALL_FAILED_INVALID_APK;
+ public static int INSTALL_FAILED_INVALID_INSTALL_LOCATION;
+ public static int INSTALL_FAILED_INVALID_URI;
+ public static int INSTALL_FAILED_MEDIA_UNAVAILABLE;
+ public static int INSTALL_FAILED_MISSING_FEATURE;
+ public static int INSTALL_FAILED_MISSING_SHARED_LIBRARY;
+ public static int INSTALL_FAILED_NEWER_SDK;
+ public static int INSTALL_FAILED_NO_MATCHING_ABIS;
+ public static int INSTALL_FAILED_NO_SHARED_USER;
+ public static int INSTALL_FAILED_OLDER_SDK;
+ public static int INSTALL_FAILED_PACKAGE_CHANGED;
+ public static int INSTALL_FAILED_PERMISSION_MODEL_DOWNGRADE;
+ public static int INSTALL_FAILED_REPLACE_COULDNT_DELETE;
+ public static int INSTALL_FAILED_SANDBOX_VERSION_DOWNGRADE;
+ public static int INSTALL_FAILED_SHARED_USER_INCOMPATIBLE;
+ public static int INSTALL_FAILED_TEST_ONLY;
+ public static int INSTALL_FAILED_UID_CHANGED;
+ public static int INSTALL_FAILED_UPDATE_INCOMPATIBLE;
+ public static int INSTALL_FAILED_USER_RESTRICTED;
+ public static int INSTALL_FAILED_VERIFICATION_FAILURE;
+ public static int INSTALL_FAILED_VERIFICATION_TIMEOUT;
+ public static int INSTALL_FAILED_VERSION_DOWNGRADE;
+ public static int INSTALL_FORCE_PERMISSION_PROMPT;
+ public static int INSTALL_FORCE_SDK;
+ public static int INSTALL_FORCE_VOLUME_UUID;
+ public static int INSTALL_FORWARD_LOCK;
+ public static int INSTALL_FROM_ADB;
+ public static int INSTALL_FULL_APP;
+ public static int INSTALL_GRANT_RUNTIME_PERMISSIONS;
+ public static int INSTALL_INSTANT_APP;
+ public static int INSTALL_INTERNAL;
+ public static int INSTALL_PARSE_FAILED_BAD_MANIFEST;
+ public static int INSTALL_PARSE_FAILED_BAD_PACKAGE_NAME;
+ public static int INSTALL_PARSE_FAILED_BAD_SHARED_USER_ID;
+ public static int INSTALL_PARSE_FAILED_CERTIFICATE_ENCODING;
+ public static int INSTALL_PARSE_FAILED_INCONSISTENT_CERTIFICATES;
+ public static int INSTALL_PARSE_FAILED_MANIFEST_EMPTY;
+ public static int INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
+ public static int INSTALL_PARSE_FAILED_NOT_APK;
+ public static int INSTALL_PARSE_FAILED_NO_CERTIFICATES;
+ public static int INSTALL_PARSE_FAILED_UNEXPECTED_EXCEPTION;
+ public static int INSTALL_REASON_DEVICE_RESTORE;
+ public static int INSTALL_REASON_DEVICE_SETUP;
+ public static int INSTALL_REASON_POLICY;
+ public static int INSTALL_REASON_UNKNOWN;
+ public static int INSTALL_REASON_USER;
+ public static int INSTALL_REPLACE_EXISTING;
+ public static int INSTALL_SUCCEEDED;
+ public static int INSTALL_VIRTUAL_PRELOAD;
+ public static int INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_ALWAYS;
+ public static int INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_ALWAYS_ASK;
+ public static int INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_ASK;
+ public static int INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_NEVER;
+ public static int INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_UNDEFINED;
+ public static int INTENT_FILTER_VERIFICATION_FAILURE;
+ public static int INTENT_FILTER_VERIFICATION_SUCCESS;
+ public static int MASK_PERMISSION_FLAGS;
public static int MATCH_ALL;
+ public static int MATCH_ANY_USER;
+ public static int MATCH_DEBUG_TRIAGED_MISSING;
public static int MATCH_DEFAULT_ONLY;
+ public static int MATCH_DIRECT_BOOT_AWARE;
+ public static int MATCH_DIRECT_BOOT_UNAWARE;
+ public static int MATCH_DISABLED_COMPONENTS;
+ public static int MATCH_DISABLED_UNTIL_USED_COMPONENTS;
+ public static int MATCH_EXPLICITLY_VISIBLE_ONLY;
+ public static int MATCH_FACTORY_ONLY;
+ public static int MATCH_INSTANT;
+ public static int MATCH_KNOWN_PACKAGES;
+ public static int MATCH_STATIC_SHARED_LIBRARIES;
+ public static int MATCH_SYSTEM_ONLY;
+ public static int MATCH_UNINSTALLED_PACKAGES;
+ public static int MATCH_VISIBLE_TO_INSTANT_APP_ONLY;
public static long MAXIMUM_VERIFICATION_TIMEOUT;
+ public static int MOVE_EXTERNAL_MEDIA;
+ public static int MOVE_FAILED_3RD_PARTY_NOT_ALLOWED_ON_INTERNAL;
+ public static int MOVE_FAILED_DEVICE_ADMIN;
+ public static int MOVE_FAILED_DOESNT_EXIST;
+ public static int MOVE_FAILED_FORWARD_LOCKED;
+ public static int MOVE_FAILED_INSUFFICIENT_STORAGE;
+ public static int MOVE_FAILED_INTERNAL_ERROR;
+ public static int MOVE_FAILED_INVALID_LOCATION;
+ public static int MOVE_FAILED_LOCKED_USER;
+ public static int MOVE_FAILED_OPERATION_PENDING;
+ public static int MOVE_FAILED_SYSTEM_PACKAGE;
+ public static int MOVE_INTERNAL;
+ public static int MOVE_SUCCEEDED;
+ public static int NOTIFY_PACKAGE_USE_ACTIVITY;
+ public static int NOTIFY_PACKAGE_USE_BACKUP;
+ public static int NOTIFY_PACKAGE_USE_BROADCAST_RECEIVER;
+ public static int NOTIFY_PACKAGE_USE_CONTENT_PROVIDER;
+ public static int NOTIFY_PACKAGE_USE_CROSS_PACKAGE;
+ public static int NOTIFY_PACKAGE_USE_FOREGROUND_SERVICE;
+ public static int NOTIFY_PACKAGE_USE_INSTRUMENTATION;
+ public static int NOTIFY_PACKAGE_USE_REASONS_COUNT;
+ public static int NOTIFY_PACKAGE_USE_SERVICE;
+ public static int NO_NATIVE_LIBRARIES;
+ public static int ONLY_IF_NO_MATCH_FOUND;
public static int PERMISSION_DENIED;
public static int PERMISSION_GRANTED;
public static int SIGNATURE_FIRST_NOT_SIGNED;
@@ -1922,8 +8628,30 @@
public static int SIGNATURE_NO_MATCH;
public static int SIGNATURE_SECOND_NOT_SIGNED;
public static int SIGNATURE_UNKNOWN_PACKAGE;
+ public static int SKIP_CURRENT_PROFILE;
+ public static java.lang.String SYSTEM_SHARED_LIBRARY_SERVICES;
+ public static java.lang.String SYSTEM_SHARED_LIBRARY_SHARED;
public static int VERIFICATION_ALLOW;
+ public static int VERIFICATION_ALLOW_WITHOUT_SUFFICIENT;
public static int VERIFICATION_REJECT;
+ public static int VERSION_CODE_HIGHEST;
+}
+
+-keep class android.content.pm.PackageManager$DexModuleRegisterCallback {
+ <init>();
+
+ public abstract void onDexModuleRegistered(java.lang.String, boolean, java.lang.String);
+
+
+}
+
+-keep class android.content.pm.PackageManager$MoveCallback {
+ <init>();
+
+ public void onCreated(int, android.os.Bundle);
+ public abstract void onStatusChanged(int, int, long);
+
+
}
-keep class android.content.pm.PackageManager$NameNotFoundException {
@@ -1934,6 +8662,535 @@
}
+-keep class android.content.pm.PackageManager$OnPermissionsChangedListener {
+
+ public abstract void onPermissionsChanged(int);
+
+
+}
+
+-keep class android.content.pm.PackageParser {
+ <init>();
+
+ public static void collectCertificates(android.content.pm.PackageParser$Package, boolean);
+ public static int computeMinSdkVersion(int, java.lang.String, int, java.lang.String[], java.lang.String[]);
+ public static int computeTargetSdkVersion(int, java.lang.String, java.lang.String[], java.lang.String[], boolean);
+ protected android.content.pm.PackageParser$Package fromCacheEntry(byte[]);
+ public static android.content.pm.PackageParser$Package fromCacheEntryStatic(byte[]);
+ public static android.content.pm.ActivityInfo generateActivityInfo(android.content.pm.PackageParser$Activity, int, android.content.pm.PackageUserState, int);
+ public static android.content.pm.ActivityInfo generateActivityInfo(android.content.pm.ActivityInfo, int, android.content.pm.PackageUserState, int);
+ public static android.content.pm.ApplicationInfo generateApplicationInfo(android.content.pm.PackageParser$Package, int, android.content.pm.PackageUserState);
+ public static android.content.pm.ApplicationInfo generateApplicationInfo(android.content.pm.PackageParser$Package, int, android.content.pm.PackageUserState, int);
+ public static android.content.pm.ApplicationInfo generateApplicationInfo(android.content.pm.ApplicationInfo, int, android.content.pm.PackageUserState, int);
+ public static android.content.pm.InstrumentationInfo generateInstrumentationInfo(android.content.pm.PackageParser$Instrumentation, int);
+ public static android.content.pm.PackageInfo generatePackageInfo(android.content.pm.PackageParser$Package, int[], int, long, long, java.util.Set, android.content.pm.PackageUserState);
+ public static android.content.pm.PackageInfo generatePackageInfo(android.content.pm.PackageParser$Package, int[], int, long, long, java.util.Set, android.content.pm.PackageUserState, int);
+ public static android.content.pm.PermissionGroupInfo generatePermissionGroupInfo(android.content.pm.PackageParser$PermissionGroup, int);
+ public static android.content.pm.PermissionInfo generatePermissionInfo(android.content.pm.PackageParser$Permission, int);
+ public static android.content.pm.ProviderInfo generateProviderInfo(android.content.pm.PackageParser$Provider, int, android.content.pm.PackageUserState, int);
+ public static android.content.pm.ServiceInfo generateServiceInfo(android.content.pm.PackageParser$Service, int, android.content.pm.PackageUserState, int);
+ public static int getActivityConfigChanges(int, int);
+ public static boolean isApkFile(java.io.File);
+ public static boolean isApkPath(java.lang.String);
+ public static boolean isAvailable(android.content.pm.PackageUserState);
+ public static android.content.pm.PackageParser$ApkLite parseApkLite(java.io.File, int);
+ public static android.content.pm.PackageParser$ApkLite parseApkLite(java.io.FileDescriptor, java.lang.String, int);
+ public android.content.pm.PackageParser$Package parseMonolithicPackage(java.io.File, int);
+ public android.content.pm.PackageParser$Package parsePackage(java.io.File, int, boolean);
+ public android.content.pm.PackageParser$Package parsePackage(java.io.File, int);
+ public static android.content.pm.PackageParser$PackageLite parsePackageLite(java.io.File, int);
+ public static java.security.PublicKey parsePublicKey(java.lang.String);
+ public void setCacheDir(java.io.File);
+ public void setCallback(android.content.pm.PackageParser$Callback);
+ public static void setCompatibilityModeEnabled(boolean);
+ public void setDisplayMetrics(android.util.DisplayMetrics);
+ public void setOnlyCoreApps(boolean);
+ public void setSeparateProcesses(java.lang.String[]);
+ protected byte[] toCacheEntry(android.content.pm.PackageParser$Package);
+ public static byte[] toCacheEntryStatic(android.content.pm.PackageParser$Package);
+ public static android.util.ArraySet toSigningKeys(android.content.pm.Signature[]);
+
+
+ public static java.lang.String ANDROID_MANIFEST_FILENAME;
+ public static java.lang.String APK_FILE_EXTENSION;
+ public static android.content.pm.PackageParser$NewPermissionInfo[] NEW_PERMISSIONS;
+ public static int PARSE_CHATTY;
+ public static int PARSE_COLLECT_CERTIFICATES;
+ public static int PARSE_ENFORCE_CODE;
+ public static int PARSE_EXTERNAL_STORAGE;
+ public static int PARSE_FORCE_SDK;
+ public static int PARSE_FORWARD_LOCK;
+ public static int PARSE_IGNORE_PROCESSES;
+ public static int PARSE_IS_SYSTEM_DIR;
+ public static int PARSE_MUST_BE_APK;
+ public static android.content.pm.PackageParser$SplitPermissionInfo[] SPLIT_PERMISSIONS;
+ public static java.util.concurrent.atomic.AtomicInteger sCachedPackageReadCount;
+}
+
+-keep class android.content.pm.PackageParser$Activity {
+ <init>(android.content.pm.PackageParser$ParseComponentArgs, android.content.pm.ActivityInfo);
+
+ public int describeContents();
+ public void setPackageName(java.lang.String);
+ public java.lang.String toString();
+ public void writeToParcel(android.os.Parcel, int);
+
+
+ public static android.os.Parcelable$Creator CREATOR;
+ public android.content.pm.ActivityInfo info;
+}
+
+-keep class android.content.pm.PackageParser$ActivityIntentInfo {
+ <init>(android.content.pm.PackageParser$Activity);
+ <init>(android.os.Parcel);
+
+ public java.lang.String toString();
+
+
+ public android.content.pm.PackageParser$Activity activity;
+}
+
+-keep class android.content.pm.PackageParser$ApkLite {
+ <init>(java.lang.String, java.lang.String, java.lang.String, boolean, java.lang.String, java.lang.String, int, int, int, int, java.util.List, android.content.pm.PackageParser$SigningDetails, boolean, boolean, boolean, boolean, boolean, boolean);
+
+ public long getLongVersionCode();
+
+
+ public java.lang.String codePath;
+ public java.lang.String configForSplit;
+ public boolean coreApp;
+ public boolean debuggable;
+ public boolean extractNativeLibs;
+ public int installLocation;
+ public boolean isFeatureSplit;
+ public boolean isolatedSplits;
+ public boolean multiArch;
+ public java.lang.String packageName;
+ public int revisionCode;
+ public android.content.pm.PackageParser$SigningDetails signingDetails;
+ public java.lang.String splitName;
+ public boolean use32bitAbi;
+ public java.lang.String usesSplitName;
+ public android.content.pm.VerifierInfo[] verifiers;
+ public int versionCode;
+ public int versionCodeMajor;
+}
+
+-keep class android.content.pm.PackageParser$Callback {
+
+ public abstract java.lang.String[] getOverlayApks(java.lang.String);
+ public abstract java.lang.String[] getOverlayPaths(java.lang.String, java.lang.String);
+ public abstract boolean hasFeature(java.lang.String);
+
+
+}
+
+-keep class android.content.pm.PackageParser$Component {
+ <init>(android.content.pm.PackageParser$Package);
+ <init>(android.content.pm.PackageParser$ParsePackageItemArgs, android.content.pm.PackageItemInfo);
+ <init>(android.content.pm.PackageParser$ParseComponentArgs, android.content.pm.ComponentInfo);
+ <init>(android.content.pm.PackageParser$Component);
+ <init>(android.os.Parcel);
+
+ public void appendComponentShortName(java.lang.StringBuilder);
+ public android.content.ComponentName getComponentName();
+ public void printComponentShortName(java.io.PrintWriter);
+ public void setPackageName(java.lang.String);
+ protected void writeToParcel(android.os.Parcel, int);
+
+
+ public java.lang.String className;
+ public java.util.ArrayList intents;
+ public android.os.Bundle metaData;
+ public int order;
+ public android.content.pm.PackageParser$Package owner;
+}
+
+-keep class android.content.pm.PackageParser$Instrumentation {
+ <init>(android.content.pm.PackageParser$ParsePackageItemArgs, android.content.pm.InstrumentationInfo);
+
+ public int describeContents();
+ public void setPackageName(java.lang.String);
+ public java.lang.String toString();
+ public void writeToParcel(android.os.Parcel, int);
+
+
+ public static android.os.Parcelable$Creator CREATOR;
+ public android.content.pm.InstrumentationInfo info;
+}
+
+-keep class android.content.pm.PackageParser$IntentInfo {
+ <init>();
+ <init>(android.os.Parcel);
+
+ public void writeIntentInfoToParcel(android.os.Parcel, int);
+
+
+ public int banner;
+ public boolean hasDefault;
+ public int icon;
+ public int labelRes;
+ public int logo;
+ public java.lang.CharSequence nonLocalizedLabel;
+ public int preferred;
+}
+
+-keep class android.content.pm.PackageParser$NewPermissionInfo {
+ <init>(java.lang.String, int, int);
+
+
+
+ public int fileVersion;
+ public java.lang.String name;
+ public int sdkVersion;
+}
+
+-keep class android.content.pm.PackageParser$Package {
+ <init>(java.lang.String);
+ <init>(android.os.Parcel);
+
+ public boolean canHaveOatDir();
+ public int describeContents();
+ public java.util.List getAllCodePaths();
+ public java.util.List getAllCodePathsExcludingResourceOnly();
+ public java.util.List getChildPackageNames();
+ public long getLatestForegroundPackageUseTimeInMills();
+ public long getLatestPackageUseTimeInMills();
+ public long getLongVersionCode();
+ public boolean hasChildPackage(java.lang.String);
+ public boolean hasComponentClassName(java.lang.String);
+ public boolean isExternal();
+ public boolean isForwardLocked();
+ public boolean isLibrary();
+ public boolean isMatch(int);
+ public boolean isOem();
+ public boolean isPrivileged();
+ public boolean isProduct();
+ public boolean isSystem();
+ public boolean isUpdatedSystemApp();
+ public boolean isVendor();
+ public void setApplicationInfoBaseCodePath(java.lang.String);
+ public void setApplicationInfoBaseResourcePath(java.lang.String);
+ public void setApplicationInfoCodePath(java.lang.String);
+ public void setApplicationInfoFlags(int, int);
+ public void setApplicationInfoResourcePath(java.lang.String);
+ public void setApplicationInfoSplitCodePaths(java.lang.String[]);
+ public void setApplicationInfoSplitResourcePaths(java.lang.String[]);
+ public void setApplicationVolumeUuid(java.lang.String);
+ public void setBaseCodePath(java.lang.String);
+ public void setCodePath(java.lang.String);
+ public void setPackageName(java.lang.String);
+ public void setSigningDetails(android.content.pm.PackageParser$SigningDetails);
+ public void setSplitCodePaths(java.lang.String[]);
+ public void setUse32bitAbi(boolean);
+ public void setVolumeUuid(java.lang.String);
+ public java.lang.String toString();
+ public void writeToParcel(android.os.Parcel, int);
+
+
+ public static android.os.Parcelable$Creator CREATOR;
+ public java.util.ArrayList activities;
+ public android.content.pm.ApplicationInfo applicationInfo;
+ public java.lang.String baseCodePath;
+ public boolean baseHardwareAccelerated;
+ public int baseRevisionCode;
+ public java.util.ArrayList childPackages;
+ public java.lang.String codePath;
+ public java.util.ArrayList configPreferences;
+ public boolean coreApp;
+ public java.lang.String cpuAbiOverride;
+ public java.util.ArrayList featureGroups;
+ public int installLocation;
+ public java.util.ArrayList instrumentation;
+ public boolean isStub;
+ public java.util.ArrayList libraryNames;
+ public java.util.ArrayList mAdoptPermissions;
+ public android.os.Bundle mAppMetaData;
+ public int mCompileSdkVersion;
+ public java.lang.String mCompileSdkVersionCodename;
+ public java.lang.Object mExtras;
+ public android.util.ArrayMap mKeySetMapping;
+ public long[] mLastPackageUsageTimeInMills;
+ public java.util.ArrayList mOriginalPackages;
+ public java.lang.String mOverlayCategory;
+ public boolean mOverlayIsStatic;
+ public int mOverlayPriority;
+ public java.lang.String mOverlayTarget;
+ public int mPreferredOrder;
+ public java.lang.String mRealPackage;
+ public java.lang.String mRequiredAccountType;
+ public boolean mRequiredForAllUsers;
+ public java.lang.String mRestrictedAccountType;
+ public java.lang.String mSharedUserId;
+ public int mSharedUserLabel;
+ public android.content.pm.PackageParser$SigningDetails mSigningDetails;
+ public android.util.ArraySet mUpgradeKeySets;
+ public int mVersionCode;
+ public int mVersionCodeMajor;
+ public java.lang.String mVersionName;
+ public java.lang.String manifestPackageName;
+ public java.lang.String packageName;
+ public android.content.pm.PackageParser$Package parentPackage;
+ public java.util.ArrayList permissionGroups;
+ public java.util.ArrayList permissions;
+ public java.util.ArrayList preferredActivityFilters;
+ public java.util.ArrayList protectedBroadcasts;
+ public java.util.ArrayList providers;
+ public java.util.ArrayList receivers;
+ public java.util.ArrayList reqFeatures;
+ public java.util.ArrayList requestedPermissions;
+ public byte[] restrictUpdateHash;
+ public java.util.ArrayList services;
+ public java.lang.String[] splitCodePaths;
+ public int[] splitFlags;
+ public java.lang.String[] splitNames;
+ public int[] splitPrivateFlags;
+ public int[] splitRevisionCodes;
+ public java.lang.String staticSharedLibName;
+ public long staticSharedLibVersion;
+ public boolean use32bitAbi;
+ public java.util.ArrayList usesLibraries;
+ public java.lang.String[] usesLibraryFiles;
+ public java.util.ArrayList usesOptionalLibraries;
+ public java.util.ArrayList usesStaticLibraries;
+ public java.lang.String[][] usesStaticLibrariesCertDigests;
+ public long[] usesStaticLibrariesVersions;
+ public boolean visibleToInstantApps;
+ public java.lang.String volumeUuid;
+}
+
+-keep class android.content.pm.PackageParser$PackageLite {
+ <init>(java.lang.String, android.content.pm.PackageParser$ApkLite, java.lang.String[], boolean[], java.lang.String[], java.lang.String[], java.lang.String[], int[]);
+
+ public java.util.List getAllCodePaths();
+
+
+ public java.lang.String baseCodePath;
+ public int baseRevisionCode;
+ public java.lang.String codePath;
+ public java.lang.String[] configForSplit;
+ public boolean coreApp;
+ public boolean debuggable;
+ public boolean extractNativeLibs;
+ public int installLocation;
+ public boolean[] isFeatureSplits;
+ public boolean isolatedSplits;
+ public boolean multiArch;
+ public java.lang.String packageName;
+ public java.lang.String[] splitCodePaths;
+ public java.lang.String[] splitNames;
+ public int[] splitRevisionCodes;
+ public boolean use32bitAbi;
+ public java.lang.String[] usesSplitNames;
+ public android.content.pm.VerifierInfo[] verifiers;
+ public int versionCode;
+ public int versionCodeMajor;
+}
+
+-keep class android.content.pm.PackageParser$PackageParserException {
+ <init>(int, java.lang.String);
+ <init>(int, java.lang.String, java.lang.Throwable);
+
+
+
+ public int error;
+}
+
+-keep class android.content.pm.PackageParser$ParseComponentArgs {
+ <init>(android.content.pm.PackageParser$Package, java.lang.String[], int, int, int, int, int, int, java.lang.String[], int, int, int);
+
+
+
+}
+
+-keep class android.content.pm.PackageParser$ParsePackageItemArgs {
+
+
+
+}
+
+-keep class android.content.pm.PackageParser$Permission {
+ <init>(android.content.pm.PackageParser$Package);
+ <init>(android.content.pm.PackageParser$Package, android.content.pm.PermissionInfo);
+
+ public int describeContents();
+ public boolean isAppOp();
+ public void setPackageName(java.lang.String);
+ public java.lang.String toString();
+ public void writeToParcel(android.os.Parcel, int);
+
+
+ public static android.os.Parcelable$Creator CREATOR;
+ public android.content.pm.PackageParser$PermissionGroup group;
+ public android.content.pm.PermissionInfo info;
+ public boolean tree;
+}
+
+-keep class android.content.pm.PackageParser$PermissionGroup {
+ <init>(android.content.pm.PackageParser$Package);
+ <init>(android.content.pm.PackageParser$Package, android.content.pm.PermissionGroupInfo);
+
+ public int describeContents();
+ public void setPackageName(java.lang.String);
+ public java.lang.String toString();
+ public void writeToParcel(android.os.Parcel, int);
+
+
+ public static android.os.Parcelable$Creator CREATOR;
+ public android.content.pm.PermissionGroupInfo info;
+}
+
+-keep class android.content.pm.PackageParser$Provider {
+ <init>(android.content.pm.PackageParser$ParseComponentArgs, android.content.pm.ProviderInfo);
+ <init>(android.content.pm.PackageParser$Provider);
+
+ public int describeContents();
+ public void setPackageName(java.lang.String);
+ public java.lang.String toString();
+ public void writeToParcel(android.os.Parcel, int);
+
+
+ public static android.os.Parcelable$Creator CREATOR;
+ public android.content.pm.ProviderInfo info;
+ public boolean syncable;
+}
+
+-keep class android.content.pm.PackageParser$Service {
+ <init>(android.content.pm.PackageParser$ParseComponentArgs, android.content.pm.ServiceInfo);
+
+ public int describeContents();
+ public void setPackageName(java.lang.String);
+ public java.lang.String toString();
+ public void writeToParcel(android.os.Parcel, int);
+
+
+ public static android.os.Parcelable$Creator CREATOR;
+ public android.content.pm.ServiceInfo info;
+}
+
+-keep class android.content.pm.PackageParser$SigningDetails {
+ <init>(android.content.pm.Signature[], int, android.util.ArraySet, android.content.pm.Signature[], int[]);
+ <init>(android.content.pm.Signature[], int, android.content.pm.Signature[], int[]);
+ <init>(android.content.pm.Signature[], int);
+ <init>(android.content.pm.PackageParser$SigningDetails);
+ <init>(android.os.Parcel);
+
+ public boolean checkCapability(android.content.pm.PackageParser$SigningDetails, int);
+ public boolean checkCapability(java.lang.String, int);
+ public boolean checkCapabilityRecover(android.content.pm.PackageParser$SigningDetails, int);
+ public int describeContents();
+ public boolean equals(java.lang.Object);
+ public boolean hasAncestor(android.content.pm.PackageParser$SigningDetails);
+ public boolean hasAncestorOrSelf(android.content.pm.PackageParser$SigningDetails);
+ public boolean hasCertificate(android.content.pm.Signature);
+ public boolean hasCertificate(android.content.pm.Signature, int);
+ public boolean hasCertificate(byte[]);
+ public boolean hasPastSigningCertificates();
+ public boolean hasSha256Certificate(byte[]);
+ public boolean hasSha256Certificate(byte[], int);
+ public boolean hasSignatures();
+ public int hashCode();
+ public boolean signaturesMatchExactly(android.content.pm.PackageParser$SigningDetails);
+ public void writeToParcel(android.os.Parcel, int);
+
+
+ public static android.os.Parcelable$Creator CREATOR;
+ public static android.content.pm.PackageParser$SigningDetails UNKNOWN;
+ public android.content.pm.Signature[] pastSigningCertificates;
+ public int[] pastSigningCertificatesFlags;
+ public android.util.ArraySet publicKeys;
+ public int signatureSchemeVersion;
+ public android.content.pm.Signature[] signatures;
+}
+
+-keep class android.content.pm.PackageParser$SplitPermissionInfo {
+ <init>(java.lang.String, java.lang.String[], int);
+
+
+
+ public java.lang.String[] newPerms;
+ public java.lang.String rootPerm;
+ public int targetSdk;
+}
+
+-keep class android.content.pm.PackageStats {
+ <init>(java.lang.String);
+ <init>(java.lang.String, int);
+ <init>(android.os.Parcel);
+ <init>(android.content.pm.PackageStats);
+
+ public int describeContents();
+ public boolean equals(java.lang.Object);
+ public int hashCode();
+ public java.lang.String toString();
+ public void writeToParcel(android.os.Parcel, int);
+
+
+ public static android.os.Parcelable$Creator CREATOR;
+ public long cacheSize;
+ public long codeSize;
+ public long dataSize;
+ public long externalCacheSize;
+ public long externalCodeSize;
+ public long externalDataSize;
+ public long externalMediaSize;
+ public long externalObbSize;
+ public java.lang.String packageName;
+ public int userHandle;
+}
+
+-keep class android.content.pm.PackageUserState {
+ <init>();
+ <init>(android.content.pm.PackageUserState);
+
+ public boolean equals(java.lang.Object);
+ public boolean isAvailable(int);
+ public boolean isEnabled(android.content.pm.ComponentInfo, int);
+ public boolean isMatch(android.content.pm.ComponentInfo, int);
+
+
+ public int appLinkGeneration;
+ public int categoryHint;
+ public long ceDataInode;
+ public java.lang.String dialogMessage;
+ public android.util.ArraySet disabledComponents;
+ public int domainVerificationStatus;
+ public int enabled;
+ public android.util.ArraySet enabledComponents;
+ public java.lang.String harmfulAppWarning;
+ public boolean hidden;
+ public int installReason;
+ public boolean installed;
+ public boolean instantApp;
+ public java.lang.String lastDisableAppCaller;
+ public boolean notLaunched;
+ public java.lang.String[] overlayPaths;
+ public boolean stopped;
+ public boolean suspended;
+ public android.os.PersistableBundle suspendedAppExtras;
+ public android.os.PersistableBundle suspendedLauncherExtras;
+ public java.lang.String suspendingPackage;
+ public boolean virtualPreload;
+}
+
+-keep class android.content.pm.ParceledListSlice {
+ <init>(java.util.List);
+
+ public int describeContents();
+ public static android.content.pm.ParceledListSlice emptyList();
+ public java.util.List getList();
+ protected android.os.Parcelable$Creator readParcelableCreator(android.os.Parcel, java.lang.ClassLoader);
+ public void setInlineCountLimit(int);
+ protected void writeElement(android.os.Parcelable, android.os.Parcel, int);
+ protected void writeElement(java.lang.Object, android.os.Parcel, int);
+ protected void writeParcelableCreator(android.os.Parcelable, android.os.Parcel);
+ protected void writeParcelableCreator(java.lang.Object, android.os.Parcel);
+ public void writeToParcel(android.os.Parcel, int);
+
+
+ public static android.os.Parcelable$ClassLoaderCreator CREATOR;
+}
+
-keep class android.content.pm.PathPermission {
<init>(java.lang.String, int, java.lang.String, java.lang.String);
<init>(android.os.Parcel);
@@ -1962,14 +9219,21 @@
public int flags;
public java.lang.CharSequence nonLocalizedDescription;
public int priority;
+ public int requestRes;
}
-keep class android.content.pm.PermissionInfo {
<init>();
<init>(android.content.pm.PermissionInfo);
+ public int calculateFootprint();
public int describeContents();
+ public static int fixProtectionLevel(int);
+ public int getProtection();
+ public int getProtectionFlags();
+ public boolean isAppOp();
public java.lang.CharSequence loadDescription(android.content.pm.PackageManager);
+ public static java.lang.String protectionToString(int);
public java.lang.String toString();
public void writeToParcel(android.os.Parcel, int);
@@ -1977,14 +9241,21 @@
public static android.os.Parcelable$Creator CREATOR;
public static int FLAG_COSTS_MONEY;
public static int FLAG_INSTALLED;
+ public static int FLAG_REMOVED;
public static int PROTECTION_DANGEROUS;
public static int PROTECTION_FLAG_APPOP;
public static int PROTECTION_FLAG_DEVELOPMENT;
public static int PROTECTION_FLAG_INSTALLER;
+ public static int PROTECTION_FLAG_INSTANT;
+ public static int PROTECTION_FLAG_OEM;
public static int PROTECTION_FLAG_PRE23;
public static int PROTECTION_FLAG_PREINSTALLED;
public static int PROTECTION_FLAG_PRIVILEGED;
+ public static int PROTECTION_FLAG_RUNTIME_ONLY;
+ public static int PROTECTION_FLAG_SETUP;
public static int PROTECTION_FLAG_SYSTEM;
+ public static int PROTECTION_FLAG_SYSTEM_TEXT_CLASSIFIER;
+ public static int PROTECTION_FLAG_VENDOR_PRIVILEGED;
public static int PROTECTION_FLAG_VERIFIER;
public static int PROTECTION_MASK_BASE;
public static int PROTECTION_MASK_FLAGS;
@@ -1996,6 +9267,7 @@
public java.lang.String group;
public java.lang.CharSequence nonLocalizedDescription;
public int protectionLevel;
+ public int requestRes;
}
-keep class android.content.pm.ProviderInfo {
@@ -2004,12 +9276,14 @@
public int describeContents();
public void dump(android.util.Printer, java.lang.String);
+ public void dump(android.util.Printer, java.lang.String, int);
public java.lang.String toString();
public void writeToParcel(android.os.Parcel, int);
public static android.os.Parcelable$Creator CREATOR;
public static int FLAG_SINGLE_USER;
+ public static int FLAG_VISIBLE_TO_INSTANT_APP;
public java.lang.String authority;
public int flags;
public boolean grantUriPermissions;
@@ -2028,20 +9302,30 @@
public int describeContents();
public void dump(android.util.Printer, java.lang.String);
+ public void dump(android.util.Printer, java.lang.String, int);
+ public android.content.pm.ComponentInfo getComponentInfo();
public int getIconResource();
public android.graphics.drawable.Drawable loadIcon(android.content.pm.PackageManager);
public java.lang.CharSequence loadLabel(android.content.pm.PackageManager);
+ public int resolveIconResId();
+ public int resolveLabelResId();
public java.lang.String toString();
public void writeToParcel(android.os.Parcel, int);
public static android.os.Parcelable$Creator CREATOR;
public android.content.pm.ActivityInfo activityInfo;
+ public android.content.pm.AuxiliaryResolveInfo auxiliaryInfo;
public android.content.IntentFilter filter;
+ public boolean handleAllWebDataURI;
public int icon;
+ public int iconResourceId;
+ public boolean instantAppAvailable;
public boolean isDefault;
+ public boolean isInstantAppAvailable;
public int labelRes;
public int match;
+ public boolean noResourceId;
public java.lang.CharSequence nonLocalizedLabel;
public int preferredOrder;
public int priority;
@@ -2049,6 +9333,8 @@
public java.lang.String resolvePackageName;
public android.content.pm.ServiceInfo serviceInfo;
public int specificIndex;
+ public boolean system;
+ public int targetUserId;
}
-keep class android.content.pm.ServiceInfo {
@@ -2062,19 +9348,52 @@
public static android.os.Parcelable$Creator CREATOR;
+ public static int FLAG_EXTERNAL_SERVICE;
public static int FLAG_ISOLATED_PROCESS;
public static int FLAG_SINGLE_USER;
public static int FLAG_STOP_WITH_TASK;
+ public static int FLAG_VISIBLE_TO_INSTANT_APP;
public int flags;
public java.lang.String permission;
}
--keep class android.content.pm.Signature {
- <init>(byte[]);
- <init>(java.lang.String);
+-keep class android.content.pm.SharedLibraryInfo {
+ <init>(java.lang.String, long, int, android.content.pm.VersionedPackage, java.util.List);
public int describeContents();
+ public android.content.pm.VersionedPackage getDeclaringPackage();
+ public java.util.List getDependentPackages();
+ public long getLongVersion();
+ public java.lang.String getName();
+ public int getType();
+ public int getVersion();
+ public boolean isBuiltin();
+ public boolean isDynamic();
+ public boolean isStatic();
+ public java.lang.String toString();
+ public void writeToParcel(android.os.Parcel, int);
+
+
+ public static android.os.Parcelable$Creator CREATOR;
+ public static int TYPE_BUILTIN;
+ public static int TYPE_DYNAMIC;
+ public static int TYPE_STATIC;
+ public static int VERSION_UNDEFINED;
+}
+
+-keep class android.content.pm.Signature {
+ <init>(byte[]);
+ <init>(java.security.cert.Certificate[]);
+ <init>(java.lang.String);
+
+ public static boolean areEffectiveMatch(android.content.pm.Signature[], android.content.pm.Signature[]);
+ public static boolean areEffectiveMatch(android.content.pm.Signature, android.content.pm.Signature);
+ public static boolean areExactMatch(android.content.pm.Signature[], android.content.pm.Signature[]);
+ public static android.content.pm.Signature bounce(java.security.cert.CertificateFactory, android.content.pm.Signature);
+ public int describeContents();
public boolean equals(java.lang.Object);
+ public android.content.pm.Signature[] getChainSignatures();
+ public java.security.PublicKey getPublicKey();
public int hashCode();
public byte[] toByteArray();
public char[] toChars();
@@ -2086,6 +9405,177 @@
public static android.os.Parcelable$Creator CREATOR;
}
+-keep class android.content.pm.SigningInfo {
+ <init>();
+ <init>(android.content.pm.PackageParser$SigningDetails);
+ <init>(android.content.pm.SigningInfo);
+
+ public int describeContents();
+ public android.content.pm.Signature[] getApkContentsSigners();
+ public android.content.pm.Signature[] getSigningCertificateHistory();
+ public boolean hasMultipleSigners();
+ public boolean hasPastSigningCertificates();
+ public void writeToParcel(android.os.Parcel, int);
+
+
+ public static android.os.Parcelable$Creator CREATOR;
+}
+
+-keep class android.content.pm.UserInfo {
+ <init>(int, java.lang.String, int);
+ <init>(int, java.lang.String, java.lang.String, int);
+ <init>();
+ <init>(android.content.pm.UserInfo);
+
+ public boolean canHaveProfile();
+ public int describeContents();
+ public android.os.UserHandle getUserHandle();
+ public boolean isAdmin();
+ public boolean isDemo();
+ public boolean isEnabled();
+ public boolean isEphemeral();
+ public boolean isGuest();
+ public boolean isInitialized();
+ public boolean isManagedProfile();
+ public boolean isPrimary();
+ public boolean isQuietModeEnabled();
+ public boolean isRestricted();
+ public boolean isSystemOnly();
+ public static boolean isSystemOnly(int);
+ public boolean supportsSwitchTo();
+ public boolean supportsSwitchToByUser();
+ public java.lang.String toString();
+ public void writeToParcel(android.os.Parcel, int);
+
+
+ public static android.os.Parcelable$Creator CREATOR;
+ public static int FLAG_ADMIN;
+ public static int FLAG_DEMO;
+ public static int FLAG_DISABLED;
+ public static int FLAG_EPHEMERAL;
+ public static int FLAG_GUEST;
+ public static int FLAG_INITIALIZED;
+ public static int FLAG_MANAGED_PROFILE;
+ public static int FLAG_MASK_USER_TYPE;
+ public static int FLAG_PRIMARY;
+ public static int FLAG_QUIET_MODE;
+ public static int FLAG_RESTRICTED;
+ public static int NO_PROFILE_GROUP_ID;
+ public long creationTime;
+ public int flags;
+ public boolean guestToRemove;
+ public java.lang.String iconPath;
+ public int id;
+ public java.lang.String lastLoggedInFingerprint;
+ public long lastLoggedInTime;
+ public java.lang.String name;
+ public boolean partial;
+ public int profileBadge;
+ public int profileGroupId;
+ public int restrictedProfileParentId;
+ public int serialNumber;
+}
+
+-keep class android.content.pm.VerifierDeviceIdentity {
+ <init>(long);
+
+ public int describeContents();
+ public boolean equals(java.lang.Object);
+ public static android.content.pm.VerifierDeviceIdentity generate();
+ public int hashCode();
+ public static android.content.pm.VerifierDeviceIdentity parse(java.lang.String);
+ public java.lang.String toString();
+ public void writeToParcel(android.os.Parcel, int);
+
+
+ public static android.os.Parcelable$Creator CREATOR;
+}
+
+-keep class android.content.pm.VerifierInfo {
+ <init>(java.lang.String, java.security.PublicKey);
+
+ public int describeContents();
+ public void writeToParcel(android.os.Parcel, int);
+
+
+ public static android.os.Parcelable$Creator CREATOR;
+ public java.lang.String packageName;
+ public java.security.PublicKey publicKey;
+}
+
+-keep class android.content.pm.VersionedPackage {
+ <init>(java.lang.String, int);
+ <init>(java.lang.String, long);
+
+ public int describeContents();
+ public long getLongVersionCode();
+ public java.lang.String getPackageName();
+ public int getVersionCode();
+ public java.lang.String toString();
+ public void writeToParcel(android.os.Parcel, int);
+
+
+ public static android.os.Parcelable$Creator CREATOR;
+}
+
+-keep class android.content.pm.dex.ArtManager {
+ <init>(android.content.Context, android.content.pm.dex.IArtManager);
+
+ public static java.lang.String getCurrentProfilePath(java.lang.String, int, java.lang.String);
+ public static java.lang.String getProfileName(java.lang.String);
+ public static java.io.File getProfileSnapshotFileForName(java.lang.String, java.lang.String);
+ public boolean isRuntimeProfilingEnabled(int);
+ public void snapshotRuntimeProfile(int, java.lang.String, java.lang.String, java.util.concurrent.Executor, android.content.pm.dex.ArtManager$SnapshotRuntimeProfileCallback);
+
+
+ public static int PROFILE_APPS;
+ public static int PROFILE_BOOT_IMAGE;
+ public static int SNAPSHOT_FAILED_CODE_PATH_NOT_FOUND;
+ public static int SNAPSHOT_FAILED_INTERNAL_ERROR;
+ public static int SNAPSHOT_FAILED_PACKAGE_NOT_FOUND;
+}
+
+-keep class android.content.pm.dex.ArtManager$SnapshotRuntimeProfileCallback {
+ <init>();
+
+ public abstract void onError(int);
+ public abstract void onSuccess(android.os.ParcelFileDescriptor);
+
+
+}
+
+-keep class android.content.pm.dex.IArtManager {
+
+ public abstract boolean isRuntimeProfilingEnabled(int, java.lang.String);
+ public abstract void snapshotRuntimeProfile(int, java.lang.String, java.lang.String, android.content.pm.dex.ISnapshotRuntimeProfileCallback, java.lang.String);
+
+
+}
+
+-keep class android.content.pm.dex.ISnapshotRuntimeProfileCallback {
+
+ public abstract void onError(int);
+ public abstract void onSuccess(android.os.ParcelFileDescriptor);
+
+
+}
+
+-keep class android.content.res.ApkAssets {
+
+ protected void finalize();
+ public java.lang.String getAssetPath();
+ public boolean isUpToDate();
+ public static android.content.res.ApkAssets loadFromFd(java.io.FileDescriptor, java.lang.String, boolean, boolean);
+ public static android.content.res.ApkAssets loadFromPath(java.lang.String);
+ public static android.content.res.ApkAssets loadFromPath(java.lang.String, boolean);
+ public static android.content.res.ApkAssets loadFromPath(java.lang.String, boolean, boolean);
+ public static android.content.res.ApkAssets loadOverlayFromPath(java.lang.String, boolean);
+ public android.content.res.XmlResourceParser openXml(java.lang.String);
+ public java.lang.String toString();
+
+
+}
+
-keep class android.content.res.AssetFileDescriptor {
<init>(android.os.ParcelFileDescriptor, long, long);
<init>(android.os.ParcelFileDescriptor, long, long, android.os.Bundle);
@@ -2109,18 +9599,37 @@
}
-keep class android.content.res.AssetManager {
+ <init>();
+ public int addAssetPath(java.lang.String);
+ public int addAssetPathAsSharedLibrary(java.lang.String);
+ public int addOverlayPath(java.lang.String);
public void close();
protected void finalize();
+ public int findCookieForPath(java.lang.String);
+ public android.content.res.ApkAssets[] getApkAssets();
+ public static java.lang.String getAssetAllocations();
+ public android.util.SparseArray getAssignedPackageIdentifiers();
+ public static int getGlobalAssetCount();
+ public static int getGlobalAssetManagerCount();
public java.lang.String[] getLocales();
+ public java.lang.String[] getNonSystemLocales();
+ public static android.content.res.AssetManager getSystem();
+ public boolean isUpToDate();
public java.lang.String[] list(java.lang.String);
public java.io.InputStream open(java.lang.String);
public java.io.InputStream open(java.lang.String, int);
public android.content.res.AssetFileDescriptor openFd(java.lang.String);
+ public java.io.InputStream openNonAsset(java.lang.String);
+ public java.io.InputStream openNonAsset(java.lang.String, int);
+ public java.io.InputStream openNonAsset(int, java.lang.String);
+ public java.io.InputStream openNonAsset(int, java.lang.String, int);
public android.content.res.AssetFileDescriptor openNonAssetFd(java.lang.String);
public android.content.res.AssetFileDescriptor openNonAssetFd(int, java.lang.String);
public android.content.res.XmlResourceParser openXmlResourceParser(java.lang.String);
public android.content.res.XmlResourceParser openXmlResourceParser(int, java.lang.String);
+ public void setApkAssets(android.content.res.ApkAssets[], boolean);
+ public void setConfiguration(int, int, java.lang.String, int, int, int, int, int, int, int, int, int, int, int, int, int, int, int);
public static int ACCESS_BUFFER;
@@ -2132,14 +9641,22 @@
-keep class android.content.res.ColorStateList {
<init>(int[][], int[]);
+ public boolean canApplyTheme();
public static android.content.res.ColorStateList createFromXml(android.content.res.Resources, org.xmlpull.v1.XmlPullParser);
public static android.content.res.ColorStateList createFromXml(android.content.res.Resources, org.xmlpull.v1.XmlPullParser, android.content.res.Resources$Theme);
public int describeContents();
public int getChangingConfigurations();
public int getColorForState(int[], int);
+ public int[] getColors();
+ public android.content.res.ConstantState getConstantState();
public int getDefaultColor();
+ public int[][] getStates();
+ public boolean hasFocusStateSpecified();
+ public boolean hasState(int);
public boolean isOpaque();
public boolean isStateful();
+ public android.content.res.ColorStateList obtainForTheme(android.content.res.Resources$Theme);
+ public android.content.res.ComplexColor obtainForTheme(android.content.res.Resources$Theme);
public java.lang.String toString();
public static android.content.res.ColorStateList valueOf(int);
public android.content.res.ColorStateList withAlpha(int);
@@ -2149,37 +9666,135 @@
public static android.os.Parcelable$Creator CREATOR;
}
--keep class android.content.res.Configuration {
- <init>();
- <init>(android.content.res.Configuration);
+-keep class android.content.res.CompatibilityInfo {
+ <init>(android.content.pm.ApplicationInfo, int, int, boolean);
- public int compareTo(android.content.res.Configuration);
- public int compareTo(java.lang.Object);
+ public boolean alwaysSupportsScreen();
+ public void applyToConfiguration(int, android.content.res.Configuration);
+ public void applyToDisplayMetrics(android.util.DisplayMetrics);
+ public static float computeCompatibleScaling(android.util.DisplayMetrics, android.util.DisplayMetrics);
public int describeContents();
- public int diff(android.content.res.Configuration);
- public boolean equals(android.content.res.Configuration);
public boolean equals(java.lang.Object);
- public int getLayoutDirection();
+ public android.content.res.CompatibilityInfo$Translator getTranslator();
public int hashCode();
- public boolean isLayoutSizeAtLeast(int);
- public boolean isScreenRound();
- public static boolean needNewResources(int, int);
- public void readFromParcel(android.os.Parcel);
- public void setLayoutDirection(java.util.Locale);
- public void setLocale(java.util.Locale);
- public void setTo(android.content.res.Configuration);
- public void setToDefaults();
+ public boolean isScalingRequired();
+ public boolean needsCompatResources();
+ public boolean neverSupportsScreen();
+ public boolean supportsScreen();
public java.lang.String toString();
- public int updateFrom(android.content.res.Configuration);
public void writeToParcel(android.os.Parcel, int);
public static android.os.Parcelable$Creator CREATOR;
+ public static android.content.res.CompatibilityInfo DEFAULT_COMPATIBILITY_INFO;
+ public static int DEFAULT_NORMAL_SHORT_DIMENSION;
+ public static float MAXIMUM_ASPECT_RATIO;
+ public int applicationDensity;
+ public float applicationInvertedScale;
+ public float applicationScale;
+}
+
+-keep class android.content.res.CompatibilityInfo$Translator {
+
+ public android.graphics.Rect getTranslatedContentInsets(android.graphics.Rect);
+ public android.graphics.Region getTranslatedTouchableArea(android.graphics.Region);
+ public android.graphics.Rect getTranslatedVisibleInsets(android.graphics.Rect);
+ public void translateCanvas(android.graphics.Canvas);
+ public void translateEventInScreenToAppWindow(android.view.MotionEvent);
+ public void translateLayoutParamsInAppWindowToScreen(android.view.WindowManager$LayoutParams);
+ public void translatePointInScreenToAppWindow(android.graphics.PointF);
+ public void translateRectInAppWindowToScreen(android.graphics.Rect);
+ public void translateRectInScreenToAppWinFrame(android.graphics.Rect);
+ public void translateRectInScreenToAppWindow(android.graphics.Rect);
+ public void translateRegionInWindowToScreen(android.graphics.Region);
+ public void translateWindowLayout(android.view.WindowManager$LayoutParams);
+
+
+ public float applicationInvertedScale;
+ public float applicationScale;
+}
+
+-keep class android.content.res.ComplexColor {
+ <init>();
+
+ public abstract boolean canApplyTheme();
+ public int getChangingConfigurations();
+ public abstract android.content.res.ConstantState getConstantState();
+ public abstract int getDefaultColor();
+ public boolean isStateful();
+ public abstract android.content.res.ComplexColor obtainForTheme(android.content.res.Resources$Theme);
+
+
+}
+
+-keep class android.content.res.Configuration {
+ <init>();
+ <init>(android.content.res.Configuration);
+
+ public void clearLocales();
+ public int compareTo(android.content.res.Configuration);
+ public int compareTo(java.lang.Object);
+ public static java.lang.String configurationDiffToString(int);
+ public int describeContents();
+ public int diff(android.content.res.Configuration);
+ public int diff(android.content.res.Configuration, boolean, boolean);
+ public int diffPublicOnly(android.content.res.Configuration);
+ public boolean equals(android.content.res.Configuration);
+ public boolean equals(java.lang.Object);
+ public static android.content.res.Configuration generateDelta(android.content.res.Configuration, android.content.res.Configuration);
+ public int getLayoutDirection();
+ public android.os.LocaleList getLocales();
+ public int hashCode();
+ public boolean isLayoutSizeAtLeast(int);
+ public boolean isOtherSeqNewer(android.content.res.Configuration);
+ public boolean isScreenHdr();
+ public boolean isScreenRound();
+ public boolean isScreenWideColorGamut();
+ public static java.lang.String localesToResourceQualifier(android.os.LocaleList);
+ public void makeDefault();
+ public static boolean needNewResources(int, int);
+ public void readFromParcel(android.os.Parcel);
+ public static void readXmlAttrs(org.xmlpull.v1.XmlPullParser, android.content.res.Configuration);
+ public static int reduceScreenLayout(int, int, int);
+ public static int resetScreenLayout(int);
+ public static java.lang.String resourceQualifierString(android.content.res.Configuration);
+ public static java.lang.String resourceQualifierString(android.content.res.Configuration, android.util.DisplayMetrics);
+ public void setLayoutDirection(java.util.Locale);
+ public void setLocale(java.util.Locale);
+ public void setLocales(android.os.LocaleList);
+ public void setTo(android.content.res.Configuration);
+ public void setToDefaults();
+ public java.lang.String toString();
+ public static java.lang.String uiModeToString(int);
+ public void unset();
+ public int updateFrom(android.content.res.Configuration);
+ public void writeResConfigToProto(android.util.proto.ProtoOutputStream, long, android.util.DisplayMetrics);
+ public void writeToParcel(android.os.Parcel, int);
+ public void writeToProto(android.util.proto.ProtoOutputStream, long);
+ public static void writeXmlAttrs(org.xmlpull.v1.XmlSerializer, android.content.res.Configuration);
+
+
+ public static int ASSETS_SEQ_UNDEFINED;
+ public static int COLOR_MODE_HDR_MASK;
+ public static int COLOR_MODE_HDR_NO;
+ public static int COLOR_MODE_HDR_SHIFT;
+ public static int COLOR_MODE_HDR_UNDEFINED;
+ public static int COLOR_MODE_HDR_YES;
+ public static int COLOR_MODE_UNDEFINED;
+ public static int COLOR_MODE_WIDE_COLOR_GAMUT_MASK;
+ public static int COLOR_MODE_WIDE_COLOR_GAMUT_NO;
+ public static int COLOR_MODE_WIDE_COLOR_GAMUT_UNDEFINED;
+ public static int COLOR_MODE_WIDE_COLOR_GAMUT_YES;
+ public static android.os.Parcelable$Creator CREATOR;
+ public static int DENSITY_DPI_ANY;
+ public static int DENSITY_DPI_NONE;
public static int DENSITY_DPI_UNDEFINED;
+ public static android.content.res.Configuration EMPTY;
public static int HARDKEYBOARDHIDDEN_NO;
public static int HARDKEYBOARDHIDDEN_UNDEFINED;
public static int HARDKEYBOARDHIDDEN_YES;
public static int KEYBOARDHIDDEN_NO;
+ public static int KEYBOARDHIDDEN_SOFT;
public static int KEYBOARDHIDDEN_UNDEFINED;
public static int KEYBOARDHIDDEN_YES;
public static int KEYBOARD_12KEY;
@@ -2187,6 +9802,22 @@
public static int KEYBOARD_QWERTY;
public static int KEYBOARD_UNDEFINED;
public static int MNC_ZERO;
+ public static int NATIVE_CONFIG_COLOR_MODE;
+ public static int NATIVE_CONFIG_DENSITY;
+ public static int NATIVE_CONFIG_KEYBOARD;
+ public static int NATIVE_CONFIG_KEYBOARD_HIDDEN;
+ public static int NATIVE_CONFIG_LAYOUTDIR;
+ public static int NATIVE_CONFIG_LOCALE;
+ public static int NATIVE_CONFIG_MCC;
+ public static int NATIVE_CONFIG_MNC;
+ public static int NATIVE_CONFIG_NAVIGATION;
+ public static int NATIVE_CONFIG_ORIENTATION;
+ public static int NATIVE_CONFIG_SCREEN_LAYOUT;
+ public static int NATIVE_CONFIG_SCREEN_SIZE;
+ public static int NATIVE_CONFIG_SMALLEST_SCREEN_SIZE;
+ public static int NATIVE_CONFIG_TOUCHSCREEN;
+ public static int NATIVE_CONFIG_UI_MODE;
+ public static int NATIVE_CONFIG_VERSION;
public static int NAVIGATIONHIDDEN_NO;
public static int NAVIGATIONHIDDEN_UNDEFINED;
public static int NAVIGATIONHIDDEN_YES;
@@ -2199,6 +9830,7 @@
public static int ORIENTATION_PORTRAIT;
public static int ORIENTATION_SQUARE;
public static int ORIENTATION_UNDEFINED;
+ public static int SCREENLAYOUT_COMPAT_NEEDED;
public static int SCREENLAYOUT_LAYOUTDIR_LTR;
public static int SCREENLAYOUT_LAYOUTDIR_MASK;
public static int SCREENLAYOUT_LAYOUTDIR_RTL;
@@ -2210,6 +9842,7 @@
public static int SCREENLAYOUT_LONG_YES;
public static int SCREENLAYOUT_ROUND_MASK;
public static int SCREENLAYOUT_ROUND_NO;
+ public static int SCREENLAYOUT_ROUND_SHIFT;
public static int SCREENLAYOUT_ROUND_UNDEFINED;
public static int SCREENLAYOUT_ROUND_YES;
public static int SCREENLAYOUT_SIZE_LARGE;
@@ -2237,7 +9870,13 @@
public static int UI_MODE_TYPE_NORMAL;
public static int UI_MODE_TYPE_TELEVISION;
public static int UI_MODE_TYPE_UNDEFINED;
+ public static int UI_MODE_TYPE_VR_HEADSET;
public static int UI_MODE_TYPE_WATCH;
+ public int assetsSeq;
+ public int colorMode;
+ public int compatScreenHeightDp;
+ public int compatScreenWidthDp;
+ public int compatSmallestScreenWidthDp;
public int densityDpi;
public float fontScale;
public int hardKeyboardHidden;
@@ -2252,38 +9891,88 @@
public int screenHeightDp;
public int screenLayout;
public int screenWidthDp;
+ public int seq;
public int smallestScreenWidthDp;
public int touchscreen;
public int uiMode;
+ public boolean userSetLocale;
+ public android.app.WindowConfiguration windowConfiguration;
+}
+
+-keep class android.content.res.ConfigurationBoundResourceCache {
+ <init>();
+
+ public java.lang.Object getInstance(long, android.content.res.Resources, android.content.res.Resources$Theme);
+ public void onConfigurationChange(int);
+ public boolean shouldInvalidateEntry(android.content.res.ConstantState, int);
+ public boolean shouldInvalidateEntry(java.lang.Object, int);
+
+
+}
+
+-keep class android.content.res.ConstantState {
+ <init>();
+
+ public abstract int getChangingConfigurations();
+ public abstract java.lang.Object newInstance();
+ public java.lang.Object newInstance(android.content.res.Resources);
+ public java.lang.Object newInstance(android.content.res.Resources, android.content.res.Resources$Theme);
+
+
+}
+
+-keep class android.content.res.FontResourcesParser {
+ <init>();
+
+ public static android.content.res.FontResourcesParser$FamilyResourceEntry parse(org.xmlpull.v1.XmlPullParser, android.content.res.Resources);
+
+
+}
+
+-keep class android.content.res.FontResourcesParser$FamilyResourceEntry {
+
+
+
}
-keep class android.content.res.Resources {
<init>(android.content.res.AssetManager, android.util.DisplayMetrics, android.content.res.Configuration);
+ <init>(java.lang.ClassLoader);
+ public int calcConfigChanges(android.content.res.Configuration);
public void finishPreloading();
public void flushLayoutCache();
public android.content.res.XmlResourceParser getAnimation(int);
+ public android.content.res.ConfigurationBoundResourceCache getAnimatorCache();
public android.content.res.AssetManager getAssets();
public boolean getBoolean(int);
+ public java.lang.ClassLoader getClassLoader();
public int getColor(int);
public int getColor(int, android.content.res.Resources$Theme);
public android.content.res.ColorStateList getColorStateList(int);
public android.content.res.ColorStateList getColorStateList(int, android.content.res.Resources$Theme);
+ public android.content.res.CompatibilityInfo getCompatibilityInfo();
public android.content.res.Configuration getConfiguration();
public float getDimension(int);
public int getDimensionPixelOffset(int);
public int getDimensionPixelSize(int);
+ public android.view.DisplayAdjustments getDisplayAdjustments();
public android.util.DisplayMetrics getDisplayMetrics();
public android.graphics.drawable.Drawable getDrawable(int);
public android.graphics.drawable.Drawable getDrawable(int, android.content.res.Resources$Theme);
public android.graphics.drawable.Drawable getDrawableForDensity(int, int);
public android.graphics.drawable.Drawable getDrawableForDensity(int, int, android.content.res.Resources$Theme);
+ public android.graphics.drawable.DrawableInflater getDrawableInflater();
+ public float getFloat(int);
+ public android.graphics.Typeface getFont(int);
public float getFraction(int, int, int);
public int getIdentifier(java.lang.String, java.lang.String, java.lang.String);
+ public android.content.res.ResourcesImpl getImpl();
public int[] getIntArray(int);
public int getInteger(int);
public android.content.res.XmlResourceParser getLayout(int);
public android.graphics.Movie getMovie(int);
+ public android.util.LongSparseArray getPreloadedDrawables();
public java.lang.String getQuantityString(int, int, java.lang.Object[]);
public java.lang.String getQuantityString(int, int);
public java.lang.CharSequence getQuantityText(int, int);
@@ -2291,6 +9980,8 @@
public java.lang.String getResourceName(int);
public java.lang.String getResourcePackageName(int);
public java.lang.String getResourceTypeName(int);
+ public android.content.res.Configuration[] getSizeConfigurations();
+ public android.content.res.ConfigurationBoundResourceCache getStateListAnimatorCache();
public java.lang.String getString(int);
public java.lang.String getString(int, java.lang.Object[]);
public java.lang.String[] getStringArray(int);
@@ -2302,15 +9993,26 @@
public void getValue(java.lang.String, android.util.TypedValue, boolean);
public void getValueForDensity(int, int, android.util.TypedValue, boolean);
public android.content.res.XmlResourceParser getXml(int);
+ public android.content.res.ComplexColor loadComplexColor(android.util.TypedValue, int, android.content.res.Resources$Theme);
public android.content.res.Resources$Theme newTheme();
public android.content.res.TypedArray obtainAttributes(android.util.AttributeSet, int[]);
+ public static android.content.res.TypedArray obtainAttributes(android.content.res.Resources, android.content.res.Resources$Theme, android.util.AttributeSet, int[]);
public android.content.res.TypedArray obtainTypedArray(int);
public java.io.InputStream openRawResource(int);
public java.io.InputStream openRawResource(int, android.util.TypedValue);
public android.content.res.AssetFileDescriptor openRawResourceFd(int);
public void parseBundleExtra(java.lang.String, android.util.AttributeSet, android.os.Bundle);
public void parseBundleExtras(android.content.res.XmlResourceParser, android.os.Bundle);
+ public void preloadFonts(int);
+ public static boolean resourceHasPackage(int);
+ public static int selectDefaultTheme(int, int);
+ public static int selectSystemTheme(int, int, int, int, int, int);
+ public void setCompatibilityInfo(android.content.res.CompatibilityInfo);
+ public void setImpl(android.content.res.ResourcesImpl);
+ public void startPreloading();
public void updateConfiguration(android.content.res.Configuration, android.util.DisplayMetrics);
+ public void updateConfiguration(android.content.res.Configuration, android.util.DisplayMetrics, android.content.res.CompatibilityInfo);
+ public static void updateSystemConfiguration(android.content.res.Configuration, android.util.DisplayMetrics, android.content.res.CompatibilityInfo);
}
@@ -2318,6 +10020,7 @@
-keep class android.content.res.Resources$NotFoundException {
<init>();
<init>(java.lang.String);
+ <init>(java.lang.String, java.lang.Exception);
@@ -2327,30 +10030,79 @@
public void applyStyle(int, boolean);
public void dump(int, java.lang.String, java.lang.String);
- protected void finalize();
+ public void encode(android.view.ViewHierarchyEncoder);
+ public int[] getAllAttributes();
public int getChangingConfigurations();
public android.graphics.drawable.Drawable getDrawable(int);
+ public android.content.res.Resources$ThemeKey getKey();
public android.content.res.Resources getResources();
+ public java.lang.String[] getTheme();
public android.content.res.TypedArray obtainStyledAttributes(int[]);
public android.content.res.TypedArray obtainStyledAttributes(int, int[]);
public android.content.res.TypedArray obtainStyledAttributes(android.util.AttributeSet, int[], int, int);
+ public void rebase();
public boolean resolveAttribute(int, android.util.TypedValue, boolean);
+ public android.content.res.TypedArray resolveAttributes(int[], int[]);
public void setTo(android.content.res.Resources$Theme);
}
--keep class android.content.res.TypedArray {
+-keep class android.content.res.Resources$ThemeKey {
+ public void append(int, boolean);
+ public android.content.res.Resources$ThemeKey clone();
+ public java.lang.Object clone();
+ public boolean equals(java.lang.Object);
+ public int hashCode();
+ public void setTo(android.content.res.Resources$ThemeKey);
+
+
+}
+
+-keep class android.content.res.ResourcesImpl {
+ <init>(android.content.res.AssetManager, android.util.DisplayMetrics, android.content.res.Configuration, android.view.DisplayAdjustments);
+
+ public int calcConfigChanges(android.content.res.Configuration);
+ public void flushLayoutCache();
+ public android.content.res.AssetManager getAssets();
+ public android.view.DisplayAdjustments getDisplayAdjustments();
+ public android.graphics.Typeface loadFont(android.content.res.Resources, android.util.TypedValue, int);
+ public void startPreloading();
+ public void updateConfiguration(android.content.res.Configuration, android.util.DisplayMetrics, android.content.res.CompatibilityInfo);
+
+
+ public static boolean TRACE_FOR_DETAILED_PRELOAD;
+}
+
+-keep class android.content.res.ThemedResourceCache {
+
+ public java.lang.Object get(long, android.content.res.Resources$Theme);
+ public void onConfigurationChange(int);
+ public void put(long, android.content.res.Resources$Theme, java.lang.Object);
+ public void put(long, android.content.res.Resources$Theme, java.lang.Object, boolean);
+ protected abstract boolean shouldInvalidateEntry(java.lang.Object, int);
+
+
+}
+
+-keep class android.content.res.TypedArray {
+ <init>(android.content.res.Resources);
+
+ public int[] extractThemeAttrs();
+ public int[] extractThemeAttrs(int[]);
public boolean getBoolean(int, boolean);
public int getChangingConfigurations();
public int getColor(int, int);
public android.content.res.ColorStateList getColorStateList(int);
+ public android.content.res.ComplexColor getComplexColor(int);
public float getDimension(int, float);
public int getDimensionPixelOffset(int, int);
public int getDimensionPixelSize(int, int);
public android.graphics.drawable.Drawable getDrawable(int);
+ public android.graphics.drawable.Drawable getDrawableForDensity(int, int);
public float getFloat(int, float);
+ public android.graphics.Typeface getFont(int);
public float getFraction(int, int, int, float);
public int getIndex(int);
public int getIndexCount();
@@ -2358,6 +10110,7 @@
public int getInteger(int, int);
public int getLayoutDimension(int, java.lang.String);
public int getLayoutDimension(int, int);
+ public java.lang.String getNonConfigurationString(int, int);
public java.lang.String getNonResourceString(int);
public java.lang.String getPositionDescription();
public int getResourceId(int, int);
@@ -2365,6 +10118,7 @@
public java.lang.String getString(int);
public java.lang.CharSequence getText(int);
public java.lang.CharSequence[] getTextArray(int);
+ public int getThemeAttributeId(int, int);
public int getType(int);
public boolean getValue(int, android.util.TypedValue);
public boolean hasValue(int);
@@ -2380,6 +10134,7 @@
-keep class android.content.res.XmlResourceParser {
public abstract void close();
+ public abstract java.lang.String getAttributeNamespace(int);
}
@@ -2400,8 +10155,11 @@
public boolean deliverSelfNotifications();
public void dispatchChange(boolean);
public void dispatchChange(boolean, android.net.Uri);
+ public android.database.IContentObserver getContentObserver();
public void onChange(boolean);
public void onChange(boolean, android.net.Uri);
+ public void onChange(boolean, android.net.Uri, int);
+ public android.database.IContentObserver releaseContentObserver();
}
@@ -2458,6 +10216,50 @@
public static int FIELD_TYPE_STRING;
}
+-keep class android.database.CursorWindow {
+ <init>(java.lang.String);
+ <init>(java.lang.String, long);
+ <init>(boolean);
+
+ public boolean allocRow();
+ public void clear();
+ public void copyStringToBuffer(int, int, android.database.CharArrayBuffer);
+ public int describeContents();
+ protected void finalize();
+ public void freeLastRow();
+ public byte[] getBlob(int, int);
+ public double getDouble(int, int);
+ public float getFloat(int, int);
+ public int getInt(int, int);
+ public long getLong(int, int);
+ public java.lang.String getName();
+ public int getNumRows();
+ public short getShort(int, int);
+ public int getStartPosition();
+ public java.lang.String getString(int, int);
+ public int getType(int, int);
+ public boolean isBlob(int, int);
+ public boolean isFloat(int, int);
+ public boolean isLong(int, int);
+ public boolean isNull(int, int);
+ public boolean isString(int, int);
+ public static android.database.CursorWindow newFromParcel(android.os.Parcel);
+ protected void onAllReferencesReleased();
+ public boolean putBlob(byte[], int, int);
+ public boolean putDouble(double, int, int);
+ public boolean putLong(long, int, int);
+ public boolean putNull(int, int);
+ public boolean putString(java.lang.String, int, int);
+ public boolean setNumColumns(int);
+ public void setStartPosition(int);
+ public java.lang.String toString();
+ public void writeToParcel(android.os.Parcel, int);
+
+
+ public static android.os.Parcelable$Creator CREATOR;
+ public long mWindowPtr;
+}
+
-keep class android.database.DataSetObserver {
<init>();
@@ -2474,6 +10276,13 @@
}
+-keep class android.database.IContentObserver {
+
+ public abstract void onChange(boolean, android.net.Uri, int);
+
+
+}
+
-keep class android.database.SQLException {
<init>();
<init>(java.lang.String);
@@ -2496,6 +10305,46 @@
}
+-keep class android.database.sqlite.SQLiteConnection {
+
+ public void dump(android.util.Printer, boolean);
+ public void execute(java.lang.String, java.lang.Object[], android.os.CancellationSignal);
+ public android.os.ParcelFileDescriptor executeForBlobFileDescriptor(java.lang.String, java.lang.Object[], android.os.CancellationSignal);
+ public int executeForChangedRowCount(java.lang.String, java.lang.Object[], android.os.CancellationSignal);
+ public int executeForCursorWindow(java.lang.String, java.lang.Object[], android.database.CursorWindow, int, int, boolean, android.os.CancellationSignal);
+ public long executeForLastInsertedRowId(java.lang.String, java.lang.Object[], android.os.CancellationSignal);
+ public long executeForLong(java.lang.String, java.lang.Object[], android.os.CancellationSignal);
+ public java.lang.String executeForString(java.lang.String, java.lang.Object[], android.os.CancellationSignal);
+ protected void finalize();
+ public int getConnectionId();
+ public boolean isPrimaryConnection();
+ public void onCancel();
+ public void prepare(java.lang.String, android.database.sqlite.SQLiteStatementInfo);
+ public java.lang.String toString();
+
+
+}
+
+-keep class android.database.sqlite.SQLiteConnectionPool {
+
+ public android.database.sqlite.SQLiteConnection acquireConnection(java.lang.String, int, android.os.CancellationSignal);
+ public void close();
+ public void collectDbStats(java.util.ArrayList);
+ public void dump(android.util.Printer, boolean);
+ protected void finalize();
+ public static android.database.sqlite.SQLiteConnectionPool open(android.database.sqlite.SQLiteDatabaseConfiguration);
+ public void reconfigure(android.database.sqlite.SQLiteDatabaseConfiguration);
+ public void releaseConnection(android.database.sqlite.SQLiteConnection);
+ public void setupIdleConnectionHandler(android.os.Looper, long);
+ public boolean shouldYieldConnection(android.database.sqlite.SQLiteConnection, int);
+ public java.lang.String toString();
+
+
+ public static int CONNECTION_FLAG_INTERACTIVE;
+ public static int CONNECTION_FLAG_PRIMARY_CONNECTION_AFFINITY;
+ public static int CONNECTION_FLAG_READ_ONLY;
+}
+
-keep class android.database.sqlite.SQLiteCursorDriver {
public abstract void cursorClosed();
@@ -2507,14 +10356,26 @@
}
+-keep class android.database.sqlite.SQLiteCustomFunction {
+ <init>(java.lang.String, int, android.database.sqlite.SQLiteDatabase$CustomFunction);
+
+
+
+ public android.database.sqlite.SQLiteDatabase$CustomFunction callback;
+ public java.lang.String name;
+ public int numArgs;
+}
+
-keep class android.database.sqlite.SQLiteDatabase {
+ public void addCustomFunction(java.lang.String, int, android.database.sqlite.SQLiteDatabase$CustomFunction);
public void beginTransaction();
public void beginTransactionNonExclusive();
public void beginTransactionWithListener(android.database.sqlite.SQLiteTransactionListener);
public void beginTransactionWithListenerNonExclusive(android.database.sqlite.SQLiteTransactionListener);
public android.database.sqlite.SQLiteStatement compileStatement(java.lang.String);
public static android.database.sqlite.SQLiteDatabase create(android.database.sqlite.SQLiteDatabase$CursorFactory);
+ public static android.database.sqlite.SQLiteDatabase createInMemory(android.database.sqlite.SQLiteDatabase$OpenParams);
public int delete(java.lang.String, java.lang.String, java.lang.String[]);
public static boolean deleteDatabase(java.io.File);
public void disableWriteAheadLogging();
@@ -2537,6 +10398,7 @@
public boolean isDatabaseIntegrityOk();
public boolean isDbLockedByCurrentThread();
public boolean isDbLockedByOtherThreads();
+ public boolean isInMemoryDatabase();
public boolean isOpen();
public boolean isReadOnly();
public boolean isWriteAheadLoggingEnabled();
@@ -2545,6 +10407,7 @@
public boolean needUpgrade(int);
protected void onAllReferencesReleased();
public static android.database.sqlite.SQLiteDatabase openDatabase(java.lang.String, android.database.sqlite.SQLiteDatabase$CursorFactory, int);
+ public static android.database.sqlite.SQLiteDatabase openDatabase(java.io.File, android.database.sqlite.SQLiteDatabase$OpenParams);
public static android.database.sqlite.SQLiteDatabase openDatabase(java.lang.String, android.database.sqlite.SQLiteDatabase$CursorFactory, int, android.database.DatabaseErrorHandler);
public static android.database.sqlite.SQLiteDatabase openOrCreateDatabase(java.io.File, android.database.sqlite.SQLiteDatabase$CursorFactory);
public static android.database.sqlite.SQLiteDatabase openOrCreateDatabase(java.lang.String, android.database.sqlite.SQLiteDatabase$CursorFactory);
@@ -2560,6 +10423,7 @@
public android.database.Cursor rawQueryWithFactory(android.database.sqlite.SQLiteDatabase$CursorFactory, java.lang.String, java.lang.String[], java.lang.String);
public android.database.Cursor rawQueryWithFactory(android.database.sqlite.SQLiteDatabase$CursorFactory, java.lang.String, java.lang.String[], java.lang.String, android.os.CancellationSignal);
public static int releaseMemory();
+ public void reopenReadWrite();
public long replace(java.lang.String, java.lang.String, android.content.ContentValues);
public long replaceOrThrow(java.lang.String, java.lang.String, android.content.ContentValues);
public void setForeignKeyConstraintsEnabled(boolean);
@@ -2573,6 +10437,7 @@
public java.lang.String toString();
public int update(java.lang.String, android.content.ContentValues, java.lang.String, java.lang.String[]);
public int updateWithOnConflict(java.lang.String, android.content.ContentValues, java.lang.String, java.lang.String[], int);
+ public void validateSql(java.lang.String, android.os.CancellationSignal);
public boolean yieldIfContended();
public boolean yieldIfContendedSafely();
public boolean yieldIfContendedSafely(long);
@@ -2585,6 +10450,7 @@
public static int CONFLICT_REPLACE;
public static int CONFLICT_ROLLBACK;
public static int CREATE_IF_NECESSARY;
+ public static int DISABLE_COMPATIBILITY_WAL;
public static int ENABLE_WRITE_AHEAD_LOGGING;
public static int MAX_SQL_CACHE_SIZE;
public static int NO_LOCALIZED_COLLATORS;
@@ -2600,6 +10466,107 @@
}
+-keep class android.database.sqlite.SQLiteDatabase$CustomFunction {
+
+ public abstract void callback(java.lang.String[]);
+
+
+}
+
+-keep class android.database.sqlite.SQLiteDatabase$OpenParams {
+
+ public android.database.sqlite.SQLiteDatabase$CursorFactory getCursorFactory();
+ public android.database.DatabaseErrorHandler getErrorHandler();
+ public long getIdleConnectionTimeout();
+ public java.lang.String getJournalMode();
+ public int getLookasideSlotCount();
+ public int getLookasideSlotSize();
+ public int getOpenFlags();
+ public java.lang.String getSynchronousMode();
+ public android.database.sqlite.SQLiteDatabase$OpenParams$Builder toBuilder();
+
+
+}
+
+-keep class android.database.sqlite.SQLiteDatabase$OpenParams$Builder {
+ <init>();
+ <init>(android.database.sqlite.SQLiteDatabase$OpenParams);
+
+ public android.database.sqlite.SQLiteDatabase$OpenParams$Builder addOpenFlags(int);
+ public android.database.sqlite.SQLiteDatabase$OpenParams build();
+ public boolean isWriteAheadLoggingEnabled();
+ public android.database.sqlite.SQLiteDatabase$OpenParams$Builder removeOpenFlags(int);
+ public android.database.sqlite.SQLiteDatabase$OpenParams$Builder setCursorFactory(android.database.sqlite.SQLiteDatabase$CursorFactory);
+ public android.database.sqlite.SQLiteDatabase$OpenParams$Builder setErrorHandler(android.database.DatabaseErrorHandler);
+ public android.database.sqlite.SQLiteDatabase$OpenParams$Builder setIdleConnectionTimeout(long);
+ public android.database.sqlite.SQLiteDatabase$OpenParams$Builder setJournalMode(java.lang.String);
+ public android.database.sqlite.SQLiteDatabase$OpenParams$Builder setLookasideConfig(int, int);
+ public android.database.sqlite.SQLiteDatabase$OpenParams$Builder setOpenFlags(int);
+ public android.database.sqlite.SQLiteDatabase$OpenParams$Builder setSynchronousMode(java.lang.String);
+ public void setWriteAheadLoggingEnabled(boolean);
+
+
+}
+
+-keep class android.database.sqlite.SQLiteDatabaseConfiguration {
+ <init>(java.lang.String, int);
+ <init>(android.database.sqlite.SQLiteDatabaseConfiguration);
+
+ public boolean isInMemoryDb();
+ public void updateParametersFrom(android.database.sqlite.SQLiteDatabaseConfiguration);
+
+
+ public static java.lang.String MEMORY_DB_PATH;
+ public java.util.ArrayList customFunctions;
+ public boolean foreignKeyConstraintsEnabled;
+ public long idleConnectionTimeoutMs;
+ public java.lang.String journalMode;
+ public java.lang.String label;
+ public java.util.Locale locale;
+ public int lookasideSlotCount;
+ public int lookasideSlotSize;
+ public int maxSqlCacheSize;
+ public int openFlags;
+ public java.lang.String path;
+ public java.lang.String syncMode;
+}
+
+-keep class android.database.sqlite.SQLiteDebug {
+
+ public static void dump(android.util.Printer, java.lang.String[]);
+ public static android.database.sqlite.SQLiteDebug$PagerStats getDatabaseInfo();
+ public static boolean shouldLogSlowQuery(long);
+
+
+ public static boolean DEBUG_LOG_SLOW_QUERIES;
+ public static boolean DEBUG_SQL_LOG;
+ public static boolean DEBUG_SQL_STATEMENTS;
+ public static boolean DEBUG_SQL_TIME;
+}
+
+-keep class android.database.sqlite.SQLiteDebug$DbStats {
+ <init>(java.lang.String, long, long, int, int, int, int);
+
+
+
+ public java.lang.String cache;
+ public java.lang.String dbName;
+ public long dbSize;
+ public int lookaside;
+ public long pageSize;
+}
+
+-keep class android.database.sqlite.SQLiteDebug$PagerStats {
+ <init>();
+
+
+
+ public java.util.ArrayList dbStats;
+ public int largestMemAlloc;
+ public int memoryUsed;
+ public int pageCacheOverflow;
+}
+
-keep class android.database.sqlite.SQLiteProgram {
public void bindAllArgsAsStrings(java.lang.String[]);
@@ -2609,8 +10576,11 @@
public void bindNull(int);
public void bindString(int, java.lang.String);
public void clearBindings();
+ protected int getConnectionFlags();
+ protected android.database.sqlite.SQLiteSession getSession();
public int getUniqueId();
protected void onAllReferencesReleased();
+ protected void onCorruption();
}
@@ -2622,6 +10592,31 @@
}
+-keep class android.database.sqlite.SQLiteSession {
+ <init>(android.database.sqlite.SQLiteConnectionPool);
+
+ public void beginTransaction(int, android.database.sqlite.SQLiteTransactionListener, int, android.os.CancellationSignal);
+ public void endTransaction(android.os.CancellationSignal);
+ public void execute(java.lang.String, java.lang.Object[], int, android.os.CancellationSignal);
+ public android.os.ParcelFileDescriptor executeForBlobFileDescriptor(java.lang.String, java.lang.Object[], int, android.os.CancellationSignal);
+ public int executeForChangedRowCount(java.lang.String, java.lang.Object[], int, android.os.CancellationSignal);
+ public int executeForCursorWindow(java.lang.String, java.lang.Object[], android.database.CursorWindow, int, int, boolean, int, android.os.CancellationSignal);
+ public long executeForLastInsertedRowId(java.lang.String, java.lang.Object[], int, android.os.CancellationSignal);
+ public long executeForLong(java.lang.String, java.lang.Object[], int, android.os.CancellationSignal);
+ public java.lang.String executeForString(java.lang.String, java.lang.Object[], int, android.os.CancellationSignal);
+ public boolean hasConnection();
+ public boolean hasNestedTransaction();
+ public boolean hasTransaction();
+ public void prepare(java.lang.String, int, android.os.CancellationSignal, android.database.sqlite.SQLiteStatementInfo);
+ public void setTransactionSuccessful();
+ public boolean yieldTransaction(long, boolean, android.os.CancellationSignal);
+
+
+ public static int TRANSACTION_MODE_DEFERRED;
+ public static int TRANSACTION_MODE_EXCLUSIVE;
+ public static int TRANSACTION_MODE_IMMEDIATE;
+}
+
-keep class android.database.sqlite.SQLiteStatement {
public void execute();
@@ -2635,6 +10630,16 @@
}
+-keep class android.database.sqlite.SQLiteStatementInfo {
+ <init>();
+
+
+
+ public java.lang.String[] columnNames;
+ public int numParameters;
+ public boolean readOnly;
+}
+
-keep class android.database.sqlite.SQLiteTransactionListener {
public abstract void onBegin();
@@ -2644,21 +10649,89 @@
}
+-keep class android.graphics.BaseCanvas {
+ <init>();
+
+ protected static void checkRange(int, int, int);
+ public void drawARGB(int, int, int, int);
+ public void drawArc(float, float, float, float, float, float, boolean, android.graphics.Paint);
+ public void drawArc(android.graphics.RectF, float, float, boolean, android.graphics.Paint);
+ public void drawBitmap(android.graphics.Bitmap, float, float, android.graphics.Paint);
+ public void drawBitmap(android.graphics.Bitmap, android.graphics.Matrix, android.graphics.Paint);
+ public void drawBitmap(android.graphics.Bitmap, android.graphics.Rect, android.graphics.Rect, android.graphics.Paint);
+ public void drawBitmap(android.graphics.Bitmap, android.graphics.Rect, android.graphics.RectF, android.graphics.Paint);
+ public void drawBitmap(int[], int, int, float, float, int, int, boolean, android.graphics.Paint);
+ public void drawBitmap(int[], int, int, int, int, int, int, boolean, android.graphics.Paint);
+ public void drawBitmapMesh(android.graphics.Bitmap, int, int, float[], int, int[], int, android.graphics.Paint);
+ public void drawCircle(float, float, float, android.graphics.Paint);
+ public void drawColor(int);
+ public void drawColor(int, android.graphics.PorterDuff$Mode);
+ public void drawLine(float, float, float, float, android.graphics.Paint);
+ public void drawLines(float[], int, int, android.graphics.Paint);
+ public void drawLines(float[], android.graphics.Paint);
+ public void drawOval(float, float, float, float, android.graphics.Paint);
+ public void drawOval(android.graphics.RectF, android.graphics.Paint);
+ public void drawPaint(android.graphics.Paint);
+ public void drawPatch(android.graphics.NinePatch, android.graphics.Rect, android.graphics.Paint);
+ public void drawPatch(android.graphics.NinePatch, android.graphics.RectF, android.graphics.Paint);
+ public void drawPath(android.graphics.Path, android.graphics.Paint);
+ public void drawPoint(float, float, android.graphics.Paint);
+ public void drawPoints(float[], int, int, android.graphics.Paint);
+ public void drawPoints(float[], android.graphics.Paint);
+ public void drawPosText(char[], int, int, float[], android.graphics.Paint);
+ public void drawPosText(java.lang.String, float[], android.graphics.Paint);
+ public void drawRGB(int, int, int);
+ public void drawRect(float, float, float, float, android.graphics.Paint);
+ public void drawRect(android.graphics.Rect, android.graphics.Paint);
+ public void drawRect(android.graphics.RectF, android.graphics.Paint);
+ public void drawRoundRect(float, float, float, float, float, float, android.graphics.Paint);
+ public void drawRoundRect(android.graphics.RectF, float, float, android.graphics.Paint);
+ public void drawText(char[], int, int, float, float, android.graphics.Paint);
+ public void drawText(java.lang.CharSequence, int, int, float, float, android.graphics.Paint);
+ public void drawText(java.lang.String, float, float, android.graphics.Paint);
+ public void drawText(java.lang.String, int, int, float, float, android.graphics.Paint);
+ public void drawTextOnPath(char[], int, int, android.graphics.Path, float, float, android.graphics.Paint);
+ public void drawTextOnPath(java.lang.String, android.graphics.Path, float, float, android.graphics.Paint);
+ public void drawTextRun(char[], int, int, int, int, float, float, boolean, android.graphics.Paint);
+ public void drawTextRun(java.lang.CharSequence, int, int, int, int, float, float, boolean, android.graphics.Paint);
+ public void drawVertices(android.graphics.Canvas$VertexMode, int, float[], int, float[], int, int[], int, short[], int, int, android.graphics.Paint);
+ public boolean isHardwareAccelerated();
+ public boolean isHwBitmapsInSwModeEnabled();
+ protected void onHwBitmapInSwMode();
+ public void setHwBitmapsInSwModeEnabled(boolean);
+ protected void throwIfCannotDraw(android.graphics.Bitmap);
+
+
+ protected int mDensity;
+ protected long mNativeCanvasWrapper;
+ protected int mScreenDensity;
+}
+
-keep class android.graphics.Bitmap {
public boolean compress(android.graphics.Bitmap$CompressFormat, int, java.io.OutputStream);
public android.graphics.Bitmap copy(android.graphics.Bitmap$Config, boolean);
public void copyPixelsFromBuffer(java.nio.Buffer);
public void copyPixelsToBuffer(java.nio.Buffer);
+ public android.graphics.Bitmap createAshmemBitmap();
+ public android.graphics.Bitmap createAshmemBitmap(android.graphics.Bitmap$Config);
public static android.graphics.Bitmap createBitmap(android.graphics.Bitmap);
public static android.graphics.Bitmap createBitmap(android.graphics.Bitmap, int, int, int, int);
public static android.graphics.Bitmap createBitmap(android.graphics.Bitmap, int, int, int, int, android.graphics.Matrix, boolean);
public static android.graphics.Bitmap createBitmap(int, int, android.graphics.Bitmap$Config);
public static android.graphics.Bitmap createBitmap(android.util.DisplayMetrics, int, int, android.graphics.Bitmap$Config);
+ public static android.graphics.Bitmap createBitmap(int, int, android.graphics.Bitmap$Config, boolean);
+ public static android.graphics.Bitmap createBitmap(int, int, android.graphics.Bitmap$Config, boolean, android.graphics.ColorSpace);
+ public static android.graphics.Bitmap createBitmap(android.util.DisplayMetrics, int, int, android.graphics.Bitmap$Config, boolean);
+ public static android.graphics.Bitmap createBitmap(android.util.DisplayMetrics, int, int, android.graphics.Bitmap$Config, boolean, android.graphics.ColorSpace);
public static android.graphics.Bitmap createBitmap(int[], int, int, int, int, android.graphics.Bitmap$Config);
public static android.graphics.Bitmap createBitmap(android.util.DisplayMetrics, int[], int, int, int, int, android.graphics.Bitmap$Config);
public static android.graphics.Bitmap createBitmap(int[], int, int, android.graphics.Bitmap$Config);
public static android.graphics.Bitmap createBitmap(android.util.DisplayMetrics, int[], int, int, android.graphics.Bitmap$Config);
+ public static android.graphics.Bitmap createBitmap(android.graphics.Picture);
+ public static android.graphics.Bitmap createBitmap(android.graphics.Picture, int, int, android.graphics.Bitmap$Config);
+ public android.graphics.GraphicBuffer createGraphicBufferHandle();
+ public static android.graphics.Bitmap createHardwareBitmap(android.graphics.GraphicBuffer);
public static android.graphics.Bitmap createScaledBitmap(android.graphics.Bitmap, int, int, boolean);
public int describeContents();
public void eraseColor(int);
@@ -2666,11 +10739,15 @@
public android.graphics.Bitmap extractAlpha(android.graphics.Paint, int[]);
public int getAllocationByteCount();
public int getByteCount();
+ public android.graphics.ColorSpace getColorSpace();
public android.graphics.Bitmap$Config getConfig();
public int getDensity();
public int getGenerationId();
public int getHeight();
+ public long getNativeInstance();
public byte[] getNinePatchChunk();
+ public android.graphics.NinePatch$InsetStruct getNinePatchInsets();
+ public void getOpticalInsets(android.graphics.Rect);
public int getPixel(int, int);
public void getPixels(int[], int, int, int, int, int, int);
public int getRowBytes();
@@ -2686,15 +10763,19 @@
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();
public boolean sameAs(android.graphics.Bitmap);
+ public static int scaleFromDensity(int, int, int);
public void setConfig(android.graphics.Bitmap$Config);
+ public static void setDefaultDensity(int);
public void setDensity(int);
public void setHasAlpha(boolean);
public void setHasMipMap(boolean);
public void setHeight(int);
+ public void setNinePatchChunk(byte[]);
public void setPixel(int, int, int);
public void setPixels(int[], int, int, int, int, int, int);
public void setPremultiplied(boolean);
@@ -2704,6 +10785,9 @@
public static android.os.Parcelable$Creator CREATOR;
public static int DENSITY_NONE;
+ public int mDensity;
+ public static volatile int sPreloadTracingNumInstantiatedBitmaps;
+ public static volatile long sPreloadTracingTotalBitmapsSize;
}
-keep class android.graphics.Bitmap$CompressFormat {
@@ -2725,6 +10809,8 @@
public static android.graphics.Bitmap$Config ALPHA_8;
public static android.graphics.Bitmap$Config ARGB_4444;
public static android.graphics.Bitmap$Config ARGB_8888;
+ public static android.graphics.Bitmap$Config HARDWARE;
+ public static android.graphics.Bitmap$Config RGBA_F16;
public static android.graphics.Bitmap$Config RGB_565;
}
@@ -2760,6 +10846,7 @@
public boolean inJustDecodeBounds;
public boolean inMutable;
public boolean inPreferQualityOverSpeed;
+ public android.graphics.ColorSpace inPreferredColorSpace;
public android.graphics.Bitmap$Config inPreferredConfig;
public boolean inPremultiplied;
public boolean inPurgeable;
@@ -2769,6 +10856,8 @@
public int inTargetDensity;
public byte[] inTempStorage;
public boolean mCancel;
+ public android.graphics.ColorSpace outColorSpace;
+ public android.graphics.Bitmap$Config outConfig;
public int outHeight;
public java.lang.String outMimeType;
public int outWidth;
@@ -2777,7 +10866,13 @@
-keep class android.graphics.Canvas {
<init>();
<init>(android.graphics.Bitmap);
+ <init>(long);
+ public boolean clipOutPath(android.graphics.Path);
+ public boolean clipOutRect(android.graphics.RectF);
+ public boolean clipOutRect(android.graphics.Rect);
+ public boolean clipOutRect(float, float, float, float);
+ public boolean clipOutRect(int, int, int, int);
public boolean clipPath(android.graphics.Path, android.graphics.Region$Op);
public boolean clipPath(android.graphics.Path);
public boolean clipRect(android.graphics.RectF, android.graphics.Region$Op);
@@ -2787,6 +10882,7 @@
public boolean clipRect(float, float, float, float, android.graphics.Region$Op);
public boolean clipRect(float, float, float, float);
public boolean clipRect(int, int, int, int);
+ public boolean clipRectUnion(android.graphics.Rect);
public boolean clipRegion(android.graphics.Region, android.graphics.Region$Op);
public boolean clipRegion(android.graphics.Region);
public void concat(android.graphics.Matrix);
@@ -2809,6 +10905,8 @@
public void drawOval(android.graphics.RectF, android.graphics.Paint);
public void drawOval(float, float, float, float, android.graphics.Paint);
public void drawPaint(android.graphics.Paint);
+ public void drawPatch(android.graphics.NinePatch, android.graphics.Rect, android.graphics.Paint);
+ public void drawPatch(android.graphics.NinePatch, android.graphics.RectF, android.graphics.Paint);
public void drawPath(android.graphics.Path, android.graphics.Paint);
public void drawPicture(android.graphics.Picture);
public void drawPicture(android.graphics.Picture, android.graphics.RectF);
@@ -2833,22 +10931,30 @@
public void drawTextRun(char[], int, int, int, int, float, float, boolean, android.graphics.Paint);
public void drawTextRun(java.lang.CharSequence, int, int, int, int, float, float, boolean, android.graphics.Paint);
public void drawVertices(android.graphics.Canvas$VertexMode, int, float[], int, float[], int, int[], int, short[], int, int, android.graphics.Paint);
+ public static void freeCaches();
+ public static void freeTextLayoutCaches();
public boolean getClipBounds(android.graphics.Rect);
public android.graphics.Rect getClipBounds();
public int getDensity();
public android.graphics.DrawFilter getDrawFilter();
+ protected javax.microedition.khronos.opengles.GL getGL();
public int getHeight();
public void getMatrix(android.graphics.Matrix);
public android.graphics.Matrix getMatrix();
public int getMaximumBitmapHeight();
public int getMaximumBitmapWidth();
+ public long getNativeCanvasWrapper();
public int getSaveCount();
public int getWidth();
+ public void insertInorderBarrier();
+ public void insertReorderBarrier();
public boolean isHardwareAccelerated();
public boolean isOpaque();
+ public boolean isRecordingFor(java.lang.Object);
public boolean quickReject(android.graphics.RectF, android.graphics.Canvas$EdgeType);
public boolean quickReject(android.graphics.Path, android.graphics.Canvas$EdgeType);
public boolean quickReject(float, float, float, float, android.graphics.Canvas$EdgeType);
+ public void release();
public void restore();
public void restoreToCount(int);
public void rotate(float);
@@ -2863,12 +10969,15 @@
public int saveLayerAlpha(android.graphics.RectF, int);
public int saveLayerAlpha(float, float, float, float, int, int);
public int saveLayerAlpha(float, float, float, float, int);
+ public int saveUnclippedLayer(int, int, int, int);
public void scale(float, float);
public void scale(float, float, float, float);
public void setBitmap(android.graphics.Bitmap);
+ public static void setCompatibilityVersion(int);
public void setDensity(int);
public void setDrawFilter(android.graphics.DrawFilter);
public void setMatrix(android.graphics.Matrix);
+ public void setScreenDensity(int);
public void skew(float, float);
public void translate(float, float);
@@ -2879,6 +10988,8 @@
public static int FULL_COLOR_LAYER_SAVE_FLAG;
public static int HAS_ALPHA_LAYER_SAVE_FLAG;
public static int MATRIX_SAVE_FLAG;
+ public static boolean sCompatibilityRestore;
+ public static boolean sCompatibilitySetBitmap;
}
-keep class android.graphics.Canvas$EdgeType {
@@ -2889,6 +11000,7 @@
public static android.graphics.Canvas$EdgeType AA;
public static android.graphics.Canvas$EdgeType BW;
+ public int nativeInt;
}
-keep class android.graphics.Canvas$VertexMode {
@@ -2900,22 +11012,277 @@
public static android.graphics.Canvas$VertexMode TRIANGLE_FAN;
public static android.graphics.Canvas$VertexMode TRIANGLE_STRIP;
+ public int nativeInt;
+}
+
+-keep class android.graphics.CanvasProperty {
+
+ public static android.graphics.CanvasProperty createFloat(float);
+ public static android.graphics.CanvasProperty createPaint(android.graphics.Paint);
+ public long getNativeContainer();
+
+
}
-keep class android.graphics.ColorFilter {
<init>();
- protected void finalize();
+ public long getNativeInstance();
}
+-keep class android.graphics.ColorSpace {
+
+ public static android.graphics.ColorSpace adapt(android.graphics.ColorSpace, float[]);
+ public static android.graphics.ColorSpace adapt(android.graphics.ColorSpace, float[], android.graphics.ColorSpace$Adaptation);
+ public static android.graphics.ColorSpace$Connector connect(android.graphics.ColorSpace, android.graphics.ColorSpace);
+ public static android.graphics.ColorSpace$Connector connect(android.graphics.ColorSpace, android.graphics.ColorSpace, android.graphics.ColorSpace$RenderIntent);
+ public static android.graphics.ColorSpace$Connector connect(android.graphics.ColorSpace);
+ public static android.graphics.ColorSpace$Connector connect(android.graphics.ColorSpace, android.graphics.ColorSpace$RenderIntent);
+ public static android.graphics.ColorSpace$Renderer createRenderer();
+ public boolean equals(java.lang.Object);
+ public float[] fromXyz(float, float, float);
+ public abstract float[] fromXyz(float[]);
+ public static android.graphics.ColorSpace get(android.graphics.ColorSpace$Named);
+ public int getComponentCount();
+ public int getId();
+ public abstract float getMaxValue(int);
+ public abstract float getMinValue(int);
+ public android.graphics.ColorSpace$Model getModel();
+ public java.lang.String getName();
+ public int hashCode();
+ public boolean isSrgb();
+ public abstract boolean isWideGamut();
+ public static android.graphics.ColorSpace match(float[], android.graphics.ColorSpace$Rgb$TransferParameters);
+ public java.lang.String toString();
+ public float[] toXyz(float, float, float);
+ public abstract float[] toXyz(float[]);
+
+
+ public static float[] ILLUMINANT_A;
+ public static float[] ILLUMINANT_B;
+ public static float[] ILLUMINANT_C;
+ public static float[] ILLUMINANT_D50;
+ public static float[] ILLUMINANT_D55;
+ public static float[] ILLUMINANT_D60;
+ public static float[] ILLUMINANT_D65;
+ public static float[] ILLUMINANT_D75;
+ public static float[] ILLUMINANT_E;
+ public static int MAX_ID;
+ public static int MIN_ID;
+}
+
+-keep class android.graphics.ColorSpace$Adaptation {
+
+ public static android.graphics.ColorSpace$Adaptation valueOf(java.lang.String);
+ public static android.graphics.ColorSpace$Adaptation[] values();
+
+ public static android.graphics.ColorSpace$Adaptation BRADFORD;
+ public static android.graphics.ColorSpace$Adaptation CIECAT02;
+ public static android.graphics.ColorSpace$Adaptation VON_KRIES;
+
+}
+
+-keep class android.graphics.ColorSpace$Connector {
+
+ public android.graphics.ColorSpace getDestination();
+ public android.graphics.ColorSpace$RenderIntent getRenderIntent();
+ public android.graphics.ColorSpace getSource();
+ public float[] transform(float, float, float);
+ public float[] transform(float[]);
+
+
+}
+
+-keep class android.graphics.ColorSpace$Model {
+
+ public int getComponentCount();
+ public static android.graphics.ColorSpace$Model valueOf(java.lang.String);
+ public static android.graphics.ColorSpace$Model[] values();
+
+ public static android.graphics.ColorSpace$Model CMYK;
+ public static android.graphics.ColorSpace$Model LAB;
+ public static android.graphics.ColorSpace$Model RGB;
+ public static android.graphics.ColorSpace$Model XYZ;
+
+}
+
+-keep class android.graphics.ColorSpace$Named {
+
+ public static android.graphics.ColorSpace$Named valueOf(java.lang.String);
+ public static android.graphics.ColorSpace$Named[] values();
+
+ public static android.graphics.ColorSpace$Named ACES;
+ public static android.graphics.ColorSpace$Named ACESCG;
+ public static android.graphics.ColorSpace$Named ADOBE_RGB;
+ public static android.graphics.ColorSpace$Named BT2020;
+ public static android.graphics.ColorSpace$Named BT709;
+ public static android.graphics.ColorSpace$Named CIE_LAB;
+ public static android.graphics.ColorSpace$Named CIE_XYZ;
+ public static android.graphics.ColorSpace$Named DCI_P3;
+ public static android.graphics.ColorSpace$Named DISPLAY_P3;
+ public static android.graphics.ColorSpace$Named EXTENDED_SRGB;
+ public static android.graphics.ColorSpace$Named LINEAR_EXTENDED_SRGB;
+ public static android.graphics.ColorSpace$Named LINEAR_SRGB;
+ public static android.graphics.ColorSpace$Named NTSC_1953;
+ public static android.graphics.ColorSpace$Named PRO_PHOTO_RGB;
+ public static android.graphics.ColorSpace$Named SMPTE_C;
+ public static android.graphics.ColorSpace$Named SRGB;
+
+}
+
+-keep class android.graphics.ColorSpace$RenderIntent {
+
+ public static android.graphics.ColorSpace$RenderIntent valueOf(java.lang.String);
+ public static android.graphics.ColorSpace$RenderIntent[] values();
+
+ public static android.graphics.ColorSpace$RenderIntent ABSOLUTE;
+ public static android.graphics.ColorSpace$RenderIntent PERCEPTUAL;
+ public static android.graphics.ColorSpace$RenderIntent RELATIVE;
+ public static android.graphics.ColorSpace$RenderIntent SATURATION;
+
+}
+
+-keep class android.graphics.ColorSpace$Renderer {
+
+ public android.graphics.ColorSpace$Renderer add(android.graphics.ColorSpace, int);
+ public android.graphics.ColorSpace$Renderer add(android.graphics.ColorSpace, float, float, float, int);
+ public android.graphics.ColorSpace$Renderer clip(boolean);
+ public android.graphics.Bitmap render();
+ public android.graphics.ColorSpace$Renderer showWhitePoint(boolean);
+ public android.graphics.ColorSpace$Renderer size(int);
+ public android.graphics.ColorSpace$Renderer uniformChromaticityScale(boolean);
+
+
+}
+
+-keep class android.graphics.ColorSpace$Rgb {
+ <init>(java.lang.String, float[], java.util.function.DoubleUnaryOperator, java.util.function.DoubleUnaryOperator);
+ <init>(java.lang.String, float[], float[], java.util.function.DoubleUnaryOperator, java.util.function.DoubleUnaryOperator, float, float);
+ <init>(java.lang.String, float[], android.graphics.ColorSpace$Rgb$TransferParameters);
+ <init>(java.lang.String, float[], float[], android.graphics.ColorSpace$Rgb$TransferParameters);
+ <init>(java.lang.String, float[], double);
+ <init>(java.lang.String, float[], float[], double);
+
+ public boolean equals(java.lang.Object);
+ public float[] fromLinear(float, float, float);
+ public float[] fromLinear(float[]);
+ public float[] fromXyz(float[]);
+ public java.util.function.DoubleUnaryOperator getEotf();
+ public float[] getInverseTransform(float[]);
+ public float[] getInverseTransform();
+ public float getMaxValue(int);
+ public float getMinValue(int);
+ public java.util.function.DoubleUnaryOperator getOetf();
+ public float[] getPrimaries(float[]);
+ public float[] getPrimaries();
+ public android.graphics.ColorSpace$Rgb$TransferParameters getTransferParameters();
+ public float[] getTransform(float[]);
+ public float[] getTransform();
+ public float[] getWhitePoint(float[]);
+ public float[] getWhitePoint();
+ public int hashCode();
+ public boolean isSrgb();
+ public boolean isWideGamut();
+ public float[] toLinear(float, float, float);
+ public float[] toLinear(float[]);
+ public float[] toXyz(float[]);
+
+
+}
+
+-keep class android.graphics.ColorSpace$Rgb$TransferParameters {
+ <init>(double, double, double, double, double);
+ <init>(double, double, double, double, double, double, double);
+
+ public boolean equals(java.lang.Object);
+ public int hashCode();
+
+
+ public double a;
+ public double b;
+ public double c;
+ public double d;
+ public double e;
+ public double f;
+ public double g;
+}
+
-keep class android.graphics.DrawFilter {
<init>();
protected void finalize();
+ public long mNativeInt;
+}
+
+-keep class android.graphics.FontFamily {
+ <init>();
+ <init>(java.lang.String[], int);
+
+ public void abortCreation();
+ public boolean addFont(java.lang.String, int, android.graphics.fonts.FontVariationAxis[], int, int);
+ public boolean addFontFromAssetManager(android.content.res.AssetManager, java.lang.String, int, boolean, int, int, int, android.graphics.fonts.FontVariationAxis[]);
+ public boolean addFontFromBuffer(java.nio.ByteBuffer, int, android.graphics.fonts.FontVariationAxis[], int, int);
+ public boolean freeze();
+
+
+ public long mNativePtr;
+}
+
+-keep class android.graphics.GraphicBuffer {
+
+ public static android.graphics.GraphicBuffer create(int, int, int, int);
+ public static android.graphics.GraphicBuffer createFromExisting(int, int, int, int, long);
+ public int describeContents();
+ public void destroy();
+ protected void finalize();
+ public int getFormat();
+ public int getHeight();
+ public int getUsage();
+ public int getWidth();
+ public boolean isDestroyed();
+ public android.graphics.Canvas lockCanvas();
+ public android.graphics.Canvas lockCanvas(android.graphics.Rect);
+ public void unlockCanvasAndPost(android.graphics.Canvas);
+ public void writeToParcel(android.os.Parcel, int);
+
+
+ public static android.os.Parcelable$Creator CREATOR;
+ public static int USAGE_HW_2D;
+ public static int USAGE_HW_COMPOSER;
+ public static int USAGE_HW_MASK;
+ public static int USAGE_HW_RENDER;
+ public static int USAGE_HW_TEXTURE;
+ public static int USAGE_HW_VIDEO_ENCODER;
+ public static int USAGE_PROTECTED;
+ public static int USAGE_SOFTWARE_MASK;
+ public static int USAGE_SW_READ_MASK;
+ public static int USAGE_SW_READ_NEVER;
+ public static int USAGE_SW_READ_OFTEN;
+ public static int USAGE_SW_READ_RARELY;
+ public static int USAGE_SW_WRITE_MASK;
+ public static int USAGE_SW_WRITE_NEVER;
+ public static int USAGE_SW_WRITE_OFTEN;
+ public static int USAGE_SW_WRITE_RARELY;
+}
+
+-keep class android.graphics.Insets {
+
+ public boolean equals(java.lang.Object);
+ public int hashCode();
+ public static android.graphics.Insets of(int, int, int, int);
+ public static android.graphics.Insets of(android.graphics.Rect);
+ public java.lang.String toString();
+
+
+ public static android.graphics.Insets NONE;
+ public int bottom;
+ public int left;
+ public int right;
+ public int top;
}
-keep class android.graphics.MaskFilter {
@@ -2931,7 +11298,6 @@
<init>(android.graphics.Matrix);
public boolean equals(java.lang.Object);
- protected void finalize();
public void getValues(float[]);
public int hashCode();
public boolean invert(android.graphics.Matrix);
@@ -2946,6 +11312,7 @@
public void mapVectors(float[], int, float[], int, int);
public void mapVectors(float[], float[]);
public void mapVectors(float[]);
+ public long ni();
public boolean postConcat(android.graphics.Matrix);
public boolean postRotate(float, float, float);
public boolean postRotate(float);
@@ -2962,6 +11329,7 @@
public boolean preSkew(float, float, float, float);
public boolean preSkew(float, float);
public boolean preTranslate(float, float);
+ public void printShortString(java.io.PrintWriter);
public boolean rectStaysRect();
public void reset();
public void set(android.graphics.Matrix);
@@ -2979,9 +11347,11 @@
public void setTranslate(float, float);
public void setValues(float[]);
public java.lang.String toShortString();
+ public void toShortString(java.lang.StringBuilder);
public java.lang.String toString();
+ public static android.graphics.Matrix IDENTITY_MATRIX;
public static int MPERSP_0;
public static int MPERSP_1;
public static int MPERSP_2;
@@ -2991,6 +11361,7 @@
public static int MSKEW_Y;
public static int MTRANS_X;
public static int MTRANS_Y;
+ public long native_instance;
}
-keep class android.graphics.Matrix$ScaleToFit {
@@ -3022,12 +11393,49 @@
}
+-keep class android.graphics.NinePatch {
+ <init>(android.graphics.Bitmap, byte[]);
+ <init>(android.graphics.Bitmap, byte[], java.lang.String);
+ <init>(android.graphics.NinePatch);
+
+ public void draw(android.graphics.Canvas, android.graphics.RectF);
+ public void draw(android.graphics.Canvas, android.graphics.Rect);
+ public void draw(android.graphics.Canvas, android.graphics.Rect, android.graphics.Paint);
+ protected void finalize();
+ public android.graphics.Bitmap getBitmap();
+ public int getDensity();
+ public int getHeight();
+ public java.lang.String getName();
+ public android.graphics.Paint getPaint();
+ public android.graphics.Region getTransparentRegion(android.graphics.Rect);
+ public int getWidth();
+ public boolean hasAlpha();
+ public static boolean isNinePatchChunk(byte[]);
+ public void setPaint(android.graphics.Paint);
+
+
+ public long mNativeChunk;
+}
+
+-keep class android.graphics.NinePatch$InsetStruct {
+
+ public static android.graphics.Rect scaleInsets(int, int, int, int, float);
+
+
+ public android.graphics.Rect opticalRect;
+ public float outlineAlpha;
+ public float outlineRadius;
+ public android.graphics.Rect outlineRect;
+}
+
-keep class android.graphics.Outline {
<init>();
<init>(android.graphics.Outline);
public boolean canClip();
public float getAlpha();
+ public float getRadius();
+ public boolean getRect(android.graphics.Rect);
public boolean isEmpty();
public void offset(int, int);
public void set(android.graphics.Outline);
@@ -3042,6 +11450,14 @@
public void setRoundRect(android.graphics.Rect, float);
+ public static int MODE_CONVEX_PATH;
+ public static int MODE_EMPTY;
+ public static int MODE_ROUND_RECT;
+ public float mAlpha;
+ public int mMode;
+ public android.graphics.Path mPath;
+ public float mRadius;
+ public android.graphics.Rect mRect;
}
-keep class android.graphics.Paint {
@@ -3055,8 +11471,9 @@
public int breakText(java.lang.String, boolean, float, float[]);
public void clearShadowLayer();
public float descent();
- protected void finalize();
+ public boolean equalsForTextMeasurement(android.graphics.Paint);
public int getAlpha();
+ public int getBidiFlags();
public int getColor();
public android.graphics.ColorFilter getColorFilter();
public boolean getFillPath(android.graphics.Path, android.graphics.Path);
@@ -3067,9 +11484,12 @@
public int getFontMetricsInt(android.graphics.Paint$FontMetricsInt);
public android.graphics.Paint$FontMetricsInt getFontMetricsInt();
public float getFontSpacing();
+ public java.lang.String getFontVariationSettings();
public int getHinting();
+ public int getHyphenEdit();
public float getLetterSpacing();
public android.graphics.MaskFilter getMaskFilter();
+ public long getNativeInstance();
public int getOffsetForAdvance(char[], int, int, int, int, boolean, float);
public int getOffsetForAdvance(java.lang.CharSequence, int, int, int, int, boolean, float);
public android.graphics.PathEffect getPathEffect();
@@ -3077,6 +11497,8 @@
public float getRunAdvance(char[], int, int, int, int, boolean, int);
public float getRunAdvance(java.lang.CharSequence, int, int, int, int, boolean, int);
public android.graphics.Shader getShader();
+ public float getStrikeThruPosition();
+ public float getStrikeThruThickness();
public android.graphics.Paint$Cap getStrokeCap();
public android.graphics.Paint$Join getStrokeJoin();
public float getStrokeMiter();
@@ -3084,10 +11506,18 @@
public android.graphics.Paint$Style getStyle();
public android.graphics.Paint$Align getTextAlign();
public void getTextBounds(java.lang.String, int, int, android.graphics.Rect);
+ public void getTextBounds(java.lang.CharSequence, int, int, android.graphics.Rect);
public void getTextBounds(char[], int, int, android.graphics.Rect);
public java.util.Locale getTextLocale();
+ public android.os.LocaleList getTextLocales();
public void getTextPath(char[], int, int, float, float, android.graphics.Path);
public void getTextPath(java.lang.String, int, int, float, float, android.graphics.Path);
+ public float getTextRunAdvances(char[], int, int, int, int, boolean, float[], int);
+ public float getTextRunAdvances(java.lang.CharSequence, int, int, int, int, boolean, float[], int);
+ public float getTextRunAdvances(java.lang.String, int, int, int, int, boolean, float[], int);
+ public int getTextRunCursor(char[], int, int, int, int, int);
+ public int getTextRunCursor(java.lang.CharSequence, int, int, int, int, int);
+ public int getTextRunCursor(java.lang.String, int, int, int, int, int);
public float getTextScaleX();
public float getTextSize();
public float getTextSkewX();
@@ -3096,8 +11526,13 @@
public int getTextWidths(java.lang.String, int, int, float[]);
public int getTextWidths(java.lang.String, float[]);
public android.graphics.Typeface getTypeface();
+ public float getUnderlinePosition();
+ public float getUnderlineThickness();
+ public float getWordSpacing();
public android.graphics.Xfermode getXfermode();
+ public boolean hasEqualAttributes(android.graphics.Paint);
public boolean hasGlyph(java.lang.String);
+ public boolean hasShadowLayer();
public boolean isAntiAlias();
public boolean isDither();
public boolean isElegantTextHeight();
@@ -3116,15 +11551,19 @@
public void setARGB(int, int, int, int);
public void setAlpha(int);
public void setAntiAlias(boolean);
+ public void setBidiFlags(int);
public void setColor(int);
public android.graphics.ColorFilter setColorFilter(android.graphics.ColorFilter);
+ public void setCompatibilityScaling(float);
public void setDither(boolean);
public void setElegantTextHeight(boolean);
public void setFakeBoldText(boolean);
public void setFilterBitmap(boolean);
public void setFlags(int);
public void setFontFeatureSettings(java.lang.String);
+ public boolean setFontVariationSettings(java.lang.String);
public void setHinting(int);
+ public void setHyphenEdit(int);
public void setLetterSpacing(float);
public void setLinearText(boolean);
public android.graphics.MaskFilter setMaskFilter(android.graphics.MaskFilter);
@@ -3141,26 +11580,47 @@
public void setSubpixelText(boolean);
public void setTextAlign(android.graphics.Paint$Align);
public void setTextLocale(java.util.Locale);
+ public void setTextLocales(android.os.LocaleList);
public void setTextScaleX(float);
public void setTextSize(float);
public void setTextSkewX(float);
public android.graphics.Typeface setTypeface(android.graphics.Typeface);
public void setUnderlineText(boolean);
+ public void setWordSpacing(float);
public android.graphics.Xfermode setXfermode(android.graphics.Xfermode);
public static int ANTI_ALIAS_FLAG;
+ public static int AUTO_HINTING_TEXT_FLAG;
+ public static int BIDI_DEFAULT_LTR;
+ public static int BIDI_DEFAULT_RTL;
+ public static int BIDI_FORCE_LTR;
+ public static int BIDI_FORCE_RTL;
+ public static int BIDI_LTR;
+ public static int BIDI_RTL;
+ public static int CURSOR_AFTER;
+ public static int CURSOR_AT;
+ public static int CURSOR_AT_OR_AFTER;
+ public static int CURSOR_AT_OR_BEFORE;
+ public static int CURSOR_BEFORE;
public static int DEV_KERN_TEXT_FLAG;
+ public static int DIRECTION_LTR;
+ public static int DIRECTION_RTL;
public static int DITHER_FLAG;
public static int EMBEDDED_BITMAP_TEXT_FLAG;
public static int FAKE_BOLD_TEXT_FLAG;
public static int FILTER_BITMAP_FLAG;
public static int HINTING_OFF;
public static int HINTING_ON;
+ public static int HYPHENEDIT_MASK_END_OF_LINE;
+ public static int HYPHENEDIT_MASK_START_OF_LINE;
+ public static int LCD_RENDER_TEXT_FLAG;
public static int LINEAR_TEXT_FLAG;
public static int STRIKE_THRU_TEXT_FLAG;
public static int SUBPIXEL_TEXT_FLAG;
public static int UNDERLINE_TEXT_FLAG;
+ public static int VERTICAL_TEXT_FLAG;
+ public int mBidiFlags;
}
-keep class android.graphics.Paint$Align {
@@ -3250,13 +11710,13 @@
public void addRoundRect(float, float, float, float, float, float, android.graphics.Path$Direction);
public void addRoundRect(android.graphics.RectF, float[], android.graphics.Path$Direction);
public void addRoundRect(float, float, float, float, float[], android.graphics.Path$Direction);
+ public float[] approximate(float);
public void arcTo(android.graphics.RectF, float, float, boolean);
public void arcTo(android.graphics.RectF, float, float);
public void arcTo(float, float, float, float, float, float, boolean);
public void close();
public void computeBounds(android.graphics.RectF, boolean);
public void cubicTo(float, float, float, float, float, float);
- protected void finalize();
public android.graphics.Path$FillType getFillType();
public void incReserve(int);
public boolean isConvex();
@@ -3274,6 +11734,7 @@
public void rLineTo(float, float);
public void rMoveTo(float, float);
public void rQuadTo(float, float, float, float);
+ public long readOnlyNI();
public void reset();
public void rewind();
public void set(android.graphics.Path);
@@ -3284,6 +11745,9 @@
public void transform(android.graphics.Matrix);
+ public boolean isSimplePath;
+ public long mNativePath;
+ public android.graphics.Region rects;
}
-keep class android.graphics.Path$Direction {
@@ -3340,6 +11804,7 @@
protected void finalize();
public int getHeight();
public int getWidth();
+ public boolean requiresHardwareAcceleration();
public void writeToStream(java.io.OutputStream);
@@ -3356,10 +11821,12 @@
public int hashCode();
public void negate();
public void offset(int, int);
+ public void printShortString(java.io.PrintWriter);
public void readFromParcel(android.os.Parcel);
public void set(int, int);
public java.lang.String toString();
public void writeToParcel(android.os.Parcel, int);
+ public void writeToProto(android.util.proto.ProtoOutputStream, long);
public static android.os.Parcelable$Creator CREATOR;
@@ -3367,9 +11834,36 @@
public int y;
}
+-keep class android.graphics.PointF {
+ <init>();
+ <init>(float, float);
+ <init>(android.graphics.Point);
+
+ public int describeContents();
+ public boolean equals(float, float);
+ public boolean equals(java.lang.Object);
+ public int hashCode();
+ public float length();
+ public static float length(float, float);
+ public void negate();
+ public void offset(float, float);
+ public void readFromParcel(android.os.Parcel);
+ public void set(float, float);
+ public void set(android.graphics.PointF);
+ public java.lang.String toString();
+ public void writeToParcel(android.os.Parcel, int);
+
+
+ public static android.os.Parcelable$Creator CREATOR;
+ public float x;
+ public float y;
+}
+
-keep class android.graphics.PorterDuff {
<init>();
+ public static android.graphics.PorterDuff$Mode intToMode(int);
+ public static int modeToInt(android.graphics.PorterDuff$Mode);
}
@@ -3398,6 +11892,7 @@
public static android.graphics.PorterDuff$Mode SRC_OVER;
public static android.graphics.PorterDuff$Mode XOR;
+ public int nativeInt;
}
-keep class android.graphics.Rasterizer {
@@ -3418,6 +11913,7 @@
public boolean contains(int, int);
public boolean contains(int, int, int, int);
public boolean contains(android.graphics.Rect);
+ public static android.graphics.Rect copyOrNull(android.graphics.Rect);
public int describeContents();
public boolean equals(java.lang.Object);
public float exactCenterX();
@@ -3426,20 +11922,26 @@
public int hashCode();
public int height();
public void inset(int, int);
+ public void inset(android.graphics.Rect);
+ public void inset(int, int, int, int);
public boolean intersect(int, int, int, int);
public boolean intersect(android.graphics.Rect);
+ public void intersectUnchecked(android.graphics.Rect);
public boolean intersects(int, int, int, int);
public static boolean intersects(android.graphics.Rect, android.graphics.Rect);
public boolean isEmpty();
public void offset(int, int);
public void offsetTo(int, int);
+ public void printShortString(java.io.PrintWriter);
public void readFromParcel(android.os.Parcel);
+ public void scale(float);
public void set(int, int, int, int);
public void set(android.graphics.Rect);
public void setEmpty();
public boolean setIntersect(android.graphics.Rect, android.graphics.Rect);
public void sort();
public java.lang.String toShortString();
+ public java.lang.String toShortString(java.lang.StringBuilder);
public java.lang.String toString();
public static android.graphics.Rect unflattenFromString(java.lang.String);
public void union(int, int, int, int);
@@ -3447,6 +11949,7 @@
public void union(int, int);
public int width();
public void writeToParcel(android.os.Parcel, int);
+ public void writeToProto(android.util.proto.ProtoOutputStream, long);
public static android.os.Parcelable$Creator CREATOR;
@@ -3479,9 +11982,11 @@
public boolean isEmpty();
public void offset(float, float);
public void offsetTo(float, float);
+ public void printShortString(java.io.PrintWriter);
public void readFromParcel(android.os.Parcel);
public void round(android.graphics.Rect);
public void roundOut(android.graphics.Rect);
+ public void scale(float);
public void set(float, float, float, float);
public void set(android.graphics.RectF);
public void set(android.graphics.Rect);
@@ -3489,6 +11994,7 @@
public boolean setIntersect(android.graphics.RectF, android.graphics.RectF);
public void sort();
public java.lang.String toShortString();
+ public java.lang.String toShortString(java.lang.StringBuilder);
public java.lang.String toString();
public void union(float, float, float, float);
public void union(android.graphics.RectF);
@@ -3521,6 +12027,8 @@
public boolean isComplex();
public boolean isEmpty();
public boolean isRect();
+ public static android.graphics.Region obtain();
+ public static android.graphics.Region obtain(android.graphics.Region);
public boolean op(android.graphics.Rect, android.graphics.Region$Op);
public boolean op(int, int, int, int, android.graphics.Region$Op);
public boolean op(android.graphics.Region, android.graphics.Region$Op);
@@ -3531,6 +12039,9 @@
public boolean quickReject(android.graphics.Rect);
public boolean quickReject(int, int, int, int);
public boolean quickReject(android.graphics.Region);
+ public void recycle();
+ public void scale(float);
+ public void scale(float, android.graphics.Region);
public boolean set(android.graphics.Region);
public boolean set(android.graphics.Rect);
public boolean set(int, int, int, int);
@@ -3544,6 +12055,7 @@
public static android.os.Parcelable$Creator CREATOR;
+ public long mNativeRegion;
}
-keep class android.graphics.Region$Op {
@@ -3558,32 +12070,73 @@
public static android.graphics.Region$Op UNION;
public static android.graphics.Region$Op XOR;
+ public int nativeInt;
}
-keep class android.graphics.Shader {
<init>();
- protected void finalize();
+ protected android.graphics.Shader copy();
+ protected void copyLocalMatrix(android.graphics.Shader);
+ protected void discardNativeInstance();
public boolean getLocalMatrix(android.graphics.Matrix);
+ public long getNativeInstance();
public void setLocalMatrix(android.graphics.Matrix);
+ protected void verifyNativeInstance();
+
+
+}
+
+-keep class android.graphics.SurfaceTexture {
+ <init>(int);
+ <init>(int, boolean);
+ <init>(boolean);
+
+ public void attachToGLContext(int);
+ public void detachFromGLContext();
+ protected void finalize();
+ public long getTimestamp();
+ public void getTransformMatrix(float[]);
+ public boolean isReleased();
+ public boolean isSingleBuffered();
+ public void release();
+ public void releaseTexImage();
+ public void setDefaultBufferSize(int, int);
+ public void setOnFrameAvailableListener(android.graphics.SurfaceTexture$OnFrameAvailableListener);
+ public void setOnFrameAvailableListener(android.graphics.SurfaceTexture$OnFrameAvailableListener, android.os.Handler);
+ public void updateTexImage();
+
+
+}
+
+-keep class android.graphics.SurfaceTexture$OnFrameAvailableListener {
+
+ public abstract void onFrameAvailable(android.graphics.SurfaceTexture);
}
-keep class android.graphics.Typeface {
+ public static void buildSystemFallback(java.lang.String, java.lang.String, android.util.ArrayMap, android.util.ArrayMap);
public static android.graphics.Typeface create(java.lang.String, int);
public static android.graphics.Typeface create(android.graphics.Typeface, int);
+ public static android.graphics.Typeface create(android.graphics.Typeface, int, boolean);
public static android.graphics.Typeface createFromAsset(android.content.res.AssetManager, java.lang.String);
public static android.graphics.Typeface createFromFile(java.io.File);
public static android.graphics.Typeface createFromFile(java.lang.String);
+ public static android.graphics.Typeface createFromResources(android.content.res.AssetManager, java.lang.String, int);
+ public static android.graphics.Typeface createFromResources(android.content.res.FontResourcesParser$FamilyResourceEntry, android.content.res.AssetManager, java.lang.String);
+ public static android.graphics.Typeface createFromTypefaceWithVariation(android.graphics.Typeface, java.util.List);
public static android.graphics.Typeface defaultFromStyle(int);
public boolean equals(java.lang.Object);
- protected void finalize();
+ public static android.graphics.Typeface findFromCache(android.content.res.AssetManager, java.lang.String);
public int getStyle();
+ public int getWeight();
public int hashCode();
public boolean isBold();
public boolean isItalic();
+ public boolean isSupportedAxes(int);
public static int BOLD;
@@ -3591,16 +12144,103 @@
public static android.graphics.Typeface DEFAULT;
public static android.graphics.Typeface DEFAULT_BOLD;
public static int ITALIC;
+ public static int MAX_WEIGHT;
public static android.graphics.Typeface MONOSPACE;
public static int NORMAL;
+ public static int RESOLVE_BY_FONT_TABLE;
public static android.graphics.Typeface SANS_SERIF;
public static android.graphics.Typeface SERIF;
+ public static int STYLE_MASK;
+ public long native_instance;
}
-keep class android.graphics.Xfermode {
<init>();
- protected void finalize();
+
+
+}
+
+-keep class android.graphics.drawable.Animatable2 {
+
+ public abstract void clearAnimationCallbacks();
+ public abstract void registerAnimationCallback(android.graphics.drawable.Animatable2$AnimationCallback);
+ public abstract boolean unregisterAnimationCallback(android.graphics.drawable.Animatable2$AnimationCallback);
+
+
+}
+
+-keep class android.graphics.drawable.Animatable2$AnimationCallback {
+ <init>();
+
+ public void onAnimationEnd(android.graphics.drawable.Drawable);
+ public void onAnimationStart(android.graphics.drawable.Drawable);
+
+
+}
+
+-keep class android.graphics.drawable.AnimatedVectorDrawable {
+ <init>();
+
+ public void applyTheme(android.content.res.Resources$Theme);
+ public boolean canApplyTheme();
+ public boolean canReverse();
+ public void clearAnimationCallbacks();
+ public void clearMutated();
+ public void draw(android.graphics.Canvas);
+ public void forceAnimationOnUI();
+ public int getAlpha();
+ public int getChangingConfigurations();
+ public android.graphics.ColorFilter getColorFilter();
+ public android.graphics.drawable.Drawable$ConstantState getConstantState();
+ public int getIntrinsicHeight();
+ public int getIntrinsicWidth();
+ public int getOpacity();
+ public android.graphics.Insets getOpticalInsets();
+ public void getOutline(android.graphics.Outline);
+ public void inflate(android.content.res.Resources, org.xmlpull.v1.XmlPullParser, android.util.AttributeSet, android.content.res.Resources$Theme);
+ public boolean isRunning();
+ public boolean isStateful();
+ public android.graphics.drawable.Drawable mutate();
+ protected void onBoundsChange(android.graphics.Rect);
+ public boolean onLayoutDirectionChanged(int);
+ protected boolean onLevelChange(int);
+ protected boolean onStateChange(int[]);
+ public void registerAnimationCallback(android.graphics.drawable.Animatable2$AnimationCallback);
+ public void reset();
+ public void reverse();
+ public void setAlpha(int);
+ public void setColorFilter(android.graphics.ColorFilter);
+ public void setHotspot(float, float);
+ public void setHotspotBounds(int, int, int, int);
+ public void setTintList(android.content.res.ColorStateList);
+ public void setTintMode(android.graphics.PorterDuff$Mode);
+ public boolean setVisible(boolean, boolean);
+ public void start();
+ public void stop();
+ public boolean unregisterAnimationCallback(android.graphics.drawable.Animatable2$AnimationCallback);
+
+
+}
+
+-keep class android.graphics.drawable.AnimatedVectorDrawable$VectorDrawableAnimatorRT {
+
+ public boolean canReverse();
+ public void end();
+ public long getAnimatorNativePtr();
+ public void init(android.animation.AnimatorSet);
+ public boolean isInfinite();
+ public boolean isRunning();
+ public boolean isStarted();
+ public void onDraw(android.graphics.Canvas);
+ public void pause();
+ protected void recordLastSeenTarget(android.view.DisplayListCanvas);
+ public void removeListener(android.animation.Animator$AnimatorListener);
+ public void reset();
+ public void resume();
+ public void reverse();
+ public void setListener(android.animation.Animator$AnimatorListener);
+ public void start();
}
@@ -3611,6 +12251,7 @@
public void applyTheme(android.content.res.Resources$Theme);
public boolean canApplyTheme();
public void clearColorFilter();
+ public void clearMutated();
public void copyBounds(android.graphics.Rect);
public android.graphics.Rect copyBounds();
public static android.graphics.drawable.Drawable createFromPath(java.lang.String);
@@ -3619,6 +12260,7 @@
public static android.graphics.drawable.Drawable createFromStream(java.io.InputStream, java.lang.String);
public static android.graphics.drawable.Drawable createFromXml(android.content.res.Resources, org.xmlpull.v1.XmlPullParser);
public static android.graphics.drawable.Drawable createFromXml(android.content.res.Resources, org.xmlpull.v1.XmlPullParser, android.content.res.Resources$Theme);
+ public static android.graphics.drawable.Drawable createFromXmlForDensity(android.content.res.Resources, org.xmlpull.v1.XmlPullParser, int, android.content.res.Resources$Theme);
public static android.graphics.drawable.Drawable createFromXmlInner(android.content.res.Resources, org.xmlpull.v1.XmlPullParser, android.util.AttributeSet);
public static android.graphics.drawable.Drawable createFromXmlInner(android.content.res.Resources, org.xmlpull.v1.XmlPullParser, android.util.AttributeSet, android.content.res.Resources$Theme);
public abstract void draw(android.graphics.Canvas);
@@ -3638,23 +12280,28 @@
public int getMinimumHeight();
public int getMinimumWidth();
public abstract int getOpacity();
+ public android.graphics.Insets getOpticalInsets();
public void getOutline(android.graphics.Outline);
public boolean getPadding(android.graphics.Rect);
public int[] getState();
public android.graphics.Region getTransparentRegion();
+ public boolean hasFocusStateSpecified();
public void inflate(android.content.res.Resources, org.xmlpull.v1.XmlPullParser, android.util.AttributeSet);
public void inflate(android.content.res.Resources, org.xmlpull.v1.XmlPullParser, android.util.AttributeSet, android.content.res.Resources$Theme);
public void invalidateSelf();
public boolean isAutoMirrored();
public boolean isFilterBitmap();
+ public boolean isProjected();
public boolean isStateful();
public boolean isVisible();
public void jumpToCurrentState();
public android.graphics.drawable.Drawable mutate();
+ protected static android.content.res.TypedArray obtainAttributes(android.content.res.Resources, android.content.res.Resources$Theme, android.util.AttributeSet, int[]);
protected void onBoundsChange(android.graphics.Rect);
public boolean onLayoutDirectionChanged(int);
protected boolean onLevelChange(int);
protected boolean onStateChange(int[]);
+ public static android.graphics.PorterDuff$Mode parseTintMode(int, android.graphics.PorterDuff$Mode);
public static int resolveOpacity(int, int);
public void scheduleSelf(java.lang.Runnable, long);
public abstract void setAlpha(int);
@@ -3676,9 +12323,11 @@
public void setTintList(android.content.res.ColorStateList);
public void setTintMode(android.graphics.PorterDuff$Mode);
public boolean setVisible(boolean, boolean);
+ public void setXfermode(android.graphics.Xfermode);
public void unscheduleSelf(java.lang.Runnable);
+ protected int mSrcDensityOverride;
}
-keep class android.graphics.drawable.Drawable$Callback {
@@ -3702,18 +12351,374 @@
}
--keep class android.media.AudioAttributes {
+-keep class android.graphics.drawable.DrawableInflater {
+ <init>(android.content.res.Resources, java.lang.ClassLoader);
+
+ public android.graphics.drawable.Drawable inflateFromXml(java.lang.String, org.xmlpull.v1.XmlPullParser, android.util.AttributeSet, android.content.res.Resources$Theme);
+ public static android.graphics.drawable.Drawable loadDrawable(android.content.Context, int);
+ public static android.graphics.drawable.Drawable loadDrawable(android.content.res.Resources, android.content.res.Resources$Theme, int);
+
+
+}
+
+-keep class android.graphics.drawable.Icon {
+
+ public void convertToAshmem();
+ public static android.graphics.drawable.Icon createFromStream(java.io.InputStream);
+ public static android.graphics.drawable.Icon createWithAdaptiveBitmap(android.graphics.Bitmap);
+ public static android.graphics.drawable.Icon createWithBitmap(android.graphics.Bitmap);
+ public static android.graphics.drawable.Icon createWithContentUri(java.lang.String);
+ public static android.graphics.drawable.Icon createWithContentUri(android.net.Uri);
+ public static android.graphics.drawable.Icon createWithData(byte[], int, int);
+ public static android.graphics.drawable.Icon createWithFilePath(java.lang.String);
+ public static android.graphics.drawable.Icon createWithResource(android.content.Context, int);
+ public static android.graphics.drawable.Icon createWithResource(android.content.res.Resources, int);
+ public static android.graphics.drawable.Icon createWithResource(java.lang.String, int);
+ public int describeContents();
+ public android.graphics.Bitmap getBitmap();
+ public byte[] getDataBytes();
+ public int getDataLength();
+ public int getDataOffset();
+ public int getResId();
+ public java.lang.String getResPackage();
+ public android.content.res.Resources getResources();
+ public int getType();
+ public android.net.Uri getUri();
+ public java.lang.String getUriString();
+ public boolean hasTint();
+ public android.graphics.drawable.Drawable loadDrawable(android.content.Context);
+ public android.graphics.drawable.Drawable loadDrawableAsUser(android.content.Context, int);
+ public void loadDrawableAsync(android.content.Context, android.os.Message);
+ public void loadDrawableAsync(android.content.Context, android.graphics.drawable.Icon$OnDrawableLoadedListener, android.os.Handler);
+ public boolean sameAs(android.graphics.drawable.Icon);
+ public static android.graphics.Bitmap scaleDownIfNecessary(android.graphics.Bitmap, int, int);
+ public void scaleDownIfNecessary(int, int);
+ public android.graphics.drawable.Icon setTint(int);
+ public android.graphics.drawable.Icon setTintList(android.content.res.ColorStateList);
+ public android.graphics.drawable.Icon setTintMode(android.graphics.PorterDuff$Mode);
+ public java.lang.String toString();
+ public void writeToParcel(android.os.Parcel, int);
+ public void writeToStream(java.io.OutputStream);
+
+
+ public static android.os.Parcelable$Creator CREATOR;
+ public static int MIN_ASHMEM_ICON_SIZE;
+ public static int TYPE_ADAPTIVE_BITMAP;
+ public static int TYPE_BITMAP;
+ public static int TYPE_DATA;
+ public static int TYPE_RESOURCE;
+ public static int TYPE_URI;
+}
+
+-keep class android.graphics.drawable.Icon$OnDrawableLoadedListener {
+
+ public abstract void onDrawableLoaded(android.graphics.drawable.Drawable);
+
+
+}
+
+-keep class android.graphics.fonts.FontVariationAxis {
+ <init>(java.lang.String, float);
+
+ public static android.graphics.fonts.FontVariationAxis[] fromFontVariationSettings(java.lang.String);
+ public int getOpenTypeTagValue();
+ public float getStyleValue();
+ public java.lang.String getTag();
+ public static int makeTag(java.lang.String);
+ public static java.lang.String toFontVariationSettings(android.graphics.fonts.FontVariationAxis[]);
+ public java.lang.String toString();
+
+
+}
+
+-keep class android.hardware.display.AmbientBrightnessDayStats {
+ <init>(java.time.LocalDate, float[]);
+ <init>(java.time.LocalDate, float[], float[]);
public int describeContents();
public boolean equals(java.lang.Object);
- public int getContentType();
- public int getFlags();
- public int getUsage();
+ public float[] getBucketBoundaries();
+ public java.time.LocalDate getLocalDate();
+ public float[] getStats();
+ public int hashCode();
+ public void log(float, float);
+ public java.lang.String toString();
+ public void writeToParcel(android.os.Parcel, int);
+
+
+ public static android.os.Parcelable$Creator CREATOR;
+}
+
+-keep class android.hardware.display.BrightnessChangeEvent {
+ <init>(android.hardware.display.BrightnessChangeEvent, boolean);
+
+ public int describeContents();
+ public void writeToParcel(android.os.Parcel, int);
+
+
+ public static android.os.Parcelable$Creator CREATOR;
+ public float batteryLevel;
+ public float brightness;
+ public int colorTemperature;
+ public boolean isDefaultBrightnessConfig;
+ public boolean isUserSetBrightness;
+ public float lastBrightness;
+ public long[] luxTimestamps;
+ public float[] luxValues;
+ public boolean nightMode;
+ public java.lang.String packageName;
+ public float powerBrightnessFactor;
+ public long timeStamp;
+ public int userId;
+}
+
+-keep class android.hardware.display.BrightnessConfiguration {
+
+ public int describeContents();
+ public boolean equals(java.lang.Object);
+ public android.util.Pair getCurve();
+ public java.lang.String getDescription();
public int hashCode();
public java.lang.String toString();
public void writeToParcel(android.os.Parcel, int);
+ public static android.os.Parcelable$Creator CREATOR;
+}
+
+-keep class android.hardware.display.DisplayManager {
+ <init>(android.content.Context);
+
+ public void connectWifiDisplay(java.lang.String);
+ public android.hardware.display.VirtualDisplay createVirtualDisplay(java.lang.String, int, int, int, android.view.Surface, int);
+ public android.hardware.display.VirtualDisplay createVirtualDisplay(java.lang.String, int, int, int, android.view.Surface, int, android.hardware.display.VirtualDisplay$Callback, android.os.Handler);
+ public android.hardware.display.VirtualDisplay createVirtualDisplay(android.media.projection.MediaProjection, java.lang.String, int, int, int, android.view.Surface, int, android.hardware.display.VirtualDisplay$Callback, android.os.Handler, java.lang.String);
+ public void disconnectWifiDisplay();
+ public void forgetWifiDisplay(java.lang.String);
+ public java.util.List getAmbientBrightnessStats();
+ public android.hardware.display.BrightnessConfiguration getBrightnessConfiguration();
+ public android.hardware.display.BrightnessConfiguration getBrightnessConfigurationForUser(int);
+ public java.util.List getBrightnessEvents();
+ public android.hardware.display.BrightnessConfiguration getDefaultBrightnessConfiguration();
+ public android.view.Display getDisplay(int);
+ public android.view.Display[] getDisplays();
+ public android.view.Display[] getDisplays(java.lang.String);
+ public android.util.Pair getMinimumBrightnessCurve();
+ public android.graphics.Point getStableDisplaySize();
+ public android.hardware.display.WifiDisplayStatus getWifiDisplayStatus();
+ public void pauseWifiDisplay();
+ public void registerDisplayListener(android.hardware.display.DisplayManager$DisplayListener, android.os.Handler);
+ public void renameWifiDisplay(java.lang.String, java.lang.String);
+ public void resumeWifiDisplay();
+ public void setBrightnessConfiguration(android.hardware.display.BrightnessConfiguration);
+ public void setBrightnessConfigurationForUser(android.hardware.display.BrightnessConfiguration, int, java.lang.String);
+ public void setSaturationLevel(float);
+ public void setTemporaryAutoBrightnessAdjustment(float);
+ public void setTemporaryBrightness(int);
+ public void startWifiDisplayScan();
+ public void stopWifiDisplayScan();
+ public void unregisterDisplayListener(android.hardware.display.DisplayManager$DisplayListener);
+
+
+ public static java.lang.String ACTION_WIFI_DISPLAY_STATUS_CHANGED;
+ public static java.lang.String DISPLAY_CATEGORY_PRESENTATION;
+ public static java.lang.String EXTRA_WIFI_DISPLAY_STATUS;
+ public static int VIRTUAL_DISPLAY_FLAG_AUTO_MIRROR;
+ public static int VIRTUAL_DISPLAY_FLAG_CAN_SHOW_WITH_INSECURE_KEYGUARD;
+ public static int VIRTUAL_DISPLAY_FLAG_DESTROY_CONTENT_ON_REMOVAL;
+ public static int VIRTUAL_DISPLAY_FLAG_OWN_CONTENT_ONLY;
+ public static int VIRTUAL_DISPLAY_FLAG_PRESENTATION;
+ public static int VIRTUAL_DISPLAY_FLAG_PUBLIC;
+ public static int VIRTUAL_DISPLAY_FLAG_ROTATES_WITH_CONTENT;
+ public static int VIRTUAL_DISPLAY_FLAG_SECURE;
+ public static int VIRTUAL_DISPLAY_FLAG_SUPPORTS_TOUCH;
+}
+
+-keep class android.hardware.display.DisplayManager$DisplayListener {
+
+ public abstract void onDisplayAdded(int);
+ public abstract void onDisplayChanged(int);
+ public abstract void onDisplayRemoved(int);
+
+
+}
+
+-keep class android.hardware.display.DisplayManagerGlobal {
+
+ public void connectWifiDisplay(java.lang.String);
+ public android.hardware.display.VirtualDisplay createVirtualDisplay(android.content.Context, android.media.projection.MediaProjection, java.lang.String, int, int, int, android.view.Surface, int, android.hardware.display.VirtualDisplay$Callback, android.os.Handler, java.lang.String);
+ public void disconnectWifiDisplay();
+ public void forgetWifiDisplay(java.lang.String);
+ public java.util.List getAmbientBrightnessStats();
+ public android.hardware.display.BrightnessConfiguration getBrightnessConfigurationForUser(int);
+ public java.util.List getBrightnessEvents(java.lang.String);
+ public android.view.Display getCompatibleDisplay(int, android.view.DisplayAdjustments);
+ public android.view.Display getCompatibleDisplay(int, android.content.res.Resources);
+ public android.hardware.display.BrightnessConfiguration getDefaultBrightnessConfiguration();
+ public int[] getDisplayIds();
+ public android.view.DisplayInfo getDisplayInfo(int);
+ public static android.hardware.display.DisplayManagerGlobal getInstance();
+ public android.util.Pair getMinimumBrightnessCurve();
+ public android.view.Display getRealDisplay(int);
+ public android.graphics.Point getStableDisplaySize();
+ public android.hardware.display.WifiDisplayStatus getWifiDisplayStatus();
+ public void pauseWifiDisplay();
+ public void registerDisplayListener(android.hardware.display.DisplayManager$DisplayListener, android.os.Handler);
+ public void releaseVirtualDisplay(android.hardware.display.IVirtualDisplayCallback);
+ public void renameWifiDisplay(java.lang.String, java.lang.String);
+ public void requestColorMode(int, int);
+ public void resizeVirtualDisplay(android.hardware.display.IVirtualDisplayCallback, int, int, int);
+ public void resumeWifiDisplay();
+ public void setBrightnessConfigurationForUser(android.hardware.display.BrightnessConfiguration, int, java.lang.String);
+ public void setSaturationLevel(float);
+ public void setTemporaryAutoBrightnessAdjustment(float);
+ public void setTemporaryBrightness(int);
+ public void setVirtualDisplaySurface(android.hardware.display.IVirtualDisplayCallback, android.view.Surface);
+ public void startWifiDisplayScan();
+ public void stopWifiDisplayScan();
+ public void unregisterDisplayListener(android.hardware.display.DisplayManager$DisplayListener);
+
+
+ public static int EVENT_DISPLAY_ADDED;
+ public static int EVENT_DISPLAY_CHANGED;
+ public static int EVENT_DISPLAY_REMOVED;
+}
+
+-keep class android.hardware.display.IVirtualDisplayCallback {
+
+ public abstract void onPaused();
+ public abstract void onResumed();
+ public abstract void onStopped();
+
+
+}
+
+-keep class android.hardware.display.VirtualDisplay {
+
+ public android.view.Display getDisplay();
+ public android.view.Surface getSurface();
+ public void release();
+ public void resize(int, int, int);
+ public void setSurface(android.view.Surface);
+ public java.lang.String toString();
+
+
+}
+
+-keep class android.hardware.display.VirtualDisplay$Callback {
+ <init>();
+
+ public void onPaused();
+ public void onResumed();
+ public void onStopped();
+
+
+}
+
+-keep class android.hardware.display.WifiDisplay {
+ <init>(java.lang.String, java.lang.String, java.lang.String, boolean, boolean, boolean);
+
+ public boolean canConnect();
+ public int describeContents();
+ public boolean equals(java.lang.Object);
+ public boolean equals(android.hardware.display.WifiDisplay);
+ public java.lang.String getDeviceAddress();
+ public java.lang.String getDeviceAlias();
+ public java.lang.String getDeviceName();
+ public java.lang.String getFriendlyDisplayName();
+ public boolean hasSameAddress(android.hardware.display.WifiDisplay);
+ public int hashCode();
+ public boolean isAvailable();
+ public boolean isRemembered();
+ public java.lang.String toString();
+ public void writeToParcel(android.os.Parcel, int);
+
+
+ public static android.os.Parcelable$Creator CREATOR;
+ public static android.hardware.display.WifiDisplay[] EMPTY_ARRAY;
+}
+
+-keep class android.hardware.display.WifiDisplaySessionInfo {
+ <init>();
+ <init>(boolean, int, java.lang.String, java.lang.String, java.lang.String);
+
+ public int describeContents();
+ public java.lang.String getGroupId();
+ public java.lang.String getIP();
+ public java.lang.String getPassphrase();
+ public int getSessionId();
+ public boolean isClient();
+ public java.lang.String toString();
+ public void writeToParcel(android.os.Parcel, int);
+
+
+ public static android.os.Parcelable$Creator CREATOR;
+}
+
+-keep class android.hardware.display.WifiDisplayStatus {
+ <init>();
+ <init>(int, int, int, android.hardware.display.WifiDisplay, android.hardware.display.WifiDisplay[], android.hardware.display.WifiDisplaySessionInfo);
+
+ public int describeContents();
+ public android.hardware.display.WifiDisplay getActiveDisplay();
+ public int getActiveDisplayState();
+ public android.hardware.display.WifiDisplay[] getDisplays();
+ public int getFeatureState();
+ public int getScanState();
+ public android.hardware.display.WifiDisplaySessionInfo getSessionInfo();
+ public java.lang.String toString();
+ public void writeToParcel(android.os.Parcel, int);
+
+
+ public static android.os.Parcelable$Creator CREATOR;
+ public static int DISPLAY_STATE_CONNECTED;
+ public static int DISPLAY_STATE_CONNECTING;
+ public static int DISPLAY_STATE_NOT_CONNECTED;
+ public static int FEATURE_STATE_DISABLED;
+ public static int FEATURE_STATE_OFF;
+ public static int FEATURE_STATE_ON;
+ public static int FEATURE_STATE_UNAVAILABLE;
+ public static int SCAN_STATE_NOT_SCANNING;
+ public static int SCAN_STATE_SCANNING;
+}
+
+-keep class android.hardware.input.InputDeviceIdentifier {
+ <init>(java.lang.String, int, int);
+
+ public int describeContents();
+ public boolean equals(java.lang.Object);
+ public java.lang.String getDescriptor();
+ public int getProductId();
+ public int getVendorId();
+ public int hashCode();
+ public void writeToParcel(android.os.Parcel, int);
+
+
+ public static android.os.Parcelable$Creator CREATOR;
+}
+
+-keep class android.media.AudioAttributes {
+
+ public java.lang.String contentTypeToString();
+ public int describeContents();
+ public boolean equals(java.lang.Object);
+ public int getAllFlags();
+ public android.os.Bundle getBundle();
+ public int getCapturePreset();
+ public int getContentType();
+ public int getFlags();
+ public java.util.Set getTags();
+ public int getUsage();
+ public int getVolumeControlStream();
+ public int hashCode();
+ public static int toLegacyStreamType(android.media.AudioAttributes);
+ public java.lang.String toString();
+ public java.lang.String usageToString();
+ public static java.lang.String usageToString(int);
+ public void writeToParcel(android.os.Parcel, int);
+ public void writeToProto(android.util.proto.ProtoOutputStream, long);
+
+
public static int CONTENT_TYPE_MOVIE;
public static int CONTENT_TYPE_MUSIC;
public static int CONTENT_TYPE_SONIFICATION;
@@ -3721,11 +12726,29 @@
public static int CONTENT_TYPE_UNKNOWN;
public static android.os.Parcelable$Creator CREATOR;
public static int FLAG_AUDIBILITY_ENFORCED;
+ public static int FLAG_BEACON;
+ public static int FLAG_BYPASS_INTERRUPTION_POLICY;
+ public static int FLAG_BYPASS_MUTE;
+ public static int FLAG_DEEP_BUFFER;
public static int FLAG_HW_AV_SYNC;
+ public static int FLAG_HW_HOTWORD;
+ public static int FLAG_LOW_LATENCY;
+ public static int FLAG_SCO;
+ public static int FLAG_SECURE;
+ public static int FLATTEN_TAGS;
+ public static int[] SDK_USAGES;
+ public static int SUPPRESSIBLE_ALARM;
+ public static int SUPPRESSIBLE_CALL;
+ public static int SUPPRESSIBLE_MEDIA;
+ public static int SUPPRESSIBLE_NEVER;
+ public static int SUPPRESSIBLE_NOTIFICATION;
+ public static int SUPPRESSIBLE_SYSTEM;
+ public static android.util.SparseIntArray SUPPRESSIBLE_USAGES;
public static int USAGE_ALARM;
public static int USAGE_ASSISTANCE_ACCESSIBILITY;
public static int USAGE_ASSISTANCE_NAVIGATION_GUIDANCE;
public static int USAGE_ASSISTANCE_SONIFICATION;
+ public static int USAGE_ASSISTANT;
public static int USAGE_GAME;
public static int USAGE_MEDIA;
public static int USAGE_NOTIFICATION;
@@ -3735,29 +12758,27 @@
public static int USAGE_NOTIFICATION_EVENT;
public static int USAGE_NOTIFICATION_RINGTONE;
public static int USAGE_UNKNOWN;
+ public static int USAGE_VIRTUAL_SOURCE;
public static int USAGE_VOICE_COMMUNICATION;
public static int USAGE_VOICE_COMMUNICATION_SIGNALLING;
}
--keep class android.media.AudioDeviceCallback {
- <init>();
-
- public void onAudioDevicesAdded(android.media.AudioDeviceInfo[]);
- public void onAudioDevicesRemoved(android.media.AudioDeviceInfo[]);
-
-
-}
-
-keep class android.media.AudioDeviceInfo {
+ public static int convertDeviceTypeToInternalDevice(int);
+ public static int convertInternalDeviceToDeviceType(int);
+ public boolean equals(java.lang.Object);
+ public java.lang.String getAddress();
public int[] getChannelCounts();
public int[] getChannelIndexMasks();
public int[] getChannelMasks();
public int[] getEncodings();
public int getId();
+ public android.media.AudioDevicePort getPort();
public java.lang.CharSequence getProductName();
public int[] getSampleRates();
public int getType();
+ public int hashCode();
public boolean isSink();
public boolean isSource();
@@ -3768,11 +12789,13 @@
public static int TYPE_BUILTIN_EARPIECE;
public static int TYPE_BUILTIN_MIC;
public static int TYPE_BUILTIN_SPEAKER;
+ public static int TYPE_BUS;
public static int TYPE_DOCK;
public static int TYPE_FM;
public static int TYPE_FM_TUNER;
public static int TYPE_HDMI;
public static int TYPE_HDMI_ARC;
+ public static int TYPE_HEARING_AID;
public static int TYPE_IP;
public static int TYPE_LINE_ANALOG;
public static int TYPE_LINE_DIGITAL;
@@ -3781,20 +12804,66 @@
public static int TYPE_UNKNOWN;
public static int TYPE_USB_ACCESSORY;
public static int TYPE_USB_DEVICE;
+ public static int TYPE_USB_HEADSET;
public static int TYPE_WIRED_HEADPHONES;
public static int TYPE_WIRED_HEADSET;
}
--keep class android.media.AudioFormat {
+-keep class android.media.AudioDevicePort {
+ public java.lang.String address();
+ public android.media.AudioDevicePortConfig buildConfig(int, int, int, android.media.AudioGainConfig);
+ public android.media.AudioPortConfig buildConfig(int, int, int, android.media.AudioGainConfig);
+ public boolean equals(java.lang.Object);
+ public java.lang.String toString();
+ public int type();
+
+
+}
+
+-keep class android.media.AudioDevicePortConfig {
+
+ public android.media.AudioDevicePort port();
+ public android.media.AudioPort port();
+
+
+}
+
+-keep class android.media.AudioFormat {
+ <init>();
+
+ public static int channelCountFromInChannelMask(int);
+ public static int channelCountFromOutChannelMask(int);
+ public static int convertChannelOutMaskToNativeMask(int);
+ public static int convertNativeChannelMaskToOutMask(int);
+ public int describeContents();
+ public boolean equals(java.lang.Object);
+ public static int[] filterPublicFormats(int[]);
+ public static int getBytesPerSample(int);
public int getChannelCount();
public int getChannelIndexMask();
public int getChannelMask();
public int getEncoding();
+ public int getPropertySetMask();
public int getSampleRate();
+ public int hashCode();
+ public static int inChannelMaskFromOutChannelMask(int);
+ public static boolean isEncodingLinearFrames(int);
+ public static boolean isEncodingLinearPcm(int);
+ public static boolean isPublicEncoding(int);
+ public static boolean isValidEncoding(int);
+ public static java.lang.String toDisplayName(int);
+ public static java.lang.String toLogFriendlyEncoding(int);
+ public java.lang.String toLogFriendlyString();
public java.lang.String toString();
+ public void writeToParcel(android.os.Parcel, int);
+ public static int AUDIO_FORMAT_HAS_PROPERTY_CHANNEL_INDEX_MASK;
+ public static int AUDIO_FORMAT_HAS_PROPERTY_CHANNEL_MASK;
+ public static int AUDIO_FORMAT_HAS_PROPERTY_ENCODING;
+ public static int AUDIO_FORMAT_HAS_PROPERTY_NONE;
+ public static int AUDIO_FORMAT_HAS_PROPERTY_SAMPLE_RATE;
public static int CHANNEL_CONFIGURATION_DEFAULT;
public static int CHANNEL_CONFIGURATION_INVALID;
public static int CHANNEL_CONFIGURATION_MONO;
@@ -3804,6 +12873,7 @@
public static int CHANNEL_IN_BACK_PROCESSED;
public static int CHANNEL_IN_DEFAULT;
public static int CHANNEL_IN_FRONT;
+ public static int CHANNEL_IN_FRONT_BACK;
public static int CHANNEL_IN_FRONT_PROCESSED;
public static int CHANNEL_IN_LEFT;
public static int CHANNEL_IN_LEFT_PROCESSED;
@@ -3818,6 +12888,7 @@
public static int CHANNEL_IN_Y_AXIS;
public static int CHANNEL_IN_Z_AXIS;
public static int CHANNEL_OUT_5POINT1;
+ public static int CHANNEL_OUT_5POINT1_SIDE;
public static int CHANNEL_OUT_7POINT1;
public static int CHANNEL_OUT_7POINT1_SURROUND;
public static int CHANNEL_OUT_BACK_CENTER;
@@ -3832,174 +12903,220 @@
public static int CHANNEL_OUT_LOW_FREQUENCY;
public static int CHANNEL_OUT_MONO;
public static int CHANNEL_OUT_QUAD;
+ public static int CHANNEL_OUT_QUAD_SIDE;
public static int CHANNEL_OUT_SIDE_LEFT;
public static int CHANNEL_OUT_SIDE_RIGHT;
public static int CHANNEL_OUT_STEREO;
public static int CHANNEL_OUT_SURROUND;
+ public static int CHANNEL_OUT_TOP_BACK_CENTER;
+ public static int CHANNEL_OUT_TOP_BACK_LEFT;
+ public static int CHANNEL_OUT_TOP_BACK_RIGHT;
+ public static int CHANNEL_OUT_TOP_CENTER;
+ public static int CHANNEL_OUT_TOP_FRONT_CENTER;
+ public static int CHANNEL_OUT_TOP_FRONT_LEFT;
+ public static int CHANNEL_OUT_TOP_FRONT_RIGHT;
+ public static android.os.Parcelable$Creator CREATOR;
+ public static int ENCODING_AAC_ELD;
+ public static int ENCODING_AAC_HE_V1;
+ public static int ENCODING_AAC_HE_V2;
+ public static int ENCODING_AAC_LC;
+ public static int ENCODING_AAC_XHE;
public static int ENCODING_AC3;
+ public static int ENCODING_AC4;
public static int ENCODING_DEFAULT;
+ public static int ENCODING_DOLBY_TRUEHD;
public static int ENCODING_DTS;
public static int ENCODING_DTS_HD;
public static int ENCODING_E_AC3;
+ public static int ENCODING_E_AC3_JOC;
+ public static int ENCODING_IEC61937;
public static int ENCODING_INVALID;
+ public static int ENCODING_MP3;
public static int ENCODING_PCM_16BIT;
public static int ENCODING_PCM_8BIT;
public static int ENCODING_PCM_FLOAT;
+ public static int SAMPLE_RATE_HZ_MAX;
+ public static int SAMPLE_RATE_HZ_MIN;
+ public static int SAMPLE_RATE_UNSPECIFIED;
+ public static int[] SURROUND_SOUND_ENCODING;
}
--keep class android.media.AudioManager {
+-keep class android.media.AudioGain {
- public int abandonAudioFocus(android.media.AudioManager$OnAudioFocusChangeListener);
- public void adjustStreamVolume(int, int, int);
- public void adjustSuggestedStreamVolume(int, int, int);
- public void adjustVolume(int, int);
- public void dispatchMediaKeyEvent(android.view.KeyEvent);
- public int generateAudioSessionId();
- public android.media.AudioDeviceInfo[] getDevices(int);
- public int getMode();
- public java.lang.String getParameters(java.lang.String);
- public java.lang.String getProperty(java.lang.String);
- public int getRingerMode();
- public int getRouting(int);
- public int getStreamMaxVolume(int);
- public int getStreamVolume(int);
- public int getVibrateSetting(int);
- public boolean isBluetoothA2dpOn();
- public boolean isBluetoothScoAvailableOffCall();
- public boolean isBluetoothScoOn();
- public boolean isMicrophoneMute();
- public boolean isMusicActive();
- public boolean isSpeakerphoneOn();
- public boolean isStreamMute(int);
- public boolean isVolumeFixed();
- public boolean isWiredHeadsetOn();
- public void loadSoundEffects();
- public void playSoundEffect(int);
- public void playSoundEffect(int, float);
- public void registerAudioDeviceCallback(android.media.AudioDeviceCallback, android.os.Handler);
- public void registerMediaButtonEventReceiver(android.content.ComponentName);
- public void registerMediaButtonEventReceiver(android.app.PendingIntent);
- public void registerRemoteControlClient(android.media.RemoteControlClient);
- public boolean registerRemoteController(android.media.RemoteController);
- public int requestAudioFocus(android.media.AudioManager$OnAudioFocusChangeListener, int, int);
- public void setBluetoothA2dpOn(boolean);
- public void setBluetoothScoOn(boolean);
- public void setMicrophoneMute(boolean);
- public void setMode(int);
- public void setParameters(java.lang.String);
- public void setRingerMode(int);
- public void setRouting(int, int, int);
- public void setSpeakerphoneOn(boolean);
- public void setStreamMute(int, boolean);
- public void setStreamSolo(int, boolean);
- public void setStreamVolume(int, int, int);
- public void setVibrateSetting(int, int);
- public void setWiredHeadsetOn(boolean);
- public boolean shouldVibrate(int);
- public void startBluetoothSco();
- public void stopBluetoothSco();
- public void unloadSoundEffects();
- public void unregisterAudioDeviceCallback(android.media.AudioDeviceCallback);
- public void unregisterMediaButtonEventReceiver(android.content.ComponentName);
- public void unregisterMediaButtonEventReceiver(android.app.PendingIntent);
- public void unregisterRemoteControlClient(android.media.RemoteControlClient);
- public void unregisterRemoteController(android.media.RemoteController);
+ public android.media.AudioGainConfig buildConfig(int, int, int[], int);
+ public int channelMask();
+ public int defaultValue();
+ public int maxValue();
+ public int minValue();
+ public int mode();
+ public int rampDurationMaxMs();
+ public int rampDurationMinMs();
+ public int stepValue();
- public static java.lang.String ACTION_AUDIO_BECOMING_NOISY;
- public static java.lang.String ACTION_HDMI_AUDIO_PLUG;
- public static java.lang.String ACTION_HEADSET_PLUG;
- public static java.lang.String ACTION_SCO_AUDIO_STATE_CHANGED;
- public static java.lang.String ACTION_SCO_AUDIO_STATE_UPDATED;
- public static int ADJUST_LOWER;
- public static int ADJUST_MUTE;
- public static int ADJUST_RAISE;
- public static int ADJUST_SAME;
- public static int ADJUST_TOGGLE_MUTE;
- public static int ADJUST_UNMUTE;
- public static int AUDIOFOCUS_GAIN;
- public static int AUDIOFOCUS_GAIN_TRANSIENT;
- public static int AUDIOFOCUS_GAIN_TRANSIENT_EXCLUSIVE;
- public static int AUDIOFOCUS_GAIN_TRANSIENT_MAY_DUCK;
- public static int AUDIOFOCUS_LOSS;
- public static int AUDIOFOCUS_LOSS_TRANSIENT;
- public static int AUDIOFOCUS_LOSS_TRANSIENT_CAN_DUCK;
- public static int AUDIOFOCUS_REQUEST_FAILED;
- public static int AUDIOFOCUS_REQUEST_GRANTED;
- public static int AUDIO_SESSION_ID_GENERATE;
+ public static int MODE_CHANNELS;
+ public static int MODE_JOINT;
+ public static int MODE_RAMP;
+}
+
+-keep class android.media.AudioGainConfig {
+
+ public int channelMask();
+ public int mode();
+ public int rampDurationMs();
+ public int[] values();
+
+
+}
+
+-keep class android.media.AudioPort {
+
+ public android.media.AudioPortConfig activeConfig();
+ public android.media.AudioPortConfig buildConfig(int, int, int, android.media.AudioGainConfig);
+ public int[] channelIndexMasks();
+ public int[] channelMasks();
+ public boolean equals(java.lang.Object);
+ public int[] formats();
+ public android.media.AudioGain[] gains();
+ public int hashCode();
+ public int id();
+ public java.lang.String name();
+ public int role();
+ public int[] samplingRates();
+ public java.lang.String toString();
+
+
+ public static int ROLE_NONE;
+ public static int ROLE_SINK;
+ public static int ROLE_SOURCE;
+ public static int TYPE_DEVICE;
+ public static int TYPE_NONE;
+ public static int TYPE_SESSION;
+ public static int TYPE_SUBMIX;
+ protected int mRole;
+}
+
+-keep class android.media.AudioPortConfig {
+
+ public int channelMask();
+ public int format();
+ public android.media.AudioGainConfig gain();
+ public android.media.AudioPort port();
+ public int samplingRate();
+ public java.lang.String toString();
+
+
+}
+
+-keep class android.media.AudioRecord {
+ <init>(int, int, int, int, int);
+ <init>(android.media.AudioAttributes, android.media.AudioFormat, int, int);
+
+ public void addOnRoutingChangedListener(android.media.AudioRouting$OnRoutingChangedListener, android.os.Handler);
+ public void addOnRoutingChangedListener(android.media.AudioRecord$OnRoutingChangedListener, android.os.Handler);
+ protected void finalize();
+ public java.util.List getActiveMicrophones();
+ public int getAudioFormat();
+ public int getAudioSessionId();
+ public int getAudioSource();
+ public int getBufferSizeInFrames();
+ public int getChannelConfiguration();
+ public int getChannelCount();
+ public android.media.AudioFormat getFormat();
+ public android.os.PersistableBundle getMetrics();
+ public static int getMinBufferSize(int, int, int);
+ public int getNotificationMarkerPosition();
+ public int getPositionNotificationPeriod();
+ public android.media.AudioDeviceInfo getPreferredDevice();
+ public int getRecordingState();
+ public android.media.AudioDeviceInfo getRoutedDevice();
+ public int getSampleRate();
+ public int getState();
+ public int getTimestamp(android.media.AudioTimestamp, int);
+ public void native_release();
+ public int read(byte[], int, int);
+ public int read(byte[], int, int, int);
+ public int read(short[], int, int);
+ public int read(short[], int, int, int);
+ public int read(float[], int, int, int);
+ public int read(java.nio.ByteBuffer, int);
+ public int read(java.nio.ByteBuffer, int, int);
+ public void release();
+ public void removeOnRoutingChangedListener(android.media.AudioRouting$OnRoutingChangedListener);
+ public void removeOnRoutingChangedListener(android.media.AudioRecord$OnRoutingChangedListener);
+ public int setNotificationMarkerPosition(int);
+ public int setPositionNotificationPeriod(int);
+ public boolean setPreferredDevice(android.media.AudioDeviceInfo);
+ public void setRecordPositionUpdateListener(android.media.AudioRecord$OnRecordPositionUpdateListener);
+ public void setRecordPositionUpdateListener(android.media.AudioRecord$OnRecordPositionUpdateListener, android.os.Handler);
+ public void startRecording();
+ public void startRecording(android.media.MediaSyncEvent);
+ public void stop();
+
+
public static int ERROR;
+ public static int ERROR_BAD_VALUE;
public static int ERROR_DEAD_OBJECT;
- public static java.lang.String EXTRA_AUDIO_PLUG_STATE;
- public static java.lang.String EXTRA_ENCODINGS;
- public static java.lang.String EXTRA_MAX_CHANNEL_COUNT;
- public static java.lang.String EXTRA_RINGER_MODE;
- public static java.lang.String EXTRA_SCO_AUDIO_PREVIOUS_STATE;
- public static java.lang.String EXTRA_SCO_AUDIO_STATE;
- public static java.lang.String EXTRA_VIBRATE_SETTING;
- public static java.lang.String EXTRA_VIBRATE_TYPE;
- public static int FLAG_ALLOW_RINGER_MODES;
- public static int FLAG_PLAY_SOUND;
- public static int FLAG_REMOVE_SOUND_AND_VIBRATE;
- public static int FLAG_SHOW_UI;
- public static int FLAG_VIBRATE;
- public static int FX_FOCUS_NAVIGATION_DOWN;
- public static int FX_FOCUS_NAVIGATION_LEFT;
- public static int FX_FOCUS_NAVIGATION_RIGHT;
- public static int FX_FOCUS_NAVIGATION_UP;
- public static int FX_KEYPRESS_DELETE;
- public static int FX_KEYPRESS_INVALID;
- public static int FX_KEYPRESS_RETURN;
- public static int FX_KEYPRESS_SPACEBAR;
- public static int FX_KEYPRESS_STANDARD;
- public static int FX_KEY_CLICK;
- public static int GET_DEVICES_ALL;
- public static int GET_DEVICES_INPUTS;
- public static int GET_DEVICES_OUTPUTS;
- public static int MODE_CURRENT;
- public static int MODE_INVALID;
- public static int MODE_IN_CALL;
- public static int MODE_IN_COMMUNICATION;
- public static int MODE_NORMAL;
- public static int MODE_RINGTONE;
- public static int NUM_STREAMS;
- public static java.lang.String PROPERTY_OUTPUT_FRAMES_PER_BUFFER;
- public static java.lang.String PROPERTY_OUTPUT_SAMPLE_RATE;
- public static java.lang.String PROPERTY_SUPPORT_MIC_NEAR_ULTRASOUND;
- public static java.lang.String PROPERTY_SUPPORT_SPEAKER_NEAR_ULTRASOUND;
- public static java.lang.String RINGER_MODE_CHANGED_ACTION;
- public static int RINGER_MODE_NORMAL;
- public static int RINGER_MODE_SILENT;
- public static int RINGER_MODE_VIBRATE;
- public static int ROUTE_ALL;
- public static int ROUTE_BLUETOOTH;
- public static int ROUTE_BLUETOOTH_A2DP;
- public static int ROUTE_BLUETOOTH_SCO;
- public static int ROUTE_EARPIECE;
- public static int ROUTE_HEADSET;
- public static int ROUTE_SPEAKER;
- public static int SCO_AUDIO_STATE_CONNECTED;
- public static int SCO_AUDIO_STATE_CONNECTING;
- public static int SCO_AUDIO_STATE_DISCONNECTED;
- public static int SCO_AUDIO_STATE_ERROR;
- public static int STREAM_ALARM;
- public static int STREAM_DTMF;
- public static int STREAM_MUSIC;
- public static int STREAM_NOTIFICATION;
- public static int STREAM_RING;
- public static int STREAM_SYSTEM;
- public static int STREAM_VOICE_CALL;
- public static int USE_DEFAULT_STREAM_TYPE;
- public static java.lang.String VIBRATE_SETTING_CHANGED_ACTION;
- public static int VIBRATE_SETTING_OFF;
- public static int VIBRATE_SETTING_ON;
- public static int VIBRATE_SETTING_ONLY_SILENT;
- public static int VIBRATE_TYPE_NOTIFICATION;
- public static int VIBRATE_TYPE_RINGER;
+ public static int ERROR_INVALID_OPERATION;
+ public static int READ_BLOCKING;
+ public static int READ_NON_BLOCKING;
+ public static int RECORDSTATE_RECORDING;
+ public static int RECORDSTATE_STOPPED;
+ public static int STATE_INITIALIZED;
+ public static int STATE_UNINITIALIZED;
+ public static java.lang.String SUBMIX_FIXED_VOLUME;
+ public static int SUCCESS;
}
--keep class android.media.AudioManager$OnAudioFocusChangeListener {
+-keep class android.media.AudioRecord$OnRecordPositionUpdateListener {
- public abstract void onAudioFocusChange(int);
+ public abstract void onMarkerReached(android.media.AudioRecord);
+ public abstract void onPeriodicNotification(android.media.AudioRecord);
+
+
+}
+
+-keep class android.media.AudioRecord$OnRoutingChangedListener {
+
+ public abstract void onRoutingChanged(android.media.AudioRecord);
+ public void onRoutingChanged(android.media.AudioRouting);
+
+
+}
+
+-keep class android.media.AudioRouting {
+
+ public abstract void addOnRoutingChangedListener(android.media.AudioRouting$OnRoutingChangedListener, android.os.Handler);
+ public abstract android.media.AudioDeviceInfo getPreferredDevice();
+ public abstract android.media.AudioDeviceInfo getRoutedDevice();
+ public abstract void removeOnRoutingChangedListener(android.media.AudioRouting$OnRoutingChangedListener);
+ public abstract boolean setPreferredDevice(android.media.AudioDeviceInfo);
+
+
+}
+
+-keep class android.media.AudioRouting$OnRoutingChangedListener {
+
+ public abstract void onRoutingChanged(android.media.AudioRouting);
+
+
+}
+
+-keep class android.media.AudioTimestamp {
+ <init>();
+
+
+
+ public static int TIMEBASE_BOOTTIME;
+ public static int TIMEBASE_MONOTONIC;
+ public long framePosition;
+ public long nanoTime;
+}
+
+-keep class android.media.IRemoteVolumeController {
+
+ public abstract void remoteVolumeChanged(android.media.session.ISessionController, int);
+ public abstract void updateRemoteController(android.media.session.ISessionController);
}
@@ -4007,6 +13124,7 @@
-keep class android.media.MediaDescription {
public int describeContents();
+ public boolean equals(java.lang.Object);
public java.lang.CharSequence getDescription();
public android.os.Bundle getExtras();
public android.graphics.Bitmap getIconBitmap();
@@ -4019,19 +13137,30 @@
public void writeToParcel(android.os.Parcel, int);
+ public static long BT_FOLDER_TYPE_ALBUMS;
+ public static long BT_FOLDER_TYPE_ARTISTS;
+ public static long BT_FOLDER_TYPE_GENRES;
+ public static long BT_FOLDER_TYPE_MIXED;
+ public static long BT_FOLDER_TYPE_PLAYLISTS;
+ public static long BT_FOLDER_TYPE_TITLES;
+ public static long BT_FOLDER_TYPE_YEARS;
public static android.os.Parcelable$Creator CREATOR;
+ public static java.lang.String EXTRA_BT_FOLDER_TYPE;
}
-keep class android.media.MediaMetadata {
public boolean containsKey(java.lang.String);
public int describeContents();
+ public boolean equals(java.lang.Object);
public android.graphics.Bitmap getBitmap(java.lang.String);
public android.media.MediaDescription getDescription();
+ public static java.lang.String getKeyFromMetadataEditorKey(int);
public long getLong(java.lang.String);
public android.media.Rating getRating(java.lang.String);
public java.lang.String getString(java.lang.String);
public java.lang.CharSequence getText(java.lang.String);
+ public int hashCode();
public java.util.Set keySet();
public int size();
public void writeToParcel(android.os.Parcel, int);
@@ -4046,6 +13175,7 @@
public static java.lang.String METADATA_KEY_ARTIST;
public static java.lang.String METADATA_KEY_ART_URI;
public static java.lang.String METADATA_KEY_AUTHOR;
+ public static java.lang.String METADATA_KEY_BT_FOLDER_TYPE;
public static java.lang.String METADATA_KEY_COMPILATION;
public static java.lang.String METADATA_KEY_COMPOSER;
public static java.lang.String METADATA_KEY_DATE;
@@ -4058,6 +13188,7 @@
public static java.lang.String METADATA_KEY_DURATION;
public static java.lang.String METADATA_KEY_GENRE;
public static java.lang.String METADATA_KEY_MEDIA_ID;
+ public static java.lang.String METADATA_KEY_MEDIA_URI;
public static java.lang.String METADATA_KEY_NUM_TRACKS;
public static java.lang.String METADATA_KEY_RATING;
public static java.lang.String METADATA_KEY_TITLE;
@@ -4067,26 +13198,68 @@
public static java.lang.String METADATA_KEY_YEAR;
}
--keep class android.media.MediaMetadataEditor {
+-keep class android.media.MediaSyncEvent {
- public synchronized void addEditableKey(int);
- public abstract void apply();
- public synchronized void clear();
- public synchronized android.graphics.Bitmap getBitmap(int, android.graphics.Bitmap);
- public synchronized int[] getEditableKeys();
- public synchronized long getLong(int, long);
- public synchronized java.lang.Object getObject(int, java.lang.Object);
- public synchronized java.lang.String getString(int, java.lang.String);
- public synchronized android.media.MediaMetadataEditor putBitmap(int, android.graphics.Bitmap);
- public synchronized android.media.MediaMetadataEditor putLong(int, long);
- public synchronized android.media.MediaMetadataEditor putObject(int, java.lang.Object);
- public synchronized android.media.MediaMetadataEditor putString(int, java.lang.String);
- public synchronized void removeEditableKeys();
+ public static android.media.MediaSyncEvent createEvent(int);
+ public int getAudioSessionId();
+ public int getType();
+ public android.media.MediaSyncEvent setAudioSessionId(int);
- public static int BITMAP_KEY_ARTWORK;
- public static int RATING_KEY_BY_OTHERS;
- public static int RATING_KEY_BY_USER;
+ public static int SYNC_EVENT_NONE;
+ public static int SYNC_EVENT_PRESENTATION_COMPLETE;
+}
+
+-keep class android.media.MicrophoneInfo {
+
+ public java.lang.String getAddress();
+ public java.util.List getChannelMapping();
+ public java.lang.String getDescription();
+ public int getDirectionality();
+ public java.util.List getFrequencyResponse();
+ public int getGroup();
+ public int getId();
+ public int getIndexInTheGroup();
+ public int getInternalDeviceType();
+ public int getLocation();
+ public float getMaxSpl();
+ public float getMinSpl();
+ public android.media.MicrophoneInfo$Coordinate3F getOrientation();
+ public android.media.MicrophoneInfo$Coordinate3F getPosition();
+ public float getSensitivity();
+ public int getType();
+ public void setChannelMapping(java.util.List);
+ public void setId(int);
+
+
+ public static int CHANNEL_MAPPING_DIRECT;
+ public static int CHANNEL_MAPPING_PROCESSED;
+ public static int DIRECTIONALITY_BI_DIRECTIONAL;
+ public static int DIRECTIONALITY_CARDIOID;
+ public static int DIRECTIONALITY_HYPER_CARDIOID;
+ public static int DIRECTIONALITY_OMNI;
+ public static int DIRECTIONALITY_SUPER_CARDIOID;
+ public static int DIRECTIONALITY_UNKNOWN;
+ public static int GROUP_UNKNOWN;
+ public static int INDEX_IN_THE_GROUP_UNKNOWN;
+ public static int LOCATION_MAINBODY;
+ public static int LOCATION_MAINBODY_MOVABLE;
+ public static int LOCATION_PERIPHERAL;
+ public static int LOCATION_UNKNOWN;
+ public static android.media.MicrophoneInfo$Coordinate3F ORIENTATION_UNKNOWN;
+ public static android.media.MicrophoneInfo$Coordinate3F POSITION_UNKNOWN;
+ public static float SENSITIVITY_UNKNOWN;
+ public static float SPL_UNKNOWN;
+}
+
+-keep class android.media.MicrophoneInfo$Coordinate3F {
+
+ public boolean equals(java.lang.Object);
+
+
+ public float x;
+ public float y;
+ public float z;
}
-keep class android.media.Rating {
@@ -4117,112 +13290,26 @@
public static int RATING_THUMB_UP_DOWN;
}
--keep class android.media.RemoteControlClient {
- <init>(android.app.PendingIntent);
- <init>(android.app.PendingIntent, android.os.Looper);
+-keep class android.media.SessionToken2 {
+ <init>(android.content.Context, java.lang.String, java.lang.String);
+ <init>(android.content.Context, java.lang.String, java.lang.String, int);
+ <init>(android.media.update.SessionToken2Provider);
- public android.media.RemoteControlClient$MetadataEditor editMetadata(boolean);
- public android.media.session.MediaSession getMediaSession();
- public void setMetadataUpdateListener(android.media.RemoteControlClient$OnMetadataUpdateListener);
- public void setOnGetPlaybackPositionListener(android.media.RemoteControlClient$OnGetPlaybackPositionListener);
- public void setPlaybackPositionUpdateListener(android.media.RemoteControlClient$OnPlaybackPositionUpdateListener);
- public void setPlaybackState(int);
- public void setPlaybackState(int, long, float);
- public void setTransportControlFlags(int);
+ public boolean equals(java.lang.Object);
+ public static android.media.SessionToken2 fromBundle(android.os.Bundle);
+ public java.lang.String getId();
+ public java.lang.String getPackageName();
+ public android.media.update.SessionToken2Provider getProvider();
+ public int getType();
+ public int getUid();
+ public int hashCode();
+ public android.os.Bundle toBundle();
+ public java.lang.String toString();
- public static int FLAG_KEY_MEDIA_FAST_FORWARD;
- public static int FLAG_KEY_MEDIA_NEXT;
- public static int FLAG_KEY_MEDIA_PAUSE;
- public static int FLAG_KEY_MEDIA_PLAY;
- public static int FLAG_KEY_MEDIA_PLAY_PAUSE;
- public static int FLAG_KEY_MEDIA_POSITION_UPDATE;
- public static int FLAG_KEY_MEDIA_PREVIOUS;
- public static int FLAG_KEY_MEDIA_RATING;
- public static int FLAG_KEY_MEDIA_REWIND;
- public static int FLAG_KEY_MEDIA_STOP;
- public static int PLAYSTATE_BUFFERING;
- public static int PLAYSTATE_ERROR;
- public static int PLAYSTATE_FAST_FORWARDING;
- public static int PLAYSTATE_PAUSED;
- public static int PLAYSTATE_PLAYING;
- public static int PLAYSTATE_REWINDING;
- public static int PLAYSTATE_SKIPPING_BACKWARDS;
- public static int PLAYSTATE_SKIPPING_FORWARDS;
- public static int PLAYSTATE_STOPPED;
-}
-
--keep class android.media.RemoteControlClient$MetadataEditor {
-
- public synchronized void apply();
- public synchronized void clear();
- public synchronized android.media.RemoteControlClient$MetadataEditor putBitmap(int, android.graphics.Bitmap);
- public android.media.MediaMetadataEditor putBitmap(int, android.graphics.Bitmap);
- public synchronized android.media.RemoteControlClient$MetadataEditor putLong(int, long);
- public android.media.MediaMetadataEditor putLong(int, long);
- public synchronized android.media.RemoteControlClient$MetadataEditor putObject(int, java.lang.Object);
- public android.media.MediaMetadataEditor putObject(int, java.lang.Object);
- public synchronized android.media.RemoteControlClient$MetadataEditor putString(int, java.lang.String);
- public android.media.MediaMetadataEditor putString(int, java.lang.String);
-
-
- public static int BITMAP_KEY_ARTWORK;
-}
-
--keep class android.media.RemoteControlClient$OnGetPlaybackPositionListener {
-
- public abstract long onGetPlaybackPosition();
-
-
-}
-
--keep class android.media.RemoteControlClient$OnMetadataUpdateListener {
-
- public abstract void onMetadataUpdate(int, java.lang.Object);
-
-
-}
-
--keep class android.media.RemoteControlClient$OnPlaybackPositionUpdateListener {
-
- public abstract void onPlaybackPositionUpdate(long);
-
-
-}
-
--keep class android.media.RemoteController {
- <init>(android.content.Context, android.media.RemoteController$OnClientUpdateListener);
- <init>(android.content.Context, android.media.RemoteController$OnClientUpdateListener, android.os.Looper);
-
- public boolean clearArtworkConfiguration();
- public android.media.RemoteController$MetadataEditor editMetadata();
- public long getEstimatedMediaPosition();
- public boolean seekTo(long);
- public boolean sendMediaKeyEvent(android.view.KeyEvent);
- public boolean setArtworkConfiguration(int, int);
- public boolean setSynchronizationMode(int);
-
-
- public static int POSITION_SYNCHRONIZATION_CHECK;
- public static int POSITION_SYNCHRONIZATION_NONE;
-}
-
--keep class android.media.RemoteController$MetadataEditor {
-
- public synchronized void apply();
-
-
-}
-
--keep class android.media.RemoteController$OnClientUpdateListener {
-
- public abstract void onClientChange(boolean);
- public abstract void onClientMetadataUpdate(android.media.RemoteController$MetadataEditor);
- public abstract void onClientPlaybackStateUpdate(int);
- public abstract void onClientPlaybackStateUpdate(int, long, long, float);
- public abstract void onClientTransportControlUpdate(int);
-
-
+ public static int TYPE_LIBRARY_SERVICE;
+ public static int TYPE_SESSION;
+ public static int TYPE_SESSION_SERVICE;
}
-keep class android.media.VolumeProvider {
@@ -4233,6 +13320,7 @@
public int getVolumeControl();
public void onAdjustVolume(int);
public void onSetVolumeTo(int);
+ public void setCallback(android.media.VolumeProvider$Callback);
public void setCurrentVolume(int);
@@ -4241,11 +13329,183 @@
public static int VOLUME_CONTROL_RELATIVE;
}
+-keep class android.media.VolumeProvider$Callback {
+ <init>();
+
+ public abstract void onVolumeChanged(android.media.VolumeProvider);
+
+
+}
+
+-keep class android.media.projection.IMediaProjection {
+
+ public abstract int applyVirtualDisplayFlags(int);
+ public abstract boolean canProjectAudio();
+ public abstract boolean canProjectSecureVideo();
+ public abstract boolean canProjectVideo();
+ public abstract void registerCallback(android.media.projection.IMediaProjectionCallback);
+ public abstract void start(android.media.projection.IMediaProjectionCallback);
+ public abstract void stop();
+ public abstract void unregisterCallback(android.media.projection.IMediaProjectionCallback);
+
+
+}
+
+-keep class android.media.projection.IMediaProjectionCallback {
+
+ public abstract void onStop();
+
+
+}
+
+-keep class android.media.projection.MediaProjection {
+ <init>(android.content.Context, android.media.projection.IMediaProjection);
+
+ public android.media.AudioRecord createAudioRecord(int, int, int, int);
+ public android.hardware.display.VirtualDisplay createVirtualDisplay(java.lang.String, int, int, int, boolean, android.view.Surface, android.hardware.display.VirtualDisplay$Callback, android.os.Handler);
+ public android.hardware.display.VirtualDisplay createVirtualDisplay(java.lang.String, int, int, int, int, android.view.Surface, android.hardware.display.VirtualDisplay$Callback, android.os.Handler);
+ public android.media.projection.IMediaProjection getProjection();
+ public void registerCallback(android.media.projection.MediaProjection$Callback, android.os.Handler);
+ public void stop();
+ public void unregisterCallback(android.media.projection.MediaProjection$Callback);
+
+
+}
+
+-keep class android.media.projection.MediaProjection$Callback {
+ <init>();
+
+ public void onStop();
+
+
+}
+
+-keep class android.media.session.ISession {
+
+ public abstract void destroy();
+ public abstract android.media.session.ISessionController getController();
+ public abstract void sendEvent(java.lang.String, android.os.Bundle);
+ public abstract void setActive(boolean);
+ public abstract void setCurrentVolume(int);
+ public abstract void setExtras(android.os.Bundle);
+ public abstract void setFlags(int);
+ public abstract void setLaunchPendingIntent(android.app.PendingIntent);
+ public abstract void setMediaButtonReceiver(android.app.PendingIntent);
+ public abstract void setMetadata(android.media.MediaMetadata);
+ public abstract void setPlaybackState(android.media.session.PlaybackState);
+ public abstract void setPlaybackToLocal(android.media.AudioAttributes);
+ public abstract void setPlaybackToRemote(int, int);
+ public abstract void setQueue(android.content.pm.ParceledListSlice);
+ public abstract void setQueueTitle(java.lang.CharSequence);
+ public abstract void setRatingType(int);
+
+
+}
+
+-keep class android.media.session.ISessionCallback {
+
+ public abstract void onAdjustVolume(java.lang.String, int, int, android.media.session.ISessionControllerCallback, int);
+ public abstract void onCommand(java.lang.String, int, int, android.media.session.ISessionControllerCallback, java.lang.String, android.os.Bundle, android.os.ResultReceiver);
+ public abstract void onCustomAction(java.lang.String, int, int, android.media.session.ISessionControllerCallback, java.lang.String, android.os.Bundle);
+ public abstract void onFastForward(java.lang.String, int, int, android.media.session.ISessionControllerCallback);
+ public abstract void onMediaButton(java.lang.String, int, int, android.content.Intent, int, android.os.ResultReceiver);
+ public abstract void onMediaButtonFromController(java.lang.String, int, int, android.media.session.ISessionControllerCallback, android.content.Intent);
+ public abstract void onNext(java.lang.String, int, int, android.media.session.ISessionControllerCallback);
+ public abstract void onPause(java.lang.String, int, int, android.media.session.ISessionControllerCallback);
+ public abstract void onPlay(java.lang.String, int, int, android.media.session.ISessionControllerCallback);
+ public abstract void onPlayFromMediaId(java.lang.String, int, int, android.media.session.ISessionControllerCallback, java.lang.String, android.os.Bundle);
+ public abstract void onPlayFromSearch(java.lang.String, int, int, android.media.session.ISessionControllerCallback, java.lang.String, android.os.Bundle);
+ public abstract void onPlayFromUri(java.lang.String, int, int, android.media.session.ISessionControllerCallback, android.net.Uri, android.os.Bundle);
+ public abstract void onPrepare(java.lang.String, int, int, android.media.session.ISessionControllerCallback);
+ public abstract void onPrepareFromMediaId(java.lang.String, int, int, android.media.session.ISessionControllerCallback, java.lang.String, android.os.Bundle);
+ public abstract void onPrepareFromSearch(java.lang.String, int, int, android.media.session.ISessionControllerCallback, java.lang.String, android.os.Bundle);
+ public abstract void onPrepareFromUri(java.lang.String, int, int, android.media.session.ISessionControllerCallback, android.net.Uri, android.os.Bundle);
+ public abstract void onPrevious(java.lang.String, int, int, android.media.session.ISessionControllerCallback);
+ public abstract void onRate(java.lang.String, int, int, android.media.session.ISessionControllerCallback, android.media.Rating);
+ public abstract void onRewind(java.lang.String, int, int, android.media.session.ISessionControllerCallback);
+ public abstract void onSeekTo(java.lang.String, int, int, android.media.session.ISessionControllerCallback, long);
+ public abstract void onSetVolumeTo(java.lang.String, int, int, android.media.session.ISessionControllerCallback, int);
+ public abstract void onSkipToTrack(java.lang.String, int, int, android.media.session.ISessionControllerCallback, long);
+ public abstract void onStop(java.lang.String, int, int, android.media.session.ISessionControllerCallback);
+
+
+}
+
+-keep class android.media.session.ISessionCallback$Stub {
+ <init>();
+
+ public android.os.IBinder asBinder();
+ public static android.media.session.ISessionCallback asInterface(android.os.IBinder);
+ public boolean onTransact(int, android.os.Parcel, android.os.Parcel, int);
+
+
+}
+
+-keep class android.media.session.ISessionController {
+
+ public abstract void adjustVolume(java.lang.String, android.media.session.ISessionControllerCallback, boolean, int, int);
+ public abstract void fastForward(java.lang.String, android.media.session.ISessionControllerCallback);
+ public abstract android.os.Bundle getExtras();
+ public abstract long getFlags();
+ public abstract android.app.PendingIntent getLaunchPendingIntent();
+ public abstract android.media.MediaMetadata getMetadata();
+ public abstract java.lang.String getPackageName();
+ public abstract android.media.session.PlaybackState getPlaybackState();
+ public abstract android.content.pm.ParceledListSlice getQueue();
+ public abstract java.lang.CharSequence getQueueTitle();
+ public abstract int getRatingType();
+ public abstract java.lang.String getTag();
+ public abstract android.media.session.ParcelableVolumeInfo getVolumeAttributes();
+ public abstract boolean isTransportControlEnabled();
+ public abstract void next(java.lang.String, android.media.session.ISessionControllerCallback);
+ public abstract void pause(java.lang.String, android.media.session.ISessionControllerCallback);
+ public abstract void play(java.lang.String, android.media.session.ISessionControllerCallback);
+ public abstract void playFromMediaId(java.lang.String, android.media.session.ISessionControllerCallback, java.lang.String, android.os.Bundle);
+ public abstract void playFromSearch(java.lang.String, android.media.session.ISessionControllerCallback, java.lang.String, android.os.Bundle);
+ public abstract void playFromUri(java.lang.String, android.media.session.ISessionControllerCallback, android.net.Uri, android.os.Bundle);
+ public abstract void prepare(java.lang.String, android.media.session.ISessionControllerCallback);
+ public abstract void prepareFromMediaId(java.lang.String, android.media.session.ISessionControllerCallback, java.lang.String, android.os.Bundle);
+ public abstract void prepareFromSearch(java.lang.String, android.media.session.ISessionControllerCallback, java.lang.String, android.os.Bundle);
+ public abstract void prepareFromUri(java.lang.String, android.media.session.ISessionControllerCallback, android.net.Uri, android.os.Bundle);
+ public abstract void previous(java.lang.String, android.media.session.ISessionControllerCallback);
+ public abstract void rate(java.lang.String, android.media.session.ISessionControllerCallback, android.media.Rating);
+ public abstract void registerCallbackListener(java.lang.String, android.media.session.ISessionControllerCallback);
+ public abstract void rewind(java.lang.String, android.media.session.ISessionControllerCallback);
+ public abstract void seekTo(java.lang.String, android.media.session.ISessionControllerCallback, long);
+ public abstract void sendCommand(java.lang.String, android.media.session.ISessionControllerCallback, java.lang.String, android.os.Bundle, android.os.ResultReceiver);
+ public abstract void sendCustomAction(java.lang.String, android.media.session.ISessionControllerCallback, java.lang.String, android.os.Bundle);
+ public abstract boolean sendMediaButton(java.lang.String, android.media.session.ISessionControllerCallback, boolean, android.view.KeyEvent);
+ public abstract void setVolumeTo(java.lang.String, android.media.session.ISessionControllerCallback, int, int);
+ public abstract void skipToQueueItem(java.lang.String, android.media.session.ISessionControllerCallback, long);
+ public abstract void stop(java.lang.String, android.media.session.ISessionControllerCallback);
+ public abstract void unregisterCallbackListener(android.media.session.ISessionControllerCallback);
+
+
+}
+
+-keep class android.media.session.ISessionControllerCallback {
+
+ public abstract void onEvent(java.lang.String, android.os.Bundle);
+ public abstract void onExtrasChanged(android.os.Bundle);
+ public abstract void onMetadataChanged(android.media.MediaMetadata);
+ public abstract void onPlaybackStateChanged(android.media.session.PlaybackState);
+ public abstract void onQueueChanged(android.content.pm.ParceledListSlice);
+ public abstract void onQueueTitleChanged(java.lang.CharSequence);
+ public abstract void onSessionDestroyed();
+ public abstract void onVolumeInfoChanged(android.media.session.ParcelableVolumeInfo);
+
+
+}
+
-keep class android.media.session.MediaController {
+ <init>(android.content.Context, android.media.session.ISessionController);
<init>(android.content.Context, android.media.session.MediaSession$Token);
public void adjustVolume(int, int);
+ public boolean controlsSameSession(android.media.session.MediaController);
public boolean dispatchMediaButtonEvent(android.view.KeyEvent);
+ public boolean dispatchMediaButtonEventAsSystemService(android.view.KeyEvent);
+ public void dispatchVolumeButtonEventAsSystemService(android.view.KeyEvent);
public android.os.Bundle getExtras();
public long getFlags();
public android.media.MediaMetadata getMetadata();
@@ -4257,6 +13517,7 @@
public int getRatingType();
public android.app.PendingIntent getSessionActivity();
public android.media.session.MediaSession$Token getSessionToken();
+ public java.lang.String getTag();
public android.media.session.MediaController$TransportControls getTransportControls();
public void registerCallback(android.media.session.MediaController$Callback);
public void registerCallback(android.media.session.MediaController$Callback, android.os.Handler);
@@ -4283,6 +13544,7 @@
}
-keep class android.media.session.MediaController$PlaybackInfo {
+ <init>(int, android.media.AudioAttributes, int, int, int);
public android.media.AudioAttributes getAudioAttributes();
public int getCurrentVolume();
@@ -4303,6 +13565,10 @@
public void playFromMediaId(java.lang.String, android.os.Bundle);
public void playFromSearch(java.lang.String, android.os.Bundle);
public void playFromUri(android.net.Uri, android.os.Bundle);
+ public void prepare();
+ public void prepareFromMediaId(java.lang.String, android.os.Bundle);
+ public void prepareFromSearch(java.lang.String, android.os.Bundle);
+ public void prepareFromUri(android.net.Uri, android.os.Bundle);
public void rewind();
public void seekTo(long);
public void sendCustomAction(android.media.session.PlaybackState$CustomAction, android.os.Bundle);
@@ -4318,10 +13584,15 @@
-keep class android.media.session.MediaSession {
<init>(android.content.Context, java.lang.String);
+ <init>(android.content.Context, java.lang.String, int);
+ public java.lang.String getCallingPackage();
public android.media.session.MediaController getController();
+ public android.media.session.MediaSessionManager$RemoteUserInfo getCurrentControllerInfo();
public android.media.session.MediaSession$Token getSessionToken();
public boolean isActive();
+ public static boolean isActiveState(int);
+ public void notifyRemoteVolumeChanged(android.media.VolumeProvider);
public void release();
public void sendSessionEvent(java.lang.String, android.os.Bundle);
public void setActive(boolean);
@@ -4340,8 +13611,11 @@
public void setSessionActivity(android.app.PendingIntent);
+ public static int FLAG_EXCLUSIVE_GLOBAL_PRIORITY;
public static int FLAG_HANDLES_MEDIA_BUTTONS;
public static int FLAG_HANDLES_TRANSPORT_CONTROLS;
+ public static int INVALID_PID;
+ public static int INVALID_UID;
}
-keep class android.media.session.MediaSession$Callback {
@@ -4356,6 +13630,10 @@
public void onPlayFromMediaId(java.lang.String, android.os.Bundle);
public void onPlayFromSearch(java.lang.String, android.os.Bundle);
public void onPlayFromUri(android.net.Uri, android.os.Bundle);
+ public void onPrepare();
+ public void onPrepareFromMediaId(java.lang.String, android.os.Bundle);
+ public void onPrepareFromSearch(java.lang.String, android.os.Bundle);
+ public void onPrepareFromUri(android.net.Uri, android.os.Bundle);
public void onRewind();
public void onSeekTo(long);
public void onSetRating(android.media.Rating);
@@ -4367,10 +13645,41 @@
}
+-keep class android.media.session.MediaSession$CallbackStub {
+ <init>(android.media.session.MediaSession);
+
+ public void onAdjustVolume(java.lang.String, int, int, android.media.session.ISessionControllerCallback, int);
+ public void onCommand(java.lang.String, int, int, android.media.session.ISessionControllerCallback, java.lang.String, android.os.Bundle, android.os.ResultReceiver);
+ public void onCustomAction(java.lang.String, int, int, android.media.session.ISessionControllerCallback, java.lang.String, android.os.Bundle);
+ public void onFastForward(java.lang.String, int, int, android.media.session.ISessionControllerCallback);
+ public void onMediaButton(java.lang.String, int, int, android.content.Intent, int, android.os.ResultReceiver);
+ public void onMediaButtonFromController(java.lang.String, int, int, android.media.session.ISessionControllerCallback, android.content.Intent);
+ public void onNext(java.lang.String, int, int, android.media.session.ISessionControllerCallback);
+ public void onPause(java.lang.String, int, int, android.media.session.ISessionControllerCallback);
+ public void onPlay(java.lang.String, int, int, android.media.session.ISessionControllerCallback);
+ public void onPlayFromMediaId(java.lang.String, int, int, android.media.session.ISessionControllerCallback, java.lang.String, android.os.Bundle);
+ public void onPlayFromSearch(java.lang.String, int, int, android.media.session.ISessionControllerCallback, java.lang.String, android.os.Bundle);
+ public void onPlayFromUri(java.lang.String, int, int, android.media.session.ISessionControllerCallback, android.net.Uri, android.os.Bundle);
+ public void onPrepare(java.lang.String, int, int, android.media.session.ISessionControllerCallback);
+ public void onPrepareFromMediaId(java.lang.String, int, int, android.media.session.ISessionControllerCallback, java.lang.String, android.os.Bundle);
+ public void onPrepareFromSearch(java.lang.String, int, int, android.media.session.ISessionControllerCallback, java.lang.String, android.os.Bundle);
+ public void onPrepareFromUri(java.lang.String, int, int, android.media.session.ISessionControllerCallback, android.net.Uri, android.os.Bundle);
+ public void onPrevious(java.lang.String, int, int, android.media.session.ISessionControllerCallback);
+ public void onRate(java.lang.String, int, int, android.media.session.ISessionControllerCallback, android.media.Rating);
+ public void onRewind(java.lang.String, int, int, android.media.session.ISessionControllerCallback);
+ public void onSeekTo(java.lang.String, int, int, android.media.session.ISessionControllerCallback, long);
+ public void onSetVolumeTo(java.lang.String, int, int, android.media.session.ISessionControllerCallback, int);
+ public void onSkipToTrack(java.lang.String, int, int, android.media.session.ISessionControllerCallback, long);
+ public void onStop(java.lang.String, int, int, android.media.session.ISessionControllerCallback);
+
+
+}
+
-keep class android.media.session.MediaSession$QueueItem {
<init>(android.media.MediaDescription, long);
public int describeContents();
+ public boolean equals(java.lang.Object);
public android.media.MediaDescription getDescription();
public long getQueueId();
public java.lang.String toString();
@@ -4382,6 +13691,7 @@
}
-keep class android.media.session.MediaSession$Token {
+ <init>(android.media.session.ISessionController);
public int describeContents();
public boolean equals(java.lang.Object);
@@ -4392,10 +13702,115 @@
public static android.os.Parcelable$Creator CREATOR;
}
+-keep class android.media.session.MediaSessionManager {
+ <init>(android.content.Context);
+
+ public void addOnActiveSessionsChangedListener(android.media.session.MediaSessionManager$OnActiveSessionsChangedListener, android.content.ComponentName);
+ public void addOnActiveSessionsChangedListener(android.media.session.MediaSessionManager$OnActiveSessionsChangedListener, android.content.ComponentName, android.os.Handler);
+ public void addOnActiveSessionsChangedListener(android.media.session.MediaSessionManager$OnActiveSessionsChangedListener, android.content.ComponentName, int, android.os.Handler);
+ public void addOnSessionTokensChangedListener(java.util.concurrent.Executor, android.media.session.MediaSessionManager$OnSessionTokensChangedListener);
+ public void addOnSessionTokensChangedListener(int, java.util.concurrent.Executor, android.media.session.MediaSessionManager$OnSessionTokensChangedListener);
+ public android.media.session.ISession createSession(android.media.session.MediaSession$CallbackStub, java.lang.String, int);
+ public boolean createSession2(android.media.SessionToken2);
+ public void destroySession2(android.media.SessionToken2);
+ public void dispatchAdjustVolume(int, int, int);
+ public void dispatchMediaKeyEvent(android.view.KeyEvent);
+ public void dispatchMediaKeyEvent(android.view.KeyEvent, boolean);
+ public void dispatchMediaKeyEventAsSystemService(android.view.KeyEvent);
+ public void dispatchVolumeKeyEvent(android.view.KeyEvent, int, boolean);
+ public void dispatchVolumeKeyEventAsSystemService(android.view.KeyEvent, int);
+ public java.util.List getActiveSessionTokens();
+ public java.util.List getActiveSessions(android.content.ComponentName);
+ public java.util.List getActiveSessionsForUser(android.content.ComponentName, int);
+ public java.util.List getAllSessionTokens();
+ public java.util.List getSessionServiceTokens();
+ public boolean isGlobalPriorityActive();
+ public boolean isTrustedForMediaControl(android.media.session.MediaSessionManager$RemoteUserInfo);
+ public void removeOnActiveSessionsChangedListener(android.media.session.MediaSessionManager$OnActiveSessionsChangedListener);
+ public void removeOnSessionTokensChangedListener(android.media.session.MediaSessionManager$OnSessionTokensChangedListener);
+ public void setCallback(android.media.session.MediaSessionManager$Callback, android.os.Handler);
+ public void setOnMediaKeyListener(android.media.session.MediaSessionManager$OnMediaKeyListener, android.os.Handler);
+ public void setOnVolumeKeyLongPressListener(android.media.session.MediaSessionManager$OnVolumeKeyLongPressListener, android.os.Handler);
+ public void setRemoteVolumeController(android.media.IRemoteVolumeController);
+
+
+ public static int RESULT_MEDIA_KEY_HANDLED;
+ public static int RESULT_MEDIA_KEY_NOT_HANDLED;
+}
+
+-keep class android.media.session.MediaSessionManager$Callback {
+ <init>();
+
+ public abstract void onAddressedPlayerChanged(android.media.session.MediaSession$Token);
+ public abstract void onAddressedPlayerChanged(android.content.ComponentName);
+ public abstract void onMediaKeyEventDispatched(android.view.KeyEvent, android.media.session.MediaSession$Token);
+ public abstract void onMediaKeyEventDispatched(android.view.KeyEvent, android.content.ComponentName);
+
+
+}
+
+-keep class android.media.session.MediaSessionManager$OnActiveSessionsChangedListener {
+
+ public abstract void onActiveSessionsChanged(java.util.List);
+
+
+}
+
+-keep class android.media.session.MediaSessionManager$OnMediaKeyListener {
+
+ public abstract boolean onMediaKey(android.view.KeyEvent);
+
+
+}
+
+-keep class android.media.session.MediaSessionManager$OnSessionTokensChangedListener {
+
+ public abstract void onSessionTokensChanged(java.util.List);
+
+
+}
+
+-keep class android.media.session.MediaSessionManager$OnVolumeKeyLongPressListener {
+
+ public abstract void onVolumeKeyLongPress(android.view.KeyEvent);
+
+
+}
+
+-keep class android.media.session.MediaSessionManager$RemoteUserInfo {
+ <init>(java.lang.String, int, int);
+ <init>(java.lang.String, int, int, android.os.IBinder);
+
+ public boolean equals(java.lang.Object);
+ public java.lang.String getPackageName();
+ public int getPid();
+ public int getUid();
+ public int hashCode();
+
+
+}
+
+-keep class android.media.session.ParcelableVolumeInfo {
+ <init>(int, android.media.AudioAttributes, int, int, int);
+ <init>(android.os.Parcel);
+
+ public int describeContents();
+ public void writeToParcel(android.os.Parcel, int);
+
+
+ public static android.os.Parcelable$Creator CREATOR;
+ public android.media.AudioAttributes audioAttrs;
+ public int controlType;
+ public int currentVolume;
+ public int maxVolume;
+ public int volumeType;
+}
+
-keep class android.media.session.PlaybackState {
public int describeContents();
public long getActions();
+ public static long getActionsFromRccControlFlags(int);
public long getActiveQueueItemId();
public long getBufferedPosition();
public java.util.List getCustomActions();
@@ -4404,7 +13819,10 @@
public long getLastPositionUpdateTime();
public float getPlaybackSpeed();
public long getPosition();
+ public static int getRccControlFlagsFromActions(long);
+ public static int getRccStateFromState(int);
public int getState();
+ public static int getStateFromRccState(int);
public java.lang.String toString();
public void writeToParcel(android.os.Parcel, int);
@@ -4416,6 +13834,10 @@
public static long ACTION_PLAY_FROM_SEARCH;
public static long ACTION_PLAY_FROM_URI;
public static long ACTION_PLAY_PAUSE;
+ public static long ACTION_PREPARE;
+ public static long ACTION_PREPARE_FROM_MEDIA_ID;
+ public static long ACTION_PREPARE_FROM_SEARCH;
+ public static long ACTION_PREPARE_FROM_URI;
public static long ACTION_REWIND;
public static long ACTION_SEEK_TO;
public static long ACTION_SET_RATING;
@@ -4453,9 +13875,25 @@
public static android.os.Parcelable$Creator CREATOR;
}
+-keep class android.media.update.SessionToken2Provider {
+
+ public abstract boolean equals_impl(java.lang.Object);
+ public abstract java.lang.String getId_imp();
+ public abstract java.lang.String getPackageName_impl();
+ public abstract int getType_impl();
+ public abstract int getUid_impl();
+ public abstract int hashCode_impl();
+ public abstract android.os.Bundle toBundle_impl();
+ public abstract java.lang.String toString_impl();
+
+
+}
+
-keep class android.net.Uri {
public abstract android.net.Uri$Builder buildUpon();
+ public void checkContentUriWithoutPermission(java.lang.String, int);
+ public void checkFileUriExposed(java.lang.String);
public int compareTo(android.net.Uri);
public int compareTo(java.lang.Object);
public static java.lang.String decode(java.lang.String);
@@ -4466,6 +13904,7 @@
public static android.net.Uri fromParts(java.lang.String, java.lang.String, java.lang.String);
public abstract java.lang.String getAuthority();
public boolean getBooleanQueryParameter(java.lang.String, boolean);
+ public android.net.Uri getCanonicalUri();
public abstract java.lang.String getEncodedAuthority();
public abstract java.lang.String getEncodedFragment();
public abstract java.lang.String getEncodedPath();
@@ -4489,9 +13928,11 @@
public boolean isAbsolute();
public abstract boolean isHierarchical();
public boolean isOpaque();
+ public boolean isPathPrefixMatch(android.net.Uri);
public abstract boolean isRelative();
public android.net.Uri normalizeScheme();
public static android.net.Uri parse(java.lang.String);
+ public java.lang.String toSafeString();
public abstract java.lang.String toString();
public static android.net.Uri withAppendedPath(android.net.Uri, java.lang.String);
public static void writeToParcel(android.os.Parcel, android.net.Uri);
@@ -4529,6 +13970,9 @@
public void clear();
public boolean containsKey(java.lang.String);
+ public static void dumpStats(com.android.internal.util.IndentingPrintWriter, java.lang.String, java.lang.Object);
+ public static void dumpStats(com.android.internal.util.IndentingPrintWriter, android.util.SparseArray);
+ public static void dumpStats(com.android.internal.util.IndentingPrintWriter, android.os.BaseBundle);
public java.lang.Object get(java.lang.String);
public boolean getBoolean(java.lang.String);
public boolean getBoolean(java.lang.String, boolean);
@@ -4542,11 +13986,17 @@
public long getLong(java.lang.String);
public long getLong(java.lang.String, long);
public long[] getLongArray(java.lang.String);
+ public java.lang.String getPairValue();
public java.lang.String getString(java.lang.String);
public java.lang.String getString(java.lang.String, java.lang.String);
public java.lang.String[] getStringArray(java.lang.String);
public boolean isEmpty();
+ public boolean isEmptyParcel();
+ public boolean isParcelled();
public java.util.Set keySet();
+ public static boolean kindofEquals(android.os.BaseBundle, android.os.BaseBundle);
+ public boolean kindofEquals(android.os.BaseBundle);
+ public boolean maybeIsEmpty();
public void putAll(android.os.PersistableBundle);
public void putBoolean(java.lang.String, boolean);
public void putBooleanArray(java.lang.String, boolean[]);
@@ -4559,13 +14009,62 @@
public void putString(java.lang.String, java.lang.String);
public void putStringArray(java.lang.String, java.lang.String[]);
public void remove(java.lang.String);
+ public static void setShouldDefuse(boolean);
public int size();
+ public int mFlags;
+}
+
+-keep class android.os.Binder {
+ <init>();
+
+ public static android.os.IBinder allowBlocking(android.os.IBinder);
+ public void attachInterface(android.os.IInterface, java.lang.String);
+ public static void blockUntilThreadAvailable();
+ public static long clearCallingIdentity();
+ public static void copyAllowBlocking(android.os.IBinder, android.os.IBinder);
+ public static android.os.IBinder defaultBlocking(android.os.IBinder);
+ public static void disableTracing();
+ public void dump(java.io.FileDescriptor, java.lang.String[]);
+ protected void dump(java.io.FileDescriptor, java.io.PrintWriter, java.lang.String[]);
+ public void dumpAsync(java.io.FileDescriptor, java.lang.String[]);
+ public static void enableTracing();
+ public static void flushPendingCommands();
+ public static int getCallingPid();
+ public static int getCallingUid();
+ public static android.os.UserHandle getCallingUserHandle();
+ public java.lang.String getInterfaceDescriptor();
+ public static int getThreadStrictModePolicy();
+ public static synchronized android.os.TransactionTracker getTransactionTracker();
+ public boolean isBinderAlive();
+ public static boolean isProxy(android.os.IInterface);
+ public static boolean isTracingEnabled();
+ public static void joinThreadPool();
+ public void linkToDeath(android.os.IBinder$DeathRecipient, int);
+ public void onShellCommand(java.io.FileDescriptor, java.io.FileDescriptor, java.io.FileDescriptor, java.lang.String[], android.os.ShellCallback, android.os.ResultReceiver);
+ protected boolean onTransact(int, android.os.Parcel, android.os.Parcel, int);
+ public boolean pingBinder();
+ public android.os.IInterface queryLocalInterface(java.lang.String);
+ public static void restoreCallingIdentity(long);
+ public static void setDumpDisabled(java.lang.String);
+ public static void setThreadStrictModePolicy(int);
+ public static void setWarnOnBlocking(boolean);
+ public void shellCommand(java.io.FileDescriptor, java.io.FileDescriptor, java.io.FileDescriptor, java.lang.String[], android.os.ShellCallback, android.os.ResultReceiver);
+ public boolean transact(int, android.os.Parcel, android.os.Parcel, int);
+ public boolean unlinkToDeath(android.os.IBinder$DeathRecipient, int);
+ public static void withCleanCallingIdentity(com.android.internal.util.FunctionalUtils$ThrowingRunnable);
+ public static java.lang.Object withCleanCallingIdentity(com.android.internal.util.FunctionalUtils$ThrowingSupplier);
+
+
+ public static boolean CHECK_PARCEL_SIZE;
+ public static boolean LOG_RUNTIME_EXCEPTION;
}
-keep class android.os.Bundle {
<init>();
+ <init>(android.os.Parcel);
+ <init>(android.os.Parcel, int);
<init>(java.lang.ClassLoader);
<init>(int);
<init>(android.os.Bundle);
@@ -4573,7 +14072,10 @@
public void clear();
public java.lang.Object clone();
+ public android.os.Bundle deepCopy();
public int describeContents();
+ public android.os.Bundle filterValues();
+ public static android.os.Bundle forPair(java.lang.String, java.lang.String);
public android.os.IBinder getBinder(java.lang.String);
public android.os.Bundle getBundle(java.lang.String);
public byte getByte(java.lang.String);
@@ -4590,6 +14092,7 @@
public float getFloat(java.lang.String);
public float getFloat(java.lang.String, float);
public float[] getFloatArray(java.lang.String);
+ public android.os.IBinder getIBinder(java.lang.String);
public java.util.ArrayList getIntegerArrayList(java.lang.String);
public android.os.Parcelable getParcelable(java.lang.String);
public android.os.Parcelable[] getParcelableArray(java.lang.String);
@@ -4598,6 +14101,7 @@
public short getShort(java.lang.String);
public short getShort(java.lang.String, short);
public short[] getShortArray(java.lang.String);
+ public int getSize();
public android.util.Size getSize(java.lang.String);
public android.util.SizeF getSizeF(java.lang.String);
public android.util.SparseArray getSparseParcelableArray(java.lang.String);
@@ -4615,10 +14119,12 @@
public void putCharSequenceArrayList(java.lang.String, java.util.ArrayList);
public void putFloat(java.lang.String, float);
public void putFloatArray(java.lang.String, float[]);
+ public void putIBinder(java.lang.String, android.os.IBinder);
public void putIntegerArrayList(java.lang.String, java.util.ArrayList);
public void putParcelable(java.lang.String, android.os.Parcelable);
public void putParcelableArray(java.lang.String, android.os.Parcelable[]);
public void putParcelableArrayList(java.lang.String, java.util.ArrayList);
+ public void putParcelableList(java.lang.String, java.util.List);
public void putSerializable(java.lang.String, java.io.Serializable);
public void putShort(java.lang.String, short);
public void putShortArray(java.lang.String, short[]);
@@ -4627,21 +14133,31 @@
public void putSparseParcelableArray(java.lang.String, android.util.SparseArray);
public void putStringArrayList(java.lang.String, java.util.ArrayList);
public void readFromParcel(android.os.Parcel);
+ public void remove(java.lang.String);
+ public boolean setAllowFds(boolean);
public void setClassLoader(java.lang.ClassLoader);
+ public void setDefusable(boolean);
+ public static android.os.Bundle setDefusable(android.os.Bundle, boolean);
+ public synchronized java.lang.String toShortString();
public synchronized java.lang.String toString();
public void writeToParcel(android.os.Parcel, int);
+ public void writeToProto(android.util.proto.ProtoOutputStream, long);
public static android.os.Parcelable$Creator CREATOR;
public static android.os.Bundle EMPTY;
+ public static android.os.Bundle STRIPPED;
}
-keep class android.os.CancellationSignal {
<init>();
public void cancel();
+ public static android.os.ICancellationSignal createTransport();
+ public static android.os.CancellationSignal fromTransport(android.os.ICancellationSignal);
public boolean isCanceled();
public void setOnCancelListener(android.os.CancellationSignal$OnCancelListener);
+ public void setRemote(android.os.ICancellationSignal);
public void throwIfCanceled();
@@ -4654,19 +14170,275 @@
}
+-keep class android.os.Debug {
+
+ public static void attachJvmtiAgent(java.lang.String, java.lang.String, java.lang.ClassLoader);
+ public static boolean cacheRegisterMap(java.lang.String);
+ public static void changeDebugPort(int);
+ public static long countInstancesOfClass(java.lang.Class);
+ public static void dumpHprofData(java.lang.String);
+ public static void dumpHprofData(java.lang.String, java.io.FileDescriptor);
+ public static void dumpHprofDataDdms();
+ public static boolean dumpJavaBacktraceToFileTimeout(int, java.lang.String, int);
+ public static boolean dumpNativeBacktraceToFileTimeout(int, java.lang.String, int);
+ public static void dumpNativeHeap(java.io.FileDescriptor);
+ public static void dumpNativeMallocInfo(java.io.FileDescriptor);
+ public static void dumpReferenceTables();
+ public static boolean dumpService(java.lang.String, java.io.FileDescriptor, java.lang.String[]);
+ public static void enableEmulatorTraceOutput();
+ public static int getBinderDeathObjectCount();
+ public static int getBinderLocalObjectCount();
+ public static int getBinderProxyObjectCount();
+ public static int getBinderReceivedTransactions();
+ public static int getBinderSentTransactions();
+ public static java.lang.String getCaller();
+ public static java.lang.String getCallers(int);
+ public static java.lang.String getCallers(int, int);
+ public static java.lang.String getCallers(int, java.lang.String);
+ public static int getGlobalAllocCount();
+ public static int getGlobalAllocSize();
+ public static int getGlobalClassInitCount();
+ public static int getGlobalClassInitTime();
+ public static int getGlobalExternalAllocCount();
+ public static int getGlobalExternalAllocSize();
+ public static int getGlobalExternalFreedCount();
+ public static int getGlobalExternalFreedSize();
+ public static int getGlobalFreedCount();
+ public static int getGlobalFreedSize();
+ public static int getGlobalGcInvocationCount();
+ public static int getLoadedClassCount();
+ public static void getMemInfo(long[]);
+ public static void getMemoryInfo(android.os.Debug$MemoryInfo);
+ public static void getMemoryInfo(int, android.os.Debug$MemoryInfo);
+ public static int getMethodTracingMode();
+ public static long getNativeHeapAllocatedSize();
+ public static long getNativeHeapFreeSize();
+ public static long getNativeHeapSize();
+ public static long getPss();
+ public static long getPss(int, long[], long[]);
+ public static java.lang.String getRuntimeStat(java.lang.String);
+ public static java.util.Map getRuntimeStats();
+ public static int getThreadAllocCount();
+ public static int getThreadAllocSize();
+ public static int getThreadExternalAllocCount();
+ public static int getThreadExternalAllocSize();
+ public static int getThreadGcInvocationCount();
+ public static java.lang.String getUnreachableMemory(int, boolean);
+ public static java.lang.String[] getVmFeatureList();
+ public static boolean isDebuggerConnected();
+ public static void printLoadedClasses(int);
+ public static void resetAllCounts();
+ public static void resetGlobalAllocCount();
+ public static void resetGlobalAllocSize();
+ public static void resetGlobalClassInitCount();
+ public static void resetGlobalClassInitTime();
+ public static void resetGlobalExternalAllocCount();
+ public static void resetGlobalExternalAllocSize();
+ public static void resetGlobalExternalFreedCount();
+ public static void resetGlobalExternalFreedSize();
+ public static void resetGlobalFreedCount();
+ public static void resetGlobalFreedSize();
+ public static void resetGlobalGcInvocationCount();
+ public static void resetThreadAllocCount();
+ public static void resetThreadAllocSize();
+ public static void resetThreadExternalAllocCount();
+ public static void resetThreadExternalAllocSize();
+ public static void resetThreadGcInvocationCount();
+ public static int setAllocationLimit(int);
+ public static void setFieldsOn(java.lang.Class);
+ public static void setFieldsOn(java.lang.Class, boolean);
+ public static int setGlobalAllocationLimit(int);
+ public static void startAllocCounting();
+ public static void startMethodTracing();
+ public static void startMethodTracing(java.lang.String);
+ public static void startMethodTracing(java.lang.String, int);
+ public static void startMethodTracing(java.lang.String, int, int);
+ public static void startMethodTracing(java.lang.String, java.io.FileDescriptor, int, int, boolean);
+ public static void startMethodTracingDdms(int, int, boolean, int);
+ public static void startMethodTracingSampling(java.lang.String, int, int);
+ public static void startNativeTracing();
+ public static void stopAllocCounting();
+ public static void stopMethodTracing();
+ public static void stopNativeTracing();
+ public static long threadCpuTimeNanos();
+ public static void waitForDebugger();
+ public static boolean waitingForDebugger();
+
+
+ public static int MEMINFO_BUFFERS;
+ public static int MEMINFO_CACHED;
+ public static int MEMINFO_COUNT;
+ public static int MEMINFO_FREE;
+ public static int MEMINFO_KERNEL_STACK;
+ public static int MEMINFO_MAPPED;
+ public static int MEMINFO_PAGE_TABLES;
+ public static int MEMINFO_SHMEM;
+ public static int MEMINFO_SLAB;
+ public static int MEMINFO_SLAB_RECLAIMABLE;
+ public static int MEMINFO_SLAB_UNRECLAIMABLE;
+ public static int MEMINFO_SWAP_FREE;
+ public static int MEMINFO_SWAP_TOTAL;
+ public static int MEMINFO_TOTAL;
+ public static int MEMINFO_VM_ALLOC_USED;
+ public static int MEMINFO_ZRAM_TOTAL;
+ public static int SHOW_CLASSLOADER;
+ public static int SHOW_FULL_DETAIL;
+ public static int SHOW_INITIALIZED;
+ public static int TRACE_COUNT_ALLOCS;
+}
+
+-keep class android.os.Debug$MemoryInfo {
+ <init>();
+
+ public int describeContents();
+ public java.lang.String getMemoryStat(java.lang.String);
+ public java.util.Map getMemoryStats();
+ public static java.lang.String getOtherLabel(int);
+ public int getOtherPrivate(int);
+ public int getOtherPrivateClean(int);
+ public int getOtherPrivateDirty(int);
+ public int getOtherPss(int);
+ public int getOtherRss(int);
+ public int getOtherSharedClean(int);
+ public int getOtherSharedDirty(int);
+ public int getOtherSwappablePss(int);
+ public int getOtherSwappedOut(int);
+ public int getOtherSwappedOutPss(int);
+ public int getSummaryCode();
+ public int getSummaryGraphics();
+ public int getSummaryJavaHeap();
+ public int getSummaryNativeHeap();
+ public int getSummaryPrivateOther();
+ public int getSummaryStack();
+ public int getSummarySystem();
+ public int getSummaryTotalPss();
+ public int getSummaryTotalSwap();
+ public int getSummaryTotalSwapPss();
+ public int getTotalPrivateClean();
+ public int getTotalPrivateDirty();
+ public int getTotalPss();
+ public int getTotalRss();
+ public int getTotalSharedClean();
+ public int getTotalSharedDirty();
+ public int getTotalSwappablePss();
+ public int getTotalSwappedOut();
+ public int getTotalSwappedOutPss();
+ public int getTotalUss();
+ public boolean hasSwappedOutPss();
+ public void readFromParcel(android.os.Parcel);
+ public void writeToParcel(android.os.Parcel, int);
+
+
+ public static android.os.Parcelable$Creator CREATOR;
+ public static int HEAP_DALVIK;
+ public static int HEAP_NATIVE;
+ public static int HEAP_UNKNOWN;
+ public static int NUM_CATEGORIES;
+ public static int NUM_DVK_STATS;
+ public static int NUM_OTHER_STATS;
+ public static int OFFSET_PRIVATE_CLEAN;
+ public static int OFFSET_PRIVATE_DIRTY;
+ public static int OFFSET_PSS;
+ public static int OFFSET_RSS;
+ public static int OFFSET_SHARED_CLEAN;
+ public static int OFFSET_SHARED_DIRTY;
+ public static int OFFSET_SWAPPABLE_PSS;
+ public static int OFFSET_SWAPPED_OUT;
+ public static int OFFSET_SWAPPED_OUT_PSS;
+ public static int OTHER_APK;
+ public static int OTHER_ART;
+ public static int OTHER_ART_APP;
+ public static int OTHER_ART_BOOT;
+ public static int OTHER_ASHMEM;
+ public static int OTHER_CURSOR;
+ public static int OTHER_DALVIK_LARGE;
+ public static int OTHER_DALVIK_NON_MOVING;
+ public static int OTHER_DALVIK_NORMAL;
+ public static int OTHER_DALVIK_OTHER;
+ public static int OTHER_DALVIK_OTHER_ACCOUNTING;
+ public static int OTHER_DALVIK_OTHER_CODE_CACHE;
+ public static int OTHER_DALVIK_OTHER_COMPILER_METADATA;
+ public static int OTHER_DALVIK_OTHER_INDIRECT_REFERENCE_TABLE;
+ public static int OTHER_DALVIK_OTHER_LINEARALLOC;
+ public static int OTHER_DALVIK_ZYGOTE;
+ public static int OTHER_DEX;
+ public static int OTHER_DEX_APP_DEX;
+ public static int OTHER_DEX_APP_VDEX;
+ public static int OTHER_DEX_BOOT_VDEX;
+ public static int OTHER_DVK_STAT_ART_END;
+ public static int OTHER_DVK_STAT_ART_START;
+ public static int OTHER_DVK_STAT_DALVIK_END;
+ public static int OTHER_DVK_STAT_DALVIK_OTHER_END;
+ public static int OTHER_DVK_STAT_DALVIK_OTHER_START;
+ public static int OTHER_DVK_STAT_DALVIK_START;
+ public static int OTHER_DVK_STAT_DEX_END;
+ public static int OTHER_DVK_STAT_DEX_START;
+ public static int OTHER_GL;
+ public static int OTHER_GL_DEV;
+ public static int OTHER_GRAPHICS;
+ public static int OTHER_JAR;
+ public static int OTHER_OAT;
+ public static int OTHER_OTHER_MEMTRACK;
+ public static int OTHER_SO;
+ public static int OTHER_STACK;
+ public static int OTHER_TTF;
+ public static int OTHER_UNKNOWN_DEV;
+ public static int OTHER_UNKNOWN_MAP;
+ public int dalvikPrivateClean;
+ public int dalvikPrivateDirty;
+ public int dalvikPss;
+ public int dalvikRss;
+ public int dalvikSharedClean;
+ public int dalvikSharedDirty;
+ public int dalvikSwappablePss;
+ public int dalvikSwappedOut;
+ public int dalvikSwappedOutPss;
+ public boolean hasSwappedOutPss;
+ public int nativePrivateClean;
+ public int nativePrivateDirty;
+ public int nativePss;
+ public int nativeRss;
+ public int nativeSharedClean;
+ public int nativeSharedDirty;
+ public int nativeSwappablePss;
+ public int nativeSwappedOut;
+ public int nativeSwappedOutPss;
+ public int otherPrivateClean;
+ public int otherPrivateDirty;
+ public int otherPss;
+ public int otherRss;
+ public int otherSharedClean;
+ public int otherSharedDirty;
+ public int otherSwappablePss;
+ public int otherSwappedOut;
+ public int otherSwappedOutPss;
+}
+
-keep class android.os.Handler {
<init>();
<init>(android.os.Handler$Callback);
<init>(android.os.Looper);
<init>(android.os.Looper, android.os.Handler$Callback);
+ <init>(boolean);
+ <init>(android.os.Handler$Callback, boolean);
+ <init>(android.os.Looper, android.os.Handler$Callback, boolean);
+ public static android.os.Handler createAsync(android.os.Looper);
+ public static android.os.Handler createAsync(android.os.Looper, android.os.Handler$Callback);
public void dispatchMessage(android.os.Message);
public void dump(android.util.Printer, java.lang.String);
+ public void dumpMine(android.util.Printer, java.lang.String);
+ public boolean executeOrSendMessage(android.os.Message);
public android.os.Looper getLooper();
+ public static android.os.Handler getMain();
public java.lang.String getMessageName(android.os.Message);
+ public java.lang.String getTraceName(android.os.Message);
public void handleMessage(android.os.Message);
+ public boolean hasCallbacks(java.lang.Runnable);
public boolean hasMessages(int);
public boolean hasMessages(int, java.lang.Object);
+ public boolean hasMessagesOrCallbacks();
+ public static android.os.Handler mainIfNull(android.os.Handler);
public android.os.Message obtainMessage();
public android.os.Message obtainMessage(int);
public android.os.Message obtainMessage(int, java.lang.Object);
@@ -4677,11 +14449,13 @@
public boolean postAtTime(java.lang.Runnable, long);
public boolean postAtTime(java.lang.Runnable, java.lang.Object, long);
public boolean postDelayed(java.lang.Runnable, long);
+ public boolean postDelayed(java.lang.Runnable, java.lang.Object, long);
public void removeCallbacks(java.lang.Runnable);
public void removeCallbacks(java.lang.Runnable, java.lang.Object);
public void removeCallbacksAndMessages(java.lang.Object);
public void removeMessages(int);
public void removeMessages(int, java.lang.Object);
+ public boolean runWithScissors(java.lang.Runnable, long);
public boolean sendEmptyMessage(int);
public boolean sendEmptyMessageAtTime(int, long);
public boolean sendEmptyMessageDelayed(int, long);
@@ -4710,6 +14484,7 @@
public abstract void linkToDeath(android.os.IBinder$DeathRecipient, int);
public abstract boolean pingBinder();
public abstract android.os.IInterface queryLocalInterface(java.lang.String);
+ public abstract void shellCommand(java.io.FileDescriptor, java.io.FileDescriptor, java.io.FileDescriptor, java.lang.String[], android.os.ShellCallback, android.os.ResultReceiver);
public abstract boolean transact(int, android.os.Parcel, android.os.Parcel, int);
public abstract boolean unlinkToDeath(android.os.IBinder$DeathRecipient, int);
@@ -4720,7 +14495,10 @@
public static int INTERFACE_TRANSACTION;
public static int LAST_CALL_TRANSACTION;
public static int LIKE_TRANSACTION;
+ public static int MAX_IPC_SIZE;
public static int PING_TRANSACTION;
+ public static int SHELL_COMMAND_TRANSACTION;
+ public static int SYSPROPS_TRANSACTION;
public static int TWEET_TRANSACTION;
}
@@ -4731,6 +14509,13 @@
}
+-keep class android.os.ICancellationSignal {
+
+ public abstract void cancel();
+
+
+}
+
-keep class android.os.IInterface {
public abstract android.os.IBinder asBinder();
@@ -4738,9 +14523,59 @@
}
+-keep class android.os.IProgressListener {
+
+ public abstract void onFinished(int, android.os.Bundle);
+ public abstract void onProgress(int, int, android.os.Bundle);
+ public abstract void onStarted(int, android.os.Bundle);
+
+
+}
+
+-keep class android.os.IRemoteCallback {
+
+ public abstract void sendResult(android.os.Bundle);
+
+
+}
+
+-keep class android.os.LocaleList {
+ <init>(java.util.Locale[]);
+ <init>(java.util.Locale, android.os.LocaleList);
+
+ public int describeContents();
+ public boolean equals(java.lang.Object);
+ public static android.os.LocaleList forLanguageTags(java.lang.String);
+ public java.util.Locale get(int);
+ public static android.os.LocaleList getAdjustedDefault();
+ public static android.os.LocaleList getDefault();
+ public static android.os.LocaleList getEmptyLocaleList();
+ public java.util.Locale getFirstMatch(java.lang.String[]);
+ public int getFirstMatchIndex(java.lang.String[]);
+ public int getFirstMatchIndexWithEnglishSupported(java.util.Collection);
+ public int getFirstMatchIndexWithEnglishSupported(java.lang.String[]);
+ public java.util.Locale getFirstMatchWithEnglishSupported(java.lang.String[]);
+ public int hashCode();
+ public int indexOf(java.util.Locale);
+ public boolean isEmpty();
+ public static boolean isPseudoLocale(java.util.Locale);
+ public static boolean isPseudoLocalesOnly(java.lang.String[]);
+ public static void setDefault(android.os.LocaleList);
+ public static void setDefault(android.os.LocaleList, int);
+ public int size();
+ public java.lang.String toLanguageTags();
+ public java.lang.String toString();
+ public void writeToParcel(android.os.Parcel, int);
+ public void writeToProto(android.util.proto.ProtoOutputStream, long);
+
+
+ public static android.os.Parcelable$Creator CREATOR;
+}
+
-keep class android.os.Looper {
public void dump(android.util.Printer, java.lang.String);
+ public void dump(android.util.Printer, java.lang.String, android.os.Handler);
public static android.os.Looper getMainLooper();
public android.os.MessageQueue getQueue();
public java.lang.Thread getThread();
@@ -4753,7 +14588,10 @@
public void quit();
public void quitSafely();
public void setMessageLogging(android.util.Printer);
+ public void setSlowLogThresholdMs(long, long);
+ public void setTraceTag(long);
public java.lang.String toString();
+ public void writeToProto(android.util.proto.ProtoOutputStream, long);
}
@@ -4780,9 +14618,12 @@
public void recycle();
public void sendToTarget();
public void setAsynchronous(boolean);
+ public android.os.Message setCallback(java.lang.Runnable);
public void setData(android.os.Bundle);
public void setTarget(android.os.Handler);
+ public android.os.Message setWhat(int);
public java.lang.String toString();
+ public static void updateCheckRecycle(int);
public void writeToParcel(android.os.Parcel, int);
@@ -4791,6 +14632,7 @@
public int arg2;
public java.lang.Object obj;
public android.os.Messenger replyTo;
+ public static java.lang.Object sPoolSync;
public int sendingUid;
public int what;
}
@@ -4801,8 +14643,11 @@
public void addOnFileDescriptorEventListener(java.io.FileDescriptor, int, android.os.MessageQueue$OnFileDescriptorEventListener);
protected void finalize();
public boolean isIdle();
+ public boolean isPolling();
+ public int postSyncBarrier();
public void removeIdleHandler(android.os.MessageQueue$IdleHandler);
public void removeOnFileDescriptorEventListener(java.io.FileDescriptor);
+ public void removeSyncBarrier(int);
}
@@ -4843,7 +14688,10 @@
-keep class android.os.Parcel {
+ public void adoptClassCookies(android.os.Parcel);
public void appendFrom(android.os.Parcel, int, int);
+ public int compareData(android.os.Parcel);
+ public java.util.Map copyClassCookies();
public android.os.IBinder[] createBinderArray();
public java.util.ArrayList createBinderArrayList();
public boolean[] createBooleanArray();
@@ -4853,6 +14701,7 @@
public float[] createFloatArray();
public int[] createIntArray();
public long[] createLongArray();
+ public java.io.FileDescriptor[] createRawFileDescriptorArray();
public java.lang.String[] createStringArray();
public java.util.ArrayList createStringArrayList();
public java.lang.Object[] createTypedArray(android.os.Parcelable$Creator);
@@ -4863,23 +14712,41 @@
public int dataSize();
public void enforceInterface(java.lang.String);
protected void finalize();
+ public long getBlobAshmemSize();
+ public java.lang.Object getClassCookie(java.lang.Class);
+ public static long getGlobalAllocCount();
+ public static long getGlobalAllocSize();
public boolean hasFileDescriptors();
+ public boolean hasReadWriteHelper();
public byte[] marshall();
public static android.os.Parcel obtain();
+ protected static android.os.Parcel obtain(int);
+ protected static android.os.Parcel obtain(long);
+ public boolean pushAllowFds(boolean);
+ public void putClassCookies(java.util.Map);
public java.lang.Object[] readArray(java.lang.ClassLoader);
public java.util.ArrayList readArrayList(java.lang.ClassLoader);
+ public void readArrayMap(android.util.ArrayMap, java.lang.ClassLoader);
+ public android.util.ArraySet readArraySet(java.lang.ClassLoader);
public void readBinderArray(android.os.IBinder[]);
public void readBinderList(java.util.List);
+ public byte[] readBlob();
+ public boolean readBoolean();
public void readBooleanArray(boolean[]);
public android.os.Bundle readBundle();
public android.os.Bundle readBundle(java.lang.ClassLoader);
public byte readByte();
public void readByteArray(byte[]);
public void readCharArray(char[]);
+ public java.lang.CharSequence readCharSequence();
+ public java.lang.CharSequence[] readCharSequenceArray();
+ public java.util.ArrayList readCharSequenceList();
+ public android.os.Parcelable readCreator(android.os.Parcelable$Creator, java.lang.ClassLoader);
public double readDouble();
public void readDoubleArray(double[]);
public void readException();
public void readException(int, java.lang.String);
+ public int readExceptionCode();
public android.os.ParcelFileDescriptor readFileDescriptor();
public float readFloat();
public void readFloatArray(float[]);
@@ -4892,35 +14759,56 @@
public void readMap(java.util.Map, java.lang.ClassLoader);
public android.os.Parcelable readParcelable(java.lang.ClassLoader);
public android.os.Parcelable[] readParcelableArray(java.lang.ClassLoader);
+ public android.os.Parcelable[] readParcelableArray(java.lang.ClassLoader, java.lang.Class);
+ public android.os.Parcelable$Creator readParcelableCreator(java.lang.ClassLoader);
+ public java.util.List readParcelableList(java.util.List, java.lang.ClassLoader);
public android.os.PersistableBundle readPersistableBundle();
public android.os.PersistableBundle readPersistableBundle(java.lang.ClassLoader);
+ public java.io.FileDescriptor readRawFileDescriptor();
+ public void readRawFileDescriptorArray(java.io.FileDescriptor[]);
public java.io.Serializable readSerializable();
public android.util.Size readSize();
public android.util.SizeF readSizeF();
public android.util.SparseArray readSparseArray(java.lang.ClassLoader);
public android.util.SparseBooleanArray readSparseBooleanArray();
+ public android.util.SparseIntArray readSparseIntArray();
public java.lang.String readString();
public void readStringArray(java.lang.String[]);
+ public java.lang.String[] readStringArray();
public void readStringList(java.util.List);
+ public java.lang.String readStringNoHelper();
public android.os.IBinder readStrongBinder();
public void readTypedArray(java.lang.Object[], android.os.Parcelable$Creator);
+ public java.lang.Object[] readTypedArray(android.os.Parcelable$Creator);
public void readTypedList(java.util.List, android.os.Parcelable$Creator);
public java.lang.Object readTypedObject(android.os.Parcelable$Creator);
public java.lang.Object readValue(java.lang.ClassLoader);
public void recycle();
+ public void restoreAllowFds(boolean);
+ public void setClassCookie(java.lang.Class, java.lang.Object);
public void setDataCapacity(int);
public void setDataPosition(int);
public void setDataSize(int);
+ public void setReadWriteHelper(android.os.Parcel$ReadWriteHelper);
+ public static void setStackTraceParceling(boolean);
public void unmarshall(byte[], int, int);
public void writeArray(java.lang.Object[]);
+ public void writeArrayMap(android.util.ArrayMap);
+ public void writeArraySet(android.util.ArraySet);
public void writeBinderArray(android.os.IBinder[]);
public void writeBinderList(java.util.List);
+ public void writeBlob(byte[]);
+ public void writeBlob(byte[], int, int);
+ public void writeBoolean(boolean);
public void writeBooleanArray(boolean[]);
public void writeBundle(android.os.Bundle);
public void writeByte(byte);
public void writeByteArray(byte[]);
public void writeByteArray(byte[], int, int);
public void writeCharArray(char[]);
+ public void writeCharSequence(java.lang.CharSequence);
+ public void writeCharSequenceArray(java.lang.CharSequence[]);
+ public void writeCharSequenceList(java.util.ArrayList);
public void writeDouble(double);
public void writeDoubleArray(double[]);
public void writeException(java.lang.Exception);
@@ -4937,19 +14825,26 @@
public void writeNoException();
public void writeParcelable(android.os.Parcelable, int);
public void writeParcelableArray(android.os.Parcelable[], int);
+ public void writeParcelableCreator(android.os.Parcelable);
+ public void writeParcelableList(java.util.List, int);
public void writePersistableBundle(android.os.PersistableBundle);
+ public void writeRawFileDescriptor(java.io.FileDescriptor);
+ public void writeRawFileDescriptorArray(java.io.FileDescriptor[]);
public void writeSerializable(java.io.Serializable);
public void writeSize(android.util.Size);
public void writeSizeF(android.util.SizeF);
public void writeSparseArray(android.util.SparseArray);
public void writeSparseBooleanArray(android.util.SparseBooleanArray);
+ public void writeSparseIntArray(android.util.SparseIntArray);
public void writeString(java.lang.String);
public void writeStringArray(java.lang.String[]);
public void writeStringList(java.util.List);
+ public void writeStringNoHelper(java.lang.String);
public void writeStrongBinder(android.os.IBinder);
public void writeStrongInterface(android.os.IInterface);
public void writeTypedArray(android.os.Parcelable[], int);
public void writeTypedList(java.util.List);
+ public void writeTypedList(java.util.List, int);
public void writeTypedObject(android.os.Parcelable, int);
public void writeValue(java.lang.Object);
@@ -4957,8 +14852,20 @@
public static android.os.Parcelable$Creator STRING_CREATOR;
}
+-keep class android.os.Parcel$ReadWriteHelper {
+ <init>();
+
+ public java.lang.String readString(android.os.Parcel);
+ public void writeString(android.os.Parcel, java.lang.String);
+
+
+ public static android.os.Parcel$ReadWriteHelper DEFAULT;
+}
+
-keep class android.os.ParcelFileDescriptor {
<init>(android.os.ParcelFileDescriptor);
+ <init>(java.io.FileDescriptor);
+ <init>(java.io.FileDescriptor, java.io.FileDescriptor);
public static android.os.ParcelFileDescriptor adoptFd(int);
public boolean canDetectErrors();
@@ -4968,21 +14875,28 @@
public static android.os.ParcelFileDescriptor[] createPipe();
public static android.os.ParcelFileDescriptor[] createReliablePipe();
public static android.os.ParcelFileDescriptor[] createReliableSocketPair();
+ public static android.os.ParcelFileDescriptor[] createReliableSocketPair(int);
public static android.os.ParcelFileDescriptor[] createSocketPair();
+ public static android.os.ParcelFileDescriptor[] createSocketPair(int);
public int describeContents();
public int detachFd();
public static android.os.ParcelFileDescriptor dup(java.io.FileDescriptor);
public android.os.ParcelFileDescriptor dup();
protected void finalize();
+ public static android.os.ParcelFileDescriptor fromData(byte[], java.lang.String);
public static android.os.ParcelFileDescriptor fromDatagramSocket(java.net.DatagramSocket);
+ public static android.os.ParcelFileDescriptor fromFd(java.io.FileDescriptor, android.os.Handler, android.os.ParcelFileDescriptor$OnCloseListener);
public static android.os.ParcelFileDescriptor fromFd(int);
public static android.os.ParcelFileDescriptor fromSocket(java.net.Socket);
public int getFd();
+ public static java.io.File getFile(java.io.FileDescriptor);
public java.io.FileDescriptor getFileDescriptor();
public long getStatSize();
public static android.os.ParcelFileDescriptor open(java.io.File, int);
public static android.os.ParcelFileDescriptor open(java.io.File, int, android.os.Handler, android.os.ParcelFileDescriptor$OnCloseListener);
public static int parseMode(java.lang.String);
+ public void releaseResources();
+ public long seekTo(long);
public java.lang.String toString();
public void writeToParcel(android.os.Parcel, int);
@@ -5012,9 +14926,17 @@
public static int CONTENTS_FILE_DESCRIPTOR;
+ public static int PARCELABLE_ELIDE_DUPLICATES;
public static int PARCELABLE_WRITE_RETURN_VALUE;
}
+-keep class android.os.Parcelable$ClassLoaderCreator {
+
+ public abstract java.lang.Object createFromParcel(android.os.Parcel, java.lang.ClassLoader);
+
+
+}
+
-keep class android.os.Parcelable$Creator {
public abstract java.lang.Object createFromParcel(android.os.Parcel);
@@ -5033,9 +14955,11 @@
public boolean match(java.lang.String);
public java.lang.String toString();
public void writeToParcel(android.os.Parcel, int);
+ public void writeToProto(android.util.proto.ProtoOutputStream, long);
public static android.os.Parcelable$Creator CREATOR;
+ public static int PATTERN_ADVANCED_GLOB;
public static int PATTERN_LITERAL;
public static int PATTERN_PREFIX;
public static int PATTERN_SIMPLE_GLOB;
@@ -5045,13 +14969,22 @@
<init>();
<init>(int);
<init>(android.os.PersistableBundle);
+ <init>(android.os.Bundle);
public java.lang.Object clone();
+ public android.os.PersistableBundle deepCopy();
public int describeContents();
+ public static android.os.PersistableBundle forPair(java.lang.String, java.lang.String);
public android.os.PersistableBundle getPersistableBundle(java.lang.String);
+ public static boolean isValidType(java.lang.Object);
public void putPersistableBundle(java.lang.String, android.os.PersistableBundle);
+ public static android.os.PersistableBundle restoreFromXml(org.xmlpull.v1.XmlPullParser);
+ public void saveToXml(org.xmlpull.v1.XmlSerializer);
+ public synchronized java.lang.String toShortString();
public synchronized java.lang.String toString();
public void writeToParcel(android.os.Parcel, int);
+ public void writeToProto(android.util.proto.ProtoOutputStream, long);
+ public void writeUnknownObject(java.lang.Object, java.lang.String, org.xmlpull.v1.XmlSerializer);
public static android.os.Parcelable$Creator CREATOR;
@@ -5061,7 +14994,10 @@
-keep class android.os.RemoteException {
<init>();
<init>(java.lang.String);
+ <init>(java.lang.String, java.lang.Throwable, boolean, boolean);
+ public java.lang.RuntimeException rethrowAsRuntimeException();
+ public java.lang.RuntimeException rethrowFromSystemServer();
}
@@ -5078,29 +15014,623 @@
public static android.os.Parcelable$Creator CREATOR;
}
+-keep class android.os.ShellCallback {
+ <init>();
+
+ public int describeContents();
+ public android.os.ParcelFileDescriptor onOpenFile(java.lang.String, java.lang.String, java.lang.String);
+ public android.os.ParcelFileDescriptor openFile(java.lang.String, java.lang.String, java.lang.String);
+ public static void writeToParcel(android.os.ShellCallback, android.os.Parcel);
+ public void writeToParcel(android.os.Parcel, int);
+
+
+ public static android.os.Parcelable$Creator CREATOR;
+}
+
+-keep class android.os.ShellCommand {
+ <init>();
+
+ public android.os.ResultReceiver adoptResultReceiver();
+ public int exec(android.os.Binder, java.io.FileDescriptor, java.io.FileDescriptor, java.io.FileDescriptor, java.lang.String[], android.os.ShellCallback, android.os.ResultReceiver);
+ public java.io.InputStream getBufferedInputStream();
+ public java.io.FileDescriptor getErrFileDescriptor();
+ public java.io.PrintWriter getErrPrintWriter();
+ public java.io.FileDescriptor getInFileDescriptor();
+ public java.lang.String getNextArg();
+ public java.lang.String getNextArgRequired();
+ public java.lang.String getNextOption();
+ public java.io.FileDescriptor getOutFileDescriptor();
+ public java.io.PrintWriter getOutPrintWriter();
+ public java.io.OutputStream getRawErrorStream();
+ public java.io.InputStream getRawInputStream();
+ public java.io.OutputStream getRawOutputStream();
+ public android.os.ShellCallback getShellCallback();
+ public int handleDefaultCommands(java.lang.String);
+ public void init(android.os.Binder, java.io.FileDescriptor, java.io.FileDescriptor, java.io.FileDescriptor, java.lang.String[], android.os.ShellCallback, int);
+ public abstract int onCommand(java.lang.String);
+ public abstract void onHelp();
+ public android.os.ParcelFileDescriptor openFileForSystem(java.lang.String, java.lang.String);
+ public java.lang.String peekNextArg();
+
+
+}
+
+-keep class android.os.StrictMode {
+
+ public static android.os.StrictMode$ThreadPolicy allowThreadDiskReads();
+ public static int allowThreadDiskReadsMask();
+ public static android.os.StrictMode$ThreadPolicy allowThreadDiskWrites();
+ public static int allowThreadDiskWritesMask();
+ public static void conditionallyCheckInstanceCounts();
+ public static void decrementExpectedActivityCount(java.lang.Class);
+ public static void disableDeathOnFileUriExposure();
+ public static void enableDeathOnFileUriExposure();
+ public static void enableDefaults();
+ public static android.os.StrictMode$Span enterCriticalSpan(java.lang.String);
+ public static android.os.StrictMode$ThreadPolicy getThreadPolicy();
+ public static int getThreadPolicyMask();
+ public static android.os.StrictMode$VmPolicy getVmPolicy();
+ public static void incrementExpectedActivityCount(java.lang.Class);
+ public static void initThreadDefaults(android.content.pm.ApplicationInfo);
+ public static void initVmDefaults(android.content.pm.ApplicationInfo);
+ public static boolean isBundledSystemApp(android.content.pm.ApplicationInfo);
+ public static void noteDiskRead();
+ public static void noteDiskWrite();
+ public static void noteResourceMismatch(java.lang.Object);
+ public static void noteSlowCall(java.lang.String);
+ public static void noteUnbufferedIO();
+ public static void onCleartextNetworkDetected(byte[]);
+ public static void onContentUriWithoutPermission(android.net.Uri, java.lang.String);
+ public static void onFileUriExposed(android.net.Uri, java.lang.String);
+ public static void onIntentReceiverLeaked(java.lang.Throwable);
+ public static void onServiceConnectionLeaked(java.lang.Throwable);
+ public static void onSqliteObjectLeaked(java.lang.String, java.lang.Throwable);
+ public static void onUntaggedSocket();
+ public static void onVmPolicyViolation(android.os.strictmode.Violation);
+ public static void onVmPolicyViolation(android.os.strictmode.Violation, boolean);
+ public static void onWebViewMethodCalledOnWrongThread(java.lang.Throwable);
+ public static void setThreadPolicy(android.os.StrictMode$ThreadPolicy);
+ public static void setThreadPolicyMask(int);
+ public static void setViolationLogger(android.os.StrictMode$ViolationLogger);
+ public static void setVmPolicy(android.os.StrictMode$VmPolicy);
+ public static java.lang.Object trackActivity(java.lang.Object);
+ public static boolean vmCleartextNetworkEnabled();
+ public static boolean vmClosableObjectLeaksEnabled();
+ public static boolean vmContentUriWithoutPermissionEnabled();
+ public static boolean vmFileUriExposureEnabled();
+ public static boolean vmRegistrationLeaksEnabled();
+ public static boolean vmSqliteObjectLeaksEnabled();
+ public static boolean vmUntaggedSocketEnabled();
+
+
+ public static java.lang.String CLEARTEXT_DETECTED_MSG;
+ public static int DETECT_CUSTOM;
+ public static int DETECT_DISK_READ;
+ public static int DETECT_DISK_WRITE;
+ public static int DETECT_NETWORK;
+ public static int DETECT_RESOURCE_MISMATCH;
+ public static int DETECT_UNBUFFERED_IO;
+ public static int DETECT_VM_ACTIVITY_LEAKS;
+ public static int DETECT_VM_CLEARTEXT_NETWORK;
+ public static int DETECT_VM_CLOSABLE_LEAKS;
+ public static int DETECT_VM_CONTENT_URI_WITHOUT_PERMISSION;
+ public static int DETECT_VM_CURSOR_LEAKS;
+ public static int DETECT_VM_FILE_URI_EXPOSURE;
+ public static int DETECT_VM_INSTANCE_LEAKS;
+ public static int DETECT_VM_NON_SDK_API_USAGE;
+ public static int DETECT_VM_REGISTRATION_LEAKS;
+ public static int DETECT_VM_UNTAGGED_SOCKET;
+ public static java.lang.String DISABLE_PROPERTY;
+ public static int NETWORK_POLICY_ACCEPT;
+ public static int NETWORK_POLICY_LOG;
+ public static int NETWORK_POLICY_REJECT;
+ public static int PENALTY_DEATH;
+ public static int PENALTY_DEATH_ON_CLEARTEXT_NETWORK;
+ public static int PENALTY_DEATH_ON_FILE_URI_EXPOSURE;
+ public static int PENALTY_DEATH_ON_NETWORK;
+ public static int PENALTY_DIALOG;
+ public static int PENALTY_DROPBOX;
+ public static int PENALTY_FLASH;
+ public static int PENALTY_GATHER;
+ public static int PENALTY_LOG;
+ public static java.lang.String VISUAL_PROPERTY;
+}
+
+-keep class android.os.StrictMode$Span {
+ <init>();
+
+ public void finish();
+
+
+}
+
+-keep class android.os.StrictMode$ThreadPolicy {
+
+ public java.lang.String toString();
+
+
+ public static android.os.StrictMode$ThreadPolicy LAX;
+}
+
+-keep class android.os.StrictMode$ViolationInfo {
+ <init>(android.os.Parcel);
+ <init>(android.os.Parcel, boolean);
+
+ public int describeContents();
+ public void dump(android.util.Printer, java.lang.String);
+ public int getPolicyMask();
+ public java.lang.String getStackTrace();
+ public int getViolationBit();
+ public java.lang.String getViolationDetails();
+ public int hashCode();
+ public void writeToParcel(android.os.Parcel, int);
+
+
+ public static android.os.Parcelable$Creator CREATOR;
+ public java.lang.String broadcastIntentAction;
+ public int durationMillis;
+ public int numAnimationsRunning;
+ public long numInstances;
+ public java.lang.String[] tags;
+ public int violationNumThisLoop;
+ public long violationUptimeMillis;
+}
+
+-keep class android.os.StrictMode$ViolationLogger {
+
+ public abstract void log(android.os.StrictMode$ViolationInfo);
+
+
+}
+
+-keep class android.os.StrictMode$VmPolicy {
+
+ public java.lang.String toString();
+
+
+ public static android.os.StrictMode$VmPolicy LAX;
+}
+
+-keep class android.os.TestLooperManager {
+ <init>(android.os.Looper);
+
+ public void execute(android.os.Message);
+ public android.os.MessageQueue getMessageQueue();
+ public android.os.MessageQueue getQueue();
+ public boolean hasMessages(android.os.Handler, java.lang.Object, int);
+ public boolean hasMessages(android.os.Handler, java.lang.Object, java.lang.Runnable);
+ public android.os.Message next();
+ public void recycle(android.os.Message);
+ public void release();
+
+
+}
+
+-keep class android.os.TransactionTracker {
+
+ public void addTrace(java.lang.Throwable);
+ public void clearTraces();
+ public void writeTracesToFile(android.os.ParcelFileDescriptor);
+
+
+}
+
-keep class android.os.UserHandle {
+ <init>(int);
<init>(android.os.Parcel);
public int describeContents();
public boolean equals(java.lang.Object);
+ public static void formatUid(java.lang.StringBuilder, int);
+ public static java.lang.String formatUid(int);
+ public static void formatUid(java.io.PrintWriter, int);
+ public static int getAppId(int);
+ public static int getAppIdFromSharedAppGid(int);
+ public static int getCacheAppGid(int);
+ public static int getCacheAppGid(int, int);
+ public static int getCallingAppId();
+ public static int getCallingUserId();
+ public int getIdentifier();
+ public static int getSharedAppGid(int);
+ public static int getSharedAppGid(int, int);
+ public static int getUid(int, int);
+ public static int getUserGid(int);
+ public static android.os.UserHandle getUserHandleForUid(int);
+ public static int getUserId(int);
public int hashCode();
+ public static boolean isApp(int);
+ public static boolean isCore(int);
+ public static boolean isIsolated(int);
+ public boolean isOwner();
+ public static boolean isSameApp(int, int);
+ public static boolean isSameUser(int, int);
+ public boolean isSystem();
+ public static int myUserId();
+ public static android.os.UserHandle of(int);
+ public static int parseUserArg(java.lang.String);
public static android.os.UserHandle readFromParcel(android.os.Parcel);
public java.lang.String toString();
public void writeToParcel(android.os.Parcel, int);
public static void writeToParcel(android.os.UserHandle, android.os.Parcel);
+ public static int AID_APP_END;
+ public static int AID_APP_START;
+ public static int AID_CACHE_GID_START;
+ public static int AID_ROOT;
+ public static int AID_SHARED_GID_START;
+ public static android.os.UserHandle ALL;
public static android.os.Parcelable$Creator CREATOR;
+ public static android.os.UserHandle CURRENT;
+ public static android.os.UserHandle CURRENT_OR_SELF;
+ public static int ERR_GID;
+ public static boolean MU_ENABLED;
+ public static android.os.UserHandle OWNER;
+ public static int PER_USER_RANGE;
+ public static android.os.UserHandle SYSTEM;
+ public static int USER_ALL;
+ public static int USER_CURRENT;
+ public static int USER_CURRENT_OR_SELF;
+ public static int USER_NULL;
+ public static int USER_OWNER;
+ public static int USER_SERIAL_SYSTEM;
+ public static int USER_SYSTEM;
+}
+
+-keep class android.os.VibrationEffect {
+ <init>();
+
+ public static android.os.VibrationEffect createOneShot(long, int);
+ public static android.os.VibrationEffect createWaveform(long[], int);
+ public static android.os.VibrationEffect createWaveform(long[], int[], int);
+ public int describeContents();
+ public static android.os.VibrationEffect get(int);
+ public static android.os.VibrationEffect get(int, boolean);
+ public static android.os.VibrationEffect get(android.net.Uri, android.content.Context);
+ public abstract long getDuration();
+ protected static int scale(int, float, int);
+ public abstract void validate();
+
+
+ public static android.os.Parcelable$Creator CREATOR;
+ public static int DEFAULT_AMPLITUDE;
+ public static int EFFECT_CLICK;
+ public static int EFFECT_DOUBLE_CLICK;
+ public static int EFFECT_HEAVY_CLICK;
+ public static int EFFECT_POP;
+ public static int EFFECT_THUD;
+ public static int EFFECT_TICK;
+ public static int MAX_AMPLITUDE;
+ public static int[] RINGTONES;
}
-keep class android.os.Vibrator {
+ <init>();
+ <init>(android.content.Context);
public abstract void cancel();
+ public int getDefaultHapticFeedbackIntensity();
+ public int getDefaultNotificationVibrationIntensity();
+ public abstract boolean hasAmplitudeControl();
public abstract boolean hasVibrator();
public void vibrate(long);
public void vibrate(long, android.media.AudioAttributes);
public void vibrate(long[], int);
public void vibrate(long[], int, android.media.AudioAttributes);
+ public void vibrate(android.os.VibrationEffect);
+ public void vibrate(android.os.VibrationEffect, android.media.AudioAttributes);
+ public abstract void vibrate(int, java.lang.String, android.os.VibrationEffect, android.media.AudioAttributes);
+
+
+ public static int VIBRATION_INTENSITY_HIGH;
+ public static int VIBRATION_INTENSITY_LOW;
+ public static int VIBRATION_INTENSITY_MEDIUM;
+ public static int VIBRATION_INTENSITY_OFF;
+}
+
+-keep class android.os.WorkSource {
+ <init>();
+ <init>(android.os.WorkSource);
+ <init>(int);
+ <init>(int, java.lang.String);
+
+ public boolean add(android.os.WorkSource);
+ public boolean add(int);
+ public boolean add(int, java.lang.String);
+ public android.os.WorkSource addReturningNewbs(android.os.WorkSource);
+ public void clear();
+ public void clearNames();
+ public android.os.WorkSource$WorkChain createWorkChain();
+ public int describeContents();
+ public boolean diff(android.os.WorkSource);
+ public static java.util.ArrayList[] diffChains(android.os.WorkSource, android.os.WorkSource);
+ public boolean equals(java.lang.Object);
+ public int get(int);
+ public java.lang.String getName(int);
+ public java.util.ArrayList getWorkChains();
+ public int hashCode();
+ public static boolean isChainedBatteryAttributionEnabled(android.content.Context);
+ public boolean isEmpty();
+ public boolean remove(android.os.WorkSource);
+ public void set(android.os.WorkSource);
+ public void set(int);
+ public void set(int, java.lang.String);
+ public android.os.WorkSource[] setReturningDiffs(android.os.WorkSource);
+ public int size();
+ public java.lang.String toString();
+ public void transferWorkChains(android.os.WorkSource);
+ public void writeToParcel(android.os.Parcel, int);
+ public void writeToProto(android.util.proto.ProtoOutputStream, long);
+
+
+ public static android.os.Parcelable$Creator CREATOR;
+}
+
+-keep class android.os.WorkSource$WorkChain {
+ <init>();
+ <init>(android.os.WorkSource$WorkChain);
+
+ public android.os.WorkSource$WorkChain addNode(int, java.lang.String);
+ public int describeContents();
+ public boolean equals(java.lang.Object);
+ public java.lang.String getAttributionTag();
+ public int getAttributionUid();
+ public int getSize();
+ public java.lang.String[] getTags();
+ public int[] getUids();
+ public int hashCode();
+ public java.lang.String toString();
+ public void writeToParcel(android.os.Parcel, int);
+
+
+ public static android.os.Parcelable$Creator CREATOR;
+}
+
+-keep class android.os.storage.DiskInfo {
+ <init>(java.lang.String, int);
+ <init>(android.os.Parcel);
+
+ public android.os.storage.DiskInfo clone();
+ public java.lang.Object clone();
+ public int describeContents();
+ public void dump(com.android.internal.util.IndentingPrintWriter);
+ public boolean equals(java.lang.Object);
+ public java.lang.String getDescription();
+ public java.lang.String getId();
+ public java.lang.String getShortDescription();
+ public int hashCode();
+ public boolean isAdoptable();
+ public boolean isDefaultPrimary();
+ public boolean isSd();
+ public boolean isUsb();
+ public java.lang.String toString();
+ public void writeToParcel(android.os.Parcel, int);
+
+
+ public static java.lang.String ACTION_DISK_SCANNED;
+ public static android.os.Parcelable$Creator CREATOR;
+ public static java.lang.String EXTRA_DISK_ID;
+ public static java.lang.String EXTRA_VOLUME_COUNT;
+ public static int FLAG_ADOPTABLE;
+ public static int FLAG_DEFAULT_PRIMARY;
+ public static int FLAG_SD;
+ public static int FLAG_USB;
+ public int flags;
+ public java.lang.String id;
+ public java.lang.String label;
+ public long size;
+ public java.lang.String sysPath;
+ public int volumeCount;
+}
+
+-keep class android.os.storage.StorageVolume {
+ <init>(java.lang.String, java.io.File, java.io.File, java.lang.String, boolean, boolean, boolean, boolean, long, android.os.UserHandle, java.lang.String, java.lang.String);
+
+ public boolean allowMassStorage();
+ public android.content.Intent createAccessIntent(java.lang.String);
+ public int describeContents();
+ public java.lang.String dump();
+ public void dump(com.android.internal.util.IndentingPrintWriter);
+ public boolean equals(java.lang.Object);
+ public java.lang.String getDescription(android.content.Context);
+ public int getFatVolumeId();
+ public java.lang.String getId();
+ public java.lang.String getInternalPath();
+ public long getMaxFileSize();
+ public android.os.UserHandle getOwner();
+ public java.lang.String getPath();
+ public java.io.File getPathFile();
+ public java.lang.String getState();
+ public java.lang.String getUserLabel();
+ public java.lang.String getUuid();
+ public int hashCode();
+ public boolean isEmulated();
+ public boolean isPrimary();
+ public boolean isRemovable();
+ public java.lang.String toString();
+ public void writeToParcel(android.os.Parcel, int);
+
+
+ public static android.os.Parcelable$Creator CREATOR;
+ public static java.lang.String EXTRA_DIRECTORY_NAME;
+ public static java.lang.String EXTRA_STORAGE_VOLUME;
+ public static int STORAGE_ID_INVALID;
+ public static int STORAGE_ID_PRIMARY;
+}
+
+-keep class android.os.storage.VolumeInfo {
+ <init>(java.lang.String, int, android.os.storage.DiskInfo, java.lang.String);
+ <init>(android.os.Parcel);
+
+ public android.content.Intent buildBrowseIntent();
+ public android.content.Intent buildBrowseIntentForUser(int);
+ public static int buildStableMtpStorageId(java.lang.String);
+ public android.os.storage.StorageVolume buildStorageVolume(android.content.Context, int, boolean);
+ public android.os.storage.VolumeInfo clone();
+ public java.lang.Object clone();
+ public int describeContents();
+ public void dump(com.android.internal.util.IndentingPrintWriter);
+ public boolean equals(java.lang.Object);
+ public static java.lang.String getBroadcastForEnvironment(java.lang.String);
+ public static java.lang.String getBroadcastForState(int);
+ public java.lang.String getDescription();
+ public static java.util.Comparator getDescriptionComparator();
+ public android.os.storage.DiskInfo getDisk();
+ public java.lang.String getDiskId();
+ public static java.lang.String getEnvironmentForState(int);
+ public java.lang.String getFsUuid();
+ public java.lang.String getId();
+ public java.io.File getInternalPath();
+ public java.io.File getInternalPathForUser(int);
+ public int getMountUserId();
+ public java.io.File getPath();
+ public java.io.File getPathForUser(int);
+ public int getState();
+ public int getStateDescription();
+ public int getType();
+ public int hashCode();
+ public boolean isMountedReadable();
+ public boolean isMountedWritable();
+ public boolean isPrimary();
+ public boolean isPrimaryPhysical();
+ public boolean isVisible();
+ public boolean isVisibleForRead(int);
+ public boolean isVisibleForUser(int);
+ public boolean isVisibleForWrite(int);
+ public java.lang.String toString();
+ public void writeToParcel(android.os.Parcel, int);
+
+
+ public static java.lang.String ACTION_VOLUME_STATE_CHANGED;
+ public static android.os.Parcelable$Creator CREATOR;
+ public static java.lang.String EXTRA_VOLUME_ID;
+ public static java.lang.String EXTRA_VOLUME_STATE;
+ public static java.lang.String ID_EMULATED_INTERNAL;
+ public static java.lang.String ID_PRIVATE_INTERNAL;
+ public static int MOUNT_FLAG_PRIMARY;
+ public static int MOUNT_FLAG_VISIBLE;
+ public static int STATE_BAD_REMOVAL;
+ public static int STATE_CHECKING;
+ public static int STATE_EJECTING;
+ public static int STATE_FORMATTING;
+ public static int STATE_MOUNTED;
+ public static int STATE_MOUNTED_READ_ONLY;
+ public static int STATE_REMOVED;
+ public static int STATE_UNMOUNTABLE;
+ public static int STATE_UNMOUNTED;
+ public static int TYPE_ASEC;
+ public static int TYPE_EMULATED;
+ public static int TYPE_OBB;
+ public static int TYPE_PRIVATE;
+ public static int TYPE_PUBLIC;
+ public android.os.storage.DiskInfo disk;
+ public java.lang.String fsLabel;
+ public java.lang.String fsType;
+ public java.lang.String fsUuid;
+ public java.lang.String id;
+ public java.lang.String internalPath;
+ public int mountFlags;
+ public int mountUserId;
+ public java.lang.String partGuid;
+ public java.lang.String path;
+ public int state;
+ public int type;
+}
+
+-keep class android.os.strictmode.Violation {
+
+
+
+}
+
+-keep class android.service.autofill.FieldClassification {
+ <init>(java.util.ArrayList);
+
+ public java.util.List getMatches();
+ public java.lang.String toString();
+
+
+}
+
+-keep class android.service.autofill.FieldClassification$Match {
+ <init>(java.lang.String, float);
+
+ public java.lang.String getCategoryId();
+ public float getScore();
+ public java.lang.String toString();
+
+
+}
+
+-keep class android.service.autofill.FillEventHistory {
+ <init>(int, android.os.Bundle);
+
+ public void addEvent(android.service.autofill.FillEventHistory$Event);
+ public int describeContents();
+ public android.os.Bundle getClientState();
+ public java.util.List getEvents();
+ public int getSessionId();
+ public java.lang.String toString();
+ public void writeToParcel(android.os.Parcel, int);
+
+
+ public static android.os.Parcelable$Creator CREATOR;
+}
+
+-keep class android.service.autofill.FillEventHistory$Event {
+ <init>(int, java.lang.String, android.os.Bundle, java.util.List, android.util.ArraySet, java.util.ArrayList, java.util.ArrayList, java.util.ArrayList, java.util.ArrayList, android.view.autofill.AutofillId[], android.service.autofill.FieldClassification[]);
+
+ public java.util.Map getChangedFields();
+ public android.os.Bundle getClientState();
+ public java.lang.String getDatasetId();
+ public java.util.Map getFieldsClassification();
+ public java.util.Set getIgnoredDatasetIds();
+ public java.util.Map getManuallyEnteredField();
+ public java.util.Set getSelectedDatasetIds();
+ public int getType();
+ public java.lang.String toString();
+
+
+ public static int TYPE_AUTHENTICATION_SELECTED;
+ public static int TYPE_CONTEXT_COMMITTED;
+ public static int TYPE_DATASET_AUTHENTICATION_SELECTED;
+ public static int TYPE_DATASET_SELECTED;
+ public static int TYPE_SAVE_SHOWN;
+}
+
+-keep class android.service.autofill.UserData {
+
+ public int describeContents();
+ public void dump(java.lang.String, java.io.PrintWriter);
+ public static void dumpConstraints(java.lang.String, java.io.PrintWriter);
+ public android.os.Bundle getAlgorithmArgs();
+ public java.lang.String[] getCategoryIds();
+ public java.lang.String getFieldClassificationAlgorithm();
+ public java.lang.String getId();
+ public static int getMaxCategoryCount();
+ public static int getMaxFieldClassificationIdsSize();
+ public static int getMaxUserDataSize();
+ public static int getMaxValueLength();
+ public static int getMinValueLength();
+ public java.lang.String[] getValues();
+ public java.lang.String toString();
+ public void writeToParcel(android.os.Parcel, int);
+
+
+ public static android.os.Parcelable$Creator CREATOR;
+}
+
+-keep class android.service.voice.IVoiceInteractionSession {
+
+ public abstract void closeSystemDialogs();
+ public abstract void destroy();
+ public abstract void handleAssist(android.os.Bundle, android.app.assist.AssistStructure, android.app.assist.AssistContent, int, int);
+ public abstract void handleScreenshot(android.graphics.Bitmap);
+ public abstract void hide();
+ public abstract void onLockscreenShown();
+ public abstract void show(android.os.Bundle, int, com.android.internal.app.IVoiceInteractionSessionShowCallback);
+ public abstract void taskFinished(android.content.Intent, int);
+ public abstract void taskStarted(android.content.Intent, int);
}
@@ -5171,6 +15701,10 @@
<init>();
public abstract int getDriverPosition();
+ public abstract float getEvBatteryCapacity();
+ public abstract int[] getEvConnectorTypes();
+ public abstract float getFuelCapacity();
+ public abstract int[] getFuelTypes();
public abstract java.lang.String getHeadunitManufacturer();
public abstract java.lang.String getHeadunitModel();
public abstract java.lang.String getHeadunitSoftwareBuild();
@@ -5295,6 +15829,11 @@
public static int SENSOR_TYPE_ABS_ACTIVE;
public static int SENSOR_TYPE_COMPASS;
public static int SENSOR_TYPE_DRIVING_STATUS;
+ public static int SENSOR_TYPE_EV_BATTERY_CHARGE_RATE;
+ public static int SENSOR_TYPE_EV_BATTERY_LEVEL;
+ public static int SENSOR_TYPE_EV_CHARGE_PORT_CONNECTED;
+ public static int SENSOR_TYPE_EV_CHARGE_PORT_OPEN;
+ public static int SENSOR_TYPE_FUEL_DOOR_OPEN;
public static int SENSOR_TYPE_NIGHT;
public static int SENSOR_TYPE_PARKING_BRAKE;
public static int SENSOR_TYPE_TRACTION_CONTROL_ACTIVE;
@@ -5311,26 +15850,13 @@
-keep class android.support.car.media.CarAudioManager {
<init>();
- public abstract void abandonAudioFocus(android.media.AudioManager$OnAudioFocusChangeListener, android.media.AudioAttributes);
public abstract android.support.car.media.CarAudioRecord createCarAudioRecord(int);
- public abstract android.media.AudioAttributes getAudioAttributesForCarUsage(int);
public abstract android.media.AudioFormat getAudioRecordAudioFormat();
public abstract int getAudioRecordMaxBufferSize();
public abstract int getAudioRecordMinBufferSize();
public abstract boolean isAudioRecordSupported();
- public abstract boolean isMediaMuted();
- public abstract int requestAudioFocus(android.media.AudioManager$OnAudioFocusChangeListener, android.media.AudioAttributes, int);
- public static int CAR_AUDIO_USAGE_ALARM;
- public static int CAR_AUDIO_USAGE_DEFAULT;
- public static int CAR_AUDIO_USAGE_MUSIC;
- public static int CAR_AUDIO_USAGE_NAVIGATION_GUIDANCE;
- public static int CAR_AUDIO_USAGE_NOTIFICATION;
- public static int CAR_AUDIO_USAGE_SYSTEM_SAFETY_ALERT;
- public static int CAR_AUDIO_USAGE_SYSTEM_SOUND;
- public static int CAR_AUDIO_USAGE_VOICE_CALL;
- public static int CAR_AUDIO_USAGE_VOICE_COMMAND;
}
-keep class android.support.car.media.CarAudioRecord {
@@ -5368,40 +15894,9 @@
public abstract void addListener(android.support.car.navigation.CarNavigationStatusManager$CarNavigationCallback);
public abstract void removeListener();
- public abstract void sendNavigationStatus(int);
- public abstract void sendNavigationTurnDistanceEvent(int, int, int, int);
- public abstract void sendNavigationTurnEvent(int, java.lang.CharSequence, int, int, int);
+ public abstract void sendEvent(int, android.os.Bundle);
- public static int DISTANCE_FEET;
- public static int DISTANCE_KILOMETERS;
- public static int DISTANCE_METERS;
- public static int DISTANCE_MILES;
- public static int DISTANCE_YARDS;
- public static int STATUS_ACTIVE;
- public static int STATUS_INACTIVE;
- public static int STATUS_UNAVAILABLE;
- public static int TURN_DEPART;
- public static int TURN_DESTINATION;
- public static int TURN_FERRY_BOAT;
- public static int TURN_FERRY_TRAIN;
- public static int TURN_FORK;
- public static int TURN_MERGE;
- public static int TURN_NAME_CHANGE;
- public static int TURN_OFF_RAMP;
- public static int TURN_ON_RAMP;
- public static int TURN_ROUNDABOUT_ENTER;
- public static int TURN_ROUNDABOUT_ENTER_AND_EXIT;
- public static int TURN_ROUNDABOUT_EXIT;
- public static int TURN_SHARP_TURN;
- public static int TURN_SIDE_LEFT;
- public static int TURN_SIDE_RIGHT;
- public static int TURN_SIDE_UNSPECIFIED;
- public static int TURN_SLIGHT_TURN;
- public static int TURN_STRAIGHT;
- public static int TURN_TURN;
- public static int TURN_UNKNOWN;
- public static int TURN_U_TURN;
}
-keep class android.support.car.navigation.CarNavigationStatusManager$CarNavigationCallback {
@@ -5412,16 +15907,249 @@
}
+-keep class android.transition.PathMotion {
+ <init>();
+ <init>(android.content.Context, android.util.AttributeSet);
+
+ public abstract android.graphics.Path getPath(float, float, float, float);
+
+
+}
+
+-keep class android.transition.Scene {
+ <init>(android.view.ViewGroup);
+ <init>(android.view.ViewGroup, android.view.View);
+ <init>(android.view.ViewGroup, android.view.ViewGroup);
+
+ public void enter();
+ public void exit();
+ public static android.transition.Scene getSceneForLayout(android.view.ViewGroup, int, android.content.Context);
+ public android.view.ViewGroup getSceneRoot();
+ public void setEnterAction(java.lang.Runnable);
+ public void setExitAction(java.lang.Runnable);
+
+
+}
+
+-keep class android.transition.Transition {
+ <init>();
+ <init>(android.content.Context, android.util.AttributeSet);
+
+ public android.transition.Transition addListener(android.transition.Transition$TransitionListener);
+ public android.transition.Transition addTarget(int);
+ public android.transition.Transition addTarget(java.lang.String);
+ public android.transition.Transition addTarget(java.lang.Class);
+ public android.transition.Transition addTarget(android.view.View);
+ protected void animate(android.animation.Animator);
+ public boolean canRemoveViews();
+ protected void cancel();
+ public abstract void captureEndValues(android.transition.TransitionValues);
+ public abstract void captureStartValues(android.transition.TransitionValues);
+ public android.transition.Transition clone();
+ public java.lang.Object clone();
+ public android.animation.Animator createAnimator(android.view.ViewGroup, android.transition.TransitionValues, android.transition.TransitionValues);
+ protected void createAnimators(android.view.ViewGroup, android.transition.TransitionValuesMaps, android.transition.TransitionValuesMaps, java.util.ArrayList, java.util.ArrayList);
+ protected void end();
+ public android.transition.Transition excludeChildren(int, boolean);
+ public android.transition.Transition excludeChildren(android.view.View, boolean);
+ public android.transition.Transition excludeChildren(java.lang.Class, boolean);
+ public android.transition.Transition excludeTarget(int, boolean);
+ public android.transition.Transition excludeTarget(java.lang.String, boolean);
+ public android.transition.Transition excludeTarget(android.view.View, boolean);
+ public android.transition.Transition excludeTarget(java.lang.Class, boolean);
+ public long getDuration();
+ public android.graphics.Rect getEpicenter();
+ public android.transition.Transition$EpicenterCallback getEpicenterCallback();
+ public android.animation.TimeInterpolator getInterpolator();
+ public java.lang.String getName();
+ public android.util.ArrayMap getNameOverrides();
+ public android.transition.PathMotion getPathMotion();
+ public android.transition.TransitionPropagation getPropagation();
+ public long getStartDelay();
+ public java.util.List getTargetIds();
+ public java.util.List getTargetNames();
+ public java.util.List getTargetTypes();
+ public java.util.List getTargetViewNames();
+ public java.util.List getTargets();
+ public java.lang.String[] getTransitionProperties();
+ public android.transition.TransitionValues getTransitionValues(android.view.View, boolean);
+ public boolean isTransitionRequired(android.transition.TransitionValues, android.transition.TransitionValues);
+ public boolean isValidTarget(android.view.View);
+ public void pause(android.view.View);
+ public android.transition.Transition removeListener(android.transition.Transition$TransitionListener);
+ public android.transition.Transition removeTarget(int);
+ public android.transition.Transition removeTarget(java.lang.String);
+ public android.transition.Transition removeTarget(android.view.View);
+ public android.transition.Transition removeTarget(java.lang.Class);
+ public void resume(android.view.View);
+ protected void runAnimators();
+ public android.transition.Transition setDuration(long);
+ public void setEpicenterCallback(android.transition.Transition$EpicenterCallback);
+ public android.transition.Transition setInterpolator(android.animation.TimeInterpolator);
+ public void setMatchOrder(int[]);
+ public void setNameOverrides(android.util.ArrayMap);
+ public void setPathMotion(android.transition.PathMotion);
+ public void setPropagation(android.transition.TransitionPropagation);
+ public android.transition.Transition setStartDelay(long);
+ protected void start();
+ public java.lang.String toString();
+
+
+ public static int MATCH_ID;
+ public static int MATCH_INSTANCE;
+ public static int MATCH_ITEM_ID;
+ public static int MATCH_NAME;
+}
+
+-keep class android.transition.Transition$EpicenterCallback {
+ <init>();
+
+ public abstract android.graphics.Rect onGetEpicenter(android.transition.Transition);
+
+
+}
+
+-keep class android.transition.Transition$TransitionListener {
+
+ public abstract void onTransitionCancel(android.transition.Transition);
+ public abstract void onTransitionEnd(android.transition.Transition);
+ public abstract void onTransitionPause(android.transition.Transition);
+ public abstract void onTransitionResume(android.transition.Transition);
+ public abstract void onTransitionStart(android.transition.Transition);
+
+
+}
+
+-keep class android.transition.TransitionManager {
+ <init>();
+
+ public static void beginDelayedTransition(android.view.ViewGroup);
+ public static void beginDelayedTransition(android.view.ViewGroup, android.transition.Transition);
+ public static void endTransitions(android.view.ViewGroup);
+ public static android.transition.Transition getDefaultTransition();
+ public android.transition.Transition getTransition(android.transition.Scene);
+ public static void go(android.transition.Scene);
+ public static void go(android.transition.Scene, android.transition.Transition);
+ public void setDefaultTransition(android.transition.Transition);
+ public void setTransition(android.transition.Scene, android.transition.Transition);
+ public void setTransition(android.transition.Scene, android.transition.Scene, android.transition.Transition);
+ public void transitionTo(android.transition.Scene);
+
+
+}
+
+-keep class android.transition.TransitionPropagation {
+ <init>();
+
+ public abstract void captureValues(android.transition.TransitionValues);
+ public abstract java.lang.String[] getPropagationProperties();
+ public abstract long getStartDelay(android.view.ViewGroup, android.transition.Transition, android.transition.TransitionValues, android.transition.TransitionValues);
+
+
+}
+
+-keep class android.transition.TransitionValues {
+ <init>();
+
+ public boolean equals(java.lang.Object);
+ public int hashCode();
+ public java.lang.String toString();
+
+
+ public java.util.Map values;
+ public android.view.View view;
+}
+
+-keep class android.transition.TransitionValuesMaps {
+
+
+
+}
+
-keep class android.util.AndroidException {
<init>();
<init>(java.lang.String);
<init>(java.lang.String, java.lang.Throwable);
<init>(java.lang.Exception);
+ <init>(java.lang.String, java.lang.Throwable, boolean, boolean);
}
+-keep class android.util.ArrayMap {
+ <init>();
+ <init>(int);
+ <init>(int, boolean);
+ <init>(android.util.ArrayMap);
+
+ public void append(java.lang.Object, java.lang.Object);
+ public void clear();
+ public boolean containsAll(java.util.Collection);
+ public boolean containsKey(java.lang.Object);
+ public boolean containsValue(java.lang.Object);
+ public void ensureCapacity(int);
+ public java.util.Set entrySet();
+ public boolean equals(java.lang.Object);
+ public void erase();
+ public java.lang.Object get(java.lang.Object);
+ public int hashCode();
+ public int indexOfKey(java.lang.Object);
+ public boolean isEmpty();
+ public java.lang.Object keyAt(int);
+ public java.util.Set keySet();
+ public java.lang.Object put(java.lang.Object, java.lang.Object);
+ public void putAll(android.util.ArrayMap);
+ public void putAll(java.util.Map);
+ public java.lang.Object remove(java.lang.Object);
+ public boolean removeAll(java.util.Collection);
+ public java.lang.Object removeAt(int);
+ public boolean retainAll(java.util.Collection);
+ public java.lang.Object setValueAt(int, java.lang.Object);
+ public int size();
+ public java.lang.String toString();
+ public void validate();
+ public java.lang.Object valueAt(int);
+ public java.util.Collection values();
+
+
+ public static android.util.ArrayMap EMPTY;
+}
+
+-keep class android.util.ArraySet {
+ <init>();
+ <init>(int);
+ <init>(int, boolean);
+ <init>(android.util.ArraySet);
+ <init>(java.util.Collection);
+
+ public boolean add(java.lang.Object);
+ public void addAll(android.util.ArraySet);
+ public boolean addAll(java.util.Collection);
+ public void append(java.lang.Object);
+ public void clear();
+ public boolean contains(java.lang.Object);
+ public boolean containsAll(java.util.Collection);
+ public void ensureCapacity(int);
+ public boolean equals(java.lang.Object);
+ public int hashCode();
+ public int indexOf(java.lang.Object);
+ public boolean isEmpty();
+ public java.util.Iterator iterator();
+ public boolean remove(java.lang.Object);
+ public boolean removeAll(android.util.ArraySet);
+ public boolean removeAll(java.util.Collection);
+ public java.lang.Object removeAt(int);
+ public boolean retainAll(java.util.Collection);
+ public int size();
+ public java.lang.Object[] toArray();
+ public java.lang.Object[] toArray(java.lang.Object[]);
+ public java.lang.String toString();
+ public java.lang.Object valueAt(int);
+
+
+}
+
-keep class android.util.AttributeSet {
public abstract boolean getAttributeBooleanValue(java.lang.String, java.lang.String, boolean);
@@ -5435,6 +16163,7 @@
public abstract int getAttributeListValue(int, java.lang.String[], int);
public abstract java.lang.String getAttributeName(int);
public abstract int getAttributeNameResource(int);
+ public java.lang.String getAttributeNamespace(int);
public abstract int getAttributeResourceValue(java.lang.String, java.lang.String, int);
public abstract int getAttributeResourceValue(int, int);
public abstract int getAttributeUnsignedIntValue(java.lang.String, java.lang.String, int);
@@ -5455,18 +16184,26 @@
public boolean equals(java.lang.Object);
public boolean equals(android.util.DisplayMetrics);
+ public boolean equalsPhysical(android.util.DisplayMetrics);
public int hashCode();
public void setTo(android.util.DisplayMetrics);
public void setToDefaults();
public java.lang.String toString();
+ public static int DENSITY_260;
public static int DENSITY_280;
+ public static int DENSITY_300;
+ public static int DENSITY_340;
public static int DENSITY_360;
public static int DENSITY_400;
public static int DENSITY_420;
+ public static int DENSITY_440;
public static int DENSITY_560;
public static int DENSITY_DEFAULT;
+ public static float DENSITY_DEFAULT_SCALE;
+ public static int DENSITY_DEVICE;
+ public static int DENSITY_DEVICE_STABLE;
public static int DENSITY_HIGH;
public static int DENSITY_LOW;
public static int DENSITY_MEDIUM;
@@ -5477,18 +16214,102 @@
public float density;
public int densityDpi;
public int heightPixels;
+ public float noncompatDensity;
+ public int noncompatDensityDpi;
+ public int noncompatHeightPixels;
+ public float noncompatScaledDensity;
+ public int noncompatWidthPixels;
+ public float noncompatXdpi;
+ public float noncompatYdpi;
public float scaledDensity;
public int widthPixels;
public float xdpi;
public float ydpi;
}
+-keep class android.util.LongArray {
+ <init>();
+ <init>(int);
+
+ public void add(long);
+ public void add(int, long);
+ public void addAll(android.util.LongArray);
+ public void clear();
+ public android.util.LongArray clone();
+ public java.lang.Object clone();
+ public static boolean elementsEqual(android.util.LongArray, android.util.LongArray);
+ public static android.util.LongArray fromArray(long[], int);
+ public long get(int);
+ public int indexOf(long);
+ public void remove(int);
+ public void resize(int);
+ public void set(int, long);
+ public int size();
+ public long[] toArray();
+ public static android.util.LongArray wrap(long[]);
+
+
+}
+
+-keep class android.util.LongSparseArray {
+ <init>();
+ <init>(int);
+
+ public void append(long, java.lang.Object);
+ public void clear();
+ public android.util.LongSparseArray clone();
+ public java.lang.Object clone();
+ public void delete(long);
+ public java.lang.Object get(long);
+ public java.lang.Object get(long, java.lang.Object);
+ public int indexOfKey(long);
+ public int indexOfValue(java.lang.Object);
+ public int indexOfValueByValue(java.lang.Object);
+ public long keyAt(int);
+ public void put(long, java.lang.Object);
+ public void remove(long);
+ public void removeAt(int);
+ public void setValueAt(int, java.lang.Object);
+ public int size();
+ public java.lang.String toString();
+ public java.lang.Object valueAt(int);
+
+
+}
+
+-keep class android.util.MergedConfiguration {
+ <init>();
+ <init>(android.content.res.Configuration, android.content.res.Configuration);
+ <init>(android.content.res.Configuration);
+ <init>(android.util.MergedConfiguration);
+
+ public int describeContents();
+ public void dump(java.io.PrintWriter, java.lang.String);
+ public boolean equals(java.lang.Object);
+ public android.content.res.Configuration getGlobalConfiguration();
+ public android.content.res.Configuration getMergedConfiguration();
+ public android.content.res.Configuration getOverrideConfiguration();
+ public int hashCode();
+ public void readFromParcel(android.os.Parcel);
+ public void setConfiguration(android.content.res.Configuration, android.content.res.Configuration);
+ public void setGlobalConfiguration(android.content.res.Configuration);
+ public void setOverrideConfiguration(android.content.res.Configuration);
+ public void setTo(android.util.MergedConfiguration);
+ public java.lang.String toString();
+ public void unset();
+ public void writeToParcel(android.os.Parcel, int);
+
+
+ public static android.os.Parcelable$Creator CREATOR;
+}
+
-keep class android.util.Pair {
<init>(java.lang.Object, java.lang.Object);
public static android.util.Pair create(java.lang.Object, java.lang.Object);
public boolean equals(java.lang.Object);
public int hashCode();
+ public java.lang.String toString();
public java.lang.Object first;
@@ -5502,6 +16323,49 @@
}
+-keep class android.util.Property {
+ <init>(java.lang.Class, java.lang.String);
+
+ public abstract java.lang.Object get(java.lang.Object);
+ public java.lang.String getName();
+ public java.lang.Class getType();
+ public boolean isReadOnly();
+ public static android.util.Property of(java.lang.Class, java.lang.Class, java.lang.String);
+ public void set(java.lang.Object, java.lang.Object);
+
+
+}
+
+-keep class android.util.Rational {
+ <init>(int, int);
+
+ public int compareTo(android.util.Rational);
+ public int compareTo(java.lang.Object);
+ public double doubleValue();
+ public boolean equals(java.lang.Object);
+ public float floatValue();
+ public static int gcd(int, int);
+ public int getDenominator();
+ public int getNumerator();
+ public int hashCode();
+ public int intValue();
+ public boolean isFinite();
+ public boolean isInfinite();
+ public boolean isNaN();
+ public boolean isZero();
+ public long longValue();
+ public static android.util.Rational parseRational(java.lang.String);
+ public short shortValue();
+ public float toFloat();
+ public java.lang.String toString();
+
+
+ public static android.util.Rational NEGATIVE_INFINITY;
+ public static android.util.Rational NaN;
+ public static android.util.Rational POSITIVE_INFINITY;
+ public static android.util.Rational ZERO;
+}
+
-keep class android.util.Size {
<init>(int, int);
@@ -5541,11 +16405,13 @@
public java.lang.Object get(int, java.lang.Object);
public int indexOfKey(int);
public int indexOfValue(java.lang.Object);
+ public int indexOfValueByValue(java.lang.Object);
public int keyAt(int);
public void put(int, java.lang.Object);
public void remove(int);
public void removeAt(int);
public void removeAtRange(int, int);
+ public java.lang.Object removeReturnOld(int);
public void setValueAt(int, java.lang.Object);
public int size();
public java.lang.String toString();
@@ -5563,12 +16429,17 @@
public android.util.SparseBooleanArray clone();
public java.lang.Object clone();
public void delete(int);
+ public boolean equals(java.lang.Object);
public boolean get(int);
public boolean get(int, boolean);
+ public int hashCode();
public int indexOfKey(int);
public int indexOfValue(boolean);
public int keyAt(int);
public void put(int, boolean);
+ public void removeAt(int);
+ public void setKeyAt(int, int);
+ public void setValueAt(int, boolean);
public int size();
public java.lang.String toString();
public boolean valueAt(int);
@@ -5576,6 +16447,31 @@
}
+-keep class android.util.SparseIntArray {
+ <init>();
+ <init>(int);
+
+ public void append(int, int);
+ public void clear();
+ public android.util.SparseIntArray clone();
+ public java.lang.Object clone();
+ public int[] copyKeys();
+ public void delete(int);
+ public int get(int);
+ public int get(int, int);
+ public int indexOfKey(int);
+ public int indexOfValue(int);
+ public int keyAt(int);
+ public void put(int, int);
+ public void removeAt(int);
+ public void setValueAt(int, int);
+ public int size();
+ public java.lang.String toString();
+ public int valueAt(int);
+
+
+}
+
-keep class android.util.TypedValue {
<init>();
@@ -5583,6 +16479,7 @@
public java.lang.CharSequence coerceToString();
public static java.lang.String coerceToString(int, int);
public static float complexToDimension(int, android.util.DisplayMetrics);
+ public static float complexToDimensionNoisy(int, android.util.DisplayMetrics);
public static int complexToDimensionPixelOffset(int, android.util.DisplayMetrics);
public static int complexToDimensionPixelSize(int, android.util.DisplayMetrics);
public static float complexToFloat(int);
@@ -5644,48 +16541,430 @@
public int type;
}
--keep class android.view.Display {
+-keep class android.util.proto.ProtoOutputStream {
+ <init>();
+ <init>(int);
+ <init>(java.io.OutputStream);
+ <init>(java.io.FileDescriptor);
+ public static int checkFieldId(long, long);
+ public static int convertObjectIdToOrdinal(int);
+ public void dump(java.lang.String);
+ public void end(long);
+ public void endObject(long);
+ public void endRepeatedObject(long);
+ public void flush();
+ public byte[] getBytes();
+ public static int getDepthFromToken(long);
+ public static int getObjectIdFromToken(long);
+ public static boolean getRepeatedFromToken(long);
+ public static int getSizePosFromToken(long);
+ public static int getTagSizeFromToken(long);
+ public static long makeFieldId(int, long);
+ public static long makeToken(int, boolean, int, int, int);
+ public long start(long);
+ public long startObject(long);
+ public long startRepeatedObject(long);
+ public static java.lang.String token2String(long);
+ public void write(long, double);
+ public void write(long, float);
+ public void write(long, int);
+ public void write(long, long);
+ public void write(long, boolean);
+ public void write(long, java.lang.String);
+ public void write(long, byte[]);
+ public void writeBool(long, boolean);
+ public void writeBytes(long, byte[]);
+ public void writeDouble(long, double);
+ public void writeEnum(long, int);
+ public void writeFixed32(long, int);
+ public void writeFixed64(long, long);
+ public void writeFloat(long, float);
+ public void writeInt32(long, int);
+ public void writeInt64(long, long);
+ public void writeObject(long, byte[]);
+ public void writePackedBool(long, boolean[]);
+ public void writePackedDouble(long, double[]);
+ public void writePackedEnum(long, int[]);
+ public void writePackedFixed32(long, int[]);
+ public void writePackedFixed64(long, long[]);
+ public void writePackedFloat(long, float[]);
+ public void writePackedInt32(long, int[]);
+ public void writePackedInt64(long, long[]);
+ public void writePackedSFixed32(long, int[]);
+ public void writePackedSFixed64(long, long[]);
+ public void writePackedSInt32(long, int[]);
+ public void writePackedSInt64(long, long[]);
+ public void writePackedUInt32(long, int[]);
+ public void writePackedUInt64(long, long[]);
+ public void writeRepeatedBool(long, boolean);
+ public void writeRepeatedBytes(long, byte[]);
+ public void writeRepeatedDouble(long, double);
+ public void writeRepeatedEnum(long, int);
+ public void writeRepeatedFixed32(long, int);
+ public void writeRepeatedFixed64(long, long);
+ public void writeRepeatedFloat(long, float);
+ public void writeRepeatedInt32(long, int);
+ public void writeRepeatedInt64(long, long);
+ public void writeRepeatedObject(long, byte[]);
+ public void writeRepeatedSFixed32(long, int);
+ public void writeRepeatedSFixed64(long, long);
+ public void writeRepeatedSInt32(long, int);
+ public void writeRepeatedSInt64(long, long);
+ public void writeRepeatedString(long, java.lang.String);
+ public void writeRepeatedUInt32(long, int);
+ public void writeRepeatedUInt64(long, long);
+ public void writeSFixed32(long, int);
+ public void writeSFixed64(long, long);
+ public void writeSInt32(long, int);
+ public void writeSInt64(long, long);
+ public void writeString(long, java.lang.String);
+ public void writeTag(int, int);
+ public void writeUInt32(long, int);
+ public void writeUInt64(long, long);
+
+
+ public static long FIELD_COUNT_MASK;
+ public static long FIELD_COUNT_PACKED;
+ public static long FIELD_COUNT_REPEATED;
+ public static int FIELD_COUNT_SHIFT;
+ public static long FIELD_COUNT_SINGLE;
+ public static long FIELD_COUNT_UNKNOWN;
+ public static int FIELD_ID_MASK;
+ public static int FIELD_ID_SHIFT;
+ public static long FIELD_TYPE_BOOL;
+ public static long FIELD_TYPE_BYTES;
+ public static long FIELD_TYPE_DOUBLE;
+ public static long FIELD_TYPE_ENUM;
+ public static long FIELD_TYPE_FIXED32;
+ public static long FIELD_TYPE_FIXED64;
+ public static long FIELD_TYPE_FLOAT;
+ public static long FIELD_TYPE_INT32;
+ public static long FIELD_TYPE_INT64;
+ public static long FIELD_TYPE_MASK;
+ public static long FIELD_TYPE_MESSAGE;
+ public static long FIELD_TYPE_SFIXED32;
+ public static long FIELD_TYPE_SFIXED64;
+ public static int FIELD_TYPE_SHIFT;
+ public static long FIELD_TYPE_SINT32;
+ public static long FIELD_TYPE_SINT64;
+ public static long FIELD_TYPE_STRING;
+ public static long FIELD_TYPE_UINT32;
+ public static long FIELD_TYPE_UINT64;
+ public static long FIELD_TYPE_UNKNOWN;
+ public static java.lang.String TAG;
+ public static int WIRE_TYPE_END_GROUP;
+ public static int WIRE_TYPE_FIXED32;
+ public static int WIRE_TYPE_FIXED64;
+ public static int WIRE_TYPE_LENGTH_DELIMITED;
+ public static int WIRE_TYPE_MASK;
+ public static int WIRE_TYPE_START_GROUP;
+ public static int WIRE_TYPE_VARINT;
+}
+
+-keep class android.view.AccessibilityInteractionController {
+ <init>(android.view.ViewRootImpl);
+
+ public void findAccessibilityNodeInfoByAccessibilityIdClientThread(long, android.graphics.Region, int, android.view.accessibility.IAccessibilityInteractionConnectionCallback, int, int, long, android.view.MagnificationSpec, android.os.Bundle);
+ public void findAccessibilityNodeInfosByTextClientThread(long, java.lang.String, android.graphics.Region, int, android.view.accessibility.IAccessibilityInteractionConnectionCallback, int, int, long, android.view.MagnificationSpec);
+ public void findAccessibilityNodeInfosByViewIdClientThread(long, java.lang.String, android.graphics.Region, int, android.view.accessibility.IAccessibilityInteractionConnectionCallback, int, int, long, android.view.MagnificationSpec);
+ public void findFocusClientThread(long, int, android.graphics.Region, int, android.view.accessibility.IAccessibilityInteractionConnectionCallback, int, int, long, android.view.MagnificationSpec);
+ public void focusSearchClientThread(long, int, android.graphics.Region, int, android.view.accessibility.IAccessibilityInteractionConnectionCallback, int, int, long, android.view.MagnificationSpec);
+ public void performAccessibilityActionClientThread(long, int, android.os.Bundle, int, android.view.accessibility.IAccessibilityInteractionConnectionCallback, int, int, long);
+
+
+}
+
+-keep class android.view.AccessibilityIterators {
+ <init>();
+
+
+
+}
+
+-keep class android.view.AccessibilityIterators$TextSegmentIterator {
+
+ public abstract int[] following(int);
+ public abstract int[] preceding(int);
+
+
+}
+
+-keep class android.view.ActionMode {
+ <init>();
+
+ public abstract void finish();
+ public abstract android.view.View getCustomView();
+ public abstract android.view.Menu getMenu();
+ public abstract android.view.MenuInflater getMenuInflater();
+ public abstract java.lang.CharSequence getSubtitle();
+ public java.lang.Object getTag();
+ public abstract java.lang.CharSequence getTitle();
+ public boolean getTitleOptionalHint();
+ public int getType();
+ public void hide(long);
+ public abstract void invalidate();
+ public void invalidateContentRect();
+ public boolean isTitleOptional();
+ public boolean isUiFocusable();
+ public void onWindowFocusChanged(boolean);
+ public abstract void setCustomView(android.view.View);
+ public abstract void setSubtitle(java.lang.CharSequence);
+ public abstract void setSubtitle(int);
+ public void setTag(java.lang.Object);
+ public abstract void setTitle(java.lang.CharSequence);
+ public abstract void setTitle(int);
+ public void setTitleOptionalHint(boolean);
+ public void setType(int);
+
+
+ public static int DEFAULT_HIDE_DURATION;
+ public static int TYPE_FLOATING;
+ public static int TYPE_PRIMARY;
+}
+
+-keep class android.view.ActionMode$Callback {
+
+ public abstract boolean onActionItemClicked(android.view.ActionMode, android.view.MenuItem);
+ public abstract boolean onCreateActionMode(android.view.ActionMode, android.view.Menu);
+ public abstract void onDestroyActionMode(android.view.ActionMode);
+ public abstract boolean onPrepareActionMode(android.view.ActionMode, android.view.Menu);
+
+
+}
+
+-keep class android.view.ActionProvider {
+ <init>(android.content.Context);
+
+ public boolean hasSubMenu();
+ public boolean isVisible();
+ public abstract android.view.View onCreateActionView();
+ public android.view.View onCreateActionView(android.view.MenuItem);
+ public boolean onPerformDefaultAction();
+ public void onPrepareSubMenu(android.view.SubMenu);
+ public boolean overridesItemVisibility();
+ public void refreshVisibility();
+ public void reset();
+ public void setSubUiVisibilityListener(android.view.ActionProvider$SubUiVisibilityListener);
+ public void setVisibilityListener(android.view.ActionProvider$VisibilityListener);
+ public void subUiVisibilityChanged(boolean);
+
+
+}
+
+-keep class android.view.ActionProvider$SubUiVisibilityListener {
+
+ public abstract void onSubUiVisibilityChanged(boolean);
+
+
+}
+
+-keep class android.view.ActionProvider$VisibilityListener {
+
+ public abstract void onActionProviderVisibilityChanged(boolean);
+
+
+}
+
+-keep class android.view.AppTransitionAnimationSpec {
+ <init>(int, android.graphics.GraphicBuffer, android.graphics.Rect);
+ <init>(android.os.Parcel);
+
+ public int describeContents();
+ public java.lang.String toString();
+ public void writeToParcel(android.os.Parcel, int);
+
+
+ public static android.os.Parcelable$Creator CREATOR;
+ public android.graphics.GraphicBuffer buffer;
+ public android.graphics.Rect rect;
+ public int taskId;
+}
+
+-keep class android.view.Choreographer {
+
+ public static long getFrameDelay();
+ public long getFrameIntervalNanos();
+ public long getFrameTime();
+ public long getFrameTimeNanos();
+ public static android.view.Choreographer getInstance();
+ public long getLastFrameTimeNanos();
+ public static android.view.Choreographer getMainThreadInstance();
+ public static android.view.Choreographer getSfInstance();
+ public void postCallback(int, java.lang.Runnable, java.lang.Object);
+ public void postCallbackDelayed(int, java.lang.Runnable, java.lang.Object, long);
+ public void postFrameCallback(android.view.Choreographer$FrameCallback);
+ public void postFrameCallbackDelayed(android.view.Choreographer$FrameCallback, long);
+ public static void releaseInstance();
+ public void removeCallbacks(int, java.lang.Runnable, java.lang.Object);
+ public void removeFrameCallback(android.view.Choreographer$FrameCallback);
+ public static void setFrameDelay(long);
+ public static long subtractFrameDelay(long);
+
+
+ public static int CALLBACK_ANIMATION;
+ public static int CALLBACK_COMMIT;
+ public static int CALLBACK_INPUT;
+ public static int CALLBACK_TRAVERSAL;
+}
+
+-keep class android.view.Choreographer$FrameCallback {
+
+ public abstract void doFrame(long);
+
+
+}
+
+-keep class android.view.ContextMenu {
+
+ public abstract void clearHeader();
+ public abstract android.view.ContextMenu setHeaderIcon(int);
+ public abstract android.view.ContextMenu setHeaderIcon(android.graphics.drawable.Drawable);
+ public abstract android.view.ContextMenu setHeaderTitle(int);
+ public abstract android.view.ContextMenu setHeaderTitle(java.lang.CharSequence);
+ public abstract android.view.ContextMenu setHeaderView(android.view.View);
+
+
+}
+
+-keep class android.view.ContextMenu$ContextMenuInfo {
+
+
+
+}
+
+-keep class android.view.ContextThemeWrapper {
+ <init>();
+ <init>(android.content.Context, int);
+ <init>(android.content.Context, android.content.res.Resources$Theme);
+
+ public void applyOverrideConfiguration(android.content.res.Configuration);
+ protected void attachBaseContext(android.content.Context);
+ public android.content.res.AssetManager getAssets();
+ public android.content.res.Configuration getOverrideConfiguration();
+ public android.content.res.Resources getResources();
+ public java.lang.Object getSystemService(java.lang.String);
+ public android.content.res.Resources$Theme getTheme();
+ public int getThemeResId();
+ protected void onApplyThemeResource(android.content.res.Resources$Theme, int, boolean);
+ public void setTheme(int);
+
+
+}
+
+-keep class android.view.Display {
+ <init>(android.hardware.display.DisplayManagerGlobal, int, android.view.DisplayInfo, android.view.DisplayAdjustments);
+ <init>(android.hardware.display.DisplayManagerGlobal, int, android.view.DisplayInfo, android.content.res.Resources);
+
+ public java.lang.String getAddress();
public long getAppVsyncOffsetNanos();
+ public int getColorMode();
public void getCurrentSizeRange(android.graphics.Point, android.graphics.Point);
+ public android.view.DisplayAdjustments getDisplayAdjustments();
public int getDisplayId();
+ public boolean getDisplayInfo(android.view.DisplayInfo);
public int getFlags();
+ public android.view.Display$HdrCapabilities getHdrCapabilities();
public int getHeight();
+ public int getLayerStack();
+ public int getMaximumSizeDimension();
public void getMetrics(android.util.DisplayMetrics);
public android.view.Display$Mode getMode();
public java.lang.String getName();
public int getOrientation();
+ public void getOverscanInsets(android.graphics.Rect);
+ public java.lang.String getOwnerPackageName();
+ public int getOwnerUid();
public int getPixelFormat();
public long getPresentationDeadlineNanos();
public void getRealMetrics(android.util.DisplayMetrics);
public void getRealSize(android.graphics.Point);
public void getRectSize(android.graphics.Rect);
public float getRefreshRate();
+ public int getRemoveMode();
public int getRotation();
public void getSize(android.graphics.Point);
public int getState();
+ public int[] getSupportedColorModes();
public android.view.Display$Mode[] getSupportedModes();
public float[] getSupportedRefreshRates();
+ public int getType();
public int getWidth();
+ public boolean hasAccess(int);
+ public static boolean hasAccess(int, int, int);
+ public static boolean isDozeState(int);
+ public boolean isHdr();
+ public boolean isPublicPresentation();
+ public static boolean isSuspendedState(int);
public boolean isValid();
+ public boolean isWideColorGamut();
+ public void requestColorMode(int);
+ public static java.lang.String stateToString(int);
public java.lang.String toString();
+ public static java.lang.String typeToString(int);
+ public static int COLOR_MODE_ADOBE_RGB;
+ public static int COLOR_MODE_BT601_525;
+ public static int COLOR_MODE_BT601_525_UNADJUSTED;
+ public static int COLOR_MODE_BT601_625;
+ public static int COLOR_MODE_BT601_625_UNADJUSTED;
+ public static int COLOR_MODE_BT709;
+ public static int COLOR_MODE_DCI_P3;
+ public static int COLOR_MODE_DEFAULT;
+ public static int COLOR_MODE_DISPLAY_P3;
+ public static int COLOR_MODE_INVALID;
+ public static int COLOR_MODE_SRGB;
public static int DEFAULT_DISPLAY;
+ public static int FLAG_CAN_SHOW_WITH_INSECURE_KEYGUARD;
public static int FLAG_PRESENTATION;
public static int FLAG_PRIVATE;
public static int FLAG_ROUND;
+ public static int FLAG_SCALING_DISABLED;
public static int FLAG_SECURE;
public static int FLAG_SUPPORTS_PROTECTED_BUFFERS;
public static int INVALID_DISPLAY;
+ public static int REMOVE_MODE_DESTROY_CONTENT;
+ public static int REMOVE_MODE_MOVE_CONTENT_TO_PRIMARY;
public static int STATE_DOZE;
public static int STATE_DOZE_SUSPEND;
public static int STATE_OFF;
public static int STATE_ON;
+ public static int STATE_ON_SUSPEND;
public static int STATE_UNKNOWN;
+ public static int STATE_VR;
+ public static int TYPE_BUILT_IN;
+ public static int TYPE_HDMI;
+ public static int TYPE_OVERLAY;
+ public static int TYPE_UNKNOWN;
+ public static int TYPE_VIRTUAL;
+ public static int TYPE_WIFI;
+}
+
+-keep class android.view.Display$HdrCapabilities {
+ <init>();
+ <init>(int[], float, float, float);
+
+ public int describeContents();
+ public boolean equals(java.lang.Object);
+ public float getDesiredMaxAverageLuminance();
+ public float getDesiredMaxLuminance();
+ public float getDesiredMinLuminance();
+ public int[] getSupportedHdrTypes();
+ public int hashCode();
+ public void readFromParcel(android.os.Parcel);
+ public void writeToParcel(android.os.Parcel, int);
+
+
+ public static android.os.Parcelable$Creator CREATOR;
+ public static int HDR_TYPE_DOLBY_VISION;
+ public static int HDR_TYPE_HDR10;
+ public static int HDR_TYPE_HLG;
+ public static float INVALID_LUMINANCE;
}
-keep class android.view.Display$Mode {
+ <init>(int, int, int, float);
public int describeContents();
public boolean equals(java.lang.Object);
@@ -5694,21 +16973,364 @@
public int getPhysicalWidth();
public float getRefreshRate();
public int hashCode();
+ public boolean matches(int, int, float);
public java.lang.String toString();
public void writeToParcel(android.os.Parcel, int);
public static android.os.Parcelable$Creator CREATOR;
+ public static android.view.Display$Mode[] EMPTY_ARRAY;
+}
+
+-keep class android.view.DisplayAdjustments {
+ <init>();
+ <init>(android.content.res.Configuration);
+ <init>(android.view.DisplayAdjustments);
+
+ public boolean equals(java.lang.Object);
+ public android.content.res.CompatibilityInfo getCompatibilityInfo();
+ public android.content.res.Configuration getConfiguration();
+ public int hashCode();
+ public void setCompatibilityInfo(android.content.res.CompatibilityInfo);
+ public void setConfiguration(android.content.res.Configuration);
+
+
+ public static android.view.DisplayAdjustments DEFAULT_DISPLAY_ADJUSTMENTS;
+}
+
+-keep class android.view.DisplayCutout {
+ <init>(android.graphics.Rect, java.util.List);
+
+ public boolean equals(java.lang.Object);
+ public static android.view.DisplayCutout fromBoundingRect(int, int, int, int);
+ public static android.view.DisplayCutout fromBounds(android.graphics.Path);
+ public static android.view.DisplayCutout fromResources(android.content.res.Resources, int, int);
+ public static android.view.DisplayCutout fromSpec(java.lang.String, int, int, float);
+ public java.util.List getBoundingRects();
+ public android.graphics.Region getBounds();
+ public int getSafeInsetBottom();
+ public int getSafeInsetLeft();
+ public int getSafeInsetRight();
+ public int getSafeInsetTop();
+ public android.graphics.Rect getSafeInsets();
+ public int hashCode();
+ public android.view.DisplayCutout inset(int, int, int, int);
+ public boolean isBoundsEmpty();
+ public boolean isEmpty();
+ public static android.graphics.Path pathFromResources(android.content.res.Resources, int, int);
+ public android.view.DisplayCutout replaceSafeInsets(android.graphics.Rect);
+ public java.lang.String toString();
+ public void writeToProto(android.util.proto.ProtoOutputStream, long);
+
+
+ public static java.lang.String EMULATION_OVERLAY_CATEGORY;
+ public static android.view.DisplayCutout NO_CUTOUT;
+}
+
+-keep class android.view.DisplayCutout$ParcelableWrapper {
+ <init>();
+ <init>(android.view.DisplayCutout);
+
+ public int describeContents();
+ public boolean equals(java.lang.Object);
+ public android.view.DisplayCutout get();
+ public int hashCode();
+ public static android.view.DisplayCutout readCutoutFromParcel(android.os.Parcel);
+ public void readFromParcel(android.os.Parcel);
+ public void set(android.view.DisplayCutout$ParcelableWrapper);
+ public void set(android.view.DisplayCutout);
+ public java.lang.String toString();
+ public static void writeCutoutToParcel(android.view.DisplayCutout, android.os.Parcel, int);
+ public void writeToParcel(android.os.Parcel, int);
+
+
+ public static android.os.Parcelable$Creator CREATOR;
+}
+
+-keep class android.view.DisplayInfo {
+ <init>();
+ <init>(android.view.DisplayInfo);
+
+ public void copyFrom(android.view.DisplayInfo);
+ public int describeContents();
+ public boolean equals(java.lang.Object);
+ public boolean equals(android.view.DisplayInfo);
+ public int findDefaultModeByRefreshRate(float);
+ public void getAppMetrics(android.util.DisplayMetrics);
+ public void getAppMetrics(android.util.DisplayMetrics, android.view.DisplayAdjustments);
+ public void getAppMetrics(android.util.DisplayMetrics, android.content.res.CompatibilityInfo, android.content.res.Configuration);
+ public android.view.Display$Mode getDefaultMode();
+ public float[] getDefaultRefreshRates();
+ public void getLogicalMetrics(android.util.DisplayMetrics, android.content.res.CompatibilityInfo, android.content.res.Configuration);
+ public android.view.Display$Mode getMode();
+ public int getNaturalHeight();
+ public int getNaturalWidth();
+ public boolean hasAccess(int);
+ public int hashCode();
+ public boolean isHdr();
+ public boolean isWideColorGamut();
+ public void readFromParcel(android.os.Parcel);
+ public java.lang.String toString();
+ public void writeToParcel(android.os.Parcel, int);
+ public void writeToProto(android.util.proto.ProtoOutputStream, long);
+
+
+ public static android.os.Parcelable$Creator CREATOR;
+ public java.lang.String address;
+ public int appHeight;
+ public long appVsyncOffsetNanos;
+ public int appWidth;
+ public int colorMode;
+ public int defaultModeId;
+ public android.view.DisplayCutout displayCutout;
+ public int flags;
+ public android.view.Display$HdrCapabilities hdrCapabilities;
+ public int largestNominalAppHeight;
+ public int largestNominalAppWidth;
+ public int layerStack;
+ public int logicalDensityDpi;
+ public int logicalHeight;
+ public int logicalWidth;
+ public int modeId;
+ public java.lang.String name;
+ public int overscanBottom;
+ public int overscanLeft;
+ public int overscanRight;
+ public int overscanTop;
+ public java.lang.String ownerPackageName;
+ public int ownerUid;
+ public float physicalXDpi;
+ public float physicalYDpi;
+ public long presentationDeadlineNanos;
+ public int removeMode;
+ public int rotation;
+ public int smallestNominalAppHeight;
+ public int smallestNominalAppWidth;
+ public int state;
+ public int[] supportedColorModes;
+ public android.view.Display$Mode[] supportedModes;
+ public int type;
+ public java.lang.String uniqueId;
+}
+
+-keep class android.view.DisplayListCanvas {
+
+ public void callDrawGLFunction2(long);
+ public void drawCircle(android.graphics.CanvasProperty, android.graphics.CanvasProperty, android.graphics.CanvasProperty, android.graphics.CanvasProperty);
+ public void drawGLFunctor2(long, java.lang.Runnable);
+ public void drawRenderNode(android.view.RenderNode);
+ public void drawRoundRect(android.graphics.CanvasProperty, android.graphics.CanvasProperty, android.graphics.CanvasProperty, android.graphics.CanvasProperty, android.graphics.CanvasProperty, android.graphics.CanvasProperty, android.graphics.CanvasProperty);
+ public int getHeight();
+ public int getMaximumBitmapHeight();
+ public int getMaximumBitmapWidth();
+ public int getWidth();
+ public void insertInorderBarrier();
+ public void insertReorderBarrier();
+ public boolean isHardwareAccelerated();
+ public boolean isOpaque();
+ public boolean isRecordingFor(java.lang.Object);
+ public void setBitmap(android.graphics.Bitmap);
+ public void setDensity(int);
+ protected void throwIfCannotDraw(android.graphics.Bitmap);
+
+
+}
+
+-keep class android.view.DragAndDropPermissions {
+
+ public int describeContents();
+ public static android.view.DragAndDropPermissions obtain(android.view.DragEvent);
+ public void release();
+ public boolean take(android.os.IBinder);
+ public boolean takeTransient();
+ public void writeToParcel(android.os.Parcel, int);
+
+
+ public static android.os.Parcelable$Creator CREATOR;
+}
+
+-keep class android.view.DragEvent {
+
+ public int describeContents();
+ public int getAction();
+ public android.content.ClipData getClipData();
+ public android.content.ClipDescription getClipDescription();
+ public com.android.internal.view.IDragAndDropPermissions getDragAndDropPermissions();
+ public java.lang.Object getLocalState();
+ public boolean getResult();
+ public float getX();
+ public float getY();
+ public static android.view.DragEvent obtain(int, float, float, java.lang.Object, android.content.ClipDescription, android.content.ClipData, com.android.internal.view.IDragAndDropPermissions, boolean);
+ public static android.view.DragEvent obtain(android.view.DragEvent);
+ public void recycle();
+ public java.lang.String toString();
+ public void writeToParcel(android.os.Parcel, int);
+
+
+ public static int ACTION_DRAG_ENDED;
+ public static int ACTION_DRAG_ENTERED;
+ public static int ACTION_DRAG_EXITED;
+ public static int ACTION_DRAG_LOCATION;
+ public static int ACTION_DRAG_STARTED;
+ public static int ACTION_DROP;
+ public static android.os.Parcelable$Creator CREATOR;
+}
+
+-keep class android.view.FrameMetrics {
+ <init>(android.view.FrameMetrics);
+
+ public long getMetric(int);
+
+
+ public static int ANIMATION_DURATION;
+ public static int COMMAND_ISSUE_DURATION;
+ public static int DRAW_DURATION;
+ public static int FIRST_DRAW_FRAME;
+ public static int INPUT_HANDLING_DURATION;
+ public static int INTENDED_VSYNC_TIMESTAMP;
+ public static int LAYOUT_MEASURE_DURATION;
+ public static int SWAP_BUFFERS_DURATION;
+ public static int SYNC_DURATION;
+ public static int TOTAL_DURATION;
+ public static int UNKNOWN_DELAY_DURATION;
+ public static int VSYNC_TIMESTAMP;
+}
+
+-keep class android.view.FrameStats {
+ <init>();
+
+ public long getEndTimeNano();
+ public int getFrameCount();
+ public long getFramePresentedTimeNano(int);
+ public long getRefreshPeriodNano();
+ public long getStartTimeNano();
+
+
+ public static long UNDEFINED_TIME_NANO;
+ protected long[] mFramesPresentedTimeNano;
+ protected long mRefreshPeriodNano;
+}
+
+-keep class android.view.IAppTransitionAnimationSpecsFuture {
+
+ public abstract android.view.AppTransitionAnimationSpec[] get();
+
+
+}
+
+-keep class android.view.IRecentsAnimationController {
+
+ public abstract void finish(boolean);
+ public abstract void hideCurrentInputMethod();
+ public abstract android.app.ActivityManager$TaskSnapshot screenshotTask(int);
+ public abstract void setAnimationTargetsBehindSystemBars(boolean);
+ public abstract void setInputConsumerEnabled(boolean);
+ public abstract void setSplitScreenMinimized(boolean);
+
+
+}
+
+-keep class android.view.IRecentsAnimationRunner {
+
+ public abstract void onAnimationCanceled();
+ public abstract void onAnimationStart(android.view.IRecentsAnimationController, android.view.RemoteAnimationTarget[], android.graphics.Rect, android.graphics.Rect);
+
+
+}
+
+-keep class android.view.IRemoteAnimationFinishedCallback {
+
+ public abstract void onAnimationFinished();
+
+
+}
+
+-keep class android.view.IRemoteAnimationRunner {
+
+ public abstract void onAnimationCancelled();
+ public abstract void onAnimationStart(android.view.RemoteAnimationTarget[], android.view.IRemoteAnimationFinishedCallback);
+
+
+}
+
+-keep class android.view.IWindow {
+
+ public abstract void closeSystemDialogs(java.lang.String);
+ public abstract void dispatchAppVisibility(boolean);
+ public abstract void dispatchDragEvent(android.view.DragEvent);
+ public abstract void dispatchGetNewSurface();
+ public abstract void dispatchPointerCaptureChanged(boolean);
+ public abstract void dispatchSystemUiVisibilityChanged(int, int, int, int);
+ public abstract void dispatchWallpaperCommand(java.lang.String, int, int, int, android.os.Bundle, boolean);
+ public abstract void dispatchWallpaperOffsets(float, float, float, float, boolean);
+ public abstract void dispatchWindowShown();
+ public abstract void executeCommand(java.lang.String, java.lang.String, android.os.ParcelFileDescriptor);
+ public abstract void moved(int, int);
+ public abstract void requestAppKeyboardShortcuts(com.android.internal.os.IResultReceiver, int);
+ public abstract void resized(android.graphics.Rect, android.graphics.Rect, android.graphics.Rect, android.graphics.Rect, android.graphics.Rect, android.graphics.Rect, boolean, android.util.MergedConfiguration, android.graphics.Rect, boolean, boolean, int, android.view.DisplayCutout$ParcelableWrapper);
+ public abstract void updatePointerIcon(float, float);
+ public abstract void windowFocusChanged(boolean, boolean);
+
+
+}
+
+-keep class android.view.IWindowFocusObserver {
+
+ public abstract void focusGained(android.os.IBinder);
+ public abstract void focusLost(android.os.IBinder);
+
+
+}
+
+-keep class android.view.IWindowId {
+
+ public abstract boolean isFocused();
+ public abstract void registerFocusObserver(android.view.IWindowFocusObserver);
+ public abstract void unregisterFocusObserver(android.view.IWindowFocusObserver);
+
+
+}
+
+-keep class android.view.InflateException {
+ <init>();
+ <init>(java.lang.String, java.lang.Throwable);
+ <init>(java.lang.String);
+ <init>(java.lang.Throwable);
+
+
+
+}
+
+-keep class android.view.InputChannel {
+ <init>();
+
+ public int describeContents();
+ public void dispose();
+ public android.view.InputChannel dup();
+ protected void finalize();
+ public java.lang.String getName();
+ public static android.view.InputChannel[] openInputChannelPair(java.lang.String);
+ public void readFromParcel(android.os.Parcel);
+ public java.lang.String toString();
+ public void transferTo(android.view.InputChannel);
+ public void writeToParcel(android.os.Parcel, int);
+
+
+ public static android.os.Parcelable$Creator CREATOR;
}
-keep class android.view.InputDevice {
public int describeContents();
+ public void disable();
+ public void enable();
public int getControllerNumber();
public java.lang.String getDescriptor();
public static android.view.InputDevice getDevice(int);
public static int[] getDeviceIds();
+ public int getGeneration();
public int getId();
+ public android.hardware.input.InputDeviceIdentifier getIdentifier();
public android.view.KeyCharacterMap getKeyCharacterMap();
public int getKeyboardType();
public android.view.InputDevice$MotionRange getMotionRange(int);
@@ -5719,9 +17341,15 @@
public int getSources();
public int getVendorId();
public android.os.Vibrator getVibrator();
+ public boolean hasButtonUnderPad();
public boolean[] hasKeys(int[]);
public boolean hasMicrophone();
+ public boolean isEnabled();
+ public boolean isExternal();
+ public boolean isFullKeyboard();
public boolean isVirtual();
+ public void setCustomPointerIcon(android.view.PointerIcon);
+ public void setPointerType(int);
public boolean supportsSource(int);
public java.lang.String toString();
public void writeToParcel(android.os.Parcel, int);
@@ -5755,6 +17383,8 @@
public static int SOURCE_JOYSTICK;
public static int SOURCE_KEYBOARD;
public static int SOURCE_MOUSE;
+ public static int SOURCE_MOUSE_RELATIVE;
+ public static int SOURCE_ROTARY_ENCODER;
public static int SOURCE_STYLUS;
public static int SOURCE_TOUCHPAD;
public static int SOURCE_TOUCHSCREEN;
@@ -5780,15 +17410,86 @@
-keep class android.view.InputEvent {
+ public abstract void cancel();
+ public abstract android.view.InputEvent copy();
public int describeContents();
public android.view.InputDevice getDevice();
public abstract int getDeviceId();
public abstract long getEventTime();
+ public abstract long getEventTimeNano();
+ public int getSequenceNumber();
public abstract int getSource();
public boolean isFromSource(int);
+ public abstract boolean isTainted();
+ protected void prepareForReuse();
+ public void recycle();
+ public void recycleIfNeededAfterDispatch();
+ public abstract void setSource(int);
+ public abstract void setTainted(boolean);
public static android.os.Parcelable$Creator CREATOR;
+ protected static int PARCEL_TOKEN_KEY_EVENT;
+ protected static int PARCEL_TOKEN_MOTION_EVENT;
+ protected boolean mRecycled;
+ protected int mSeq;
+}
+
+-keep class android.view.InputEventConsistencyVerifier {
+ <init>(java.lang.Object, int);
+ <init>(java.lang.Object, int, java.lang.String);
+
+ public static boolean isInstrumentationEnabled();
+ public void onGenericMotionEvent(android.view.MotionEvent, int);
+ public void onInputEvent(android.view.InputEvent, int);
+ public void onKeyEvent(android.view.KeyEvent, int);
+ public void onTouchEvent(android.view.MotionEvent, int);
+ public void onTrackballEvent(android.view.MotionEvent, int);
+ public void onUnhandledEvent(android.view.InputEvent, int);
+ public void reset();
+
+
+ public static int FLAG_RAW_DEVICE_INPUT;
+}
+
+-keep class android.view.InputEventReceiver {
+ <init>(android.view.InputChannel, android.os.Looper);
+
+ public boolean consumeBatchedInputEvents(long);
+ public void dispose();
+ protected void finalize();
+ public void finishInputEvent(android.view.InputEvent, boolean);
+ public void onBatchedInputEventPending();
+ public void onInputEvent(android.view.InputEvent, int);
+
+
+}
+
+-keep class android.view.InputQueue {
+ <init>();
+
+ public void dispose();
+ public void dispose(boolean);
+ protected void finalize();
+ public long getNativePtr();
+ public void sendInputEvent(android.view.InputEvent, java.lang.Object, boolean, android.view.InputQueue$FinishedInputEventCallback);
+
+
+}
+
+-keep class android.view.InputQueue$Callback {
+
+ public abstract void onInputQueueCreated(android.view.InputQueue);
+ public abstract void onInputQueueDestroyed(android.view.InputQueue);
+
+
+}
+
+-keep class android.view.InputQueue$FinishedInputEventCallback {
+
+ public abstract void onFinishedInputEvent(java.lang.Object, boolean);
+
+
}
-keep class android.view.KeyCharacterMap {
@@ -5801,6 +17502,7 @@
public static int getDeadChar(int, int);
public char getDisplayLabel(int);
public android.view.KeyEvent[] getEvents(char[]);
+ public android.view.KeyCharacterMap$FallbackAction getFallbackAction(int, int);
public boolean getKeyData(int, android.view.KeyCharacterMap$KeyData);
public int getKeyboardType();
public char getMatch(int, char[]);
@@ -5828,6 +17530,16 @@
public static int VIRTUAL_KEYBOARD;
}
+-keep class android.view.KeyCharacterMap$FallbackAction {
+
+ public static android.view.KeyCharacterMap$FallbackAction obtain();
+ public void recycle();
+
+
+ public int keyCode;
+ public int metaState;
+}
+
-keep class android.view.KeyCharacterMap$KeyData {
<init>();
@@ -5850,10 +17562,15 @@
<init>(android.view.KeyEvent);
<init>(android.view.KeyEvent, long, int);
+ public static java.lang.String actionToString(int);
+ public void cancel();
public static android.view.KeyEvent changeAction(android.view.KeyEvent, int);
public static android.view.KeyEvent changeFlags(android.view.KeyEvent, int);
public static android.view.KeyEvent changeTimeRepeat(android.view.KeyEvent, long, int);
public static android.view.KeyEvent changeTimeRepeat(android.view.KeyEvent, long, int, int);
+ public android.view.KeyEvent copy();
+ public android.view.InputEvent copy();
+ public static android.view.KeyEvent createFromParcelBody(android.os.Parcel);
public boolean dispatch(android.view.KeyEvent$Callback);
public boolean dispatch(android.view.KeyEvent$Callback, android.view.KeyEvent$DispatcherState, java.lang.Object);
public int getAction();
@@ -5863,10 +17580,12 @@
public char getDisplayLabel();
public long getDownTime();
public long getEventTime();
+ public long getEventTimeNano();
public int getFlags();
public android.view.KeyCharacterMap getKeyCharacterMap();
public int getKeyCode();
public boolean getKeyData(android.view.KeyCharacterMap$KeyData);
+ public int getKeyboardDevice();
public char getMatch(char[]);
public char getMatch(char[], int);
public static int getMaxKeyCode();
@@ -5881,13 +17600,18 @@
public int getUnicodeChar(int);
public boolean hasModifiers(int);
public boolean hasNoModifiers();
+ public static boolean isAltKey(int);
public boolean isAltPressed();
public boolean isCanceled();
public boolean isCapsLockOn();
+ public static boolean isConfirmKey(int);
public boolean isCtrlPressed();
+ public boolean isDown();
public boolean isFunctionPressed();
public static boolean isGamepadButton(int);
public boolean isLongPress();
+ public static boolean isMediaKey(int);
+ public static boolean isMetaKey(int);
public boolean isMetaPressed();
public static boolean isModifierKey(int);
public boolean isNumLockOn();
@@ -5896,13 +17620,23 @@
public boolean isShiftPressed();
public boolean isSymPressed();
public boolean isSystem();
+ public static boolean isSystemKey(int);
+ public boolean isTainted();
public boolean isTracking();
+ public boolean isWakeKey();
+ public static boolean isWakeKey(int);
public static int keyCodeFromString(java.lang.String);
public static java.lang.String keyCodeToString(int);
public static boolean metaStateHasModifiers(int, int);
public static boolean metaStateHasNoModifiers(int);
+ public static java.lang.String metaStateToString(int);
public static int normalizeMetaState(int);
+ public static android.view.KeyEvent obtain(long, long, int, int, int, int, int, int, int, int, java.lang.String);
+ public static android.view.KeyEvent obtain(android.view.KeyEvent);
+ public void recycle();
+ public void recycleIfNeededAfterDispatch();
public void setSource(int);
+ public void setTainted(boolean);
public void startTracking();
public java.lang.String toString();
public void writeToParcel(android.os.Parcel, int);
@@ -5919,7 +17653,10 @@
public static int FLAG_FROM_SYSTEM;
public static int FLAG_KEEP_TOUCH_MODE;
public static int FLAG_LONG_PRESS;
+ public static int FLAG_PREDISPATCH;
public static int FLAG_SOFT_KEYBOARD;
+ public static int FLAG_START_TRACKING;
+ public static int FLAG_TAINTED;
public static int FLAG_TRACKING;
public static int FLAG_VIRTUAL_HARD_KEY;
public static int FLAG_WOKE_HERE;
@@ -5937,6 +17674,7 @@
public static int KEYCODE_8;
public static int KEYCODE_9;
public static int KEYCODE_A;
+ public static int KEYCODE_ALL_APPS;
public static int KEYCODE_ALT_LEFT;
public static int KEYCODE_ALT_RIGHT;
public static int KEYCODE_APOSTROPHE;
@@ -5995,15 +17733,21 @@
public static int KEYCODE_CLEAR;
public static int KEYCODE_COMMA;
public static int KEYCODE_CONTACTS;
+ public static int KEYCODE_COPY;
public static int KEYCODE_CTRL_LEFT;
public static int KEYCODE_CTRL_RIGHT;
+ public static int KEYCODE_CUT;
public static int KEYCODE_D;
public static int KEYCODE_DEL;
public static int KEYCODE_DPAD_CENTER;
public static int KEYCODE_DPAD_DOWN;
+ public static int KEYCODE_DPAD_DOWN_LEFT;
+ public static int KEYCODE_DPAD_DOWN_RIGHT;
public static int KEYCODE_DPAD_LEFT;
public static int KEYCODE_DPAD_RIGHT;
public static int KEYCODE_DPAD_UP;
+ public static int KEYCODE_DPAD_UP_LEFT;
+ public static int KEYCODE_DPAD_UP_RIGHT;
public static int KEYCODE_DVR;
public static int KEYCODE_E;
public static int KEYCODE_EISU;
@@ -6110,6 +17854,7 @@
public static int KEYCODE_PAGE_DOWN;
public static int KEYCODE_PAGE_UP;
public static int KEYCODE_PAIRING;
+ public static int KEYCODE_PASTE;
public static int KEYCODE_PERIOD;
public static int KEYCODE_PICTSYMBOLS;
public static int KEYCODE_PLUS;
@@ -6121,6 +17866,7 @@
public static int KEYCODE_PROG_YELLOW;
public static int KEYCODE_Q;
public static int KEYCODE_R;
+ public static int KEYCODE_REFRESH;
public static int KEYCODE_RIGHT_BRACKET;
public static int KEYCODE_RO;
public static int KEYCODE_S;
@@ -6134,13 +17880,22 @@
public static int KEYCODE_SLEEP;
public static int KEYCODE_SOFT_LEFT;
public static int KEYCODE_SOFT_RIGHT;
+ public static int KEYCODE_SOFT_SLEEP;
public static int KEYCODE_SPACE;
public static int KEYCODE_STAR;
public static int KEYCODE_STB_INPUT;
public static int KEYCODE_STB_POWER;
+ public static int KEYCODE_STEM_1;
+ public static int KEYCODE_STEM_2;
+ public static int KEYCODE_STEM_3;
+ public static int KEYCODE_STEM_PRIMARY;
public static int KEYCODE_SWITCH_CHARSET;
public static int KEYCODE_SYM;
public static int KEYCODE_SYSRQ;
+ public static int KEYCODE_SYSTEM_NAVIGATION_DOWN;
+ public static int KEYCODE_SYSTEM_NAVIGATION_LEFT;
+ public static int KEYCODE_SYSTEM_NAVIGATION_RIGHT;
+ public static int KEYCODE_SYSTEM_NAVIGATION_UP;
public static int KEYCODE_T;
public static int KEYCODE_TAB;
public static int KEYCODE_TV;
@@ -6193,10 +17948,12 @@
public static int KEYCODE_ZOOM_OUT;
public static int MAX_KEYCODE;
public static int META_ALT_LEFT_ON;
+ public static int META_ALT_LOCKED;
public static int META_ALT_MASK;
public static int META_ALT_ON;
public static int META_ALT_RIGHT_ON;
public static int META_CAPS_LOCK_ON;
+ public static int META_CAP_LOCKED;
public static int META_CTRL_LEFT_ON;
public static int META_CTRL_MASK;
public static int META_CTRL_ON;
@@ -6208,10 +17965,12 @@
public static int META_META_RIGHT_ON;
public static int META_NUM_LOCK_ON;
public static int META_SCROLL_LOCK_ON;
+ public static int META_SELECTING;
public static int META_SHIFT_LEFT_ON;
public static int META_SHIFT_MASK;
public static int META_SHIFT_ON;
public static int META_SHIFT_RIGHT_ON;
+ public static int META_SYM_LOCKED;
public static int META_SYM_ON;
}
@@ -6238,10 +17997,6125 @@
}
+-keep class android.view.KeyboardShortcutGroup {
+ <init>(java.lang.CharSequence, java.util.List);
+ <init>(java.lang.CharSequence);
+ <init>(java.lang.CharSequence, java.util.List, boolean);
+ <init>(java.lang.CharSequence, boolean);
+
+ public void addItem(android.view.KeyboardShortcutInfo);
+ public int describeContents();
+ public java.util.List getItems();
+ public java.lang.CharSequence getLabel();
+ public boolean isSystemGroup();
+ public void writeToParcel(android.os.Parcel, int);
+
+
+ public static android.os.Parcelable$Creator CREATOR;
+}
+
+-keep class android.view.KeyboardShortcutInfo {
+ <init>(java.lang.CharSequence, android.graphics.drawable.Icon, int, int);
+ <init>(java.lang.CharSequence, int, int);
+ <init>(java.lang.CharSequence, char, int);
+
+ public int describeContents();
+ public char getBaseCharacter();
+ public android.graphics.drawable.Icon getIcon();
+ public int getKeycode();
+ public java.lang.CharSequence getLabel();
+ public int getModifiers();
+ public void writeToParcel(android.os.Parcel, int);
+
+
+ public static android.os.Parcelable$Creator CREATOR;
+}
+
+-keep class android.view.LayoutInflater {
+ <init>(android.content.Context);
+ <init>(android.view.LayoutInflater, android.content.Context);
+
+ public abstract android.view.LayoutInflater cloneInContext(android.content.Context);
+ public android.view.View createView(java.lang.String, java.lang.String, android.util.AttributeSet);
+ public static android.view.LayoutInflater from(android.content.Context);
+ public android.content.Context getContext();
+ public android.view.LayoutInflater$Factory getFactory();
+ public android.view.LayoutInflater$Factory2 getFactory2();
+ public android.view.LayoutInflater$Filter getFilter();
+ public android.view.View inflate(int, android.view.ViewGroup);
+ public android.view.View inflate(org.xmlpull.v1.XmlPullParser, android.view.ViewGroup);
+ public android.view.View inflate(int, android.view.ViewGroup, boolean);
+ public android.view.View inflate(org.xmlpull.v1.XmlPullParser, android.view.ViewGroup, boolean);
+ protected android.view.View onCreateView(java.lang.String, android.util.AttributeSet);
+ protected android.view.View onCreateView(android.view.View, java.lang.String, android.util.AttributeSet);
+ public void setFactory(android.view.LayoutInflater$Factory);
+ public void setFactory2(android.view.LayoutInflater$Factory2);
+ public void setFilter(android.view.LayoutInflater$Filter);
+ public void setPrivateFactory(android.view.LayoutInflater$Factory2);
+
+
+ protected android.content.Context mContext;
+}
+
+-keep class android.view.LayoutInflater$Factory {
+
+ public abstract android.view.View onCreateView(java.lang.String, android.content.Context, android.util.AttributeSet);
+
+
+}
+
+-keep class android.view.LayoutInflater$Factory2 {
+
+ public abstract android.view.View onCreateView(android.view.View, java.lang.String, android.content.Context, android.util.AttributeSet);
+
+
+}
+
+-keep class android.view.LayoutInflater$Filter {
+
+ public abstract boolean onLoadClass(java.lang.Class);
+
+
+}
+
+-keep class android.view.MagnificationSpec {
+
+ public void clear();
+ public int describeContents();
+ public boolean equals(java.lang.Object);
+ public int hashCode();
+ public void initialize(float, float, float);
+ public boolean isNop();
+ public static android.view.MagnificationSpec obtain(android.view.MagnificationSpec);
+ public static android.view.MagnificationSpec obtain();
+ public void recycle();
+ public void setTo(android.view.MagnificationSpec);
+ public java.lang.String toString();
+ public void writeToParcel(android.os.Parcel, int);
+
+
+ public static android.os.Parcelable$Creator CREATOR;
+ public float offsetX;
+ public float offsetY;
+ public float scale;
+}
+
+-keep class android.view.Menu {
+
+ public abstract android.view.MenuItem add(java.lang.CharSequence);
+ public abstract android.view.MenuItem add(int);
+ public abstract android.view.MenuItem add(int, int, int, java.lang.CharSequence);
+ public abstract android.view.MenuItem add(int, int, int, int);
+ public abstract int addIntentOptions(int, int, int, android.content.ComponentName, android.content.Intent[], android.content.Intent, int, android.view.MenuItem[]);
+ public abstract android.view.SubMenu addSubMenu(java.lang.CharSequence);
+ public abstract android.view.SubMenu addSubMenu(int);
+ public abstract android.view.SubMenu addSubMenu(int, int, int, java.lang.CharSequence);
+ public abstract android.view.SubMenu addSubMenu(int, int, int, int);
+ public abstract void clear();
+ public abstract void close();
+ public abstract android.view.MenuItem findItem(int);
+ public abstract android.view.MenuItem getItem(int);
+ public abstract boolean hasVisibleItems();
+ public abstract boolean isShortcutKey(int, android.view.KeyEvent);
+ public abstract boolean performIdentifierAction(int, int);
+ public abstract boolean performShortcut(int, android.view.KeyEvent, int);
+ public abstract void removeGroup(int);
+ public abstract void removeItem(int);
+ public abstract void setGroupCheckable(int, boolean, boolean);
+ public void setGroupDividerEnabled(boolean);
+ public abstract void setGroupEnabled(int, boolean);
+ public abstract void setGroupVisible(int, boolean);
+ public abstract void setQwertyMode(boolean);
+ public abstract int size();
+
+
+ public static int CATEGORY_ALTERNATIVE;
+ public static int CATEGORY_CONTAINER;
+ public static int CATEGORY_MASK;
+ public static int CATEGORY_SECONDARY;
+ public static int CATEGORY_SHIFT;
+ public static int CATEGORY_SYSTEM;
+ public static int FIRST;
+ public static int FLAG_ALWAYS_PERFORM_CLOSE;
+ public static int FLAG_APPEND_TO_GROUP;
+ public static int FLAG_PERFORM_NO_CLOSE;
+ public static int NONE;
+ public static int SUPPORTED_MODIFIERS_MASK;
+ public static int USER_MASK;
+ public static int USER_SHIFT;
+}
+
+-keep class android.view.MenuInflater {
+ <init>(android.content.Context);
+ <init>(android.content.Context, java.lang.Object);
+
+ public void inflate(int, android.view.Menu);
+
+
+}
+
+-keep class android.view.MenuItem {
+
+ public abstract boolean collapseActionView();
+ public abstract boolean expandActionView();
+ public abstract android.view.ActionProvider getActionProvider();
+ public abstract android.view.View getActionView();
+ public int getAlphabeticModifiers();
+ public abstract char getAlphabeticShortcut();
+ public java.lang.CharSequence getContentDescription();
+ public abstract int getGroupId();
+ public abstract android.graphics.drawable.Drawable getIcon();
+ public android.content.res.ColorStateList getIconTintList();
+ public android.graphics.PorterDuff$Mode getIconTintMode();
+ public abstract android.content.Intent getIntent();
+ public abstract int getItemId();
+ public abstract android.view.ContextMenu$ContextMenuInfo getMenuInfo();
+ public int getNumericModifiers();
+ public abstract char getNumericShortcut();
+ public abstract int getOrder();
+ public abstract android.view.SubMenu getSubMenu();
+ public abstract java.lang.CharSequence getTitle();
+ public abstract java.lang.CharSequence getTitleCondensed();
+ public java.lang.CharSequence getTooltipText();
+ public abstract boolean hasSubMenu();
+ public abstract boolean isActionViewExpanded();
+ public abstract boolean isCheckable();
+ public abstract boolean isChecked();
+ public abstract boolean isEnabled();
+ public abstract boolean isVisible();
+ public boolean requiresActionButton();
+ public boolean requiresOverflow();
+ public abstract android.view.MenuItem setActionProvider(android.view.ActionProvider);
+ public abstract android.view.MenuItem setActionView(android.view.View);
+ public abstract android.view.MenuItem setActionView(int);
+ public abstract android.view.MenuItem setAlphabeticShortcut(char);
+ public android.view.MenuItem setAlphabeticShortcut(char, int);
+ public abstract android.view.MenuItem setCheckable(boolean);
+ public abstract android.view.MenuItem setChecked(boolean);
+ public android.view.MenuItem setContentDescription(java.lang.CharSequence);
+ public abstract android.view.MenuItem setEnabled(boolean);
+ public abstract android.view.MenuItem setIcon(android.graphics.drawable.Drawable);
+ public abstract android.view.MenuItem setIcon(int);
+ public android.view.MenuItem setIconTintList(android.content.res.ColorStateList);
+ public android.view.MenuItem setIconTintMode(android.graphics.PorterDuff$Mode);
+ public abstract android.view.MenuItem setIntent(android.content.Intent);
+ public abstract android.view.MenuItem setNumericShortcut(char);
+ public android.view.MenuItem setNumericShortcut(char, int);
+ public abstract android.view.MenuItem setOnActionExpandListener(android.view.MenuItem$OnActionExpandListener);
+ public abstract android.view.MenuItem setOnMenuItemClickListener(android.view.MenuItem$OnMenuItemClickListener);
+ public abstract android.view.MenuItem setShortcut(char, char);
+ public android.view.MenuItem setShortcut(char, char, int, int);
+ public abstract void setShowAsAction(int);
+ public abstract android.view.MenuItem setShowAsActionFlags(int);
+ public abstract android.view.MenuItem setTitle(java.lang.CharSequence);
+ public abstract android.view.MenuItem setTitle(int);
+ public abstract android.view.MenuItem setTitleCondensed(java.lang.CharSequence);
+ public android.view.MenuItem setTooltipText(java.lang.CharSequence);
+ public abstract android.view.MenuItem setVisible(boolean);
+
+
+ public static int SHOW_AS_ACTION_ALWAYS;
+ public static int SHOW_AS_ACTION_COLLAPSE_ACTION_VIEW;
+ public static int SHOW_AS_ACTION_IF_ROOM;
+ public static int SHOW_AS_ACTION_NEVER;
+ public static int SHOW_AS_ACTION_WITH_TEXT;
+}
+
+-keep class android.view.MenuItem$OnActionExpandListener {
+
+ public abstract boolean onMenuItemActionCollapse(android.view.MenuItem);
+ public abstract boolean onMenuItemActionExpand(android.view.MenuItem);
+
+
+}
+
+-keep class android.view.MenuItem$OnMenuItemClickListener {
+
+ public abstract boolean onMenuItemClick(android.view.MenuItem);
+
+
+}
+
+-keep class android.view.MotionEvent {
+
+ public static java.lang.String actionToString(int);
+ public void addBatch(long, float, float, float, float, int);
+ public void addBatch(long, android.view.MotionEvent$PointerCoords[], int);
+ public boolean addBatch(android.view.MotionEvent);
+ public static int axisFromString(java.lang.String);
+ public static java.lang.String axisToString(int);
+ public static java.lang.String buttonStateToString(int);
+ public void cancel();
+ public android.view.MotionEvent clampNoHistory(float, float, float, float);
+ public android.view.MotionEvent copy();
+ public android.view.InputEvent copy();
+ public static android.view.MotionEvent createFromParcelBody(android.os.Parcel);
+ protected void finalize();
+ public int findPointerIndex(int);
+ public int getAction();
+ public int getActionButton();
+ public int getActionIndex();
+ public int getActionMasked();
+ public float getAxisValue(int);
+ public float getAxisValue(int, int);
+ public int getButtonState();
+ public int getDeviceId();
+ public long getDownTime();
+ public int getEdgeFlags();
+ public long getEventTime();
+ public long getEventTimeNano();
+ public int getFlags();
+ public float getHistoricalAxisValue(int, int);
+ public float getHistoricalAxisValue(int, int, int);
+ public long getHistoricalEventTime(int);
+ public long getHistoricalEventTimeNano(int);
+ public float getHistoricalOrientation(int);
+ public float getHistoricalOrientation(int, int);
+ public void getHistoricalPointerCoords(int, int, android.view.MotionEvent$PointerCoords);
+ public float getHistoricalPressure(int);
+ public float getHistoricalPressure(int, int);
+ public float getHistoricalSize(int);
+ public float getHistoricalSize(int, int);
+ public float getHistoricalToolMajor(int);
+ public float getHistoricalToolMajor(int, int);
+ public float getHistoricalToolMinor(int);
+ public float getHistoricalToolMinor(int, int);
+ public float getHistoricalTouchMajor(int);
+ public float getHistoricalTouchMajor(int, int);
+ public float getHistoricalTouchMinor(int);
+ public float getHistoricalTouchMinor(int, int);
+ public float getHistoricalX(int);
+ public float getHistoricalX(int, int);
+ public float getHistoricalY(int);
+ public float getHistoricalY(int, int);
+ public int getHistorySize();
+ public int getMetaState();
+ public float getOrientation();
+ public float getOrientation(int);
+ public void getPointerCoords(int, android.view.MotionEvent$PointerCoords);
+ public int getPointerCount();
+ public int getPointerId(int);
+ public int getPointerIdBits();
+ public void getPointerProperties(int, android.view.MotionEvent$PointerProperties);
+ public float getPressure();
+ public float getPressure(int);
+ public float getRawX();
+ public float getRawY();
+ public float getSize();
+ public float getSize(int);
+ public int getSource();
+ public float getToolMajor();
+ public float getToolMajor(int);
+ public float getToolMinor();
+ public float getToolMinor(int);
+ public int getToolType(int);
+ public float getTouchMajor();
+ public float getTouchMajor(int);
+ public float getTouchMinor();
+ public float getTouchMinor(int);
+ public float getX();
+ public float getX(int);
+ public float getXPrecision();
+ public float getY();
+ public float getY(int);
+ public float getYPrecision();
+ public boolean isButtonPressed(int);
+ public boolean isHoverExitPending();
+ public boolean isTainted();
+ 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);
+ 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);
+ public static android.view.MotionEvent obtain(long, long, int, int, float, float, float, float, int, float, float, int, int);
+ public static android.view.MotionEvent obtain(long, long, int, float, float, int);
+ public static android.view.MotionEvent obtain(android.view.MotionEvent);
+ public static android.view.MotionEvent obtainNoHistory(android.view.MotionEvent);
+ public void offsetLocation(float, float);
+ public void recycle();
+ public void scale(float);
+ public void setAction(int);
+ public void setActionButton(int);
+ public void setButtonState(int);
+ public void setDownTime(long);
+ public void setEdgeFlags(int);
+ public void setHoverExitPending(boolean);
+ public void setLocation(float, float);
+ public void setSource(int);
+ public void setTainted(boolean);
+ public void setTargetAccessibilityFocus(boolean);
+ public android.view.MotionEvent split(int);
+ public java.lang.String toString();
+ public static java.lang.String toolTypeToString(int);
+ public void transform(android.graphics.Matrix);
+ public void writeToParcel(android.os.Parcel, int);
+
+
+ public static int ACTION_BUTTON_PRESS;
+ public static int ACTION_BUTTON_RELEASE;
+ public static int ACTION_CANCEL;
+ public static int ACTION_DOWN;
+ public static int ACTION_HOVER_ENTER;
+ public static int ACTION_HOVER_EXIT;
+ public static int ACTION_HOVER_MOVE;
+ public static int ACTION_MASK;
+ public static int ACTION_MOVE;
+ public static int ACTION_OUTSIDE;
+ public static int ACTION_POINTER_1_DOWN;
+ public static int ACTION_POINTER_1_UP;
+ public static int ACTION_POINTER_2_DOWN;
+ public static int ACTION_POINTER_2_UP;
+ public static int ACTION_POINTER_3_DOWN;
+ public static int ACTION_POINTER_3_UP;
+ public static int ACTION_POINTER_DOWN;
+ public static int ACTION_POINTER_ID_MASK;
+ public static int ACTION_POINTER_ID_SHIFT;
+ public static int ACTION_POINTER_INDEX_MASK;
+ public static int ACTION_POINTER_INDEX_SHIFT;
+ public static int ACTION_POINTER_UP;
+ public static int ACTION_SCROLL;
+ public static int ACTION_UP;
+ public static int AXIS_BRAKE;
+ public static int AXIS_DISTANCE;
+ public static int AXIS_GAS;
+ public static int AXIS_GENERIC_1;
+ public static int AXIS_GENERIC_10;
+ public static int AXIS_GENERIC_11;
+ public static int AXIS_GENERIC_12;
+ public static int AXIS_GENERIC_13;
+ public static int AXIS_GENERIC_14;
+ public static int AXIS_GENERIC_15;
+ public static int AXIS_GENERIC_16;
+ public static int AXIS_GENERIC_2;
+ public static int AXIS_GENERIC_3;
+ public static int AXIS_GENERIC_4;
+ public static int AXIS_GENERIC_5;
+ public static int AXIS_GENERIC_6;
+ public static int AXIS_GENERIC_7;
+ public static int AXIS_GENERIC_8;
+ public static int AXIS_GENERIC_9;
+ public static int AXIS_HAT_X;
+ public static int AXIS_HAT_Y;
+ public static int AXIS_HSCROLL;
+ public static int AXIS_LTRIGGER;
+ public static int AXIS_ORIENTATION;
+ public static int AXIS_PRESSURE;
+ public static int AXIS_RELATIVE_X;
+ public static int AXIS_RELATIVE_Y;
+ public static int AXIS_RTRIGGER;
+ public static int AXIS_RUDDER;
+ public static int AXIS_RX;
+ public static int AXIS_RY;
+ public static int AXIS_RZ;
+ public static int AXIS_SCROLL;
+ public static int AXIS_SIZE;
+ public static int AXIS_THROTTLE;
+ public static int AXIS_TILT;
+ public static int AXIS_TOOL_MAJOR;
+ public static int AXIS_TOOL_MINOR;
+ public static int AXIS_TOUCH_MAJOR;
+ public static int AXIS_TOUCH_MINOR;
+ public static int AXIS_VSCROLL;
+ public static int AXIS_WHEEL;
+ public static int AXIS_X;
+ public static int AXIS_Y;
+ public static int AXIS_Z;
+ public static int BUTTON_BACK;
+ public static int BUTTON_FORWARD;
+ public static int BUTTON_PRIMARY;
+ public static int BUTTON_SECONDARY;
+ public static int BUTTON_STYLUS_PRIMARY;
+ public static int BUTTON_STYLUS_SECONDARY;
+ public static int BUTTON_TERTIARY;
+ public static android.os.Parcelable$Creator CREATOR;
+ public static int EDGE_BOTTOM;
+ public static int EDGE_LEFT;
+ public static int EDGE_RIGHT;
+ public static int EDGE_TOP;
+ public static int FLAG_HOVER_EXIT_PENDING;
+ public static int FLAG_IS_GENERATED_GESTURE;
+ public static int FLAG_TAINTED;
+ public static int FLAG_TARGET_ACCESSIBILITY_FOCUS;
+ public static int FLAG_WINDOW_IS_OBSCURED;
+ public static int FLAG_WINDOW_IS_PARTIALLY_OBSCURED;
+ public static int INVALID_POINTER_ID;
+ public static int TOOL_TYPE_ERASER;
+ public static int TOOL_TYPE_FINGER;
+ public static int TOOL_TYPE_MOUSE;
+ public static int TOOL_TYPE_STYLUS;
+ public static int TOOL_TYPE_UNKNOWN;
+}
+
+-keep class android.view.MotionEvent$PointerCoords {
+ <init>();
+ <init>(android.view.MotionEvent$PointerCoords);
+
+ public void clear();
+ public void copyFrom(android.view.MotionEvent$PointerCoords);
+ public static android.view.MotionEvent$PointerCoords[] createArray(int);
+ public float getAxisValue(int);
+ public void setAxisValue(int, float);
+
+
+ public float orientation;
+ public float pressure;
+ public float size;
+ public float toolMajor;
+ public float toolMinor;
+ public float touchMajor;
+ public float touchMinor;
+ public float x;
+ public float y;
+}
+
+-keep class android.view.MotionEvent$PointerProperties {
+ <init>();
+ <init>(android.view.MotionEvent$PointerProperties);
+
+ public void clear();
+ public void copyFrom(android.view.MotionEvent$PointerProperties);
+ public static android.view.MotionEvent$PointerProperties[] createArray(int);
+ public boolean equals(java.lang.Object);
+ public int hashCode();
+
+
+ public int id;
+ public int toolType;
+}
+
+-keep class android.view.PointerIcon {
+
+ public static android.view.PointerIcon create(android.graphics.Bitmap, float, float);
+ public int describeContents();
+ public boolean equals(java.lang.Object);
+ public static android.view.PointerIcon getDefaultIcon(android.content.Context);
+ public static android.view.PointerIcon getNullIcon();
+ public static android.view.PointerIcon getSystemIcon(android.content.Context, int);
+ public int getType();
+ public static android.view.PointerIcon load(android.content.res.Resources, int);
+ public android.view.PointerIcon load(android.content.Context);
+ public static void setUseLargeIcons(boolean);
+ public void writeToParcel(android.os.Parcel, int);
+
+
+ public static android.os.Parcelable$Creator CREATOR;
+ public static int TYPE_ALIAS;
+ public static int TYPE_ALL_SCROLL;
+ public static int TYPE_ARROW;
+ public static int TYPE_CELL;
+ public static int TYPE_CONTEXT_MENU;
+ public static int TYPE_COPY;
+ public static int TYPE_CROSSHAIR;
+ public static int TYPE_CUSTOM;
+ public static int TYPE_DEFAULT;
+ public static int TYPE_GRAB;
+ public static int TYPE_GRABBING;
+ public static int TYPE_HAND;
+ public static int TYPE_HELP;
+ public static int TYPE_HORIZONTAL_DOUBLE_ARROW;
+ public static int TYPE_NOT_SPECIFIED;
+ public static int TYPE_NO_DROP;
+ public static int TYPE_NULL;
+ public static int TYPE_SPOT_ANCHOR;
+ public static int TYPE_SPOT_HOVER;
+ public static int TYPE_SPOT_TOUCH;
+ public static int TYPE_TEXT;
+ public static int TYPE_TOP_LEFT_DIAGONAL_DOUBLE_ARROW;
+ public static int TYPE_TOP_RIGHT_DIAGONAL_DOUBLE_ARROW;
+ public static int TYPE_VERTICAL_DOUBLE_ARROW;
+ public static int TYPE_VERTICAL_TEXT;
+ public static int TYPE_WAIT;
+ public static int TYPE_ZOOM_IN;
+ public static int TYPE_ZOOM_OUT;
+}
+
+-keep class android.view.RecordingCanvas {
+ <init>(long);
+
+ public void drawARGB(int, int, int, int);
+ public void drawArc(float, float, float, float, float, float, boolean, android.graphics.Paint);
+ public void drawArc(android.graphics.RectF, float, float, boolean, android.graphics.Paint);
+ public void drawBitmap(android.graphics.Bitmap, float, float, android.graphics.Paint);
+ public void drawBitmap(android.graphics.Bitmap, android.graphics.Matrix, android.graphics.Paint);
+ public void drawBitmap(android.graphics.Bitmap, android.graphics.Rect, android.graphics.Rect, android.graphics.Paint);
+ public void drawBitmap(android.graphics.Bitmap, android.graphics.Rect, android.graphics.RectF, android.graphics.Paint);
+ public void drawBitmap(int[], int, int, float, float, int, int, boolean, android.graphics.Paint);
+ public void drawBitmap(int[], int, int, int, int, int, int, boolean, android.graphics.Paint);
+ public void drawBitmapMesh(android.graphics.Bitmap, int, int, float[], int, int[], int, android.graphics.Paint);
+ public void drawCircle(float, float, float, android.graphics.Paint);
+ public void drawColor(int);
+ public void drawColor(int, android.graphics.PorterDuff$Mode);
+ public void drawLine(float, float, float, float, android.graphics.Paint);
+ public void drawLines(float[], int, int, android.graphics.Paint);
+ public void drawLines(float[], android.graphics.Paint);
+ public void drawOval(float, float, float, float, android.graphics.Paint);
+ public void drawOval(android.graphics.RectF, android.graphics.Paint);
+ public void drawPaint(android.graphics.Paint);
+ public void drawPatch(android.graphics.NinePatch, android.graphics.Rect, android.graphics.Paint);
+ public void drawPatch(android.graphics.NinePatch, android.graphics.RectF, android.graphics.Paint);
+ public void drawPath(android.graphics.Path, android.graphics.Paint);
+ public void drawPicture(android.graphics.Picture);
+ public void drawPicture(android.graphics.Picture, android.graphics.Rect);
+ public void drawPicture(android.graphics.Picture, android.graphics.RectF);
+ public void drawPoint(float, float, android.graphics.Paint);
+ public void drawPoints(float[], int, int, android.graphics.Paint);
+ public void drawPoints(float[], android.graphics.Paint);
+ public void drawPosText(char[], int, int, float[], android.graphics.Paint);
+ public void drawPosText(java.lang.String, float[], android.graphics.Paint);
+ public void drawRGB(int, int, int);
+ public void drawRect(float, float, float, float, android.graphics.Paint);
+ public void drawRect(android.graphics.Rect, android.graphics.Paint);
+ public void drawRect(android.graphics.RectF, android.graphics.Paint);
+ public void drawRoundRect(float, float, float, float, float, float, android.graphics.Paint);
+ public void drawRoundRect(android.graphics.RectF, float, float, android.graphics.Paint);
+ public void drawText(char[], int, int, float, float, android.graphics.Paint);
+ public void drawText(java.lang.CharSequence, int, int, float, float, android.graphics.Paint);
+ public void drawText(java.lang.String, float, float, android.graphics.Paint);
+ public void drawText(java.lang.String, int, int, float, float, android.graphics.Paint);
+ public void drawTextOnPath(char[], int, int, android.graphics.Path, float, float, android.graphics.Paint);
+ public void drawTextOnPath(java.lang.String, android.graphics.Path, float, float, android.graphics.Paint);
+ public void drawTextRun(char[], int, int, int, int, float, float, boolean, android.graphics.Paint);
+ public void drawTextRun(java.lang.CharSequence, int, int, int, int, float, float, boolean, android.graphics.Paint);
+ public void drawVertices(android.graphics.Canvas$VertexMode, int, float[], int, float[], int, int[], int, short[], int, int, android.graphics.Paint);
+
+
+}
+
+-keep class android.view.RemoteAnimationAdapter {
+ <init>(android.view.IRemoteAnimationRunner, long, long);
+ <init>(android.os.Parcel);
+
+ public int describeContents();
+ public int getCallingPid();
+ public long getDuration();
+ public android.view.IRemoteAnimationRunner getRunner();
+ public long getStatusBarTransitionDelay();
+ public void setCallingPid(int);
+ public void writeToParcel(android.os.Parcel, int);
+
+
+ public static android.os.Parcelable$Creator CREATOR;
+}
+
+-keep class android.view.RemoteAnimationDefinition {
+ <init>();
+ <init>(android.os.Parcel);
+
+ public void addRemoteAnimation(int, int, android.view.RemoteAnimationAdapter);
+ public void addRemoteAnimation(int, android.view.RemoteAnimationAdapter);
+ public int describeContents();
+ public android.view.RemoteAnimationAdapter getAdapter(int, android.util.ArraySet);
+ public boolean hasTransition(int, android.util.ArraySet);
+ public void setCallingPid(int);
+ public void writeToParcel(android.os.Parcel, int);
+
+
+ public static android.os.Parcelable$Creator CREATOR;
+}
+
+-keep class android.view.RemoteAnimationTarget {
+ <init>(int, int, android.view.SurfaceControl, boolean, android.graphics.Rect, android.graphics.Rect, int, android.graphics.Point, android.graphics.Rect, android.app.WindowConfiguration, boolean);
+ <init>(android.os.Parcel);
+
+ public int describeContents();
+ public void dump(java.io.PrintWriter, java.lang.String);
+ public void writeToParcel(android.os.Parcel, int);
+ public void writeToProto(android.util.proto.ProtoOutputStream, long);
+
+
+ public static android.os.Parcelable$Creator CREATOR;
+ public static int MODE_CLOSING;
+ public static int MODE_OPENING;
+ public android.graphics.Rect clipRect;
+ public android.graphics.Rect contentInsets;
+ public boolean isNotInRecents;
+ public boolean isTranslucent;
+ public android.view.SurfaceControl leash;
+ public int mode;
+ public android.graphics.Point position;
+ public int prefixOrderIndex;
+ public android.graphics.Rect sourceContainerBounds;
+ public int taskId;
+ public android.app.WindowConfiguration windowConfiguration;
+}
+
+-keep class android.view.RenderNode {
+
+ public void addAnimator(android.view.RenderNodeAnimator);
+ public static android.view.RenderNode adopt(long);
+ public static android.view.RenderNode create(java.lang.String, android.view.View);
+ public void destroy();
+ public void discardDisplayList();
+ public void end(android.view.DisplayListCanvas);
+ public void endAllAnimators();
+ public float getAlpha();
+ public int getAmbientShadowColor();
+ public float getCameraDistance();
+ public boolean getClipToOutline();
+ public int getDebugSize();
+ public float getElevation();
+ public void getInverseMatrix(android.graphics.Matrix);
+ public void getMatrix(android.graphics.Matrix);
+ public float getPivotX();
+ public float getPivotY();
+ public float getRotation();
+ public float getRotationX();
+ public float getRotationY();
+ public float getScaleX();
+ public float getScaleY();
+ public int getSpotShadowColor();
+ public float getTranslationX();
+ public float getTranslationY();
+ public float getTranslationZ();
+ public boolean hasIdentityMatrix();
+ public boolean hasOverlappingRendering();
+ public boolean hasShadow();
+ public boolean isAttached();
+ public boolean isPivotExplicitlySet();
+ public boolean isValid();
+ public boolean offsetLeftAndRight(int);
+ public boolean offsetTopAndBottom(int);
+ public void output();
+ public void registerVectorDrawableAnimator(android.graphics.drawable.AnimatedVectorDrawable$VectorDrawableAnimatorRT);
+ public void requestPositionUpdates(android.view.SurfaceView);
+ public boolean resetPivot();
+ public boolean setAlpha(float);
+ public boolean setAmbientShadowColor(int);
+ public boolean setAnimationMatrix(android.graphics.Matrix);
+ public boolean setBottom(int);
+ public boolean setCameraDistance(float);
+ public boolean setClipBounds(android.graphics.Rect);
+ public boolean setClipToBounds(boolean);
+ public boolean setClipToOutline(boolean);
+ public boolean setElevation(float);
+ public boolean setHasOverlappingRendering(boolean);
+ public boolean setLayerPaint(android.graphics.Paint);
+ public boolean setLayerType(int);
+ public boolean setLeft(int);
+ public boolean setLeftTopRightBottom(int, int, int, int);
+ public boolean setOutline(android.graphics.Outline);
+ public boolean setPivotX(float);
+ public boolean setPivotY(float);
+ public boolean setProjectBackwards(boolean);
+ public boolean setProjectionReceiver(boolean);
+ public boolean setRevealClip(boolean, float, float, float);
+ public boolean setRight(int);
+ public boolean setRotation(float);
+ public boolean setRotationX(float);
+ public boolean setRotationY(float);
+ public boolean setScaleX(float);
+ public boolean setScaleY(float);
+ public boolean setSpotShadowColor(int);
+ public boolean setStaticMatrix(android.graphics.Matrix);
+ public boolean setTop(int);
+ public boolean setTranslationX(float);
+ public boolean setTranslationY(float);
+ public boolean setTranslationZ(float);
+ public android.view.DisplayListCanvas start(int, int);
+
+
+}
+
+-keep class android.view.RenderNodeAnimator {
+ <init>(int, float);
+ <init>(android.graphics.CanvasProperty, float);
+ <init>(android.graphics.CanvasProperty, int, float);
+ <init>(int, int, float, float);
+
+ public void cancel();
+ public android.animation.Animator clone();
+ public java.lang.Object clone();
+ public void end();
+ public long getDuration();
+ public android.animation.TimeInterpolator getInterpolator();
+ public long getStartDelay();
+ public long getTotalDuration();
+ public boolean isRunning();
+ public boolean isStarted();
+ public static int mapViewPropertyToRenderProperty(int);
+ protected void onFinished();
+ public void pause();
+ public void resume();
+ public void setAllowRunningAsynchronously(boolean);
+ public android.view.RenderNodeAnimator setDuration(long);
+ public android.animation.Animator setDuration(long);
+ public void setInterpolator(android.animation.TimeInterpolator);
+ public void setStartDelay(long);
+ public void setStartValue(float);
+ public void setTarget(android.view.View);
+ public void setTarget(android.view.DisplayListCanvas);
+ public void start();
+
+
+ public static int ALPHA;
+ public static int LAST_VALUE;
+ public static int PAINT_ALPHA;
+ public static int PAINT_STROKE_WIDTH;
+ public static int ROTATION;
+ public static int ROTATION_X;
+ public static int ROTATION_Y;
+ public static int SCALE_X;
+ public static int SCALE_Y;
+ public static int TRANSLATION_X;
+ public static int TRANSLATION_Y;
+ public static int TRANSLATION_Z;
+ public static int X;
+ public static int Y;
+ public static int Z;
+}
+
+-keep class android.view.SearchEvent {
+ <init>(android.view.InputDevice);
+
+ public android.view.InputDevice getInputDevice();
+
+
+}
+
+-keep class android.view.SubMenu {
+
+ public abstract void clearHeader();
+ public abstract android.view.MenuItem getItem();
+ public abstract android.view.SubMenu setHeaderIcon(int);
+ public abstract android.view.SubMenu setHeaderIcon(android.graphics.drawable.Drawable);
+ public abstract android.view.SubMenu setHeaderTitle(int);
+ public abstract android.view.SubMenu setHeaderTitle(java.lang.CharSequence);
+ public abstract android.view.SubMenu setHeaderView(android.view.View);
+ public abstract android.view.SubMenu setIcon(int);
+ public abstract android.view.SubMenu setIcon(android.graphics.drawable.Drawable);
+
+
+}
+
+-keep class android.view.Surface {
+ <init>();
+ <init>(android.graphics.SurfaceTexture);
+
+ public void allocateBuffers();
+ public void attachAndQueueBuffer(android.graphics.GraphicBuffer);
+ public void copyFrom(android.view.SurfaceControl);
+ public void createFrom(android.view.SurfaceControl);
+ public int describeContents();
+ public void destroy();
+ protected void finalize();
+ public int getGenerationId();
+ public long getNextFrameNumber();
+ public void hwuiDestroy();
+ public boolean isAutoRefreshEnabled();
+ public boolean isConsumerRunningBehind();
+ public boolean isSharedBufferModeEnabled();
+ public boolean isSingleBuffered();
+ public boolean isValid();
+ public android.graphics.Canvas lockCanvas(android.graphics.Rect);
+ public android.graphics.Canvas lockHardwareCanvas();
+ public android.graphics.Canvas lockHardwareWideColorGamutCanvas();
+ public void readFromParcel(android.os.Parcel);
+ public void release();
+ public static java.lang.String rotationToString(int);
+ public void setAutoRefreshEnabled(boolean);
+ public void setSharedBufferModeEnabled(boolean);
+ public java.lang.String toString();
+ public void transferFrom(android.view.Surface);
+ public void unlockCanvas(android.graphics.Canvas);
+ public void unlockCanvasAndPost(android.graphics.Canvas);
+ public void writeToParcel(android.os.Parcel, int);
+
+
+ public static android.os.Parcelable$Creator CREATOR;
+ public static int ROTATION_0;
+ public static int ROTATION_180;
+ public static int ROTATION_270;
+ public static int ROTATION_90;
+ public static int SCALING_MODE_FREEZE;
+ public static int SCALING_MODE_NO_SCALE_CROP;
+ public static int SCALING_MODE_SCALE_CROP;
+ public static int SCALING_MODE_SCALE_TO_WINDOW;
+}
+
+-keep class android.view.Surface$OutOfResourcesException {
+ <init>();
+ <init>(java.lang.String);
+
+
+
+}
+
+-keep class android.view.SurfaceControl {
+ <init>(android.view.SurfaceControl);
+
+ public static android.graphics.GraphicBuffer captureLayers(android.os.IBinder, android.graphics.Rect, float);
+ public static boolean clearAnimationFrameStats();
+ public boolean clearContentFrameStats();
+ public static void closeTransaction();
+ public static void closeTransactionSync();
+ public static android.os.IBinder createDisplay(java.lang.String, boolean);
+ public void deferTransactionUntil(android.os.IBinder, long);
+ public void deferTransactionUntil(android.view.Surface, long);
+ public int describeContents();
+ public void destroy();
+ public static void destroyDisplay(android.os.IBinder);
+ public void detachChildren();
+ public void disconnect();
+ protected void finalize();
+ public static int getActiveColorMode(android.os.IBinder);
+ public static int getActiveConfig(android.os.IBinder);
+ public static boolean getAnimationFrameStats(android.view.WindowAnimationFrameStats);
+ public static android.os.IBinder getBuiltInDisplay(int);
+ public boolean getContentFrameStats(android.view.WindowContentFrameStats);
+ public static int[] getDisplayColorModes(android.os.IBinder);
+ public static android.view.SurfaceControl$PhysicalDisplayInfo[] getDisplayConfigs(android.os.IBinder);
+ public android.os.IBinder getHandle();
+ public static android.view.Display$HdrCapabilities getHdrCapabilities(android.os.IBinder);
+ public int getHeight();
+ public int getWidth();
+ public void hide();
+ public static void mergeToGlobalTransaction(android.view.SurfaceControl$Transaction);
+ public static void openTransaction();
+ public void release();
+ public void reparent(android.os.IBinder);
+ public void reparentChildren(android.os.IBinder);
+ public static void screenshot(android.os.IBinder, android.view.Surface, int, int, int, int, boolean);
+ public static void screenshot(android.os.IBinder, android.view.Surface, int, int);
+ public static void screenshot(android.os.IBinder, android.view.Surface);
+ public static android.graphics.Bitmap screenshot(android.graphics.Rect, int, int, int, int, boolean, int);
+ public static android.graphics.Bitmap screenshot(android.graphics.Rect, int, int, int);
+ public static android.graphics.GraphicBuffer screenshotToBuffer(android.graphics.Rect, int, int, int, int, boolean, int);
+ public static boolean setActiveColorMode(android.os.IBinder, int);
+ public static boolean setActiveConfig(android.os.IBinder, int);
+ public void setAlpha(float);
+ public static void setAnimationTransaction();
+ public void setColor(float[]);
+ public static void setDisplayLayerStack(android.os.IBinder, int);
+ public static void setDisplayPowerMode(android.os.IBinder, int);
+ public static void setDisplayProjection(android.os.IBinder, int, android.graphics.Rect, android.graphics.Rect);
+ public static void setDisplaySize(android.os.IBinder, int, int);
+ public static void setDisplaySurface(android.os.IBinder, android.view.Surface);
+ public void setFinalCrop(android.graphics.Rect);
+ public void setGeometryAppliesWithResize();
+ public void setLayer(int);
+ public void setLayerStack(int);
+ public void setMatrix(float, float, float, float);
+ public void setMatrix(android.graphics.Matrix, float[]);
+ public void setOpaque(boolean);
+ public void setOverrideScalingMode(int);
+ public void setPosition(float, float);
+ public void setRelativeLayer(android.view.SurfaceControl, int);
+ public void setSecure(boolean);
+ public void setSize(int, int);
+ public void setTransparentRegionHint(android.graphics.Region);
+ public void setWindowCrop(android.graphics.Rect);
+ public void show();
+ public java.lang.String toString();
+ public void writeToParcel(android.os.Parcel, int);
+ public void writeToProto(android.util.proto.ProtoOutputStream, long);
+
+
+ public static int BUILT_IN_DISPLAY_ID_HDMI;
+ public static int BUILT_IN_DISPLAY_ID_MAIN;
+ public static android.os.Parcelable$Creator CREATOR;
+ public static int CURSOR_WINDOW;
+ public static int FX_SURFACE_DIM;
+ public static int FX_SURFACE_MASK;
+ public static int FX_SURFACE_NORMAL;
+ public static int HIDDEN;
+ public static int NON_PREMULTIPLIED;
+ public static int OPAQUE;
+ public static int POWER_MODE_DOZE;
+ public static int POWER_MODE_DOZE_SUSPEND;
+ public static int POWER_MODE_NORMAL;
+ public static int POWER_MODE_OFF;
+ public static int POWER_MODE_ON_SUSPEND;
+ public static int PROTECTED_APP;
+ public static int SECURE;
+ public static int WINDOW_TYPE_DONT_SCREENSHOT;
+}
+
+-keep class android.view.SurfaceControl$PhysicalDisplayInfo {
+ <init>();
+ <init>(android.view.SurfaceControl$PhysicalDisplayInfo);
+
+ public void copyFrom(android.view.SurfaceControl$PhysicalDisplayInfo);
+ public boolean equals(java.lang.Object);
+ public boolean equals(android.view.SurfaceControl$PhysicalDisplayInfo);
+ public int hashCode();
+ public java.lang.String toString();
+
+
+ public long appVsyncOffsetNanos;
+ public float density;
+ public int height;
+ public long presentationDeadlineNanos;
+ public float refreshRate;
+ public boolean secure;
+ public int width;
+ public float xDpi;
+ public float yDpi;
+}
+
+-keep class android.view.SurfaceControl$Transaction {
+ <init>();
+
+ public void apply();
+ public void apply(boolean);
+ public void close();
+ public android.view.SurfaceControl$Transaction deferTransactionUntil(android.view.SurfaceControl, android.os.IBinder, long);
+ public android.view.SurfaceControl$Transaction deferTransactionUntilSurface(android.view.SurfaceControl, android.view.Surface, long);
+ public android.view.SurfaceControl$Transaction destroy(android.view.SurfaceControl);
+ public android.view.SurfaceControl$Transaction detachChildren(android.view.SurfaceControl);
+ public android.view.SurfaceControl$Transaction hide(android.view.SurfaceControl);
+ public android.view.SurfaceControl$Transaction merge(android.view.SurfaceControl$Transaction);
+ public android.view.SurfaceControl$Transaction reparent(android.view.SurfaceControl, android.os.IBinder);
+ public android.view.SurfaceControl$Transaction reparentChildren(android.view.SurfaceControl, android.os.IBinder);
+ public android.view.SurfaceControl$Transaction setAlpha(android.view.SurfaceControl, float);
+ public android.view.SurfaceControl$Transaction setAnimationTransaction();
+ public android.view.SurfaceControl$Transaction setColor(android.view.SurfaceControl, float[]);
+ public android.view.SurfaceControl$Transaction setDisplayLayerStack(android.os.IBinder, int);
+ public android.view.SurfaceControl$Transaction setDisplayProjection(android.os.IBinder, int, android.graphics.Rect, android.graphics.Rect);
+ public android.view.SurfaceControl$Transaction setDisplaySize(android.os.IBinder, int, int);
+ public android.view.SurfaceControl$Transaction setDisplaySurface(android.os.IBinder, android.view.Surface);
+ public android.view.SurfaceControl$Transaction setEarlyWakeup();
+ public android.view.SurfaceControl$Transaction setFinalCrop(android.view.SurfaceControl, android.graphics.Rect);
+ public android.view.SurfaceControl$Transaction setGeometryAppliesWithResize(android.view.SurfaceControl);
+ public android.view.SurfaceControl$Transaction setLayer(android.view.SurfaceControl, int);
+ public android.view.SurfaceControl$Transaction setLayerStack(android.view.SurfaceControl, int);
+ public android.view.SurfaceControl$Transaction setMatrix(android.view.SurfaceControl, float, float, float, float);
+ public android.view.SurfaceControl$Transaction setMatrix(android.view.SurfaceControl, android.graphics.Matrix, float[]);
+ public android.view.SurfaceControl$Transaction setOpaque(android.view.SurfaceControl, boolean);
+ public android.view.SurfaceControl$Transaction setOverrideScalingMode(android.view.SurfaceControl, int);
+ public android.view.SurfaceControl$Transaction setPosition(android.view.SurfaceControl, float, float);
+ public android.view.SurfaceControl$Transaction setRelativeLayer(android.view.SurfaceControl, android.view.SurfaceControl, int);
+ public android.view.SurfaceControl$Transaction setSecure(android.view.SurfaceControl, boolean);
+ public android.view.SurfaceControl$Transaction setSize(android.view.SurfaceControl, int, int);
+ public android.view.SurfaceControl$Transaction setTransparentRegionHint(android.view.SurfaceControl, android.graphics.Region);
+ public android.view.SurfaceControl$Transaction setWindowCrop(android.view.SurfaceControl, android.graphics.Rect);
+ public android.view.SurfaceControl$Transaction show(android.view.SurfaceControl);
+
+
+ public static libcore.util.NativeAllocationRegistry sRegistry;
+}
+
+-keep class android.view.SurfaceHolder {
+
+ public abstract void addCallback(android.view.SurfaceHolder$Callback);
+ public abstract android.view.Surface getSurface();
+ public abstract android.graphics.Rect getSurfaceFrame();
+ public abstract boolean isCreating();
+ public abstract android.graphics.Canvas lockCanvas();
+ public abstract android.graphics.Canvas lockCanvas(android.graphics.Rect);
+ public android.graphics.Canvas lockHardwareCanvas();
+ public abstract void removeCallback(android.view.SurfaceHolder$Callback);
+ public abstract void setFixedSize(int, int);
+ public abstract void setFormat(int);
+ public abstract void setKeepScreenOn(boolean);
+ public abstract void setSizeFromLayout();
+ public abstract void setType(int);
+ public abstract void unlockCanvasAndPost(android.graphics.Canvas);
+
+
+ public static int SURFACE_TYPE_GPU;
+ public static int SURFACE_TYPE_HARDWARE;
+ public static int SURFACE_TYPE_NORMAL;
+ public static int SURFACE_TYPE_PUSH_BUFFERS;
+}
+
+-keep class android.view.SurfaceHolder$Callback {
+
+ public abstract void surfaceChanged(android.view.SurfaceHolder, int, int, int);
+ public abstract void surfaceCreated(android.view.SurfaceHolder);
+ public abstract void surfaceDestroyed(android.view.SurfaceHolder);
+
+
+}
+
+-keep class android.view.SurfaceHolder$Callback2 {
+
+ public abstract void surfaceRedrawNeeded(android.view.SurfaceHolder);
+ public void surfaceRedrawNeededAsync(android.view.SurfaceHolder, java.lang.Runnable);
+
+
+}
+
+-keep class android.view.SurfaceView {
+ <init>(android.content.Context);
+ <init>(android.content.Context, android.util.AttributeSet);
+ <init>(android.content.Context, android.util.AttributeSet, int);
+ <init>(android.content.Context, android.util.AttributeSet, int, int);
+
+ protected void applyChildSurfaceTransaction_renderWorker(android.view.SurfaceControl$Transaction, android.view.Surface, long);
+ protected void dispatchDraw(android.graphics.Canvas);
+ public void draw(android.graphics.Canvas);
+ public boolean gatherTransparentRegion(android.graphics.Region);
+ public android.view.SurfaceHolder getHolder();
+ public boolean isFixedSize();
+ protected void onAttachedToWindow();
+ protected void onDetachedFromWindow();
+ protected void onMeasure(int, int);
+ protected void onWindowVisibilityChanged(int);
+ protected boolean setFrame(int, int, int, int);
+ public void setResizeBackgroundColor(int);
+ public void setSecure(boolean);
+ public void setVisibility(int);
+ public void setZOrderMediaOverlay(boolean);
+ public void setZOrderOnTop(boolean);
+ public void surfacePositionLost_uiRtSync(long);
+ protected void updateSurface();
+ public void updateSurfacePosition_renderWorker(long, int, int, int, int);
+ public void windowStopped(boolean);
+
+
+}
+
+-keep class android.view.ThreadedRenderer {
+
+ public void addRenderNode(android.view.RenderNode, boolean);
+ public static int copySurfaceInto(android.view.Surface, android.graphics.Rect, android.graphics.Bitmap);
+ public static android.view.ThreadedRenderer create(android.content.Context, boolean, java.lang.String);
+ public static android.graphics.Bitmap createHardwareBitmap(android.view.RenderNode, int, int);
+ public static void disable(boolean);
+ public static void disableVsync();
+ public void drawRenderNode(android.view.RenderNode);
+ public static void enableForegroundTrimming();
+ protected void finalize();
+ public static boolean isAvailable();
+ 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);
+ public static void setFPSDivisor(int);
+ public static void setHighContrastText(boolean);
+ public static void setIsolatedProcess(boolean);
+ public static void setupDiskCache(java.io.File);
+ public static void trimMemory(int);
+
+
+ public static java.lang.String DEBUG_DIRTY_REGIONS_PROPERTY;
+ public static java.lang.String DEBUG_FPS_DIVISOR;
+ public static java.lang.String DEBUG_OVERDRAW_PROPERTY;
+ public static java.lang.String DEBUG_SHOW_LAYERS_UPDATES_PROPERTY;
+ public static java.lang.String DEBUG_SHOW_NON_RECTANGULAR_CLIP_PROPERTY;
+ public static int EGL_CONTEXT_PRIORITY_HIGH_IMG;
+ public static int EGL_CONTEXT_PRIORITY_LOW_IMG;
+ public static int EGL_CONTEXT_PRIORITY_MEDIUM_IMG;
+ public static java.lang.String OVERDRAW_PROPERTY_SHOW;
+ public static java.lang.String PROFILE_PROPERTY;
+ public static java.lang.String PROFILE_PROPERTY_VISUALIZE_BARS;
+ public static boolean sRendererDisabled;
+ public static boolean sSystemRendererDisabled;
+ public static boolean sTrimForeground;
+}
+
+-keep class android.view.ThreadedRenderer$FrameDrawingCallback {
+
+ public abstract void onFrameDraw(long);
+
+
+}
+
+-keep class android.view.TouchDelegate {
+ <init>(android.graphics.Rect, android.view.View);
+
+ public boolean onTouchEvent(android.view.MotionEvent);
+
+
+ public static int ABOVE;
+ public static int BELOW;
+ public static int TO_LEFT;
+ public static int TO_RIGHT;
+}
+
+-keep class android.view.View {
+ <init>(android.content.Context);
+ <init>(android.content.Context, android.util.AttributeSet);
+ <init>(android.content.Context, android.util.AttributeSet, int);
+ <init>(android.content.Context, android.util.AttributeSet, int, int);
+
+ public void addChildrenForAccessibility(java.util.ArrayList);
+ public void addExtraDataToAccessibilityNodeInfo(android.view.accessibility.AccessibilityNodeInfo, java.lang.String, android.os.Bundle);
+ public void addFocusables(java.util.ArrayList, int);
+ public void addFocusables(java.util.ArrayList, int, int);
+ public void addFrameMetricsListener(android.view.Window, android.view.Window$OnFrameMetricsAvailableListener, android.os.Handler);
+ public void addKeyboardNavigationClusters(java.util.Collection, int);
+ public void addOnAttachStateChangeListener(android.view.View$OnAttachStateChangeListener);
+ public void addOnLayoutChangeListener(android.view.View$OnLayoutChangeListener);
+ public void addOnUnhandledKeyEventListener(android.view.View$OnUnhandledKeyEventListener);
+ public void addTouchables(java.util.ArrayList);
+ public android.view.ViewPropertyAnimator animate();
+ public void announceForAccessibility(java.lang.CharSequence);
+ public void applyDrawableToTransparentRegion(android.graphics.drawable.Drawable, android.graphics.Region);
+ public void autofill(android.view.autofill.AutofillValue);
+ public void autofill(android.util.SparseArray);
+ protected boolean awakenScrollBars();
+ protected boolean awakenScrollBars(int);
+ protected boolean awakenScrollBars(int, boolean);
+ public void bringToFront();
+ public void buildDrawingCache();
+ public void buildDrawingCache(boolean);
+ public void buildLayer();
+ public boolean callOnClick();
+ public boolean canHaveDisplayList();
+ public boolean canNotifyAutofillEnterExitEvent();
+ public boolean canResolveLayoutDirection();
+ public boolean canResolveTextAlignment();
+ public boolean canResolveTextDirection();
+ public boolean canScrollHorizontally(int);
+ public boolean canScrollVertically(int);
+ public void cancelDragAndDrop();
+ public void cancelLongPress();
+ public void cancelPendingInputEvents();
+ public void captureTransitioningViews(java.util.List);
+ public boolean checkInputConnectionProxy(android.view.View);
+ public void clearAccessibilityFocus();
+ public void clearAnimation();
+ public void clearFocus();
+ public static int combineMeasuredStates(int, int);
+ protected boolean computeFitSystemWindows(android.graphics.Rect, android.graphics.Rect);
+ protected int computeHorizontalScrollExtent();
+ protected int computeHorizontalScrollOffset();
+ protected int computeHorizontalScrollRange();
+ protected void computeOpaqueFlags();
+ public void computeScroll();
+ public android.view.WindowInsets computeSystemWindowInsets(android.view.WindowInsets, android.graphics.Rect);
+ protected int computeVerticalScrollExtent();
+ protected int computeVerticalScrollOffset();
+ protected int computeVerticalScrollRange();
+ public android.view.accessibility.AccessibilityNodeInfo createAccessibilityNodeInfo();
+ public android.view.accessibility.AccessibilityNodeInfo createAccessibilityNodeInfoInternal();
+ public void createContextMenu(android.view.ContextMenu);
+ public android.graphics.Bitmap createSnapshot(android.view.ViewDebug$CanvasProvider, boolean);
+ protected void damageInParent();
+ public void debug();
+ protected void debug(int);
+ protected static java.lang.String debugIndent(int);
+ public void destroyDrawingCache();
+ protected void destroyHardwareResources();
+ public boolean dispatchActivityResult(java.lang.String, int, int, android.content.Intent);
+ public android.view.WindowInsets dispatchApplyWindowInsets(android.view.WindowInsets);
+ public boolean dispatchCapturedPointerEvent(android.view.MotionEvent);
+ public void dispatchConfigurationChanged(android.content.res.Configuration);
+ public void dispatchDisplayHint(int);
+ public boolean dispatchDragEvent(android.view.DragEvent);
+ protected void dispatchDraw(android.graphics.Canvas);
+ public void dispatchDrawableHotspotChanged(float, float);
+ public void dispatchFinishTemporaryDetach();
+ protected boolean dispatchGenericFocusedEvent(android.view.MotionEvent);
+ public boolean dispatchGenericMotionEvent(android.view.MotionEvent);
+ protected boolean dispatchGenericPointerEvent(android.view.MotionEvent);
+ protected void dispatchGetDisplayList();
+ protected boolean dispatchHoverEvent(android.view.MotionEvent);
+ public boolean dispatchKeyEvent(android.view.KeyEvent);
+ public boolean dispatchKeyEventPreIme(android.view.KeyEvent);
+ public boolean dispatchKeyShortcutEvent(android.view.KeyEvent);
+ public boolean dispatchNestedFling(float, float, boolean);
+ public boolean dispatchNestedPreFling(float, float);
+ public boolean dispatchNestedPrePerformAccessibilityAction(int, android.os.Bundle);
+ public boolean dispatchNestedPreScroll(int, int, int[], int[]);
+ public boolean dispatchNestedScroll(int, int, int, int, int[]);
+ public void dispatchPointerCaptureChanged(boolean);
+ public boolean dispatchPointerEvent(android.view.MotionEvent);
+ public boolean dispatchPopulateAccessibilityEvent(android.view.accessibility.AccessibilityEvent);
+ public boolean dispatchPopulateAccessibilityEventInternal(android.view.accessibility.AccessibilityEvent);
+ public void dispatchProvideAutofillStructure(android.view.ViewStructure, int);
+ public void dispatchProvideStructure(android.view.ViewStructure);
+ protected void dispatchRestoreInstanceState(android.util.SparseArray);
+ protected void dispatchSaveInstanceState(android.util.SparseArray);
+ protected void dispatchSetActivated(boolean);
+ protected void dispatchSetPressed(boolean);
+ protected void dispatchSetSelected(boolean);
+ public void dispatchStartTemporaryDetach();
+ public void dispatchSystemUiVisibilityChanged(int);
+ public boolean dispatchTouchEvent(android.view.MotionEvent);
+ public boolean dispatchTrackballEvent(android.view.MotionEvent);
+ public boolean dispatchUnhandledMove(android.view.View, int);
+ protected void dispatchVisibilityChanged(android.view.View, int);
+ public void dispatchWindowFocusChanged(boolean);
+ public void dispatchWindowSystemUiVisiblityChanged(int);
+ public void dispatchWindowVisibilityChanged(int);
+ public void draw(android.graphics.Canvas);
+ public void drawableHotspotChanged(float, float);
+ protected void drawableStateChanged();
+ public void encode(android.view.ViewHierarchyEncoder);
+ protected void encodeProperties(android.view.ViewHierarchyEncoder);
+ public android.view.View findFocus();
+ public void findNamedViews(java.util.Map);
+ public android.view.View findViewByAccessibilityIdTraversal(int);
+ public android.view.View findViewByAutofillIdTraversal(int);
+ public android.view.View findViewById(int);
+ public android.view.View findViewByPredicate(java.util.function.Predicate);
+ public android.view.View findViewByPredicateInsideOut(android.view.View, java.util.function.Predicate);
+ protected android.view.View findViewByPredicateTraversal(java.util.function.Predicate, android.view.View);
+ protected android.view.View findViewTraversal(int);
+ public android.view.View findViewWithTag(java.lang.Object);
+ protected android.view.View findViewWithTagTraversal(java.lang.Object);
+ public void findViewsWithText(java.util.ArrayList, java.lang.CharSequence, int);
+ protected boolean fitSystemWindows(android.graphics.Rect);
+ public boolean fitsSystemWindows();
+ public android.view.View focusSearch(int);
+ public void forceHasOverlappingRendering(boolean);
+ public void forceLayout();
+ public boolean gatherTransparentRegion(android.graphics.Region);
+ public static int generateViewId();
+ public java.lang.CharSequence getAccessibilityClassName();
+ public android.view.View$AccessibilityDelegate getAccessibilityDelegate();
+ public int getAccessibilityLiveRegion();
+ public android.view.accessibility.AccessibilityNodeProvider getAccessibilityNodeProvider();
+ public java.lang.CharSequence getAccessibilityPaneTitle();
+ public int getAccessibilitySelectionEnd();
+ public int getAccessibilitySelectionStart();
+ public int getAccessibilityTraversalAfter();
+ public int getAccessibilityTraversalBefore();
+ public int getAccessibilityViewId();
+ public int getAccessibilityWindowId();
+ public float getAlpha();
+ public android.view.animation.Animation getAnimation();
+ public android.os.IBinder getApplicationWindowToken();
+ public java.lang.String[] getAutofillHints();
+ public android.view.autofill.AutofillId getAutofillId();
+ public int getAutofillType();
+ public android.view.autofill.AutofillValue getAutofillValue();
+ public int getAutofillViewId();
+ public android.graphics.drawable.Drawable getBackground();
+ public android.content.res.ColorStateList getBackgroundTintList();
+ public android.graphics.PorterDuff$Mode getBackgroundTintMode();
+ public int getBaseline();
+ public int getBottom();
+ protected float getBottomFadingEdgeStrength();
+ protected int getBottomPaddingOffset();
+ public void getBoundsOnScreen(android.graphics.Rect);
+ public void getBoundsOnScreen(android.graphics.Rect, boolean);
+ public float getCameraDistance();
+ public android.graphics.Rect getClipBounds();
+ public boolean getClipBounds(android.graphics.Rect);
+ public boolean getClipToOutline();
+ public java.lang.CharSequence getContentDescription();
+ public android.content.Context getContext();
+ protected android.view.ContextMenu$ContextMenuInfo getContextMenuInfo();
+ public boolean getDefaultFocusHighlightEnabled();
+ public static int getDefaultSize(int, int);
+ public android.view.Display getDisplay();
+ public int[] getDrawableState();
+ public android.graphics.Bitmap getDrawingCache();
+ public android.graphics.Bitmap getDrawingCache(boolean);
+ public int getDrawingCacheBackgroundColor();
+ public int getDrawingCacheQuality();
+ public void getDrawingRect(android.graphics.Rect);
+ public long getDrawingTime();
+ public float getElevation();
+ protected int getFadeHeight(boolean);
+ protected int getFadeTop(boolean);
+ public boolean getFilterTouchesWhenObscured();
+ public boolean getFitsSystemWindows();
+ public int getFocusable();
+ public java.util.ArrayList getFocusables(int);
+ public void getFocusedRect(android.graphics.Rect);
+ public android.graphics.drawable.Drawable getForeground();
+ public int getForegroundGravity();
+ public android.content.res.ColorStateList getForegroundTintList();
+ public android.graphics.PorterDuff$Mode getForegroundTintMode();
+ public boolean getGlobalVisibleRect(android.graphics.Rect, android.graphics.Point);
+ public boolean getGlobalVisibleRect(android.graphics.Rect);
+ public android.os.Handler getHandler();
+ public boolean getHasOverlappingRendering();
+ public int getHeight();
+ public void getHitRect(android.graphics.Rect);
+ public int getHorizontalFadingEdgeLength();
+ protected float getHorizontalScrollFactor();
+ protected int getHorizontalScrollbarHeight();
+ public void getHotspotBounds(android.graphics.Rect);
+ public int getId();
+ public int getImportantForAccessibility();
+ public int getImportantForAutofill();
+ public android.graphics.Matrix getInverseMatrix();
+ public java.lang.CharSequence getIterableTextForAccessibility();
+ public android.view.AccessibilityIterators$TextSegmentIterator getIteratorForGranularity(int);
+ public boolean getKeepScreenOn();
+ public android.view.KeyEvent$DispatcherState getKeyDispatcherState();
+ public int getLabelFor();
+ public int getLayerType();
+ public int getLayoutDirection();
+ public android.view.ViewGroup$LayoutParams getLayoutParams();
+ public int getLeft();
+ protected float getLeftFadingEdgeStrength();
+ protected int getLeftPaddingOffset();
+ public boolean getLocalVisibleRect(android.graphics.Rect);
+ public void getLocationInSurface(int[]);
+ public void getLocationInWindow(int[]);
+ public int[] getLocationOnScreen();
+ public void getLocationOnScreen(int[]);
+ public android.graphics.Matrix getMatrix();
+ public int getMeasuredHeight();
+ public int getMeasuredHeightAndState();
+ public int getMeasuredState();
+ public int getMeasuredWidth();
+ public int getMeasuredWidthAndState();
+ public int getMinimumHeight();
+ public int getMinimumWidth();
+ public int getNextClusterForwardId();
+ public int getNextFocusDownId();
+ public int getNextFocusForwardId();
+ public int getNextFocusLeftId();
+ public int getNextFocusRightId();
+ public int getNextFocusUpId();
+ public android.view.View$OnFocusChangeListener getOnFocusChangeListener();
+ public android.graphics.Insets getOpticalInsets();
+ public int getOutlineAmbientShadowColor();
+ public android.view.ViewOutlineProvider getOutlineProvider();
+ public int getOutlineSpotShadowColor();
+ public void getOutsets(android.graphics.Rect);
+ public int getOverScrollMode();
+ public android.view.ViewOverlay getOverlay();
+ public int getPaddingBottom();
+ public int getPaddingEnd();
+ public int getPaddingLeft();
+ public int getPaddingRight();
+ public int getPaddingStart();
+ public int getPaddingTop();
+ public android.view.ViewParent getParent();
+ public android.view.ViewParent getParentForAccessibility();
+ public float getPivotX();
+ public float getPivotY();
+ public android.view.PointerIcon getPointerIcon();
+ public int getRawLayoutDirection();
+ public int getRawTextAlignment();
+ public int getRawTextDirection();
+ public android.content.res.Resources getResources();
+ public boolean getRevealOnFocusHint();
+ public int getRight();
+ protected float getRightFadingEdgeStrength();
+ protected int getRightPaddingOffset();
+ public android.view.View getRootView();
+ public android.view.WindowInsets getRootWindowInsets();
+ public float getRotation();
+ public float getRotationX();
+ public float getRotationY();
+ public float getScaleX();
+ public float getScaleY();
+ public int getScrollBarDefaultDelayBeforeFade();
+ public int getScrollBarFadeDuration();
+ public int getScrollBarSize();
+ public int getScrollBarStyle();
+ public int getScrollIndicators();
+ public int getScrollX();
+ public int getScrollY();
+ public int getSolidColor();
+ public android.animation.StateListAnimator getStateListAnimator();
+ protected int getSuggestedMinimumHeight();
+ protected int getSuggestedMinimumWidth();
+ public int getSystemUiVisibility();
+ public java.lang.Object getTag();
+ public java.lang.Object getTag(int);
+ public int getTextAlignment();
+ public int getTextDirection();
+ public android.view.ThreadedRenderer getThreadedRenderer();
+ public java.lang.CharSequence getTooltip();
+ public java.lang.CharSequence getTooltipText();
+ public android.view.View getTooltipView();
+ public int getTop();
+ protected float getTopFadingEdgeStrength();
+ protected int getTopPaddingOffset();
+ public android.view.TouchDelegate getTouchDelegate();
+ public java.util.ArrayList getTouchables();
+ public float getTransitionAlpha();
+ public java.lang.String getTransitionName();
+ public float getTranslationX();
+ public float getTranslationY();
+ public float getTranslationZ();
+ public int getVerticalFadingEdgeLength();
+ protected float getVerticalScrollFactor();
+ public int getVerticalScrollbarPosition();
+ public int getVerticalScrollbarWidth();
+ public android.view.ViewRootImpl getViewRootImpl();
+ public android.view.ViewTreeObserver getViewTreeObserver();
+ public int getVisibility();
+ public int getWidth();
+ protected android.view.IWindow getWindow();
+ protected int getWindowAttachCount();
+ public void getWindowDisplayFrame(android.graphics.Rect);
+ public android.view.WindowId getWindowId();
+ public int getWindowSystemUiVisibility();
+ public android.os.IBinder getWindowToken();
+ public int getWindowVisibility();
+ public void getWindowVisibleDisplayFrame(android.graphics.Rect);
+ public float getX();
+ public float getY();
+ public float getZ();
+ protected boolean handleScrollBarDragging(android.view.MotionEvent);
+ public boolean hasExplicitFocusable();
+ public boolean hasFocus();
+ public boolean hasFocusable();
+ protected boolean hasHoveredChild();
+ public boolean hasNestedScrollingParent();
+ public boolean hasOnClickListeners();
+ protected boolean hasOpaqueScrollbars();
+ public boolean hasOverlappingRendering();
+ public boolean hasPointerCapture();
+ public boolean hasShadow();
+ public boolean hasTransientState();
+ public boolean hasWindowFocus();
+ public boolean includeForAccessibility();
+ public static android.view.View inflate(android.content.Context, int, android.view.ViewGroup);
+ protected void initializeFadingEdge(android.content.res.TypedArray);
+ protected void initializeFadingEdgeInternal(android.content.res.TypedArray);
+ protected void initializeScrollbars(android.content.res.TypedArray);
+ protected void initializeScrollbarsInternal(android.content.res.TypedArray);
+ protected void internalSetPadding(int, int, int, int);
+ public void invalidate(android.graphics.Rect);
+ public void invalidate(int, int, int, int);
+ public void invalidate();
+ public void invalidate(boolean);
+ public void invalidateDrawable(android.graphics.drawable.Drawable);
+ public void invalidateOutline();
+ protected void invalidateParentCaches();
+ protected void invalidateParentIfNeeded();
+ protected void invalidateParentIfNeededAndWasQuickRejected();
+ public boolean isAccessibilityFocused();
+ public boolean isAccessibilityHeading();
+ public boolean isAccessibilitySelectionExtendable();
+ public boolean isActionableForAccessibility();
+ public boolean isActivated();
+ public boolean isAssistBlocked();
+ public boolean isAttachedToWindow();
+ public boolean isAutofilled();
+ public boolean isClickable();
+ public boolean isContextClickable();
+ public static boolean isDefaultFocusHighlightEnabled();
+ public boolean isDefaultFocusHighlightNeeded(android.graphics.drawable.Drawable, android.graphics.drawable.Drawable);
+ public boolean isDirty();
+ public boolean isDrawingCacheEnabled();
+ public boolean isDuplicateParentStateEnabled();
+ public boolean isEnabled();
+ public boolean isFocusable();
+ public boolean isFocusableInTouchMode();
+ public boolean isFocused();
+ public boolean isFocusedByDefault();
+ public boolean isForegroundInsidePadding();
+ public boolean isHapticFeedbackEnabled();
+ public boolean isHardwareAccelerated();
+ public boolean isHorizontalFadingEdgeEnabled();
+ public boolean isHorizontalScrollBarEnabled();
+ public boolean isHovered();
+ public boolean isImportantForAccessibility();
+ public boolean isImportantForAutofill();
+ public boolean isInEditMode();
+ public boolean isInLayout();
+ public boolean isInScrollingContainer();
+ public boolean isInTouchMode();
+ public boolean isKeyboardNavigationCluster();
+ public boolean isLaidOut();
+ public boolean isLayoutDirectionInherited();
+ public boolean isLayoutDirectionResolved();
+ public static boolean isLayoutModeOptical(java.lang.Object);
+ public boolean isLayoutRequested();
+ public boolean isLayoutRtl();
+ public boolean isLongClickable();
+ public boolean isNestedScrollingEnabled();
+ public boolean isOpaque();
+ protected boolean isPaddingOffsetRequired();
+ public boolean isPaddingRelative();
+ public boolean isPivotSet();
+ public boolean isPressed();
+ public boolean isRootNamespace();
+ public boolean isSaveEnabled();
+ public boolean isSaveFromParentEnabled();
+ public boolean isScreenReaderFocusable();
+ public boolean isScrollContainer();
+ public boolean isScrollbarFadingEnabled();
+ public boolean isSelected();
+ public boolean isShown();
+ public boolean isSoundEffectsEnabled();
+ public boolean isTemporarilyDetached();
+ public boolean isTextAlignmentInherited();
+ public boolean isTextAlignmentResolved();
+ public boolean isTextDirectionInherited();
+ public boolean isTextDirectionResolved();
+ public boolean isVerticalFadingEdgeEnabled();
+ public boolean isVerticalScrollBarEnabled();
+ protected boolean isVerticalScrollBarHidden();
+ public boolean isVisibleToUser();
+ protected boolean isVisibleToUser(android.graphics.Rect);
+ public boolean isVisibleToUserForAutofill(int);
+ public void jumpDrawablesToCurrentState();
+ public android.view.View keyboardNavigationClusterSearch(android.view.View, int);
+ public void layout(int, int, int, int);
+ public void makeOptionalFitsSystemWindows();
+ public void mapRectFromViewToScreenCoords(android.graphics.RectF, boolean);
+ public void measure(int, int);
+ protected static int[] mergeDrawableStates(int[], int[]);
+ public void notifyEnterOrExitForAutoFillIfNeeded(boolean);
+ public void notifySubtreeAccessibilityStateChangedIfNeeded();
+ public void notifyViewAccessibilityStateChangedIfNeeded(int);
+ public void offsetLeftAndRight(int);
+ public void offsetTopAndBottom(int);
+ public void onActivityResult(int, int, android.content.Intent);
+ protected void onAnimationEnd();
+ protected void onAnimationStart();
+ public android.view.WindowInsets onApplyWindowInsets(android.view.WindowInsets);
+ protected void onAttachedToWindow();
+ public void onCancelPendingInputEvents();
+ public boolean onCapturedPointerEvent(android.view.MotionEvent);
+ public boolean onCheckIsTextEditor();
+ public void onCloseSystemDialogs(java.lang.String);
+ protected void onConfigurationChanged(android.content.res.Configuration);
+ protected void onCreateContextMenu(android.view.ContextMenu);
+ protected int[] onCreateDrawableState(int);
+ public android.view.inputmethod.InputConnection onCreateInputConnection(android.view.inputmethod.EditorInfo);
+ protected void onDetachedFromWindow();
+ protected void onDetachedFromWindowInternal();
+ protected void onDisplayHint(int);
+ public boolean onDragEvent(android.view.DragEvent);
+ protected void onDraw(android.graphics.Canvas);
+ public void onDrawForeground(android.graphics.Canvas);
+ protected void onDrawHorizontalScrollBar(android.graphics.Canvas, android.graphics.drawable.Drawable, int, int, int, int);
+ protected void onDrawScrollBars(android.graphics.Canvas);
+ protected void onDrawVerticalScrollBar(android.graphics.Canvas, android.graphics.drawable.Drawable, int, int, int, int);
+ public boolean onFilterTouchEventForSecurity(android.view.MotionEvent);
+ protected void onFinishInflate();
+ public void onFinishTemporaryDetach();
+ protected void onFocusChanged(boolean, int, android.graphics.Rect);
+ protected void onFocusLost();
+ public boolean onGenericMotionEvent(android.view.MotionEvent);
+ public void onHoverChanged(boolean);
+ public boolean onHoverEvent(android.view.MotionEvent);
+ public void onInitializeAccessibilityEvent(android.view.accessibility.AccessibilityEvent);
+ public void onInitializeAccessibilityEventInternal(android.view.accessibility.AccessibilityEvent);
+ public void onInitializeAccessibilityNodeInfo(android.view.accessibility.AccessibilityNodeInfo);
+ public void onInitializeAccessibilityNodeInfoInternal(android.view.accessibility.AccessibilityNodeInfo);
+ public boolean onKeyDown(int, android.view.KeyEvent);
+ public boolean onKeyLongPress(int, android.view.KeyEvent);
+ public boolean onKeyMultiple(int, int, android.view.KeyEvent);
+ public boolean onKeyPreIme(int, android.view.KeyEvent);
+ public boolean onKeyShortcut(int, android.view.KeyEvent);
+ public boolean onKeyUp(int, android.view.KeyEvent);
+ protected void onLayout(boolean, int, int, int, int);
+ protected void onMeasure(int, int);
+ public void onMovedToDisplay(int, android.content.res.Configuration);
+ protected void onOverScrolled(int, int, boolean, boolean);
+ public void onPointerCaptureChange(boolean);
+ public void onPopulateAccessibilityEvent(android.view.accessibility.AccessibilityEvent);
+ public void onPopulateAccessibilityEventInternal(android.view.accessibility.AccessibilityEvent);
+ public void onProvideAutofillStructure(android.view.ViewStructure, int);
+ public void onProvideAutofillVirtualStructure(android.view.ViewStructure, int);
+ public void onProvideStructure(android.view.ViewStructure);
+ public void onProvideVirtualStructure(android.view.ViewStructure);
+ public void onResolveDrawables(int);
+ public android.view.PointerIcon onResolvePointerIcon(android.view.MotionEvent, int);
+ protected void onRestoreInstanceState(android.os.Parcelable);
+ public void onRtlPropertiesChanged(int);
+ protected android.os.Parcelable onSaveInstanceState();
+ public void onScreenStateChanged(int);
+ protected void onScrollChanged(int, int, int, int);
+ protected boolean onSetAlpha(int);
+ protected void onSizeChanged(int, int, int, int);
+ public void onStartTemporaryDetach();
+ public boolean onTouchEvent(android.view.MotionEvent);
+ public boolean onTrackballEvent(android.view.MotionEvent);
+ public void onVisibilityAggregated(boolean);
+ protected void onVisibilityChanged(android.view.View, int);
+ public void onWindowFocusChanged(boolean);
+ public void onWindowSystemUiVisibilityChanged(int);
+ protected void onWindowVisibilityChanged(int);
+ public void outputDirtyFlags(java.lang.String, boolean, int);
+ protected boolean overScrollBy(int, int, int, int, int, int, int, int, boolean);
+ public boolean performAccessibilityAction(int, android.os.Bundle);
+ public boolean performAccessibilityActionInternal(int, android.os.Bundle);
+ protected boolean performButtonActionOnTouchDown(android.view.MotionEvent);
+ public boolean performClick();
+ public boolean performContextClick(float, float);
+ public boolean performContextClick();
+ public boolean performHapticFeedback(int);
+ public boolean performHapticFeedback(int, int);
+ public boolean performLongClick();
+ public boolean performLongClick(float, float);
+ public void playSoundEffect(int);
+ public boolean pointInView(float, float, float);
+ public boolean post(java.lang.Runnable);
+ public boolean postDelayed(java.lang.Runnable, long);
+ public void postInvalidate();
+ public void postInvalidate(int, int, int, int);
+ public void postInvalidateDelayed(long);
+ public void postInvalidateDelayed(long, int, int, int, int);
+ public void postInvalidateOnAnimation();
+ public void postInvalidateOnAnimation(int, int, int, int);
+ public void postOnAnimation(java.lang.Runnable);
+ public void postOnAnimationDelayed(java.lang.Runnable, long);
+ protected void recomputePadding();
+ public void refreshDrawableState();
+ public void releasePointerCapture();
+ public boolean removeCallbacks(java.lang.Runnable);
+ public void removeFrameMetricsListener(android.view.Window$OnFrameMetricsAvailableListener);
+ public void removeOnAttachStateChangeListener(android.view.View$OnAttachStateChangeListener);
+ public void removeOnLayoutChangeListener(android.view.View$OnLayoutChangeListener);
+ public void removeOnUnhandledKeyEventListener(android.view.View$OnUnhandledKeyEventListener);
+ public boolean requestAccessibilityFocus();
+ public void requestApplyInsets();
+ public void requestFitSystemWindows();
+ public boolean requestFocus();
+ public boolean requestFocus(int);
+ public boolean requestFocus(int, android.graphics.Rect);
+ public boolean requestFocusFromTouch();
+ public void requestKeyboardShortcuts(java.util.List, int);
+ public void requestLayout();
+ public void requestPointerCapture();
+ public boolean requestRectangleOnScreen(android.graphics.Rect);
+ public boolean requestRectangleOnScreen(android.graphics.Rect, boolean);
+ public void requestUnbufferedDispatch(android.view.MotionEvent);
+ public android.view.View requireViewById(int);
+ public void resetPaddingToInitialValues();
+ public void resetPivot();
+ protected void resetResolvedDrawables();
+ public void resetResolvedLayoutDirection();
+ public void resetResolvedPadding();
+ public void resetResolvedTextAlignment();
+ public void resetResolvedTextDirection();
+ public void resetRtlProperties();
+ protected void resolveDrawables();
+ public boolean resolveLayoutDirection();
+ public void resolveLayoutParams();
+ public void resolvePadding();
+ public boolean resolveRtlPropertiesIfNeeded();
+ public static int resolveSize(int, int);
+ public static int resolveSizeAndState(int, int, int);
+ public boolean resolveTextAlignment();
+ public boolean resolveTextDirection();
+ public boolean restoreDefaultFocus();
+ public boolean restoreFocusInCluster(int);
+ public boolean restoreFocusNotInCluster();
+ public void restoreHierarchyState(android.util.SparseArray);
+ public void saveHierarchyState(android.util.SparseArray);
+ public void scheduleDrawable(android.graphics.drawable.Drawable, java.lang.Runnable, long);
+ public void scrollBy(int, int);
+ public void scrollTo(int, int);
+ public void sendAccessibilityEvent(int);
+ public void sendAccessibilityEventInternal(int);
+ public void sendAccessibilityEventUnchecked(android.view.accessibility.AccessibilityEvent);
+ public void sendAccessibilityEventUncheckedInternal(android.view.accessibility.AccessibilityEvent);
+ public void setAccessibilityDelegate(android.view.View$AccessibilityDelegate);
+ public void setAccessibilityHeading(boolean);
+ public void setAccessibilityLiveRegion(int);
+ public void setAccessibilityPaneTitle(java.lang.CharSequence);
+ public void setAccessibilitySelection(int, int);
+ public void setAccessibilityTraversalAfter(int);
+ public void setAccessibilityTraversalBefore(int);
+ public void setActivated(boolean);
+ public void setAlpha(float);
+ public void setAnimation(android.view.animation.Animation);
+ public void setAnimationMatrix(android.graphics.Matrix);
+ public void setAssistBlocked(boolean);
+ public void setAutofillHints(java.lang.String[]);
+ public void setAutofillId(android.view.autofill.AutofillId);
+ public void setAutofilled(boolean);
+ public void setBackground(android.graphics.drawable.Drawable);
+ public void setBackgroundColor(int);
+ public void setBackgroundDrawable(android.graphics.drawable.Drawable);
+ public void setBackgroundResource(int);
+ public void setBackgroundTintList(android.content.res.ColorStateList);
+ public void setBackgroundTintMode(android.graphics.PorterDuff$Mode);
+ public void setBottom(int);
+ public void setCameraDistance(float);
+ public void setClickable(boolean);
+ public void setClipBounds(android.graphics.Rect);
+ public void setClipToOutline(boolean);
+ public void setContentDescription(java.lang.CharSequence);
+ public void setContextClickable(boolean);
+ public void setDefaultFocusHighlightEnabled(boolean);
+ public void setDisabledSystemUiVisibility(int);
+ public void setDrawingCacheBackgroundColor(int);
+ public void setDrawingCacheEnabled(boolean);
+ public void setDrawingCacheQuality(int);
+ public void setDuplicateParentStateEnabled(boolean);
+ public void setElevation(float);
+ public void setEnabled(boolean);
+ public void setFadingEdgeLength(int);
+ public void setFilterTouchesWhenObscured(boolean);
+ public void setFitsSystemWindows(boolean);
+ public void setFocusable(boolean);
+ public void setFocusable(int);
+ public void setFocusableInTouchMode(boolean);
+ public void setFocusedByDefault(boolean);
+ public void setFocusedInCluster();
+ public void setForeground(android.graphics.drawable.Drawable);
+ public void setForegroundGravity(int);
+ public void setForegroundTintList(android.content.res.ColorStateList);
+ public void setForegroundTintMode(android.graphics.PorterDuff$Mode);
+ protected boolean setFrame(int, int, int, int);
+ public void setHapticFeedbackEnabled(boolean);
+ public void setHasTransientState(boolean);
+ public void setHorizontalFadingEdgeEnabled(boolean);
+ public void setHorizontalScrollBarEnabled(boolean);
+ public void setHovered(boolean);
+ public void setId(int);
+ public void setImportantForAccessibility(int);
+ public void setImportantForAutofill(int);
+ public void setIsRootNamespace(boolean);
+ public void setKeepScreenOn(boolean);
+ public void setKeyboardNavigationCluster(boolean);
+ public void setLabelFor(int);
+ public void setLayerPaint(android.graphics.Paint);
+ public void setLayerType(int, android.graphics.Paint);
+ public void setLayoutDirection(int);
+ public void setLayoutParams(android.view.ViewGroup$LayoutParams);
+ public void setLeft(int);
+ public void setLeftTopRightBottom(int, int, int, int);
+ public void setLongClickable(boolean);
+ protected void setMeasuredDimension(int, int);
+ public void setMinimumHeight(int);
+ public void setMinimumWidth(int);
+ public void setNestedScrollingEnabled(boolean);
+ public void setNextClusterForwardId(int);
+ public void setNextFocusDownId(int);
+ public void setNextFocusForwardId(int);
+ public void setNextFocusLeftId(int);
+ public void setNextFocusRightId(int);
+ public void setNextFocusUpId(int);
+ public void setNotifyAutofillManagerOnClick(boolean);
+ public void setOnApplyWindowInsetsListener(android.view.View$OnApplyWindowInsetsListener);
+ public void setOnCapturedPointerListener(android.view.View$OnCapturedPointerListener);
+ public void setOnClickListener(android.view.View$OnClickListener);
+ public void setOnContextClickListener(android.view.View$OnContextClickListener);
+ public void setOnCreateContextMenuListener(android.view.View$OnCreateContextMenuListener);
+ public void setOnDragListener(android.view.View$OnDragListener);
+ public void setOnFocusChangeListener(android.view.View$OnFocusChangeListener);
+ public void setOnGenericMotionListener(android.view.View$OnGenericMotionListener);
+ public void setOnHoverListener(android.view.View$OnHoverListener);
+ public void setOnKeyListener(android.view.View$OnKeyListener);
+ public void setOnLongClickListener(android.view.View$OnLongClickListener);
+ public void setOnScrollChangeListener(android.view.View$OnScrollChangeListener);
+ public void setOnSystemUiVisibilityChangeListener(android.view.View$OnSystemUiVisibilityChangeListener);
+ public void setOnTouchListener(android.view.View$OnTouchListener);
+ public void setOpticalInsets(android.graphics.Insets);
+ public void setOutlineAmbientShadowColor(int);
+ public void setOutlineProvider(android.view.ViewOutlineProvider);
+ public void setOutlineSpotShadowColor(int);
+ public void setOverScrollMode(int);
+ public void setPadding(int, int, int, int);
+ public void setPaddingRelative(int, int, int, int);
+ public void setPivotX(float);
+ public void setPivotY(float);
+ public void setPointerIcon(android.view.PointerIcon);
+ public void setPressed(boolean);
+ public void setRevealClip(boolean, float, float, float);
+ public void setRevealOnFocusHint(boolean);
+ public void setRight(int);
+ public void setRotation(float);
+ public void setRotationX(float);
+ public void setRotationY(float);
+ public void setSaveEnabled(boolean);
+ public void setSaveFromParentEnabled(boolean);
+ public void setScaleX(float);
+ public void setScaleY(float);
+ public void setScreenReaderFocusable(boolean);
+ public void setScrollBarDefaultDelayBeforeFade(int);
+ public void setScrollBarFadeDuration(int);
+ public void setScrollBarSize(int);
+ public void setScrollBarStyle(int);
+ public void setScrollContainer(boolean);
+ public void setScrollIndicators(int);
+ public void setScrollIndicators(int, int);
+ public void setScrollX(int);
+ public void setScrollY(int);
+ public void setScrollbarFadingEnabled(boolean);
+ public void setSelected(boolean);
+ public void setSoundEffectsEnabled(boolean);
+ public void setStateListAnimator(android.animation.StateListAnimator);
+ public void setSystemUiVisibility(int);
+ public void setTag(java.lang.Object);
+ public void setTag(int, java.lang.Object);
+ public void setTagInternal(int, java.lang.Object);
+ public void setTextAlignment(int);
+ public void setTextDirection(int);
+ public void setTooltip(java.lang.CharSequence);
+ public void setTooltipText(java.lang.CharSequence);
+ public void setTop(int);
+ public void setTouchDelegate(android.view.TouchDelegate);
+ public void setTransitionAlpha(float);
+ public void setTransitionName(java.lang.String);
+ public void setTransitionVisibility(int);
+ public void setTranslationX(float);
+ public void setTranslationY(float);
+ public void setTranslationZ(float);
+ public void setVerticalFadingEdgeEnabled(boolean);
+ public void setVerticalScrollBarEnabled(boolean);
+ public void setVerticalScrollbarPosition(int);
+ public void setVisibility(int);
+ public void setWillNotCacheDrawing(boolean);
+ public void setWillNotDraw(boolean);
+ public void setX(float);
+ public void setY(float);
+ public void setZ(float);
+ public boolean showContextMenu();
+ public boolean showContextMenu(float, float);
+ public android.view.ActionMode startActionMode(android.view.ActionMode$Callback);
+ public android.view.ActionMode startActionMode(android.view.ActionMode$Callback, int);
+ public void startActivityForResult(android.content.Intent, int);
+ public void startAnimation(android.view.animation.Animation);
+ public boolean startDrag(android.content.ClipData, android.view.View$DragShadowBuilder, java.lang.Object, int);
+ public boolean startDragAndDrop(android.content.ClipData, android.view.View$DragShadowBuilder, java.lang.Object, int);
+ public boolean startMovingTask(float, float);
+ public boolean startNestedScroll(int);
+ public void stopNestedScroll();
+ public boolean toGlobalMotionEvent(android.view.MotionEvent);
+ public boolean toLocalMotionEvent(android.view.MotionEvent);
+ public java.lang.String toString();
+ public void transformFromViewToWindowSpace(int[]);
+ public void transformMatrixToGlobal(android.graphics.Matrix);
+ public void transformMatrixToLocal(android.graphics.Matrix);
+ public void unscheduleDrawable(android.graphics.drawable.Drawable, java.lang.Runnable);
+ public void unscheduleDrawable(android.graphics.drawable.Drawable);
+ public android.view.RenderNode updateDisplayListIfDirty();
+ public void updateDragShadow(android.view.View$DragShadowBuilder);
+ protected boolean verifyDrawable(android.graphics.drawable.Drawable);
+ public boolean willNotCacheDrawing();
+ public boolean willNotDraw();
+
+
+ public static int ACCESSIBILITY_CURSOR_POSITION_UNDEFINED;
+ public static int ACCESSIBILITY_LIVE_REGION_ASSERTIVE;
+ public static int ACCESSIBILITY_LIVE_REGION_NONE;
+ public static int ACCESSIBILITY_LIVE_REGION_POLITE;
+ public static android.util.Property ALPHA;
+ public static int AUTOFILL_FLAG_INCLUDE_NOT_IMPORTANT_VIEWS;
+ public static java.lang.String AUTOFILL_HINT_CREDIT_CARD_EXPIRATION_DATE;
+ public static java.lang.String AUTOFILL_HINT_CREDIT_CARD_EXPIRATION_DAY;
+ public static java.lang.String AUTOFILL_HINT_CREDIT_CARD_EXPIRATION_MONTH;
+ public static java.lang.String AUTOFILL_HINT_CREDIT_CARD_EXPIRATION_YEAR;
+ public static java.lang.String AUTOFILL_HINT_CREDIT_CARD_NUMBER;
+ public static java.lang.String AUTOFILL_HINT_CREDIT_CARD_SECURITY_CODE;
+ public static java.lang.String AUTOFILL_HINT_EMAIL_ADDRESS;
+ public static java.lang.String AUTOFILL_HINT_NAME;
+ public static java.lang.String AUTOFILL_HINT_PASSWORD;
+ public static java.lang.String AUTOFILL_HINT_PHONE;
+ public static java.lang.String AUTOFILL_HINT_POSTAL_ADDRESS;
+ public static java.lang.String AUTOFILL_HINT_POSTAL_CODE;
+ public static java.lang.String AUTOFILL_HINT_USERNAME;
+ public static int AUTOFILL_TYPE_DATE;
+ public static int AUTOFILL_TYPE_LIST;
+ public static int AUTOFILL_TYPE_NONE;
+ public static int AUTOFILL_TYPE_TEXT;
+ public static int AUTOFILL_TYPE_TOGGLE;
+ public static boolean DEBUG_DRAW;
+ public static java.lang.String DEBUG_LAYOUT_PROPERTY;
+ public static int DRAG_FLAG_GLOBAL;
+ public static int DRAG_FLAG_GLOBAL_PERSISTABLE_URI_PERMISSION;
+ public static int DRAG_FLAG_GLOBAL_PREFIX_URI_PERMISSION;
+ public static int DRAG_FLAG_GLOBAL_URI_READ;
+ public static int DRAG_FLAG_GLOBAL_URI_WRITE;
+ public static int DRAG_FLAG_OPAQUE;
+ public static int DRAWING_CACHE_QUALITY_AUTO;
+ public static int DRAWING_CACHE_QUALITY_HIGH;
+ public static int DRAWING_CACHE_QUALITY_LOW;
+ protected static int[] EMPTY_STATE_SET;
+ protected static int[] ENABLED_FOCUSED_SELECTED_STATE_SET;
+ protected static int[] ENABLED_FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET;
+ protected static int[] ENABLED_FOCUSED_STATE_SET;
+ protected static int[] ENABLED_FOCUSED_WINDOW_FOCUSED_STATE_SET;
+ protected static int[] ENABLED_SELECTED_STATE_SET;
+ protected static int[] ENABLED_SELECTED_WINDOW_FOCUSED_STATE_SET;
+ protected static int[] ENABLED_STATE_SET;
+ protected static int[] ENABLED_WINDOW_FOCUSED_STATE_SET;
+ public static int FIND_VIEWS_WITH_ACCESSIBILITY_NODE_PROVIDERS;
+ public static int FIND_VIEWS_WITH_CONTENT_DESCRIPTION;
+ public static int FIND_VIEWS_WITH_TEXT;
+ public static int FOCUSABLE;
+ public static int FOCUSABLES_ALL;
+ public static int FOCUSABLES_TOUCH_MODE;
+ public static int FOCUSABLE_AUTO;
+ protected static int[] FOCUSED_SELECTED_STATE_SET;
+ protected static int[] FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET;
+ protected static int[] FOCUSED_STATE_SET;
+ protected static int[] FOCUSED_WINDOW_FOCUSED_STATE_SET;
+ public static int FOCUS_BACKWARD;
+ public static int FOCUS_DOWN;
+ public static int FOCUS_FORWARD;
+ public static int FOCUS_LEFT;
+ public static int FOCUS_RIGHT;
+ public static int FOCUS_UP;
+ public static int GONE;
+ public static int HAPTIC_FEEDBACK_ENABLED;
+ public static int IMPORTANT_FOR_ACCESSIBILITY_AUTO;
+ public static int IMPORTANT_FOR_ACCESSIBILITY_NO;
+ public static int IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS;
+ public static int IMPORTANT_FOR_ACCESSIBILITY_YES;
+ public static int IMPORTANT_FOR_AUTOFILL_AUTO;
+ public static int IMPORTANT_FOR_AUTOFILL_NO;
+ public static int IMPORTANT_FOR_AUTOFILL_NO_EXCLUDE_DESCENDANTS;
+ public static int IMPORTANT_FOR_AUTOFILL_YES;
+ public static int IMPORTANT_FOR_AUTOFILL_YES_EXCLUDE_DESCENDANTS;
+ public static int INVISIBLE;
+ public static int KEEP_SCREEN_ON;
+ public static int LAST_APP_AUTOFILL_ID;
+ public static int LAYER_TYPE_HARDWARE;
+ public static int LAYER_TYPE_NONE;
+ public static int LAYER_TYPE_SOFTWARE;
+ public static int LAYOUT_DIRECTION_INHERIT;
+ public static int LAYOUT_DIRECTION_LOCALE;
+ public static int LAYOUT_DIRECTION_LTR;
+ public static int LAYOUT_DIRECTION_RTL;
+ public static int LAYOUT_DIRECTION_UNDEFINED;
+ public static int MEASURED_HEIGHT_STATE_SHIFT;
+ public static int MEASURED_SIZE_MASK;
+ public static int MEASURED_STATE_MASK;
+ public static int MEASURED_STATE_TOO_SMALL;
+ public static int NAVIGATION_BAR_TRANSIENT;
+ public static int NAVIGATION_BAR_TRANSLUCENT;
+ public static int NAVIGATION_BAR_TRANSPARENT;
+ public static int NAVIGATION_BAR_UNHIDE;
+ public static int NOT_FOCUSABLE;
+ public static int NO_ID;
+ public static int OVER_SCROLL_ALWAYS;
+ public static int OVER_SCROLL_IF_CONTENT_SCROLLS;
+ public static int OVER_SCROLL_NEVER;
+ protected static int[] PRESSED_ENABLED_FOCUSED_SELECTED_STATE_SET;
+ protected static int[] PRESSED_ENABLED_FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET;
+ protected static int[] PRESSED_ENABLED_FOCUSED_STATE_SET;
+ protected static int[] PRESSED_ENABLED_FOCUSED_WINDOW_FOCUSED_STATE_SET;
+ protected static int[] PRESSED_ENABLED_SELECTED_STATE_SET;
+ protected static int[] PRESSED_ENABLED_SELECTED_WINDOW_FOCUSED_STATE_SET;
+ protected static int[] PRESSED_ENABLED_STATE_SET;
+ protected static int[] PRESSED_ENABLED_WINDOW_FOCUSED_STATE_SET;
+ protected static int[] PRESSED_FOCUSED_SELECTED_STATE_SET;
+ protected static int[] PRESSED_FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET;
+ protected static int[] PRESSED_FOCUSED_STATE_SET;
+ protected static int[] PRESSED_FOCUSED_WINDOW_FOCUSED_STATE_SET;
+ protected static int[] PRESSED_SELECTED_STATE_SET;
+ protected static int[] PRESSED_SELECTED_WINDOW_FOCUSED_STATE_SET;
+ protected static int[] PRESSED_STATE_SET;
+ protected static int[] PRESSED_WINDOW_FOCUSED_STATE_SET;
+ public static int PUBLIC_STATUS_BAR_VISIBILITY_MASK;
+ public static android.util.Property ROTATION;
+ public static android.util.Property ROTATION_X;
+ public static android.util.Property ROTATION_Y;
+ public static android.util.Property SCALE_X;
+ public static android.util.Property SCALE_Y;
+ public static int SCREEN_STATE_OFF;
+ public static int SCREEN_STATE_ON;
+ public static int SCROLLBARS_INSIDE_INSET;
+ public static int SCROLLBARS_INSIDE_OVERLAY;
+ public static int SCROLLBARS_OUTSIDE_INSET;
+ public static int SCROLLBARS_OUTSIDE_OVERLAY;
+ public static int SCROLLBAR_POSITION_DEFAULT;
+ public static int SCROLLBAR_POSITION_LEFT;
+ public static int SCROLLBAR_POSITION_RIGHT;
+ public static int SCROLL_AXIS_HORIZONTAL;
+ public static int SCROLL_AXIS_NONE;
+ public static int SCROLL_AXIS_VERTICAL;
+ public static int SCROLL_INDICATOR_BOTTOM;
+ public static int SCROLL_INDICATOR_END;
+ public static int SCROLL_INDICATOR_LEFT;
+ public static int SCROLL_INDICATOR_RIGHT;
+ public static int SCROLL_INDICATOR_START;
+ public static int SCROLL_INDICATOR_TOP;
+ protected static int[] SELECTED_STATE_SET;
+ protected static int[] SELECTED_WINDOW_FOCUSED_STATE_SET;
+ public static int SOUND_EFFECTS_ENABLED;
+ public static int STATUS_BAR_DISABLE_BACK;
+ public static int STATUS_BAR_DISABLE_CLOCK;
+ public static int STATUS_BAR_DISABLE_EXPAND;
+ public static int STATUS_BAR_DISABLE_HOME;
+ public static int STATUS_BAR_DISABLE_NOTIFICATION_ALERTS;
+ public static int STATUS_BAR_DISABLE_NOTIFICATION_ICONS;
+ public static int STATUS_BAR_DISABLE_NOTIFICATION_TICKER;
+ public static int STATUS_BAR_DISABLE_RECENT;
+ public static int STATUS_BAR_DISABLE_SEARCH;
+ public static int STATUS_BAR_DISABLE_SYSTEM_INFO;
+ public static int STATUS_BAR_HIDDEN;
+ public static int STATUS_BAR_TRANSIENT;
+ public static int STATUS_BAR_TRANSLUCENT;
+ public static int STATUS_BAR_TRANSPARENT;
+ public static int STATUS_BAR_UNHIDE;
+ public static int STATUS_BAR_VISIBLE;
+ public static int SYSTEM_UI_CLEARABLE_FLAGS;
+ public static int SYSTEM_UI_FLAG_FULLSCREEN;
+ public static int SYSTEM_UI_FLAG_HIDE_NAVIGATION;
+ public static int SYSTEM_UI_FLAG_IMMERSIVE;
+ public static int SYSTEM_UI_FLAG_IMMERSIVE_STICKY;
+ public static int SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN;
+ public static int SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION;
+ public static int SYSTEM_UI_FLAG_LAYOUT_STABLE;
+ public static int SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR;
+ public static int SYSTEM_UI_FLAG_LIGHT_STATUS_BAR;
+ public static int SYSTEM_UI_FLAG_LOW_PROFILE;
+ public static int SYSTEM_UI_FLAG_VISIBLE;
+ public static int SYSTEM_UI_LAYOUT_FLAGS;
+ public static int SYSTEM_UI_TRANSPARENT;
+ public static int TEXT_ALIGNMENT_CENTER;
+ public static int TEXT_ALIGNMENT_GRAVITY;
+ public static int TEXT_ALIGNMENT_INHERIT;
+ public static int TEXT_ALIGNMENT_TEXT_END;
+ public static int TEXT_ALIGNMENT_TEXT_START;
+ public static int TEXT_ALIGNMENT_VIEW_END;
+ public static int TEXT_ALIGNMENT_VIEW_START;
+ public static int TEXT_DIRECTION_ANY_RTL;
+ public static int TEXT_DIRECTION_FIRST_STRONG;
+ public static int TEXT_DIRECTION_FIRST_STRONG_LTR;
+ public static int TEXT_DIRECTION_FIRST_STRONG_RTL;
+ public static int TEXT_DIRECTION_INHERIT;
+ public static int TEXT_DIRECTION_LOCALE;
+ public static int TEXT_DIRECTION_LTR;
+ public static int TEXT_DIRECTION_RTL;
+ public static android.util.Property TRANSLATION_X;
+ public static android.util.Property TRANSLATION_Y;
+ public static android.util.Property TRANSLATION_Z;
+ protected static java.lang.String VIEW_LOG_TAG;
+ public static int VISIBLE;
+ protected static int[] WINDOW_FOCUSED_STATE_SET;
+ public static android.util.Property X;
+ public static android.util.Property Y;
+ public static android.util.Property Z;
+ public java.lang.String[] mAttributes;
+ protected int mBottom;
+ public boolean mCachingFailed;
+ protected android.content.Context mContext;
+ protected android.view.animation.Animation mCurrentAnimation;
+ public static boolean mDebugViewAttributes;
+ protected android.view.InputEventConsistencyVerifier mInputEventConsistencyVerifier;
+ protected android.view.ViewGroup$LayoutParams mLayoutParams;
+ protected int mLeft;
+ protected int mPaddingBottom;
+ protected int mPaddingLeft;
+ protected int mPaddingRight;
+ protected int mPaddingTop;
+ protected android.view.ViewParent mParent;
+ public int mPrivateFlags;
+ protected int mRight;
+ protected int mScrollX;
+ protected int mScrollY;
+ protected java.lang.Object mTag;
+ protected int mTop;
+ public android.view.View$TransformationInfo mTransformationInfo;
+ protected int mUserPaddingBottom;
+ protected int mUserPaddingLeft;
+ protected int mUserPaddingRight;
+ protected static boolean sPreserveMarginParamsInLayoutParamConversion;
+}
+
+-keep class android.view.View$AccessibilityDelegate {
+ <init>();
+
+ public void addExtraDataToAccessibilityNodeInfo(android.view.View, android.view.accessibility.AccessibilityNodeInfo, java.lang.String, android.os.Bundle);
+ public android.view.accessibility.AccessibilityNodeInfo createAccessibilityNodeInfo(android.view.View);
+ public boolean dispatchPopulateAccessibilityEvent(android.view.View, android.view.accessibility.AccessibilityEvent);
+ public android.view.accessibility.AccessibilityNodeProvider getAccessibilityNodeProvider(android.view.View);
+ public void onInitializeAccessibilityEvent(android.view.View, android.view.accessibility.AccessibilityEvent);
+ public void onInitializeAccessibilityNodeInfo(android.view.View, android.view.accessibility.AccessibilityNodeInfo);
+ public void onPopulateAccessibilityEvent(android.view.View, android.view.accessibility.AccessibilityEvent);
+ public boolean onRequestSendAccessibilityEvent(android.view.ViewGroup, android.view.View, android.view.accessibility.AccessibilityEvent);
+ public boolean performAccessibilityAction(android.view.View, int, android.os.Bundle);
+ public void sendAccessibilityEvent(android.view.View, int);
+ public void sendAccessibilityEventUnchecked(android.view.View, android.view.accessibility.AccessibilityEvent);
+
+
+}
+
+-keep class android.view.View$AttachInfo {
+
+
+
+ public android.view.Surface mDragSurface;
+}
+
+-keep class android.view.View$AttachInfo$InvalidateInfo {
+
+ public static android.view.View$AttachInfo$InvalidateInfo obtain();
+ public void recycle();
+
+
+}
+
+-keep class android.view.View$DragShadowBuilder {
+ <init>(android.view.View);
+ <init>();
+
+ public android.view.View getView();
+ public void onDrawShadow(android.graphics.Canvas);
+ public void onProvideShadowMetrics(android.graphics.Point, android.graphics.Point);
+
+
+}
+
+-keep class android.view.View$OnApplyWindowInsetsListener {
+
+ public abstract android.view.WindowInsets onApplyWindowInsets(android.view.View, android.view.WindowInsets);
+
+
+}
+
+-keep class android.view.View$OnAttachStateChangeListener {
+
+ public abstract void onViewAttachedToWindow(android.view.View);
+ public abstract void onViewDetachedFromWindow(android.view.View);
+
+
+}
+
+-keep class android.view.View$OnCapturedPointerListener {
+
+ public abstract boolean onCapturedPointer(android.view.View, android.view.MotionEvent);
+
+
+}
+
+-keep class android.view.View$OnClickListener {
+
+ public abstract void onClick(android.view.View);
+
+
+}
+
+-keep class android.view.View$OnContextClickListener {
+
+ public abstract boolean onContextClick(android.view.View);
+
+
+}
+
+-keep class android.view.View$OnCreateContextMenuListener {
+
+ public abstract void onCreateContextMenu(android.view.ContextMenu, android.view.View, android.view.ContextMenu$ContextMenuInfo);
+
+
+}
+
+-keep class android.view.View$OnDragListener {
+
+ public abstract boolean onDrag(android.view.View, android.view.DragEvent);
+
+
+}
+
+-keep class android.view.View$OnFocusChangeListener {
+
+ public abstract void onFocusChange(android.view.View, boolean);
+
+
+}
+
+-keep class android.view.View$OnGenericMotionListener {
+
+ public abstract boolean onGenericMotion(android.view.View, android.view.MotionEvent);
+
+
+}
+
+-keep class android.view.View$OnHoverListener {
+
+ public abstract boolean onHover(android.view.View, android.view.MotionEvent);
+
+
+}
+
+-keep class android.view.View$OnKeyListener {
+
+ public abstract boolean onKey(android.view.View, int, android.view.KeyEvent);
+
+
+}
+
+-keep class android.view.View$OnLayoutChangeListener {
+
+ public abstract void onLayoutChange(android.view.View, int, int, int, int, int, int, int, int);
+
+
+}
+
+-keep class android.view.View$OnLongClickListener {
+
+ public abstract boolean onLongClick(android.view.View);
+
+
+}
+
+-keep class android.view.View$OnScrollChangeListener {
+
+ public abstract void onScrollChange(android.view.View, int, int, int, int);
+
+
+}
+
+-keep class android.view.View$OnSystemUiVisibilityChangeListener {
+
+ public abstract void onSystemUiVisibilityChange(int);
+
+
+}
+
+-keep class android.view.View$OnTouchListener {
+
+ public abstract boolean onTouch(android.view.View, android.view.MotionEvent);
+
+
+}
+
+-keep class android.view.View$OnUnhandledKeyEventListener {
+
+ public abstract boolean onUnhandledKeyEvent(android.view.View, android.view.KeyEvent);
+
+
+}
+
+-keep class android.view.View$TransformationInfo {
+
+
+
+}
+
+-keep class android.view.ViewDebug {
+ <init>();
+
+ public static void capture(android.view.View, java.io.OutputStream, android.view.View);
+ public static void captureLayers(android.view.View, java.io.DataOutputStream);
+ public static void dump(android.view.View, boolean, boolean, java.io.OutputStream);
+ public static void dumpCapturedView(java.lang.String, java.lang.Object);
+ public static void dumpTheme(android.view.View, java.io.OutputStream);
+ public static void dumpv2(android.view.View, java.io.ByteArrayOutputStream);
+ public static android.view.View findView(android.view.View, java.lang.String);
+ public static java.lang.String flagsToString(java.lang.Class, java.lang.String, int);
+ public static long getViewInstanceCount();
+ public static long getViewRootImplCount();
+ public static java.lang.String intToString(java.lang.Class, java.lang.String, int);
+ public static java.lang.Object invokeViewMethod(android.view.View, java.lang.reflect.Method, java.lang.Object[]);
+ public static void outputDisplayList(android.view.View, android.view.View);
+ public static void profileViewAndChildren(android.view.View, java.io.BufferedWriter);
+ public static void setLayoutParameter(android.view.View, java.lang.String, int);
+ public static void startHierarchyTracing(java.lang.String, android.view.View);
+ public static void startRecyclerTracing(java.lang.String, android.view.View);
+ public static void stopHierarchyTracing();
+ public static void stopRecyclerTracing();
+ public static void trace(android.view.View, android.view.ViewDebug$RecyclerTraceType, int[]);
+ public static void trace(android.view.View, android.view.ViewDebug$HierarchyTraceType);
+
+
+ public static boolean DEBUG_DRAG;
+ public static boolean DEBUG_POSITIONING;
+ public static boolean TRACE_HIERARCHY;
+ public static boolean TRACE_RECYCLER;
+}
+
+-keep class android.view.ViewDebug$CanvasProvider {
+
+ public abstract android.graphics.Bitmap createBitmap();
+ public abstract android.graphics.Canvas getCanvas(android.view.View, int, int);
+
+
+}
+
+-keep class android.view.ViewDebug$HierarchyTraceType {
+
+ public static android.view.ViewDebug$HierarchyTraceType valueOf(java.lang.String);
+ public static android.view.ViewDebug$HierarchyTraceType[] values();
+
+ public static android.view.ViewDebug$HierarchyTraceType BUILD_CACHE;
+ public static android.view.ViewDebug$HierarchyTraceType DRAW;
+ public static android.view.ViewDebug$HierarchyTraceType INVALIDATE;
+ public static android.view.ViewDebug$HierarchyTraceType INVALIDATE_CHILD;
+ public static android.view.ViewDebug$HierarchyTraceType INVALIDATE_CHILD_IN_PARENT;
+ public static android.view.ViewDebug$HierarchyTraceType ON_LAYOUT;
+ public static android.view.ViewDebug$HierarchyTraceType ON_MEASURE;
+ public static android.view.ViewDebug$HierarchyTraceType REQUEST_LAYOUT;
+
+}
+
+-keep class android.view.ViewDebug$RecyclerTraceType {
+
+ public static android.view.ViewDebug$RecyclerTraceType valueOf(java.lang.String);
+ public static android.view.ViewDebug$RecyclerTraceType[] values();
+
+ public static android.view.ViewDebug$RecyclerTraceType BIND_VIEW;
+ public static android.view.ViewDebug$RecyclerTraceType MOVE_FROM_ACTIVE_TO_SCRAP_HEAP;
+ public static android.view.ViewDebug$RecyclerTraceType MOVE_TO_SCRAP_HEAP;
+ public static android.view.ViewDebug$RecyclerTraceType NEW_VIEW;
+ public static android.view.ViewDebug$RecyclerTraceType RECYCLE_FROM_ACTIVE_HEAP;
+ public static android.view.ViewDebug$RecyclerTraceType RECYCLE_FROM_SCRAP_HEAP;
+
+}
+
+-keep class android.view.ViewGroup {
+ <init>(android.content.Context);
+ <init>(android.content.Context, android.util.AttributeSet);
+ <init>(android.content.Context, android.util.AttributeSet, int);
+ <init>(android.content.Context, android.util.AttributeSet, int, int);
+
+ public void addChildrenForAccessibility(java.util.ArrayList);
+ public void addFocusables(java.util.ArrayList, int, int);
+ public void addKeyboardNavigationClusters(java.util.Collection, int);
+ public boolean addStatesFromChildren();
+ public void addTouchables(java.util.ArrayList);
+ public void addTransientView(android.view.View, int);
+ public void addView(android.view.View);
+ public void addView(android.view.View, int);
+ public void addView(android.view.View, int, int);
+ public void addView(android.view.View, android.view.ViewGroup$LayoutParams);
+ public void addView(android.view.View, int, android.view.ViewGroup$LayoutParams);
+ protected boolean addViewInLayout(android.view.View, int, android.view.ViewGroup$LayoutParams);
+ protected boolean addViewInLayout(android.view.View, int, android.view.ViewGroup$LayoutParams, boolean);
+ protected void attachLayoutAnimationParameters(android.view.View, android.view.ViewGroup$LayoutParams, int, int);
+ protected void attachViewToParent(android.view.View, int, android.view.ViewGroup$LayoutParams);
+ public void bringChildToFront(android.view.View);
+ public java.util.ArrayList buildTouchDispatchChildList();
+ protected boolean canAnimate();
+ public void captureTransitioningViews(java.util.List);
+ protected boolean checkLayoutParams(android.view.ViewGroup$LayoutParams);
+ public void childDrawableStateChanged(android.view.View);
+ public void childHasTransientStateChanged(android.view.View, boolean);
+ protected void cleanupLayoutState(android.view.View);
+ public void clearChildFocus(android.view.View);
+ public void clearDisappearingChildren();
+ public void clearFocus();
+ public android.graphics.Bitmap createSnapshot(android.view.ViewDebug$CanvasProvider, boolean);
+ protected void debug(int);
+ protected void destroyHardwareResources();
+ protected void detachAllViewsFromParent();
+ protected void detachViewFromParent(android.view.View);
+ protected void detachViewFromParent(int);
+ protected void detachViewsFromParent(int, int);
+ public boolean dispatchActivityResult(java.lang.String, int, int, android.content.Intent);
+ public android.view.WindowInsets dispatchApplyWindowInsets(android.view.WindowInsets);
+ public boolean dispatchCapturedPointerEvent(android.view.MotionEvent);
+ public void dispatchConfigurationChanged(android.content.res.Configuration);
+ public void dispatchDisplayHint(int);
+ public boolean dispatchDragEvent(android.view.DragEvent);
+ protected void dispatchDraw(android.graphics.Canvas);
+ public void dispatchDrawableHotspotChanged(float, float);
+ public void dispatchFinishTemporaryDetach();
+ protected void dispatchFreezeSelfOnly(android.util.SparseArray);
+ protected boolean dispatchGenericFocusedEvent(android.view.MotionEvent);
+ protected boolean dispatchGenericPointerEvent(android.view.MotionEvent);
+ protected void dispatchGetDisplayList();
+ protected boolean dispatchHoverEvent(android.view.MotionEvent);
+ public boolean dispatchKeyEvent(android.view.KeyEvent);
+ public boolean dispatchKeyEventPreIme(android.view.KeyEvent);
+ public boolean dispatchKeyShortcutEvent(android.view.KeyEvent);
+ public void dispatchPointerCaptureChanged(boolean);
+ public boolean dispatchPopulateAccessibilityEventInternal(android.view.accessibility.AccessibilityEvent);
+ public void dispatchProvideAutofillStructure(android.view.ViewStructure, int);
+ public void dispatchProvideStructure(android.view.ViewStructure);
+ protected void dispatchRestoreInstanceState(android.util.SparseArray);
+ protected void dispatchSaveInstanceState(android.util.SparseArray);
+ public void dispatchSetActivated(boolean);
+ protected void dispatchSetPressed(boolean);
+ public void dispatchSetSelected(boolean);
+ public void dispatchStartTemporaryDetach();
+ public void dispatchSystemUiVisibilityChanged(int);
+ protected void dispatchThawSelfOnly(android.util.SparseArray);
+ public boolean dispatchTouchEvent(android.view.MotionEvent);
+ public boolean dispatchTrackballEvent(android.view.MotionEvent);
+ public boolean dispatchUnhandledMove(android.view.View, int);
+ protected void dispatchVisibilityChanged(android.view.View, int);
+ public void dispatchWindowFocusChanged(boolean);
+ public void dispatchWindowSystemUiVisiblityChanged(int);
+ public void dispatchWindowVisibilityChanged(int);
+ protected boolean drawChild(android.graphics.Canvas, android.view.View, long);
+ protected void drawableStateChanged();
+ protected void encodeProperties(android.view.ViewHierarchyEncoder);
+ public void endViewTransition(android.view.View);
+ public android.view.View findFocus();
+ public void findNamedViews(java.util.Map);
+ public android.view.View findViewByAccessibilityIdTraversal(int);
+ public android.view.View findViewByAutofillIdTraversal(int);
+ protected android.view.View findViewByPredicateTraversal(java.util.function.Predicate, android.view.View);
+ protected android.view.View findViewTraversal(int);
+ protected android.view.View findViewWithTagTraversal(java.lang.Object);
+ public void findViewsWithText(java.util.ArrayList, java.lang.CharSequence, int);
+ public android.view.View focusSearch(android.view.View, int);
+ public void focusableViewAvailable(android.view.View);
+ public boolean gatherTransparentRegion(android.graphics.Region);
+ protected android.view.ViewGroup$LayoutParams generateDefaultLayoutParams();
+ public android.view.ViewGroup$LayoutParams generateLayoutParams(android.util.AttributeSet);
+ protected android.view.ViewGroup$LayoutParams generateLayoutParams(android.view.ViewGroup$LayoutParams);
+ public java.lang.CharSequence getAccessibilityClassName();
+ public android.view.View getChildAt(int);
+ public int getChildCount();
+ protected int getChildDrawingOrder(int, int);
+ public static int getChildMeasureSpec(int, int, int);
+ protected boolean getChildStaticTransformation(android.view.View, android.view.animation.Transformation);
+ public boolean getChildVisibleRect(android.view.View, android.graphics.Rect, android.graphics.Point);
+ public boolean getChildVisibleRect(android.view.View, android.graphics.Rect, android.graphics.Point, boolean);
+ public boolean getClipChildren();
+ public boolean getClipToPadding();
+ public int getDescendantFocusability();
+ public android.view.View getFocusedChild();
+ public android.view.animation.LayoutAnimationController getLayoutAnimation();
+ public android.view.animation.Animation$AnimationListener getLayoutAnimationListener();
+ public int getLayoutMode();
+ public android.animation.LayoutTransition getLayoutTransition();
+ public int getNestedScrollAxes();
+ public android.view.ViewGroupOverlay getOverlay();
+ public android.view.ViewOverlay getOverlay();
+ public int getPersistentDrawingCache();
+ public boolean getTouchscreenBlocksFocus();
+ public android.view.View getTransientView(int);
+ public int getTransientViewCount();
+ public int getTransientViewIndex(int);
+ public boolean hasFocus();
+ protected boolean hasHoveredChild();
+ public boolean hasTransientState();
+ public int indexOfChild(android.view.View);
+ protected void internalSetPadding(int, int, int, int);
+ public void invalidateChild(android.view.View, android.graphics.Rect);
+ public android.view.ViewParent invalidateChildInParent(int[], android.graphics.Rect);
+ public boolean isAlwaysDrawnWithCacheEnabled();
+ public boolean isAnimationCacheEnabled();
+ protected boolean isChildrenDrawingOrderEnabled();
+ protected boolean isChildrenDrawnWithCacheEnabled();
+ public boolean isLayoutSuppressed();
+ public boolean isMotionEventSplittingEnabled();
+ public boolean isShowingContextMenuWithCoords();
+ protected boolean isTransformedTouchPointInView(float, float, android.view.View, android.graphics.PointF);
+ public boolean isTransitionGroup();
+ public void jumpDrawablesToCurrentState();
+ public void layout(int, int, int, int);
+ public void makeOptionalFitsSystemWindows();
+ protected void measureChild(android.view.View, int, int);
+ protected void measureChildWithMargins(android.view.View, int, int, int, int);
+ protected void measureChildren(int, int);
+ public void notifySubtreeAccessibilityStateChanged(android.view.View, android.view.View, int);
+ public void notifySubtreeAccessibilityStateChangedIfNeeded();
+ public void offsetChildrenTopAndBottom(int);
+ public void offsetDescendantRectToMyCoords(android.view.View, android.graphics.Rect);
+ public void offsetRectIntoDescendantCoords(android.view.View, android.graphics.Rect);
+ protected void onAttachedToWindow();
+ protected void onChildVisibilityChanged(android.view.View, int, int);
+ protected int[] onCreateDrawableState(int);
+ protected void onDebugDraw(android.graphics.Canvas);
+ protected void onDebugDrawMargins(android.graphics.Canvas, android.graphics.Paint);
+ public void onDescendantInvalidated(android.view.View, android.view.View);
+ protected void onDetachedFromWindow();
+ public void onInitializeAccessibilityNodeInfoInternal(android.view.accessibility.AccessibilityNodeInfo);
+ public boolean onInterceptHoverEvent(android.view.MotionEvent);
+ public boolean onInterceptTouchEvent(android.view.MotionEvent);
+ protected abstract void onLayout(boolean, int, int, int, int);
+ public boolean onNestedFling(android.view.View, float, float, boolean);
+ public boolean onNestedPreFling(android.view.View, float, float);
+ public boolean onNestedPrePerformAccessibilityAction(android.view.View, int, android.os.Bundle);
+ public void onNestedPreScroll(android.view.View, int, int, int[]);
+ public void onNestedScroll(android.view.View, int, int, int, int);
+ public void onNestedScrollAccepted(android.view.View, android.view.View, int);
+ protected boolean onRequestFocusInDescendants(int, android.graphics.Rect);
+ public boolean onRequestSendAccessibilityEvent(android.view.View, android.view.accessibility.AccessibilityEvent);
+ public boolean onRequestSendAccessibilityEventInternal(android.view.View, android.view.accessibility.AccessibilityEvent);
+ public android.view.PointerIcon onResolvePointerIcon(android.view.MotionEvent, int);
+ protected void onSetLayoutParams(android.view.View, android.view.ViewGroup$LayoutParams);
+ public boolean onStartNestedScroll(android.view.View, android.view.View, int);
+ public void onStopNestedScroll(android.view.View);
+ public void onViewAdded(android.view.View);
+ public void onViewRemoved(android.view.View);
+ public void recomputeViewAttributes(android.view.View);
+ public void removeAllViews();
+ public void removeAllViewsInLayout();
+ protected void removeDetachedView(android.view.View, boolean);
+ public void removeTransientView(android.view.View);
+ public void removeView(android.view.View);
+ public void removeViewAt(int);
+ public void removeViewInLayout(android.view.View);
+ public void removeViews(int, int);
+ public void removeViewsInLayout(int, int);
+ public void requestChildFocus(android.view.View, android.view.View);
+ public boolean requestChildRectangleOnScreen(android.view.View, android.graphics.Rect, boolean);
+ public void requestDisallowInterceptTouchEvent(boolean);
+ public boolean requestFocus(int, android.graphics.Rect);
+ public boolean requestSendAccessibilityEvent(android.view.View, android.view.accessibility.AccessibilityEvent);
+ public void requestTransitionStart(android.animation.LayoutTransition);
+ public void requestTransparentRegion(android.view.View);
+ protected void resetResolvedDrawables();
+ public void resetResolvedLayoutDirection();
+ public void resetResolvedPadding();
+ public void resetResolvedTextAlignment();
+ public void resetResolvedTextDirection();
+ protected void resolveDrawables();
+ public boolean resolveLayoutDirection();
+ public void resolveLayoutParams();
+ public void resolvePadding();
+ public boolean resolveRtlPropertiesIfNeeded();
+ public boolean resolveTextAlignment();
+ public boolean resolveTextDirection();
+ public boolean restoreDefaultFocus();
+ public boolean restoreFocusInCluster(int);
+ public boolean restoreFocusNotInCluster();
+ public void scheduleLayoutAnimation();
+ public void setAddStatesFromChildren(boolean);
+ public void setAlwaysDrawnWithCacheEnabled(boolean);
+ public void setAnimationCacheEnabled(boolean);
+ protected void setChildrenDrawingCacheEnabled(boolean);
+ protected void setChildrenDrawingOrderEnabled(boolean);
+ protected void setChildrenDrawnWithCacheEnabled(boolean);
+ public void setClipChildren(boolean);
+ public void setClipToPadding(boolean);
+ public void setDescendantFocusability(int);
+ public void setLayoutAnimation(android.view.animation.LayoutAnimationController);
+ public void setLayoutAnimationListener(android.view.animation.Animation$AnimationListener);
+ public void setLayoutMode(int);
+ public void setLayoutTransition(android.animation.LayoutTransition);
+ public void setMotionEventSplittingEnabled(boolean);
+ public void setOnHierarchyChangeListener(android.view.ViewGroup$OnHierarchyChangeListener);
+ public void setPersistentDrawingCache(int);
+ protected void setStaticTransformationsEnabled(boolean);
+ public void setTouchscreenBlocksFocus(boolean);
+ public void setTransitionGroup(boolean);
+ public boolean shouldDelayChildPressedState();
+ public boolean showContextMenuForChild(android.view.View);
+ public boolean showContextMenuForChild(android.view.View, float, float);
+ public android.view.ActionMode startActionModeForChild(android.view.View, android.view.ActionMode$Callback);
+ public android.view.ActionMode startActionModeForChild(android.view.View, android.view.ActionMode$Callback, int);
+ public void startLayoutAnimation();
+ public void startViewTransition(android.view.View);
+ public void suppressLayout(boolean);
+ public void transformPointToViewLocal(float[], android.view.View);
+ public void updateViewLayout(android.view.View, android.view.ViewGroup$LayoutParams);
+
+
+ protected static int CLIP_TO_PADDING_MASK;
+ protected static int FLAG_DISALLOW_INTERCEPT;
+ protected static int FLAG_SUPPORT_STATIC_TRANSFORMATIONS;
+ protected static int FLAG_USE_CHILD_DRAWING_ORDER;
+ public static int FOCUS_AFTER_DESCENDANTS;
+ public static int FOCUS_BEFORE_DESCENDANTS;
+ public static int FOCUS_BLOCK_DESCENDANTS;
+ public static int LAYOUT_MODE_CLIP_BOUNDS;
+ public static int LAYOUT_MODE_DEFAULT;
+ public static int LAYOUT_MODE_OPTICAL_BOUNDS;
+ public static int PERSISTENT_ALL_CACHES;
+ public static int PERSISTENT_ANIMATION_CACHE;
+ public static int PERSISTENT_NO_CACHE;
+ public static int PERSISTENT_SCROLLING_CACHE;
+ protected java.util.ArrayList mDisappearingChildren;
+ protected int mGroupFlags;
+ protected android.view.ViewGroup$OnHierarchyChangeListener mOnHierarchyChangeListener;
+ protected int mPersistentDrawingCache;
+}
+
+-keep class android.view.ViewGroup$LayoutParams {
+ <init>(android.content.Context, android.util.AttributeSet);
+ <init>(int, int);
+ <init>(android.view.ViewGroup$LayoutParams);
+
+ public java.lang.String debug(java.lang.String);
+ protected void encodeProperties(android.view.ViewHierarchyEncoder);
+ public void onDebugDraw(android.view.View, android.graphics.Canvas, android.graphics.Paint);
+ public void resolveLayoutDirection(int);
+ protected void setBaseAttributes(android.content.res.TypedArray, int, int);
+ protected static java.lang.String sizeToString(int);
+
+
+ public static int FILL_PARENT;
+ public static int MATCH_PARENT;
+ public static int WRAP_CONTENT;
+ public int height;
+ public android.view.animation.LayoutAnimationController$AnimationParameters layoutAnimationParameters;
+ public int width;
+}
+
+-keep class android.view.ViewGroup$MarginLayoutParams {
+ <init>(android.content.Context, android.util.AttributeSet);
+ <init>(int, int);
+ <init>(android.view.ViewGroup$MarginLayoutParams);
+ <init>(android.view.ViewGroup$LayoutParams);
+
+ public void copyMarginsFrom(android.view.ViewGroup$MarginLayoutParams);
+ protected void encodeProperties(android.view.ViewHierarchyEncoder);
+ public int getLayoutDirection();
+ public int getMarginEnd();
+ public int getMarginStart();
+ public boolean isLayoutRtl();
+ public boolean isMarginRelative();
+ public void onDebugDraw(android.view.View, android.graphics.Canvas, android.graphics.Paint);
+ public void resolveLayoutDirection(int);
+ public void setLayoutDirection(int);
+ public void setMarginEnd(int);
+ public void setMarginStart(int);
+ public void setMargins(int, int, int, int);
+ public void setMarginsRelative(int, int, int, int);
+
+
+ public static int DEFAULT_MARGIN_RELATIVE;
+ public int bottomMargin;
+ public int leftMargin;
+ public int rightMargin;
+ public int topMargin;
+}
+
+-keep class android.view.ViewGroup$OnHierarchyChangeListener {
+
+ public abstract void onChildViewAdded(android.view.View, android.view.View);
+ public abstract void onChildViewRemoved(android.view.View, android.view.View);
+
+
+}
+
+-keep class android.view.ViewGroupOverlay {
+
+ public void add(android.view.View);
+ public void remove(android.view.View);
+
+
+}
+
+-keep class android.view.ViewHierarchyEncoder {
+ <init>(java.io.ByteArrayOutputStream);
+
+ public void addProperty(java.lang.String, boolean);
+ public void addProperty(java.lang.String, short);
+ public void addProperty(java.lang.String, int);
+ public void addProperty(java.lang.String, float);
+ public void addProperty(java.lang.String, java.lang.String);
+ public void addPropertyKey(java.lang.String);
+ public void beginObject(java.lang.Object);
+ public void endObject();
+ public void endStream();
+
+
+}
+
+-keep class android.view.ViewOutlineProvider {
+ <init>();
+
+ public abstract void getOutline(android.view.View, android.graphics.Outline);
+
+
+ public static android.view.ViewOutlineProvider BACKGROUND;
+ public static android.view.ViewOutlineProvider BOUNDS;
+ public static android.view.ViewOutlineProvider PADDED_BOUNDS;
+}
+
+-keep class android.view.ViewOverlay {
+
+ public void add(android.graphics.drawable.Drawable);
+ public void clear();
+ public void remove(android.graphics.drawable.Drawable);
+
+
+}
+
+-keep class android.view.ViewParent {
+
+ public abstract void bringChildToFront(android.view.View);
+ public abstract boolean canResolveLayoutDirection();
+ public abstract boolean canResolveTextAlignment();
+ public abstract boolean canResolveTextDirection();
+ public abstract void childDrawableStateChanged(android.view.View);
+ public abstract void childHasTransientStateChanged(android.view.View, boolean);
+ public abstract void clearChildFocus(android.view.View);
+ public abstract void createContextMenu(android.view.ContextMenu);
+ public abstract android.view.View focusSearch(android.view.View, int);
+ public abstract void focusableViewAvailable(android.view.View);
+ public abstract boolean getChildVisibleRect(android.view.View, android.graphics.Rect, android.graphics.Point);
+ public abstract int getLayoutDirection();
+ public abstract android.view.ViewParent getParent();
+ public abstract android.view.ViewParent getParentForAccessibility();
+ public abstract int getTextAlignment();
+ public abstract int getTextDirection();
+ public abstract void invalidateChild(android.view.View, android.graphics.Rect);
+ public abstract android.view.ViewParent invalidateChildInParent(int[], android.graphics.Rect);
+ public abstract boolean isLayoutDirectionResolved();
+ public abstract boolean isLayoutRequested();
+ public abstract boolean isTextAlignmentResolved();
+ public abstract boolean isTextDirectionResolved();
+ public abstract android.view.View keyboardNavigationClusterSearch(android.view.View, int);
+ public abstract void notifySubtreeAccessibilityStateChanged(android.view.View, android.view.View, int);
+ public void onDescendantInvalidated(android.view.View, android.view.View);
+ public abstract boolean onNestedFling(android.view.View, float, float, boolean);
+ public abstract boolean onNestedPreFling(android.view.View, float, float);
+ public abstract boolean onNestedPrePerformAccessibilityAction(android.view.View, int, android.os.Bundle);
+ public abstract void onNestedPreScroll(android.view.View, int, int, int[]);
+ public abstract void onNestedScroll(android.view.View, int, int, int, int);
+ public abstract void onNestedScrollAccepted(android.view.View, android.view.View, int);
+ public abstract boolean onStartNestedScroll(android.view.View, android.view.View, int);
+ public abstract void onStopNestedScroll(android.view.View);
+ public abstract void recomputeViewAttributes(android.view.View);
+ public abstract void requestChildFocus(android.view.View, android.view.View);
+ public abstract boolean requestChildRectangleOnScreen(android.view.View, android.graphics.Rect, boolean);
+ public abstract void requestDisallowInterceptTouchEvent(boolean);
+ public abstract void requestFitSystemWindows();
+ public abstract void requestLayout();
+ public abstract boolean requestSendAccessibilityEvent(android.view.View, android.view.accessibility.AccessibilityEvent);
+ public abstract void requestTransparentRegion(android.view.View);
+ public abstract boolean showContextMenuForChild(android.view.View);
+ public abstract boolean showContextMenuForChild(android.view.View, float, float);
+ public abstract android.view.ActionMode startActionModeForChild(android.view.View, android.view.ActionMode$Callback);
+ public abstract android.view.ActionMode startActionModeForChild(android.view.View, android.view.ActionMode$Callback, int);
+
+
+}
+
+-keep class android.view.ViewPropertyAnimator {
+
+ public android.view.ViewPropertyAnimator alpha(float);
+ public android.view.ViewPropertyAnimator alphaBy(float);
+ public void cancel();
+ public long getDuration();
+ public android.animation.TimeInterpolator getInterpolator();
+ public long getStartDelay();
+ public android.view.ViewPropertyAnimator rotation(float);
+ public android.view.ViewPropertyAnimator rotationBy(float);
+ public android.view.ViewPropertyAnimator rotationX(float);
+ public android.view.ViewPropertyAnimator rotationXBy(float);
+ public android.view.ViewPropertyAnimator rotationY(float);
+ public android.view.ViewPropertyAnimator rotationYBy(float);
+ public android.view.ViewPropertyAnimator scaleX(float);
+ public android.view.ViewPropertyAnimator scaleXBy(float);
+ public android.view.ViewPropertyAnimator scaleY(float);
+ public android.view.ViewPropertyAnimator scaleYBy(float);
+ public android.view.ViewPropertyAnimator setDuration(long);
+ public android.view.ViewPropertyAnimator setInterpolator(android.animation.TimeInterpolator);
+ public android.view.ViewPropertyAnimator setListener(android.animation.Animator$AnimatorListener);
+ public android.view.ViewPropertyAnimator setStartDelay(long);
+ public android.view.ViewPropertyAnimator setUpdateListener(android.animation.ValueAnimator$AnimatorUpdateListener);
+ public void start();
+ public android.view.ViewPropertyAnimator translationX(float);
+ public android.view.ViewPropertyAnimator translationXBy(float);
+ public android.view.ViewPropertyAnimator translationY(float);
+ public android.view.ViewPropertyAnimator translationYBy(float);
+ public android.view.ViewPropertyAnimator translationZ(float);
+ public android.view.ViewPropertyAnimator translationZBy(float);
+ public android.view.ViewPropertyAnimator withEndAction(java.lang.Runnable);
+ public android.view.ViewPropertyAnimator withLayer();
+ public android.view.ViewPropertyAnimator withStartAction(java.lang.Runnable);
+ public android.view.ViewPropertyAnimator x(float);
+ public android.view.ViewPropertyAnimator xBy(float);
+ public android.view.ViewPropertyAnimator y(float);
+ public android.view.ViewPropertyAnimator yBy(float);
+ public android.view.ViewPropertyAnimator z(float);
+ public android.view.ViewPropertyAnimator zBy(float);
+
+
+}
+
+-keep class android.view.ViewRootImpl {
+ <init>(android.content.Context, android.view.Display);
+
+ public static void addConfigCallback(android.view.ViewRootImpl$ConfigChangedCallback);
+ public static void addFirstDrawHandler(java.lang.Runnable);
+ public void addWindowCallbacks(android.view.WindowCallbacks);
+ public void bringChildToFront(android.view.View);
+ public boolean canResolveLayoutDirection();
+ public boolean canResolveTextAlignment();
+ public boolean canResolveTextDirection();
+ public void cancelInvalidate(android.view.View);
+ public void childDrawableStateChanged(android.view.View);
+ public void childHasTransientStateChanged(android.view.View, boolean);
+ public void clearChildFocus(android.view.View);
+ public void createContextMenu(android.view.ContextMenu);
+ public void debug();
+ public void detachFunctor(long);
+ public void dispatchAppVisibility(boolean);
+ public void dispatchCheckFocus();
+ public void dispatchCloseSystemDialogs(java.lang.String);
+ public void dispatchDragEvent(android.view.DragEvent);
+ public void dispatchGetNewSurface();
+ public void dispatchInputEvent(android.view.InputEvent);
+ public void dispatchInputEvent(android.view.InputEvent, android.view.InputEventReceiver);
+ public void dispatchInvalidateDelayed(android.view.View, long);
+ public void dispatchInvalidateOnAnimation(android.view.View);
+ public void dispatchInvalidateRectDelayed(android.view.View$AttachInfo$InvalidateInfo, long);
+ public void dispatchInvalidateRectOnAnimation(android.view.View$AttachInfo$InvalidateInfo);
+ public void dispatchKeyFromAutofill(android.view.KeyEvent);
+ public void dispatchKeyFromIme(android.view.KeyEvent);
+ public void dispatchMoved(int, int);
+ public void dispatchPointerCaptureChanged(boolean);
+ public void dispatchRequestKeyboardShortcuts(com.android.internal.os.IResultReceiver, int);
+ public void dispatchSystemUiVisibilityChanged(int, int, int, int);
+ public void dispatchUnhandledInputEvent(android.view.InputEvent);
+ public boolean dispatchUnhandledKeyEvent(android.view.KeyEvent);
+ public void dispatchWindowShown();
+ public void dump(java.lang.String, java.io.FileDescriptor, java.io.PrintWriter, java.lang.String[]);
+ public void dumpGfxInfo(int[]);
+ public android.view.View focusSearch(android.view.View, int);
+ public void focusableViewAvailable(android.view.View);
+ public android.view.View getAccessibilityFocusedHost();
+ public android.view.accessibility.AccessibilityNodeInfo getAccessibilityFocusedVirtualView();
+ public android.view.AccessibilityInteractionController getAccessibilityInteractionController();
+ public boolean getChildVisibleRect(android.view.View, android.graphics.Rect, android.graphics.Point);
+ public int getDisplayId();
+ public int getHeight();
+ public void getLastTouchPoint(android.graphics.Point);
+ public int getLastTouchSource();
+ public int getLayoutDirection();
+ public android.view.ViewParent getParent();
+ public android.view.ViewParent getParentForAccessibility();
+ public int getTextAlignment();
+ public int getTextDirection();
+ public java.lang.CharSequence getTitle();
+ public android.view.View getView();
+ public int getWidth();
+ public int getWindowFlags();
+ public void handleDispatchSystemUiVisibilityChanged(android.view.ViewRootImpl$SystemUiVisibilityInfo);
+ public void handleDispatchWindowShown();
+ public void handleRequestKeyboardShortcuts(com.android.internal.os.IResultReceiver, int);
+ public void invalidateChild(android.view.View, android.graphics.Rect);
+ public android.view.ViewParent invalidateChildInParent(int[], android.graphics.Rect);
+ public static void invokeFunctor(long, boolean);
+ public boolean isLayoutDirectionResolved();
+ public boolean isLayoutRequested();
+ public boolean isTextAlignmentResolved();
+ public boolean isTextDirectionResolved();
+ public static boolean isViewDescendantOf(android.view.View, android.view.View);
+ public android.view.View keyboardNavigationClusterSearch(android.view.View, int);
+ public void loadSystemProperties();
+ public void notifyChildRebuilt();
+ public void notifySubtreeAccessibilityStateChanged(android.view.View, android.view.View, int);
+ public void onDescendantInvalidated(android.view.View, android.view.View);
+ public void onMovedToDisplay(int, android.content.res.Configuration);
+ public boolean onNestedFling(android.view.View, float, float, boolean);
+ public boolean onNestedPreFling(android.view.View, float, float);
+ public boolean onNestedPrePerformAccessibilityAction(android.view.View, int, android.os.Bundle);
+ public void onNestedPreScroll(android.view.View, int, int, int[]);
+ public void onNestedScroll(android.view.View, int, int, int, int);
+ public void onNestedScrollAccepted(android.view.View, android.view.View, int);
+ public void onPostDraw(android.view.DisplayListCanvas);
+ public void onPreDraw(android.view.DisplayListCanvas);
+ public boolean onStartNestedScroll(android.view.View, android.view.View, int);
+ public void onStopNestedScroll(android.view.View);
+ public void onWindowTitleChanged();
+ public boolean performHapticFeedback(int, boolean);
+ public void playSoundEffect(int);
+ public void profile();
+ public void recomputeViewAttributes(android.view.View);
+ public void registerAnimatingRenderNode(android.view.RenderNode);
+ public void registerRtFrameCallback(android.view.ThreadedRenderer$FrameDrawingCallback);
+ public void registerVectorDrawableAnimator(android.graphics.drawable.AnimatedVectorDrawable$VectorDrawableAnimatorRT);
+ public void removeWindowCallbacks(android.view.WindowCallbacks);
+ public void reportActivityRelaunched();
+ public void reportDrawFinish();
+ public void requestChildFocus(android.view.View, android.view.View);
+ public boolean requestChildRectangleOnScreen(android.view.View, android.graphics.Rect, boolean);
+ public void requestDisallowInterceptTouchEvent(boolean);
+ public void requestFitSystemWindows();
+ public void requestInvalidateRootRenderNode();
+ public void requestLayout();
+ public boolean requestSendAccessibilityEvent(android.view.View, android.view.accessibility.AccessibilityEvent);
+ public void requestTransitionStart(android.animation.LayoutTransition);
+ public void requestTransparentRegion(android.view.View);
+ public void requestUpdateConfiguration(android.content.res.Configuration);
+ public void setActivityConfigCallback(android.view.ViewRootImpl$ActivityConfigCallback);
+ public void setDragFocus(android.view.View, android.view.DragEvent);
+ public void setIsAmbientMode(boolean);
+ public void setPausedForTransition(boolean);
+ public void setReportNextDraw();
+ public void setView(android.view.View, android.view.WindowManager$LayoutParams, android.view.View);
+ public boolean showContextMenuForChild(android.view.View);
+ public boolean showContextMenuForChild(android.view.View, float, float);
+ public android.view.ActionMode startActionModeForChild(android.view.View, android.view.ActionMode$Callback);
+ public android.view.ActionMode startActionModeForChild(android.view.View, android.view.ActionMode$Callback, int);
+ public void synthesizeInputEvent(android.view.InputEvent);
+ public void updateConfiguration(int);
+ public void updatePointerIcon(float, float);
+ public void windowFocusChanged(boolean, boolean);
+
+
+ public static java.lang.String PROPERTY_EMULATOR_WIN_OUTSET_BOTTOM_PX;
+ protected android.view.InputEventConsistencyVerifier mInputEventConsistencyVerifier;
+ public boolean mIsAnimating;
+ public android.view.Surface mSurface;
+ public boolean mTraversalScheduled;
+ public android.view.WindowManager$LayoutParams mWindowAttributes;
+}
+
+-keep class android.view.ViewRootImpl$ActivityConfigCallback {
+
+ public abstract void onConfigurationChanged(android.content.res.Configuration, int);
+
+
+}
+
+-keep class android.view.ViewRootImpl$ConfigChangedCallback {
+
+ public abstract void onConfigurationChanged(android.content.res.Configuration);
+
+
+}
+
+-keep class android.view.ViewRootImpl$SystemUiVisibilityInfo {
+
+
+
+}
+
+-keep class android.view.ViewStructure {
+ <init>();
+
+ public abstract int addChildCount(int);
+ public abstract void asyncCommit();
+ public abstract android.view.ViewStructure asyncNewChild(int);
+ public abstract android.view.autofill.AutofillId getAutofillId();
+ public abstract int getChildCount();
+ public abstract android.os.Bundle getExtras();
+ public abstract java.lang.CharSequence getHint();
+ public abstract android.graphics.Rect getTempRect();
+ public abstract java.lang.CharSequence getText();
+ public abstract int getTextSelectionEnd();
+ public abstract int getTextSelectionStart();
+ public abstract boolean hasExtras();
+ public abstract android.view.ViewStructure newChild(int);
+ public abstract android.view.ViewStructure$HtmlInfo$Builder newHtmlInfoBuilder(java.lang.String);
+ public abstract void setAccessibilityFocused(boolean);
+ public abstract void setActivated(boolean);
+ public abstract void setAlpha(float);
+ public abstract void setAssistBlocked(boolean);
+ public abstract void setAutofillHints(java.lang.String[]);
+ public abstract void setAutofillId(android.view.autofill.AutofillId);
+ public abstract void setAutofillId(android.view.autofill.AutofillId, int);
+ public abstract void setAutofillOptions(java.lang.CharSequence[]);
+ public abstract void setAutofillType(int);
+ public abstract void setAutofillValue(android.view.autofill.AutofillValue);
+ public abstract void setCheckable(boolean);
+ public abstract void setChecked(boolean);
+ public abstract void setChildCount(int);
+ public abstract void setClassName(java.lang.String);
+ public abstract void setClickable(boolean);
+ public abstract void setContentDescription(java.lang.CharSequence);
+ public abstract void setContextClickable(boolean);
+ public abstract void setDataIsSensitive(boolean);
+ public abstract void setDimens(int, int, int, int, int, int);
+ public abstract void setElevation(float);
+ public abstract void setEnabled(boolean);
+ public abstract void setFocusable(boolean);
+ public abstract void setFocused(boolean);
+ public abstract void setHint(java.lang.CharSequence);
+ public abstract void setHtmlInfo(android.view.ViewStructure$HtmlInfo);
+ public abstract void setId(int, java.lang.String, java.lang.String, java.lang.String);
+ public void setImportantForAutofill(int);
+ public abstract void setInputType(int);
+ public abstract void setLocaleList(android.os.LocaleList);
+ public abstract void setLongClickable(boolean);
+ public void setMaxTextEms(int);
+ public void setMaxTextLength(int);
+ public void setMinTextEms(int);
+ public abstract void setOpaque(boolean);
+ public abstract void setSelected(boolean);
+ public abstract void setText(java.lang.CharSequence);
+ public abstract void setText(java.lang.CharSequence, int, int);
+ public void setTextIdEntry(java.lang.String);
+ public abstract void setTextLines(int[], int[]);
+ public abstract void setTextStyle(float, int, int, int);
+ public abstract void setTransformation(android.graphics.Matrix);
+ public abstract void setVisibility(int);
+ public abstract void setWebDomain(java.lang.String);
+
+
+}
+
+-keep class android.view.ViewStructure$HtmlInfo {
+ <init>();
+
+ public abstract java.util.List getAttributes();
+ public abstract java.lang.String getTag();
+
+
+}
+
+-keep class android.view.ViewStructure$HtmlInfo$Builder {
+ <init>();
+
+ public abstract android.view.ViewStructure$HtmlInfo$Builder addAttribute(java.lang.String, java.lang.String);
+ public abstract android.view.ViewStructure$HtmlInfo build();
+
+
+}
+
+-keep class android.view.ViewTreeObserver {
+
+ public void addOnComputeInternalInsetsListener(android.view.ViewTreeObserver$OnComputeInternalInsetsListener);
+ public void addOnDrawListener(android.view.ViewTreeObserver$OnDrawListener);
+ public void addOnEnterAnimationCompleteListener(android.view.ViewTreeObserver$OnEnterAnimationCompleteListener);
+ public void addOnGlobalFocusChangeListener(android.view.ViewTreeObserver$OnGlobalFocusChangeListener);
+ public void addOnGlobalLayoutListener(android.view.ViewTreeObserver$OnGlobalLayoutListener);
+ public void addOnPreDrawListener(android.view.ViewTreeObserver$OnPreDrawListener);
+ public void addOnScrollChangedListener(android.view.ViewTreeObserver$OnScrollChangedListener);
+ public void addOnTouchModeChangeListener(android.view.ViewTreeObserver$OnTouchModeChangeListener);
+ public void addOnWindowAttachListener(android.view.ViewTreeObserver$OnWindowAttachListener);
+ public void addOnWindowFocusChangeListener(android.view.ViewTreeObserver$OnWindowFocusChangeListener);
+ public void addOnWindowShownListener(android.view.ViewTreeObserver$OnWindowShownListener);
+ public void dispatchOnDraw();
+ public void dispatchOnEnterAnimationComplete();
+ public void dispatchOnGlobalLayout();
+ public boolean dispatchOnPreDraw();
+ public void dispatchOnWindowShown();
+ public boolean isAlive();
+ public void removeGlobalOnLayoutListener(android.view.ViewTreeObserver$OnGlobalLayoutListener);
+ public void removeOnComputeInternalInsetsListener(android.view.ViewTreeObserver$OnComputeInternalInsetsListener);
+ public void removeOnDrawListener(android.view.ViewTreeObserver$OnDrawListener);
+ public void removeOnEnterAnimationCompleteListener(android.view.ViewTreeObserver$OnEnterAnimationCompleteListener);
+ public void removeOnGlobalFocusChangeListener(android.view.ViewTreeObserver$OnGlobalFocusChangeListener);
+ public void removeOnGlobalLayoutListener(android.view.ViewTreeObserver$OnGlobalLayoutListener);
+ public void removeOnPreDrawListener(android.view.ViewTreeObserver$OnPreDrawListener);
+ public void removeOnScrollChangedListener(android.view.ViewTreeObserver$OnScrollChangedListener);
+ public void removeOnTouchModeChangeListener(android.view.ViewTreeObserver$OnTouchModeChangeListener);
+ public void removeOnWindowAttachListener(android.view.ViewTreeObserver$OnWindowAttachListener);
+ public void removeOnWindowFocusChangeListener(android.view.ViewTreeObserver$OnWindowFocusChangeListener);
+ public void removeOnWindowShownListener(android.view.ViewTreeObserver$OnWindowShownListener);
+
+
+}
+
+-keep class android.view.ViewTreeObserver$InternalInsetsInfo {
+ <init>();
+
+ public boolean equals(java.lang.Object);
+ public int hashCode();
+ public void setTouchableInsets(int);
+
+
+ public static int TOUCHABLE_INSETS_CONTENT;
+ public static int TOUCHABLE_INSETS_FRAME;
+ public static int TOUCHABLE_INSETS_REGION;
+ public static int TOUCHABLE_INSETS_VISIBLE;
+ public android.graphics.Rect contentInsets;
+ public android.graphics.Region touchableRegion;
+ public android.graphics.Rect visibleInsets;
+}
+
+-keep class android.view.ViewTreeObserver$OnComputeInternalInsetsListener {
+
+ public abstract void onComputeInternalInsets(android.view.ViewTreeObserver$InternalInsetsInfo);
+
+
+}
+
+-keep class android.view.ViewTreeObserver$OnDrawListener {
+
+ public abstract void onDraw();
+
+
+}
+
+-keep class android.view.ViewTreeObserver$OnEnterAnimationCompleteListener {
+
+ public abstract void onEnterAnimationComplete();
+
+
+}
+
+-keep class android.view.ViewTreeObserver$OnGlobalFocusChangeListener {
+
+ public abstract void onGlobalFocusChanged(android.view.View, android.view.View);
+
+
+}
+
+-keep class android.view.ViewTreeObserver$OnGlobalLayoutListener {
+
+ public abstract void onGlobalLayout();
+
+
+}
+
+-keep class android.view.ViewTreeObserver$OnPreDrawListener {
+
+ public abstract boolean onPreDraw();
+
+
+}
+
+-keep class android.view.ViewTreeObserver$OnScrollChangedListener {
+
+ public abstract void onScrollChanged();
+
+
+}
+
+-keep class android.view.ViewTreeObserver$OnTouchModeChangeListener {
+
+ public abstract void onTouchModeChanged(boolean);
+
+
+}
+
+-keep class android.view.ViewTreeObserver$OnWindowAttachListener {
+
+ public abstract void onWindowAttached();
+ public abstract void onWindowDetached();
+
+
+}
+
+-keep class android.view.ViewTreeObserver$OnWindowFocusChangeListener {
+
+ public abstract void onWindowFocusChanged(boolean);
+
+
+}
+
+-keep class android.view.ViewTreeObserver$OnWindowShownListener {
+
+ public abstract void onWindowShown();
+
+
+}
+
+-keep class android.view.Window {
+ <init>(android.content.Context);
+
+ public abstract void addContentView(android.view.View, android.view.ViewGroup$LayoutParams);
+ public void addFlags(int);
+ public void addOnFrameMetricsAvailableListener(android.view.Window$OnFrameMetricsAvailableListener, android.os.Handler);
+ public void addPrivateFlags(int);
+ public abstract void alwaysReadCloseOnTouchAttr();
+ public abstract void clearContentView();
+ public void clearFlags(int);
+ public abstract void closeAllPanels();
+ public abstract void closePanel(int);
+ public void destroy();
+ public void dispatchOnWindowDismissed(boolean, boolean);
+ public void dispatchOnWindowSwipeDismissed();
+ protected void dispatchWindowAttributesChanged(android.view.WindowManager$LayoutParams);
+ public android.view.View findViewById(int);
+ public boolean getAllowEnterTransitionOverlap();
+ public boolean getAllowReturnTransitionOverlap();
+ public android.view.WindowManager$LayoutParams getAttributes();
+ public android.view.Window$Callback getCallback();
+ public int getColorMode();
+ public android.view.Window getContainer();
+ public android.transition.Scene getContentScene();
+ public android.content.Context getContext();
+ public abstract android.view.View getCurrentFocus();
+ public abstract android.view.View getDecorView();
+ public static int getDefaultFeatures(android.content.Context);
+ public float getElevation();
+ public android.transition.Transition getEnterTransition();
+ public android.transition.Transition getExitTransition();
+ protected int getFeatures();
+ protected int getForcedWindowFlags();
+ public abstract android.view.LayoutInflater getLayoutInflater();
+ protected int getLocalFeatures();
+ public android.media.session.MediaController getMediaController();
+ public abstract int getNavigationBarColor();
+ public int getNavigationBarDividerColor();
+ public android.transition.Transition getReenterTransition();
+ public android.transition.Transition getReturnTransition();
+ public android.transition.Transition getSharedElementEnterTransition();
+ public android.transition.Transition getSharedElementExitTransition();
+ public android.transition.Transition getSharedElementReenterTransition();
+ public android.transition.Transition getSharedElementReturnTransition();
+ public boolean getSharedElementsUseOverlay();
+ public abstract int getStatusBarColor();
+ public long getTransitionBackgroundFadeDuration();
+ public android.transition.TransitionManager getTransitionManager();
+ public abstract int getVolumeControlStream();
+ public android.view.Window$WindowControllerCallback getWindowControllerCallback();
+ public android.view.WindowManager getWindowManager();
+ public android.content.res.TypedArray getWindowStyle();
+ public boolean hasChildren();
+ public boolean hasFeature(int);
+ protected boolean hasSoftInputMode();
+ protected boolean haveDimAmount();
+ public void injectInputEvent(android.view.InputEvent);
+ public abstract void invalidatePanelMenu(int);
+ public boolean isActive();
+ public boolean isCloseOnSwipeEnabled();
+ public boolean isDestroyed();
+ public abstract boolean isFloating();
+ public boolean isOverlayWithDecorCaptionEnabled();
+ public abstract boolean isShortcutKey(int, android.view.KeyEvent);
+ public boolean isWideColorGamut();
+ public void makeActive();
+ public void notifyRestrictedCaptionAreaCallback(int, int, int, int);
+ protected abstract void onActive();
+ public abstract void onConfigurationChanged(android.content.res.Configuration);
+ public abstract void onMultiWindowModeChanged();
+ public abstract void onPictureInPictureModeChanged(boolean);
+ public abstract void openPanel(int, android.view.KeyEvent);
+ public abstract android.view.View peekDecorView();
+ public abstract boolean performContextMenuIdentifierAction(int, int);
+ public abstract boolean performPanelIdentifierAction(int, int, int);
+ public abstract boolean performPanelShortcut(int, int, android.view.KeyEvent, int);
+ protected void removeFeature(int);
+ public void removeOnFrameMetricsAvailableListener(android.view.Window$OnFrameMetricsAvailableListener);
+ public abstract void reportActivityRelaunched();
+ public boolean requestFeature(int);
+ public android.view.View requireViewById(int);
+ public abstract void restoreHierarchyState(android.os.Bundle);
+ public abstract android.os.Bundle saveHierarchyState();
+ public void setAllowEnterTransitionOverlap(boolean);
+ public void setAllowReturnTransitionOverlap(boolean);
+ public void setAttributes(android.view.WindowManager$LayoutParams);
+ public abstract void setBackgroundDrawable(android.graphics.drawable.Drawable);
+ public void setBackgroundDrawableResource(int);
+ public void setCallback(android.view.Window$Callback);
+ public abstract void setChildDrawable(int, android.graphics.drawable.Drawable);
+ public abstract void setChildInt(int, int);
+ public void setClipToOutline(boolean);
+ public void setCloseOnSwipeEnabled(boolean);
+ public void setCloseOnTouchOutside(boolean);
+ public void setCloseOnTouchOutsideIfNotSet(boolean);
+ public void setColorMode(int);
+ public void setContainer(android.view.Window);
+ public abstract void setContentView(int);
+ public abstract void setContentView(android.view.View);
+ public abstract void setContentView(android.view.View, android.view.ViewGroup$LayoutParams);
+ public abstract void setDecorCaptionShade(int);
+ public void setDefaultIcon(int);
+ public void setDefaultLogo(int);
+ protected void setDefaultWindowFormat(int);
+ public void setDimAmount(float);
+ public void setElevation(float);
+ public void setEnterTransition(android.transition.Transition);
+ public void setExitTransition(android.transition.Transition);
+ public abstract void setFeatureDrawable(int, android.graphics.drawable.Drawable);
+ public abstract void setFeatureDrawableAlpha(int, int);
+ public abstract void setFeatureDrawableResource(int, int);
+ public abstract void setFeatureDrawableUri(int, android.net.Uri);
+ public abstract void setFeatureInt(int, int);
+ public void setFlags(int, int);
+ public void setFormat(int);
+ public void setGravity(int);
+ public void setIcon(int);
+ public void setLayout(int, int);
+ public void setLocalFocus(boolean, boolean);
+ public void setLogo(int);
+ public void setMediaController(android.media.session.MediaController);
+ public abstract void setNavigationBarColor(int);
+ public void setNavigationBarDividerColor(int);
+ protected void setNeedsMenuKey(int);
+ public void setOnWindowDismissedCallback(android.view.Window$OnWindowDismissedCallback);
+ public void setOnWindowSwipeDismissedCallback(android.view.Window$OnWindowSwipeDismissedCallback);
+ public void setOverlayWithDecorCaptionEnabled(boolean);
+ public void setReenterTransition(android.transition.Transition);
+ public abstract void setResizingCaptionDrawable(android.graphics.drawable.Drawable);
+ public void setRestrictedCaptionAreaListener(android.view.Window$OnRestrictedCaptionAreaChangedListener);
+ public void setReturnTransition(android.transition.Transition);
+ public void setSharedElementEnterTransition(android.transition.Transition);
+ public void setSharedElementExitTransition(android.transition.Transition);
+ public void setSharedElementReenterTransition(android.transition.Transition);
+ public void setSharedElementReturnTransition(android.transition.Transition);
+ public void setSharedElementsUseOverlay(boolean);
+ public void setSoftInputMode(int);
+ public abstract void setStatusBarColor(int);
+ public void setSustainedPerformanceMode(boolean);
+ public void setTheme(int);
+ public abstract void setTitle(java.lang.CharSequence);
+ public abstract void setTitleColor(int);
+ public void setTransitionBackgroundFadeDuration(long);
+ public void setTransitionManager(android.transition.TransitionManager);
+ public void setType(int);
+ public void setUiOptions(int);
+ public void setUiOptions(int, int);
+ public abstract void setVolumeControlStream(int);
+ public void setWindowAnimations(int);
+ public void setWindowControllerCallback(android.view.Window$WindowControllerCallback);
+ public void setWindowManager(android.view.WindowManager, android.os.IBinder, java.lang.String);
+ public void setWindowManager(android.view.WindowManager, android.os.IBinder, java.lang.String, boolean);
+ public boolean shouldCloseOnTouch(android.content.Context, android.view.MotionEvent);
+ public abstract boolean superDispatchGenericMotionEvent(android.view.MotionEvent);
+ public abstract boolean superDispatchKeyEvent(android.view.KeyEvent);
+ public abstract boolean superDispatchKeyShortcutEvent(android.view.KeyEvent);
+ public abstract boolean superDispatchTouchEvent(android.view.MotionEvent);
+ public abstract boolean superDispatchTrackballEvent(android.view.MotionEvent);
+ public abstract void takeInputQueue(android.view.InputQueue$Callback);
+ public abstract void takeKeyEvents(boolean);
+ public abstract void takeSurface(android.view.SurfaceHolder$Callback2);
+ public abstract void togglePanel(int, android.view.KeyEvent);
+
+
+ public static int DECOR_CAPTION_SHADE_AUTO;
+ public static int DECOR_CAPTION_SHADE_DARK;
+ public static int DECOR_CAPTION_SHADE_LIGHT;
+ protected static int DEFAULT_FEATURES;
+ public static int FEATURE_ACTION_BAR;
+ public static int FEATURE_ACTION_BAR_OVERLAY;
+ public static int FEATURE_ACTION_MODE_OVERLAY;
+ public static int FEATURE_ACTIVITY_TRANSITIONS;
+ public static int FEATURE_CONTENT_TRANSITIONS;
+ public static int FEATURE_CONTEXT_MENU;
+ public static int FEATURE_CUSTOM_TITLE;
+ public static int FEATURE_INDETERMINATE_PROGRESS;
+ public static int FEATURE_LEFT_ICON;
+ public static int FEATURE_MAX;
+ public static int FEATURE_NO_TITLE;
+ public static int FEATURE_OPTIONS_PANEL;
+ public static int FEATURE_PROGRESS;
+ public static int FEATURE_RIGHT_ICON;
+ public static int FEATURE_SWIPE_TO_DISMISS;
+ public static int ID_ANDROID_CONTENT;
+ public static java.lang.String NAVIGATION_BAR_BACKGROUND_TRANSITION_NAME;
+ public static int PROGRESS_END;
+ public static int PROGRESS_INDETERMINATE_OFF;
+ public static int PROGRESS_INDETERMINATE_ON;
+ public static int PROGRESS_SECONDARY_END;
+ public static int PROGRESS_SECONDARY_START;
+ public static int PROGRESS_START;
+ public static int PROGRESS_VISIBILITY_OFF;
+ public static int PROGRESS_VISIBILITY_ON;
+ public static java.lang.String STATUS_BAR_BACKGROUND_TRANSITION_NAME;
+}
+
+-keep class android.view.Window$Callback {
+
+ public abstract boolean dispatchGenericMotionEvent(android.view.MotionEvent);
+ public abstract boolean dispatchKeyEvent(android.view.KeyEvent);
+ public abstract boolean dispatchKeyShortcutEvent(android.view.KeyEvent);
+ public abstract boolean dispatchPopulateAccessibilityEvent(android.view.accessibility.AccessibilityEvent);
+ public abstract boolean dispatchTouchEvent(android.view.MotionEvent);
+ public abstract boolean dispatchTrackballEvent(android.view.MotionEvent);
+ public abstract void onActionModeFinished(android.view.ActionMode);
+ public abstract void onActionModeStarted(android.view.ActionMode);
+ public abstract void onAttachedToWindow();
+ public abstract void onContentChanged();
+ public abstract boolean onCreatePanelMenu(int, android.view.Menu);
+ public abstract android.view.View onCreatePanelView(int);
+ public abstract void onDetachedFromWindow();
+ public abstract boolean onMenuItemSelected(int, android.view.MenuItem);
+ public abstract boolean onMenuOpened(int, android.view.Menu);
+ public abstract void onPanelClosed(int, android.view.Menu);
+ public void onPointerCaptureChanged(boolean);
+ public abstract boolean onPreparePanel(int, android.view.View, android.view.Menu);
+ public void onProvideKeyboardShortcuts(java.util.List, android.view.Menu, int);
+ public abstract boolean onSearchRequested();
+ public abstract boolean onSearchRequested(android.view.SearchEvent);
+ public abstract void onWindowAttributesChanged(android.view.WindowManager$LayoutParams);
+ public abstract void onWindowFocusChanged(boolean);
+ public abstract android.view.ActionMode onWindowStartingActionMode(android.view.ActionMode$Callback);
+ public abstract android.view.ActionMode onWindowStartingActionMode(android.view.ActionMode$Callback, int);
+
+
+}
+
+-keep class android.view.Window$OnFrameMetricsAvailableListener {
+
+ public abstract void onFrameMetricsAvailable(android.view.Window, android.view.FrameMetrics, int);
+
+
+}
+
+-keep class android.view.Window$OnRestrictedCaptionAreaChangedListener {
+
+ public abstract void onRestrictedCaptionAreaChanged(android.graphics.Rect);
+
+
+}
+
+-keep class android.view.Window$OnWindowDismissedCallback {
+
+ public abstract void onWindowDismissed(boolean, boolean);
+
+
+}
+
+-keep class android.view.Window$OnWindowSwipeDismissedCallback {
+
+ public abstract void onWindowSwipeDismissed();
+
+
+}
+
+-keep class android.view.Window$WindowControllerCallback {
+
+ public abstract void enterPictureInPictureModeIfPossible();
+ public abstract void exitFreeformMode();
+ public abstract boolean isTaskRoot();
+
+
+}
+
+-keep class android.view.WindowAnimationFrameStats {
+ <init>();
+
+ public int describeContents();
+ public void init(long, long[]);
+ public java.lang.String toString();
+ public void writeToParcel(android.os.Parcel, int);
+
+
+ public static android.os.Parcelable$Creator CREATOR;
+}
+
+-keep class android.view.WindowCallbacks {
+
+ public abstract boolean onContentDrawn(int, int, int, int);
+ public abstract void onPostDraw(android.view.DisplayListCanvas);
+ public abstract void onRequestDraw(boolean);
+ public abstract void onWindowDragResizeEnd();
+ public abstract void onWindowDragResizeStart(android.graphics.Rect, boolean, android.graphics.Rect, android.graphics.Rect, int);
+ public abstract void onWindowSizeIsChanging(android.graphics.Rect, boolean, android.graphics.Rect, android.graphics.Rect);
+
+
+ public static int RESIZE_MODE_DOCKED_DIVIDER;
+ public static int RESIZE_MODE_FREEFORM;
+ public static int RESIZE_MODE_INVALID;
+}
+
+-keep class android.view.WindowContentFrameStats {
+ <init>();
+
+ public int describeContents();
+ public long getFramePostedTimeNano(int);
+ public long getFrameReadyTimeNano(int);
+ public void init(long, long[], long[], long[]);
+ public java.lang.String toString();
+ public void writeToParcel(android.os.Parcel, int);
+
+
+ public static android.os.Parcelable$Creator CREATOR;
+}
+
+-keep class android.view.WindowId {
+ <init>(android.view.IWindowId);
+ <init>(android.os.IBinder);
+
+ public int describeContents();
+ public boolean equals(java.lang.Object);
+ public android.view.IWindowId getTarget();
+ public int hashCode();
+ public boolean isFocused();
+ public void registerFocusObserver(android.view.WindowId$FocusObserver);
+ public java.lang.String toString();
+ public void unregisterFocusObserver(android.view.WindowId$FocusObserver);
+ public void writeToParcel(android.os.Parcel, int);
+
+
+ public static android.os.Parcelable$Creator CREATOR;
+}
+
+-keep class android.view.WindowId$FocusObserver {
+ <init>();
+
+ public abstract void onFocusGained(android.view.WindowId);
+ public abstract void onFocusLost(android.view.WindowId);
+
+
+}
+
+-keep class android.view.WindowInsets {
+ <init>(android.graphics.Rect, android.graphics.Rect, android.graphics.Rect, boolean, boolean, android.view.DisplayCutout);
+ <init>(android.view.WindowInsets);
+ <init>(android.graphics.Rect);
+
+ public android.view.WindowInsets consumeDisplayCutout();
+ public android.view.WindowInsets consumeStableInsets();
+ public android.view.WindowInsets consumeSystemWindowInsets();
+ public android.view.WindowInsets consumeSystemWindowInsets(boolean, boolean, boolean, boolean);
+ public android.view.WindowInsets consumeWindowDecorInsets();
+ public android.view.WindowInsets consumeWindowDecorInsets(boolean, boolean, boolean, boolean);
+ public boolean equals(java.lang.Object);
+ public android.view.DisplayCutout getDisplayCutout();
+ public int getStableInsetBottom();
+ public int getStableInsetLeft();
+ public int getStableInsetRight();
+ public int getStableInsetTop();
+ public int getSystemWindowInsetBottom();
+ public int getSystemWindowInsetLeft();
+ public int getSystemWindowInsetRight();
+ public int getSystemWindowInsetTop();
+ public android.graphics.Rect getSystemWindowInsets();
+ public int getWindowDecorInsetBottom();
+ public int getWindowDecorInsetLeft();
+ public int getWindowDecorInsetRight();
+ public int getWindowDecorInsetTop();
+ public boolean hasInsets();
+ public boolean hasStableInsets();
+ public boolean hasSystemWindowInsets();
+ public boolean hasWindowDecorInsets();
+ public int hashCode();
+ public android.view.WindowInsets inset(android.graphics.Rect);
+ public android.view.WindowInsets inset(int, int, int, int);
+ public boolean isConsumed();
+ public boolean isRound();
+ public android.view.WindowInsets replaceSystemWindowInsets(int, int, int, int);
+ public android.view.WindowInsets replaceSystemWindowInsets(android.graphics.Rect);
+ public android.view.WindowInsets replaceWindowDecorInsets(int, int, int, int);
+ public boolean shouldAlwaysConsumeNavBar();
+ public java.lang.String toString();
+
+
+ public static android.view.WindowInsets CONSUMED;
+}
+
+-keep class android.view.WindowManager {
+
+ public abstract android.graphics.Region getCurrentImeTouchRegion();
+ public abstract android.view.Display getDefaultDisplay();
+ public abstract void removeViewImmediate(android.view.View);
+ public abstract void requestAppKeyboardShortcuts(android.view.WindowManager$KeyboardShortcutsReceiver, int);
+
+
+ public static int DOCKED_BOTTOM;
+ public static int DOCKED_INVALID;
+ public static int DOCKED_LEFT;
+ public static int DOCKED_RIGHT;
+ public static int DOCKED_TOP;
+ public static java.lang.String INPUT_CONSUMER_NAVIGATION;
+ public static java.lang.String INPUT_CONSUMER_PIP;
+ public static java.lang.String INPUT_CONSUMER_RECENTS_ANIMATION;
+ public static java.lang.String INPUT_CONSUMER_WALLPAPER;
+ public static java.lang.String PARCEL_KEY_SHORTCUTS_ARRAY;
+ public static int TAKE_SCREENSHOT_FULLSCREEN;
+ public static int TAKE_SCREENSHOT_SELECTED_REGION;
+ public static int TRANSIT_ACTIVITY_CLOSE;
+ public static int TRANSIT_ACTIVITY_OPEN;
+ public static int TRANSIT_ACTIVITY_RELAUNCH;
+ public static int TRANSIT_CRASHING_ACTIVITY_CLOSE;
+ public static int TRANSIT_DOCK_TASK_FROM_RECENTS;
+ public static int TRANSIT_FLAG_KEYGUARD_GOING_AWAY_NO_ANIMATION;
+ public static int TRANSIT_FLAG_KEYGUARD_GOING_AWAY_TO_SHADE;
+ public static int TRANSIT_FLAG_KEYGUARD_GOING_AWAY_WITH_WALLPAPER;
+ public static int TRANSIT_KEYGUARD_GOING_AWAY;
+ public static int TRANSIT_KEYGUARD_GOING_AWAY_ON_WALLPAPER;
+ public static int TRANSIT_KEYGUARD_OCCLUDE;
+ public static int TRANSIT_KEYGUARD_UNOCCLUDE;
+ public static int TRANSIT_NONE;
+ public static int TRANSIT_TASK_CLOSE;
+ public static int TRANSIT_TASK_IN_PLACE;
+ public static int TRANSIT_TASK_OPEN;
+ public static int TRANSIT_TASK_OPEN_BEHIND;
+ public static int TRANSIT_TASK_TO_BACK;
+ public static int TRANSIT_TASK_TO_FRONT;
+ public static int TRANSIT_TRANSLUCENT_ACTIVITY_CLOSE;
+ public static int TRANSIT_TRANSLUCENT_ACTIVITY_OPEN;
+ public static int TRANSIT_UNSET;
+ public static int TRANSIT_WALLPAPER_CLOSE;
+ public static int TRANSIT_WALLPAPER_INTRA_CLOSE;
+ public static int TRANSIT_WALLPAPER_INTRA_OPEN;
+ public static int TRANSIT_WALLPAPER_OPEN;
+}
+
+-keep class android.view.WindowManager$KeyboardShortcutsReceiver {
+
+ public abstract void onKeyboardShortcutsReceived(java.util.List);
+
+
+}
+
+-keep class android.view.WindowManager$LayoutParams {
+ <init>();
+ <init>(int);
+ <init>(int, int);
+ <init>(int, int, int);
+ <init>(int, int, int, int, int);
+ <init>(int, int, int, int, int, int, int);
+ <init>(android.os.Parcel);
+
+ public int copyFrom(android.view.WindowManager$LayoutParams);
+ public java.lang.String debug(java.lang.String);
+ public int describeContents();
+ public void dumpDimensions(java.lang.StringBuilder);
+ protected void encodeProperties(android.view.ViewHierarchyEncoder);
+ public int getColorMode();
+ public java.lang.CharSequence getTitle();
+ public long getUserActivityTimeout();
+ public boolean isFullscreen();
+ public static boolean isSystemAlertWindowType(int);
+ public static boolean mayUseInputMethod(int);
+ public void scale(float);
+ public void setColorMode(int);
+ public void setSurfaceInsets(android.view.View, boolean, boolean);
+ public void setTitle(java.lang.CharSequence);
+ public void setUserActivityTimeout(long);
+ public java.lang.String toString();
+ public java.lang.String toString(java.lang.String);
+ public void writeToParcel(android.os.Parcel, int);
+ public void writeToProto(android.util.proto.ProtoOutputStream, long);
+
+
+ public static int ACCESSIBILITY_ANCHOR_CHANGED;
+ public static int ACCESSIBILITY_TITLE_CHANGED;
+ public static int ALPHA_CHANGED;
+ public static int ANIMATION_CHANGED;
+ public static float BRIGHTNESS_OVERRIDE_FULL;
+ public static float BRIGHTNESS_OVERRIDE_NONE;
+ public static float BRIGHTNESS_OVERRIDE_OFF;
+ public static int BUTTON_BRIGHTNESS_CHANGED;
+ public static int COLOR_MODE_CHANGED;
+ public static android.os.Parcelable$Creator CREATOR;
+ public static int DIM_AMOUNT_CHANGED;
+ public static int EVERYTHING_CHANGED;
+ public static int FIRST_APPLICATION_WINDOW;
+ public static int FIRST_SUB_WINDOW;
+ public static int FIRST_SYSTEM_WINDOW;
+ public static int FLAGS_CHANGED;
+ public static int FLAG_ALLOW_LOCK_WHILE_SCREEN_ON;
+ public static int FLAG_ALT_FOCUSABLE_IM;
+ public static int FLAG_BLUR_BEHIND;
+ public static int FLAG_DIM_BEHIND;
+ public static int FLAG_DISMISS_KEYGUARD;
+ public static int FLAG_DITHER;
+ public static int FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS;
+ public static int FLAG_FORCE_NOT_FULLSCREEN;
+ public static int FLAG_FULLSCREEN;
+ public static int FLAG_HARDWARE_ACCELERATED;
+ public static int FLAG_IGNORE_CHEEK_PRESSES;
+ public static int FLAG_KEEP_SCREEN_ON;
+ public static int FLAG_LAYOUT_ATTACHED_IN_DECOR;
+ public static int FLAG_LAYOUT_INSET_DECOR;
+ public static int FLAG_LAYOUT_IN_OVERSCAN;
+ public static int FLAG_LAYOUT_IN_SCREEN;
+ public static int FLAG_LAYOUT_NO_LIMITS;
+ public static int FLAG_LOCAL_FOCUS_MODE;
+ public static int FLAG_NOT_FOCUSABLE;
+ public static int FLAG_NOT_TOUCHABLE;
+ public static int FLAG_NOT_TOUCH_MODAL;
+ public static int FLAG_SCALED;
+ public static int FLAG_SECURE;
+ public static int FLAG_SHOW_WALLPAPER;
+ public static int FLAG_SHOW_WHEN_LOCKED;
+ public static int FLAG_SLIPPERY;
+ public static int FLAG_SPLIT_TOUCH;
+ public static int FLAG_TOUCHABLE_WHEN_WAKING;
+ public static int FLAG_TRANSLUCENT_NAVIGATION;
+ public static int FLAG_TRANSLUCENT_STATUS;
+ public static int FLAG_TURN_SCREEN_ON;
+ public static int FLAG_WATCH_OUTSIDE_TOUCH;
+ public static int FORMAT_CHANGED;
+ public static int INPUT_FEATURES_CHANGED;
+ public static int INPUT_FEATURE_DISABLE_POINTER_GESTURES;
+ public static int INPUT_FEATURE_DISABLE_USER_ACTIVITY;
+ public static int INPUT_FEATURE_NO_INPUT_CHANNEL;
+ public static int INVALID_WINDOW_TYPE;
+ public static int LAST_APPLICATION_WINDOW;
+ public static int LAST_SUB_WINDOW;
+ public static int LAST_SYSTEM_WINDOW;
+ public static int LAYOUT_CHANGED;
+ public static int LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS;
+ public static int LAYOUT_IN_DISPLAY_CUTOUT_MODE_DEFAULT;
+ public static int LAYOUT_IN_DISPLAY_CUTOUT_MODE_NEVER;
+ public static int LAYOUT_IN_DISPLAY_CUTOUT_MODE_SHORT_EDGES;
+ public static int MEMORY_TYPE_CHANGED;
+ public static int MEMORY_TYPE_GPU;
+ public static int MEMORY_TYPE_HARDWARE;
+ public static int MEMORY_TYPE_NORMAL;
+ public static int MEMORY_TYPE_PUSH_BUFFERS;
+ public static int NEEDS_MENU_KEY_CHANGED;
+ public static int NEEDS_MENU_SET_FALSE;
+ public static int NEEDS_MENU_SET_TRUE;
+ public static int NEEDS_MENU_UNSET;
+ public static int PREFERRED_DISPLAY_MODE_ID;
+ public static int PREFERRED_REFRESH_RATE_CHANGED;
+ public static int PRIVATE_FLAGS_CHANGED;
+ public static int PRIVATE_FLAG_ACQUIRES_SLEEP_TOKEN;
+ public static int PRIVATE_FLAG_COMPATIBLE_WINDOW;
+ public static int PRIVATE_FLAG_DISABLE_WALLPAPER_TOUCH_EVENTS;
+ public static int PRIVATE_FLAG_FAKE_HARDWARE_ACCELERATED;
+ public static int PRIVATE_FLAG_FORCE_DECOR_VIEW_VISIBILITY;
+ public static int PRIVATE_FLAG_FORCE_DRAW_STATUS_BAR_BACKGROUND;
+ public static int PRIVATE_FLAG_FORCE_HARDWARE_ACCELERATED;
+ public static int PRIVATE_FLAG_FORCE_STATUS_BAR_VISIBLE_TRANSPARENT;
+ public static int PRIVATE_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS;
+ public static int PRIVATE_FLAG_INHERIT_TRANSLUCENT_DECOR;
+ public static int PRIVATE_FLAG_IS_ROUNDED_CORNERS_OVERLAY;
+ public static int PRIVATE_FLAG_IS_SCREEN_DECOR;
+ public static int PRIVATE_FLAG_KEYGUARD;
+ public static int PRIVATE_FLAG_LAYOUT_CHILD_WINDOW_IN_PARENT_FRAME;
+ public static int PRIVATE_FLAG_NO_MOVE_ANIMATION;
+ public static int PRIVATE_FLAG_PRESERVE_GEOMETRY;
+ public static int PRIVATE_FLAG_SHOW_FOR_ALL_USERS;
+ public static int PRIVATE_FLAG_SUSTAINED_PERFORMANCE_MODE;
+ public static int PRIVATE_FLAG_SYSTEM_ERROR;
+ public static int PRIVATE_FLAG_WANTS_OFFSET_NOTIFICATIONS;
+ public static int PRIVATE_FLAG_WILL_NOT_REPLACE_ON_RELAUNCH;
+ public static int ROTATION_ANIMATION_CHANGED;
+ public static int ROTATION_ANIMATION_CROSSFADE;
+ public static int ROTATION_ANIMATION_JUMPCUT;
+ public static int ROTATION_ANIMATION_ROTATE;
+ public static int ROTATION_ANIMATION_SEAMLESS;
+ public static int ROTATION_ANIMATION_UNSPECIFIED;
+ public static int SCREEN_BRIGHTNESS_CHANGED;
+ public static int SCREEN_ORIENTATION_CHANGED;
+ public static int SOFT_INPUT_ADJUST_NOTHING;
+ public static int SOFT_INPUT_ADJUST_PAN;
+ public static int SOFT_INPUT_ADJUST_RESIZE;
+ public static int SOFT_INPUT_ADJUST_UNSPECIFIED;
+ public static int SOFT_INPUT_IS_FORWARD_NAVIGATION;
+ public static int SOFT_INPUT_MASK_ADJUST;
+ public static int SOFT_INPUT_MASK_STATE;
+ public static int SOFT_INPUT_MODE_CHANGED;
+ public static int SOFT_INPUT_STATE_ALWAYS_HIDDEN;
+ public static int SOFT_INPUT_STATE_ALWAYS_VISIBLE;
+ public static int SOFT_INPUT_STATE_HIDDEN;
+ public static int SOFT_INPUT_STATE_UNCHANGED;
+ public static int SOFT_INPUT_STATE_UNSPECIFIED;
+ public static int SOFT_INPUT_STATE_VISIBLE;
+ public static int SURFACE_INSETS_CHANGED;
+ public static int SYSTEM_UI_LISTENER_CHANGED;
+ public static int SYSTEM_UI_VISIBILITY_CHANGED;
+ public static int TITLE_CHANGED;
+ public static int TRANSLUCENT_FLAGS_CHANGED;
+ public static int TYPE_ACCESSIBILITY_OVERLAY;
+ public static int TYPE_APPLICATION;
+ public static int TYPE_APPLICATION_ABOVE_SUB_PANEL;
+ public static int TYPE_APPLICATION_ATTACHED_DIALOG;
+ public static int TYPE_APPLICATION_MEDIA;
+ public static int TYPE_APPLICATION_MEDIA_OVERLAY;
+ public static int TYPE_APPLICATION_OVERLAY;
+ public static int TYPE_APPLICATION_PANEL;
+ public static int TYPE_APPLICATION_STARTING;
+ public static int TYPE_APPLICATION_SUB_PANEL;
+ public static int TYPE_BASE_APPLICATION;
+ public static int TYPE_BOOT_PROGRESS;
+ public static int TYPE_CHANGED;
+ public static int TYPE_DISPLAY_OVERLAY;
+ public static int TYPE_DOCK_DIVIDER;
+ public static int TYPE_DRAG;
+ public static int TYPE_DRAWN_APPLICATION;
+ public static int TYPE_DREAM;
+ public static int TYPE_INPUT_CONSUMER;
+ public static int TYPE_INPUT_METHOD;
+ public static int TYPE_INPUT_METHOD_DIALOG;
+ public static int TYPE_KEYGUARD;
+ public static int TYPE_KEYGUARD_DIALOG;
+ public static int TYPE_MAGNIFICATION_OVERLAY;
+ public static int TYPE_NAVIGATION_BAR;
+ public static int TYPE_NAVIGATION_BAR_PANEL;
+ public static int TYPE_PHONE;
+ public static int TYPE_POINTER;
+ public static int TYPE_PRESENTATION;
+ public static int TYPE_PRIORITY_PHONE;
+ public static int TYPE_PRIVATE_PRESENTATION;
+ public static int TYPE_QS_DIALOG;
+ public static int TYPE_SCREENSHOT;
+ public static int TYPE_SEARCH_BAR;
+ public static int TYPE_SECURE_SYSTEM_OVERLAY;
+ public static int TYPE_STATUS_BAR;
+ public static int TYPE_STATUS_BAR_PANEL;
+ public static int TYPE_STATUS_BAR_SUB_PANEL;
+ public static int TYPE_SYSTEM_ALERT;
+ public static int TYPE_SYSTEM_DIALOG;
+ public static int TYPE_SYSTEM_ERROR;
+ public static int TYPE_SYSTEM_OVERLAY;
+ public static int TYPE_TOAST;
+ public static int TYPE_VOICE_INTERACTION;
+ public static int TYPE_VOICE_INTERACTION_STARTING;
+ public static int TYPE_VOLUME_OVERLAY;
+ public static int TYPE_WALLPAPER;
+ public static int USER_ACTIVITY_TIMEOUT_CHANGED;
+ public long accessibilityIdOfAnchor;
+ public java.lang.CharSequence accessibilityTitle;
+ public float alpha;
+ public float buttonBrightness;
+ public float dimAmount;
+ public int flags;
+ public int format;
+ public int gravity;
+ public boolean hasManualSurfaceInsets;
+ public boolean hasSystemUiListeners;
+ public long hideTimeoutMilliseconds;
+ public float horizontalMargin;
+ public float horizontalWeight;
+ public int inputFeatures;
+ public int layoutInDisplayCutoutMode;
+ public int memoryType;
+ public int needsMenuKey;
+ public java.lang.String packageName;
+ public int preferredDisplayModeId;
+ public float preferredRefreshRate;
+ public boolean preservePreviousSurfaceInsets;
+ public int privateFlags;
+ public int rotationAnimation;
+ public float screenBrightness;
+ public int screenOrientation;
+ public int softInputMode;
+ public int subtreeSystemUiVisibility;
+ public android.graphics.Rect surfaceInsets;
+ public int systemUiVisibility;
+ public android.os.IBinder token;
+ public int type;
+ public long userActivityTimeout;
+ public float verticalMargin;
+ public float verticalWeight;
+ public int windowAnimations;
+ public int x;
+ public int y;
+}
+
+-keep class android.view.accessibility.AccessibilityEvent {
+
+ public void appendRecord(android.view.accessibility.AccessibilityRecord);
+ protected void clear();
+ public int describeContents();
+ public static java.lang.String eventTypeToString(int);
+ public int getAction();
+ public int getContentChangeTypes();
+ public long getEventTime();
+ public int getEventType();
+ public int getMovementGranularity();
+ public java.lang.CharSequence getPackageName();
+ public android.view.accessibility.AccessibilityRecord getRecord(int);
+ public int getRecordCount();
+ public int getWindowChanges();
+ public void initFromParcel(android.os.Parcel);
+ public static android.view.accessibility.AccessibilityEvent obtain(int);
+ public static android.view.accessibility.AccessibilityEvent obtain(android.view.accessibility.AccessibilityEvent);
+ public static android.view.accessibility.AccessibilityEvent obtain();
+ public static android.view.accessibility.AccessibilityEvent obtainWindowsChangedEvent(int, int);
+ public void recycle();
+ public void setAction(int);
+ public void setContentChangeTypes(int);
+ public void setEventTime(long);
+ public void setEventType(int);
+ public void setMovementGranularity(int);
+ public void setPackageName(java.lang.CharSequence);
+ public void setSealed(boolean);
+ public void setWindowChanges(int);
+ public java.lang.String toString();
+ public void writeToParcel(android.os.Parcel, int);
+
+
+ public static int CONTENT_CHANGE_TYPE_CONTENT_DESCRIPTION;
+ public static int CONTENT_CHANGE_TYPE_PANE_APPEARED;
+ public static int CONTENT_CHANGE_TYPE_PANE_DISAPPEARED;
+ public static int CONTENT_CHANGE_TYPE_PANE_TITLE;
+ public static int CONTENT_CHANGE_TYPE_SUBTREE;
+ public static int CONTENT_CHANGE_TYPE_TEXT;
+ public static int CONTENT_CHANGE_TYPE_UNDEFINED;
+ public static android.os.Parcelable$Creator CREATOR;
+ public static boolean DEBUG_ORIGIN;
+ public static int INVALID_POSITION;
+ public static int MAX_TEXT_LENGTH;
+ public static int TYPES_ALL_MASK;
+ public static int TYPE_ANNOUNCEMENT;
+ public static int TYPE_ASSIST_READING_CONTEXT;
+ public static int TYPE_GESTURE_DETECTION_END;
+ public static int TYPE_GESTURE_DETECTION_START;
+ public static int TYPE_NOTIFICATION_STATE_CHANGED;
+ public static int TYPE_TOUCH_EXPLORATION_GESTURE_END;
+ public static int TYPE_TOUCH_EXPLORATION_GESTURE_START;
+ public static int TYPE_TOUCH_INTERACTION_END;
+ public static int TYPE_TOUCH_INTERACTION_START;
+ public static int TYPE_VIEW_ACCESSIBILITY_FOCUSED;
+ public static int TYPE_VIEW_ACCESSIBILITY_FOCUS_CLEARED;
+ public static int TYPE_VIEW_CLICKED;
+ public static int TYPE_VIEW_CONTEXT_CLICKED;
+ public static int TYPE_VIEW_FOCUSED;
+ public static int TYPE_VIEW_HOVER_ENTER;
+ public static int TYPE_VIEW_HOVER_EXIT;
+ public static int TYPE_VIEW_LONG_CLICKED;
+ public static int TYPE_VIEW_SCROLLED;
+ public static int TYPE_VIEW_SELECTED;
+ public static int TYPE_VIEW_TEXT_CHANGED;
+ public static int TYPE_VIEW_TEXT_SELECTION_CHANGED;
+ public static int TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY;
+ public static int TYPE_WINDOWS_CHANGED;
+ public static int TYPE_WINDOW_CONTENT_CHANGED;
+ public static int TYPE_WINDOW_STATE_CHANGED;
+ public static int WINDOWS_CHANGE_ACCESSIBILITY_FOCUSED;
+ public static int WINDOWS_CHANGE_ACTIVE;
+ public static int WINDOWS_CHANGE_ADDED;
+ public static int WINDOWS_CHANGE_BOUNDS;
+ public static int WINDOWS_CHANGE_CHILDREN;
+ public static int WINDOWS_CHANGE_FOCUSED;
+ public static int WINDOWS_CHANGE_LAYER;
+ public static int WINDOWS_CHANGE_PARENT;
+ public static int WINDOWS_CHANGE_PIP;
+ public static int WINDOWS_CHANGE_REMOVED;
+ public static int WINDOWS_CHANGE_TITLE;
+ public java.lang.StackTraceElement[] originStackTrace;
+}
+
+-keep class android.view.accessibility.AccessibilityNodeInfo {
+
+ public void addAction(android.view.accessibility.AccessibilityNodeInfo$AccessibilityAction);
+ public void addAction(int);
+ public void addChild(android.view.View);
+ public void addChild(android.view.View, int);
+ public void addChildUnchecked(android.view.View);
+ public boolean canOpenPopup();
+ public int describeContents();
+ protected void enforceNotSealed();
+ protected void enforceSealed();
+ public boolean equals(java.lang.Object);
+ public java.util.List findAccessibilityNodeInfosByText(java.lang.String);
+ public java.util.List findAccessibilityNodeInfosByViewId(java.lang.String);
+ public android.view.accessibility.AccessibilityNodeInfo findFocus(int);
+ public android.view.accessibility.AccessibilityNodeInfo focusSearch(int);
+ public static int getAccessibilityViewId(long);
+ public java.util.List getActionList();
+ public int getActions();
+ public java.util.List getAvailableExtraData();
+ public void getBoundsInParent(android.graphics.Rect);
+ public void getBoundsInScreen(android.graphics.Rect);
+ public android.graphics.Rect getBoundsInScreen();
+ public android.view.accessibility.AccessibilityNodeInfo getChild(int);
+ public int getChildCount();
+ public long getChildId(int);
+ public android.util.LongArray getChildNodeIds();
+ public java.lang.CharSequence getClassName();
+ public android.view.accessibility.AccessibilityNodeInfo$CollectionInfo getCollectionInfo();
+ public android.view.accessibility.AccessibilityNodeInfo$CollectionItemInfo getCollectionItemInfo();
+ public int getConnectionId();
+ public java.lang.CharSequence getContentDescription();
+ public int getDrawingOrder();
+ public java.lang.CharSequence getError();
+ public android.os.Bundle getExtras();
+ public java.lang.CharSequence getHintText();
+ public int getInputType();
+ public android.view.accessibility.AccessibilityNodeInfo getLabelFor();
+ public android.view.accessibility.AccessibilityNodeInfo getLabeledBy();
+ public int getLiveRegion();
+ public int getMaxTextLength();
+ public int getMovementGranularities();
+ public java.lang.CharSequence getOriginalText();
+ public java.lang.CharSequence getPackageName();
+ public java.lang.CharSequence getPaneTitle();
+ public android.view.accessibility.AccessibilityNodeInfo getParent();
+ public long getParentNodeId();
+ public android.view.accessibility.AccessibilityNodeInfo$RangeInfo getRangeInfo();
+ public long getSourceNodeId();
+ public java.lang.CharSequence getText();
+ public int getTextSelectionEnd();
+ public int getTextSelectionStart();
+ public java.lang.CharSequence getTooltipText();
+ public android.view.accessibility.AccessibilityNodeInfo getTraversalAfter();
+ public android.view.accessibility.AccessibilityNodeInfo getTraversalBefore();
+ public java.lang.String getViewIdResourceName();
+ public static int getVirtualDescendantId(long);
+ public android.view.accessibility.AccessibilityWindowInfo getWindow();
+ public int getWindowId();
+ public boolean hasExtras();
+ public int hashCode();
+ public static java.lang.String idToString(long);
+ public boolean isAccessibilityFocused();
+ public boolean isCheckable();
+ public boolean isChecked();
+ public boolean isClickable();
+ public boolean isContentInvalid();
+ public boolean isContextClickable();
+ public boolean isDismissable();
+ public boolean isEditable();
+ public boolean isEnabled();
+ public boolean isFocusable();
+ public boolean isFocused();
+ public boolean isHeading();
+ public boolean isImportantForAccessibility();
+ public boolean isLongClickable();
+ public boolean isMultiLine();
+ public boolean isPassword();
+ public boolean isScreenReaderFocusable();
+ public boolean isScrollable();
+ public boolean isSealed();
+ public boolean isSelected();
+ public boolean isShowingHintText();
+ public boolean isVisibleToUser();
+ public static long makeNodeId(int, int);
+ public static android.view.accessibility.AccessibilityNodeInfo obtain(android.view.View);
+ public static android.view.accessibility.AccessibilityNodeInfo obtain(android.view.View, int);
+ public static android.view.accessibility.AccessibilityNodeInfo obtain();
+ public static android.view.accessibility.AccessibilityNodeInfo obtain(android.view.accessibility.AccessibilityNodeInfo);
+ public boolean performAction(int);
+ public boolean performAction(int, android.os.Bundle);
+ public void recycle();
+ public boolean refresh(android.os.Bundle, boolean);
+ public boolean refresh();
+ public boolean refreshWithExtraData(java.lang.String, android.os.Bundle);
+ public void removeAction(int);
+ public boolean removeAction(android.view.accessibility.AccessibilityNodeInfo$AccessibilityAction);
+ public void removeAllActions();
+ public boolean removeChild(android.view.View);
+ public boolean removeChild(android.view.View, int);
+ public void setAccessibilityFocused(boolean);
+ public void setAvailableExtraData(java.util.List);
+ public void setBoundsInParent(android.graphics.Rect);
+ public void setBoundsInScreen(android.graphics.Rect);
+ public void setCanOpenPopup(boolean);
+ public void setCheckable(boolean);
+ public void setChecked(boolean);
+ public void setClassName(java.lang.CharSequence);
+ public void setClickable(boolean);
+ public void setCollectionInfo(android.view.accessibility.AccessibilityNodeInfo$CollectionInfo);
+ public void setCollectionItemInfo(android.view.accessibility.AccessibilityNodeInfo$CollectionItemInfo);
+ public void setConnectionId(int);
+ public void setContentDescription(java.lang.CharSequence);
+ public void setContentInvalid(boolean);
+ public void setContextClickable(boolean);
+ public void setDismissable(boolean);
+ public void setDrawingOrder(int);
+ public void setEditable(boolean);
+ public void setEnabled(boolean);
+ public void setError(java.lang.CharSequence);
+ public void setFocusable(boolean);
+ public void setFocused(boolean);
+ public void setHeading(boolean);
+ public void setHintText(java.lang.CharSequence);
+ public void setImportantForAccessibility(boolean);
+ public void setInputType(int);
+ public void setLabelFor(android.view.View);
+ public void setLabelFor(android.view.View, int);
+ public void setLabeledBy(android.view.View);
+ public void setLabeledBy(android.view.View, int);
+ public void setLiveRegion(int);
+ public void setLongClickable(boolean);
+ public void setMaxTextLength(int);
+ public void setMovementGranularities(int);
+ public void setMultiLine(boolean);
+ public static void setNumInstancesInUseCounter(java.util.concurrent.atomic.AtomicInteger);
+ public void setPackageName(java.lang.CharSequence);
+ public void setPaneTitle(java.lang.CharSequence);
+ public void setParent(android.view.View);
+ public void setParent(android.view.View, int);
+ public void setPassword(boolean);
+ public void setRangeInfo(android.view.accessibility.AccessibilityNodeInfo$RangeInfo);
+ public void setScreenReaderFocusable(boolean);
+ public void setScrollable(boolean);
+ public void setSealed(boolean);
+ public void setSelected(boolean);
+ public void setShowingHintText(boolean);
+ public void setSource(android.view.View);
+ public void setSource(android.view.View, int);
+ public void setSourceNodeId(long, int);
+ public void setText(java.lang.CharSequence);
+ public void setTextSelection(int, int);
+ public void setTooltipText(java.lang.CharSequence);
+ public void setTraversalAfter(android.view.View);
+ public void setTraversalAfter(android.view.View, int);
+ public void setTraversalBefore(android.view.View);
+ public void setTraversalBefore(android.view.View, int);
+ public void setViewIdResourceName(java.lang.String);
+ public void setVisibleToUser(boolean);
+ public java.lang.String toString();
+ public void writeToParcel(android.os.Parcel, int);
+ public void writeToParcelNoRecycle(android.os.Parcel, int);
+
+
+ public static int ACTION_ACCESSIBILITY_FOCUS;
+ public static java.lang.String ACTION_ARGUMENT_ACCESSIBLE_CLICKABLE_SPAN;
+ public static java.lang.String ACTION_ARGUMENT_COLUMN_INT;
+ public static java.lang.String ACTION_ARGUMENT_EXTEND_SELECTION_BOOLEAN;
+ public static java.lang.String ACTION_ARGUMENT_HTML_ELEMENT_STRING;
+ public static java.lang.String ACTION_ARGUMENT_MOVEMENT_GRANULARITY_INT;
+ public static java.lang.String ACTION_ARGUMENT_MOVE_WINDOW_X;
+ public static java.lang.String ACTION_ARGUMENT_MOVE_WINDOW_Y;
+ public static java.lang.String ACTION_ARGUMENT_PROGRESS_VALUE;
+ public static java.lang.String ACTION_ARGUMENT_ROW_INT;
+ public static java.lang.String ACTION_ARGUMENT_SELECTION_END_INT;
+ public static java.lang.String ACTION_ARGUMENT_SELECTION_START_INT;
+ public static java.lang.String ACTION_ARGUMENT_SET_TEXT_CHARSEQUENCE;
+ public static int ACTION_CLEAR_ACCESSIBILITY_FOCUS;
+ public static int ACTION_CLEAR_FOCUS;
+ public static int ACTION_CLEAR_SELECTION;
+ public static int ACTION_CLICK;
+ public static int ACTION_COLLAPSE;
+ public static int ACTION_COPY;
+ public static int ACTION_CUT;
+ public static int ACTION_DISMISS;
+ public static int ACTION_EXPAND;
+ public static int ACTION_FOCUS;
+ public static int ACTION_LONG_CLICK;
+ public static int ACTION_NEXT_AT_MOVEMENT_GRANULARITY;
+ public static int ACTION_NEXT_HTML_ELEMENT;
+ public static int ACTION_PASTE;
+ public static int ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY;
+ public static int ACTION_PREVIOUS_HTML_ELEMENT;
+ public static int ACTION_SCROLL_BACKWARD;
+ public static int ACTION_SCROLL_FORWARD;
+ public static int ACTION_SELECT;
+ public static int ACTION_SET_SELECTION;
+ public static int ACTION_SET_TEXT;
+ public static android.os.Parcelable$Creator CREATOR;
+ public static java.lang.String EXTRA_DATA_REQUESTED_KEY;
+ public static java.lang.String EXTRA_DATA_TEXT_CHARACTER_LOCATION_ARG_LENGTH;
+ public static java.lang.String EXTRA_DATA_TEXT_CHARACTER_LOCATION_ARG_START_INDEX;
+ public static java.lang.String EXTRA_DATA_TEXT_CHARACTER_LOCATION_KEY;
+ public static int FLAG_INCLUDE_NOT_IMPORTANT_VIEWS;
+ public static int FLAG_PREFETCH_DESCENDANTS;
+ public static int FLAG_PREFETCH_PREDECESSORS;
+ public static int FLAG_PREFETCH_SIBLINGS;
+ public static int FLAG_REPORT_VIEW_IDS;
+ public static int FOCUS_ACCESSIBILITY;
+ public static int FOCUS_INPUT;
+ public static int LAST_LEGACY_STANDARD_ACTION;
+ public static int MOVEMENT_GRANULARITY_CHARACTER;
+ public static int MOVEMENT_GRANULARITY_LINE;
+ public static int MOVEMENT_GRANULARITY_PAGE;
+ public static int MOVEMENT_GRANULARITY_PARAGRAPH;
+ public static int MOVEMENT_GRANULARITY_WORD;
+ public static int ROOT_ITEM_ID;
+ public static long ROOT_NODE_ID;
+ public static int UNDEFINED_CONNECTION_ID;
+ public static int UNDEFINED_ITEM_ID;
+ public static long UNDEFINED_NODE_ID;
+ public static int UNDEFINED_SELECTION_INDEX;
+}
+
+-keep class android.view.accessibility.AccessibilityNodeInfo$AccessibilityAction {
+ <init>(int, java.lang.CharSequence);
+
+ public boolean equals(java.lang.Object);
+ public int getId();
+ public java.lang.CharSequence getLabel();
+ public int hashCode();
+ public java.lang.String toString();
+
+
+ public static android.view.accessibility.AccessibilityNodeInfo$AccessibilityAction ACTION_ACCESSIBILITY_FOCUS;
+ public static android.view.accessibility.AccessibilityNodeInfo$AccessibilityAction ACTION_CLEAR_ACCESSIBILITY_FOCUS;
+ public static android.view.accessibility.AccessibilityNodeInfo$AccessibilityAction ACTION_CLEAR_FOCUS;
+ public static android.view.accessibility.AccessibilityNodeInfo$AccessibilityAction ACTION_CLEAR_SELECTION;
+ public static android.view.accessibility.AccessibilityNodeInfo$AccessibilityAction ACTION_CLICK;
+ public static android.view.accessibility.AccessibilityNodeInfo$AccessibilityAction ACTION_COLLAPSE;
+ public static android.view.accessibility.AccessibilityNodeInfo$AccessibilityAction ACTION_CONTEXT_CLICK;
+ public static android.view.accessibility.AccessibilityNodeInfo$AccessibilityAction ACTION_COPY;
+ public static android.view.accessibility.AccessibilityNodeInfo$AccessibilityAction ACTION_CUT;
+ public static android.view.accessibility.AccessibilityNodeInfo$AccessibilityAction ACTION_DISMISS;
+ public static android.view.accessibility.AccessibilityNodeInfo$AccessibilityAction ACTION_EXPAND;
+ public static android.view.accessibility.AccessibilityNodeInfo$AccessibilityAction ACTION_FOCUS;
+ public static android.view.accessibility.AccessibilityNodeInfo$AccessibilityAction ACTION_HIDE_TOOLTIP;
+ public static android.view.accessibility.AccessibilityNodeInfo$AccessibilityAction ACTION_LONG_CLICK;
+ public static android.view.accessibility.AccessibilityNodeInfo$AccessibilityAction ACTION_MOVE_WINDOW;
+ public static android.view.accessibility.AccessibilityNodeInfo$AccessibilityAction ACTION_NEXT_AT_MOVEMENT_GRANULARITY;
+ public static android.view.accessibility.AccessibilityNodeInfo$AccessibilityAction ACTION_NEXT_HTML_ELEMENT;
+ public static android.view.accessibility.AccessibilityNodeInfo$AccessibilityAction ACTION_PASTE;
+ public static android.view.accessibility.AccessibilityNodeInfo$AccessibilityAction ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY;
+ public static android.view.accessibility.AccessibilityNodeInfo$AccessibilityAction ACTION_PREVIOUS_HTML_ELEMENT;
+ public static android.view.accessibility.AccessibilityNodeInfo$AccessibilityAction ACTION_SCROLL_BACKWARD;
+ public static android.view.accessibility.AccessibilityNodeInfo$AccessibilityAction ACTION_SCROLL_DOWN;
+ public static android.view.accessibility.AccessibilityNodeInfo$AccessibilityAction ACTION_SCROLL_FORWARD;
+ public static android.view.accessibility.AccessibilityNodeInfo$AccessibilityAction ACTION_SCROLL_LEFT;
+ public static android.view.accessibility.AccessibilityNodeInfo$AccessibilityAction ACTION_SCROLL_RIGHT;
+ public static android.view.accessibility.AccessibilityNodeInfo$AccessibilityAction ACTION_SCROLL_TO_POSITION;
+ public static android.view.accessibility.AccessibilityNodeInfo$AccessibilityAction ACTION_SCROLL_UP;
+ public static android.view.accessibility.AccessibilityNodeInfo$AccessibilityAction ACTION_SELECT;
+ public static android.view.accessibility.AccessibilityNodeInfo$AccessibilityAction ACTION_SET_PROGRESS;
+ public static android.view.accessibility.AccessibilityNodeInfo$AccessibilityAction ACTION_SET_SELECTION;
+ public static android.view.accessibility.AccessibilityNodeInfo$AccessibilityAction ACTION_SET_TEXT;
+ public static android.view.accessibility.AccessibilityNodeInfo$AccessibilityAction ACTION_SHOW_ON_SCREEN;
+ public static android.view.accessibility.AccessibilityNodeInfo$AccessibilityAction ACTION_SHOW_TOOLTIP;
+ public long mSerializationFlag;
+ public static android.util.ArraySet sStandardActions;
+}
+
+-keep class android.view.accessibility.AccessibilityNodeInfo$CollectionInfo {
+
+ public int getColumnCount();
+ public int getRowCount();
+ public int getSelectionMode();
+ public boolean isHierarchical();
+ public static android.view.accessibility.AccessibilityNodeInfo$CollectionInfo obtain(android.view.accessibility.AccessibilityNodeInfo$CollectionInfo);
+ public static android.view.accessibility.AccessibilityNodeInfo$CollectionInfo obtain(int, int, boolean);
+ public static android.view.accessibility.AccessibilityNodeInfo$CollectionInfo obtain(int, int, boolean, int);
+
+
+ public static int SELECTION_MODE_MULTIPLE;
+ public static int SELECTION_MODE_NONE;
+ public static int SELECTION_MODE_SINGLE;
+}
+
+-keep class android.view.accessibility.AccessibilityNodeInfo$CollectionItemInfo {
+
+ public int getColumnIndex();
+ public int getColumnSpan();
+ public int getRowIndex();
+ public int getRowSpan();
+ public boolean isHeading();
+ public boolean isSelected();
+ public static android.view.accessibility.AccessibilityNodeInfo$CollectionItemInfo obtain(android.view.accessibility.AccessibilityNodeInfo$CollectionItemInfo);
+ public static android.view.accessibility.AccessibilityNodeInfo$CollectionItemInfo obtain(int, int, int, int, boolean);
+ public static android.view.accessibility.AccessibilityNodeInfo$CollectionItemInfo obtain(int, int, int, int, boolean, boolean);
+
+
+}
+
+-keep class android.view.accessibility.AccessibilityNodeInfo$RangeInfo {
+
+ public float getCurrent();
+ public float getMax();
+ public float getMin();
+ public int getType();
+ public static android.view.accessibility.AccessibilityNodeInfo$RangeInfo obtain(android.view.accessibility.AccessibilityNodeInfo$RangeInfo);
+ public static android.view.accessibility.AccessibilityNodeInfo$RangeInfo obtain(int, float, float, float);
+
+
+ public static int RANGE_TYPE_FLOAT;
+ public static int RANGE_TYPE_INT;
+ public static int RANGE_TYPE_PERCENT;
+}
+
+-keep class android.view.accessibility.AccessibilityNodeProvider {
+ <init>();
+
+ public void addExtraDataToAccessibilityNodeInfo(int, android.view.accessibility.AccessibilityNodeInfo, java.lang.String, android.os.Bundle);
+ public android.view.accessibility.AccessibilityNodeInfo createAccessibilityNodeInfo(int);
+ public java.util.List findAccessibilityNodeInfosByText(java.lang.String, int);
+ public android.view.accessibility.AccessibilityNodeInfo findFocus(int);
+ public boolean performAction(int, int, android.os.Bundle);
+
+
+ public static int HOST_VIEW_ID;
+}
+
+-keep class android.view.accessibility.AccessibilityRecord {
+
+ public int getAddedCount();
+ public java.lang.CharSequence getBeforeText();
+ public java.lang.CharSequence getClassName();
+ public java.lang.CharSequence getContentDescription();
+ public int getCurrentItemIndex();
+ public int getFromIndex();
+ public int getItemCount();
+ public int getMaxScrollX();
+ public int getMaxScrollY();
+ public android.os.Parcelable getParcelableData();
+ public int getRemovedCount();
+ public int getScrollDeltaX();
+ public int getScrollDeltaY();
+ public int getScrollX();
+ public int getScrollY();
+ public android.view.accessibility.AccessibilityNodeInfo getSource();
+ public long getSourceNodeId();
+ public java.util.List getText();
+ public int getToIndex();
+ public int getWindowId();
+ public boolean isChecked();
+ public boolean isEnabled();
+ public boolean isFullScreen();
+ public boolean isImportantForAccessibility();
+ public boolean isPassword();
+ public boolean isScrollable();
+ public static android.view.accessibility.AccessibilityRecord obtain(android.view.accessibility.AccessibilityRecord);
+ public static android.view.accessibility.AccessibilityRecord obtain();
+ public void recycle();
+ public void setAddedCount(int);
+ public void setBeforeText(java.lang.CharSequence);
+ public void setChecked(boolean);
+ public void setClassName(java.lang.CharSequence);
+ public void setConnectionId(int);
+ public void setContentDescription(java.lang.CharSequence);
+ public void setCurrentItemIndex(int);
+ public void setEnabled(boolean);
+ public void setFromIndex(int);
+ public void setFullScreen(boolean);
+ public void setImportantForAccessibility(boolean);
+ public void setItemCount(int);
+ public void setMaxScrollX(int);
+ public void setMaxScrollY(int);
+ public void setParcelableData(android.os.Parcelable);
+ public void setPassword(boolean);
+ public void setRemovedCount(int);
+ public void setScrollDeltaX(int);
+ public void setScrollDeltaY(int);
+ public void setScrollX(int);
+ public void setScrollY(int);
+ public void setScrollable(boolean);
+ public void setSealed(boolean);
+ public void setSource(android.view.View);
+ public void setSource(android.view.View, int);
+ public void setSourceNodeId(long);
+ public void setToIndex(int);
+ public void setWindowId(int);
+ public java.lang.String toString();
+
+
+ protected static boolean DEBUG_CONCISE_TOSTRING;
+}
+
+-keep class android.view.accessibility.AccessibilityWindowInfo {
+
+ public void addChild(int);
+ public boolean changed(android.view.accessibility.AccessibilityWindowInfo);
+ public int describeContents();
+ public int differenceFrom(android.view.accessibility.AccessibilityWindowInfo);
+ public boolean equals(java.lang.Object);
+ public android.view.accessibility.AccessibilityNodeInfo getAnchor();
+ public void getBoundsInScreen(android.graphics.Rect);
+ public android.view.accessibility.AccessibilityWindowInfo getChild(int);
+ public int getChildCount();
+ public int getId();
+ public int getLayer();
+ public android.view.accessibility.AccessibilityWindowInfo getParent();
+ public android.view.accessibility.AccessibilityNodeInfo getRoot();
+ public java.lang.CharSequence getTitle();
+ public int getType();
+ public int hashCode();
+ public boolean isAccessibilityFocused();
+ public boolean isActive();
+ public boolean isFocused();
+ public boolean isInPictureInPictureMode();
+ public static android.view.accessibility.AccessibilityWindowInfo obtain();
+ public static android.view.accessibility.AccessibilityWindowInfo obtain(android.view.accessibility.AccessibilityWindowInfo);
+ public void recycle();
+ public void setAccessibilityFocused(boolean);
+ public void setActive(boolean);
+ public void setAnchorId(long);
+ public void setBoundsInScreen(android.graphics.Rect);
+ public void setConnectionId(int);
+ public void setFocused(boolean);
+ public void setId(int);
+ public void setLayer(int);
+ public static void setNumInstancesInUseCounter(java.util.concurrent.atomic.AtomicInteger);
+ public void setParentId(int);
+ public void setPictureInPicture(boolean);
+ public void setTitle(java.lang.CharSequence);
+ public void setType(int);
+ public java.lang.String toString();
+ public void writeToParcel(android.os.Parcel, int);
+
+
+ public static int ACTIVE_WINDOW_ID;
+ public static int ANY_WINDOW_ID;
+ public static android.os.Parcelable$Creator CREATOR;
+ public static int PICTURE_IN_PICTURE_ACTION_REPLACER_WINDOW_ID;
+ public static int TYPE_ACCESSIBILITY_OVERLAY;
+ public static int TYPE_APPLICATION;
+ public static int TYPE_INPUT_METHOD;
+ public static int TYPE_SPLIT_SCREEN_DIVIDER;
+ public static int TYPE_SYSTEM;
+ public static int UNDEFINED_WINDOW_ID;
+}
+
+-keep class android.view.accessibility.IAccessibilityInteractionConnectionCallback {
+
+ public abstract void setFindAccessibilityNodeInfoResult(android.view.accessibility.AccessibilityNodeInfo, int);
+ public abstract void setFindAccessibilityNodeInfosResult(java.util.List, int);
+ public abstract void setPerformAccessibilityActionResult(boolean, int);
+
+
+}
+
+-keep class android.view.animation.Animation {
+ <init>();
+ <init>(android.content.Context, android.util.AttributeSet);
+
+ protected void applyTransformation(float, android.view.animation.Transformation);
+ public void cancel();
+ protected android.view.animation.Animation clone();
+ protected java.lang.Object clone();
+ public long computeDurationHint();
+ public void detach();
+ protected void ensureInterpolator();
+ protected void finalize();
+ public int getBackgroundColor();
+ public boolean getDetachWallpaper();
+ public long getDuration();
+ public boolean getFillAfter();
+ public boolean getFillBefore();
+ public android.view.animation.Interpolator getInterpolator();
+ public void getInvalidateRegion(int, int, int, int, android.graphics.RectF, android.view.animation.Transformation);
+ public int getRepeatCount();
+ public int getRepeatMode();
+ protected float getScaleFactor();
+ public boolean getShowWallpaper();
+ public long getStartOffset();
+ public long getStartTime();
+ public boolean getTransformation(long, android.view.animation.Transformation);
+ public boolean getTransformation(long, android.view.animation.Transformation, float);
+ public int getZAdjustment();
+ public boolean hasAlpha();
+ public boolean hasEnded();
+ public boolean hasStarted();
+ public void initialize(int, int, int, int);
+ public void initializeInvalidateRegion(int, int, int, int);
+ public boolean isFillEnabled();
+ public boolean isInitialized();
+ public void reset();
+ protected float resolveSize(int, float, int, int);
+ public void restrictDuration(long);
+ public void scaleCurrentDuration(float);
+ public void setAnimationListener(android.view.animation.Animation$AnimationListener);
+ public void setBackgroundColor(int);
+ public void setDetachWallpaper(boolean);
+ public void setDuration(long);
+ public void setFillAfter(boolean);
+ public void setFillBefore(boolean);
+ public void setFillEnabled(boolean);
+ public void setInterpolator(android.content.Context, int);
+ public void setInterpolator(android.view.animation.Interpolator);
+ public void setListenerHandler(android.os.Handler);
+ public void setRepeatCount(int);
+ public void setRepeatMode(int);
+ public void setShowWallpaper(boolean);
+ public void setStartOffset(long);
+ public void setStartTime(long);
+ public void setZAdjustment(int);
+ public void start();
+ public void startNow();
+ public boolean willChangeBounds();
+ public boolean willChangeTransformationMatrix();
+
+
+ public static int ABSOLUTE;
+ public static int INFINITE;
+ public static int RELATIVE_TO_PARENT;
+ public static int RELATIVE_TO_SELF;
+ public static int RESTART;
+ public static int REVERSE;
+ public static int START_ON_FIRST_FRAME;
+ public static int ZORDER_BOTTOM;
+ public static int ZORDER_NORMAL;
+ public static int ZORDER_TOP;
+}
+
+-keep class android.view.animation.Animation$AnimationListener {
+
+ public abstract void onAnimationEnd(android.view.animation.Animation);
+ public abstract void onAnimationRepeat(android.view.animation.Animation);
+ public abstract void onAnimationStart(android.view.animation.Animation);
+
+
+}
+
+-keep class android.view.animation.Interpolator {
+
+
+
+}
+
+-keep class android.view.animation.LayoutAnimationController {
+ <init>(android.content.Context, android.util.AttributeSet);
+ <init>(android.view.animation.Animation);
+ <init>(android.view.animation.Animation, float);
+
+ public android.view.animation.Animation getAnimation();
+ public android.view.animation.Animation getAnimationForView(android.view.View);
+ public float getDelay();
+ protected long getDelayForView(android.view.View);
+ public android.view.animation.Interpolator getInterpolator();
+ public int getOrder();
+ protected int getTransformedIndex(android.view.animation.LayoutAnimationController$AnimationParameters);
+ public boolean isDone();
+ public void setAnimation(android.content.Context, int);
+ public void setAnimation(android.view.animation.Animation);
+ public void setDelay(float);
+ public void setInterpolator(android.content.Context, int);
+ public void setInterpolator(android.view.animation.Interpolator);
+ public void setOrder(int);
+ public void start();
+ public boolean willOverlap();
+
+
+ public static int ORDER_NORMAL;
+ public static int ORDER_RANDOM;
+ public static int ORDER_REVERSE;
+ protected android.view.animation.Animation mAnimation;
+ protected android.view.animation.Interpolator mInterpolator;
+ protected java.util.Random mRandomizer;
+}
+
+-keep class android.view.animation.LayoutAnimationController$AnimationParameters {
+ <init>();
+
+
+
+ public int count;
+ public int index;
+}
+
+-keep class android.view.animation.Transformation {
+ <init>();
+
+ public void clear();
+ public void compose(android.view.animation.Transformation);
+ public float getAlpha();
+ public android.graphics.Rect getClipRect();
+ public android.graphics.Matrix getMatrix();
+ public int getTransformationType();
+ public boolean hasClipRect();
+ public void postCompose(android.view.animation.Transformation);
+ public void printShortString(java.io.PrintWriter);
+ public void set(android.view.animation.Transformation);
+ public void setAlpha(float);
+ public void setClipRect(android.graphics.Rect);
+ public void setClipRect(int, int, int, int);
+ public void setTransformationType(int);
+ public java.lang.String toShortString();
+ public void toShortString(java.lang.StringBuilder);
+ public java.lang.String toString();
+
+
+ public static int TYPE_ALPHA;
+ public static int TYPE_BOTH;
+ public static int TYPE_IDENTITY;
+ public static int TYPE_MATRIX;
+ protected float mAlpha;
+ protected android.graphics.Matrix mMatrix;
+ protected int mTransformationType;
+}
+
+-keep class android.view.autofill.AutofillId {
+ <init>(int);
+ <init>(android.view.autofill.AutofillId, int);
+ <init>(int, int);
+
+ public int describeContents();
+ public boolean equals(java.lang.Object);
+ public int getViewId();
+ public int getVirtualChildId();
+ public int hashCode();
+ public boolean isVirtual();
+ public java.lang.String toString();
+ public void writeToParcel(android.os.Parcel, int);
+
+
+ public static android.os.Parcelable$Creator CREATOR;
+}
+
+-keep class android.view.autofill.AutofillManager {
+ <init>(android.content.Context, android.view.autofill.IAutoFillManager);
+
+ public void cancel();
+ public void commit();
+ public void disableAutofillServices();
+ public void disableOwnedAutofillServices();
+ public void dump(java.lang.String, java.io.PrintWriter);
+ public void enableCompatibilityMode();
+ public android.content.ComponentName getAutofillServiceComponentName();
+ public java.util.List getAvailableFieldClassificationAlgorithms();
+ public static int getDatasetIdFromAuthenticationId(int);
+ public java.lang.String getDefaultFieldClassificationAlgorithm();
+ public android.service.autofill.FillEventHistory getFillEventHistory();
+ public android.view.autofill.AutofillId getNextAutofillId();
+ public static int getRequestIdFromAuthenticationId(int);
+ public android.service.autofill.UserData getUserData();
+ public java.lang.String getUserDataId();
+ public boolean hasAutofillFeature();
+ public boolean hasEnabledAutofillServices();
+ public boolean isAutofillSupported();
+ public boolean isAutofillUiShowing();
+ public boolean isCompatibilityModeEnabledLocked();
+ public boolean isEnabled();
+ public boolean isFieldClassificationEnabled();
+ public static int makeAuthenticationId(int, int);
+ public void notifyValueChanged(android.view.View);
+ public void notifyValueChanged(android.view.View, int, android.view.autofill.AutofillValue);
+ public void notifyViewClicked(android.view.View);
+ public void notifyViewClicked(android.view.View, int);
+ public void notifyViewEntered(android.view.View);
+ public void notifyViewEntered(android.view.View, int, android.graphics.Rect);
+ public void notifyViewExited(android.view.View);
+ public void notifyViewExited(android.view.View, int);
+ public void notifyViewVisibilityChanged(android.view.View, boolean);
+ public void notifyViewVisibilityChanged(android.view.View, int, boolean);
+ public void onActivityFinishing();
+ public void onAuthenticationResult(int, android.content.Intent, android.view.View);
+ public void onCreate(android.os.Bundle);
+ public void onInvisibleForAutofill();
+ public void onPendingSaveUi(int, android.os.IBinder);
+ public void onSaveInstanceState(android.os.Bundle);
+ public void onVisibleForAutofill();
+ public void registerCallback(android.view.autofill.AutofillManager$AutofillCallback);
+ public void requestAutofill(android.view.View);
+ public void requestAutofill(android.view.View, int, android.graphics.Rect);
+ public void requestHideFillUi();
+ public void setUserData(android.service.autofill.UserData);
+ public void unregisterCallback(android.view.autofill.AutofillManager$AutofillCallback);
+
+
+ public static int ACTION_START_SESSION;
+ public static int ACTION_VALUE_CHANGED;
+ public static int ACTION_VIEW_ENTERED;
+ public static int ACTION_VIEW_EXITED;
+ public static int AUTHENTICATION_ID_DATASET_ID_UNDEFINED;
+ public static java.lang.String EXTRA_ASSIST_STRUCTURE;
+ public static java.lang.String EXTRA_AUTHENTICATION_RESULT;
+ public static java.lang.String EXTRA_CLIENT_STATE;
+ public static java.lang.String EXTRA_RESTORE_SESSION_TOKEN;
+ public static int FC_SERVICE_TIMEOUT;
+ public static int FLAG_ADD_CLIENT_DEBUG;
+ public static int FLAG_ADD_CLIENT_ENABLED;
+ public static int FLAG_ADD_CLIENT_VERBOSE;
+ public static int NO_SESSION;
+ public static int PENDING_UI_OPERATION_CANCEL;
+ public static int PENDING_UI_OPERATION_RESTORE;
+ public static int SET_STATE_FLAG_DEBUG;
+ public static int SET_STATE_FLAG_ENABLED;
+ public static int SET_STATE_FLAG_RESET_CLIENT;
+ public static int SET_STATE_FLAG_RESET_SESSION;
+ public static int SET_STATE_FLAG_VERBOSE;
+ public static int STATE_ACTIVE;
+ public static int STATE_DISABLED_BY_SERVICE;
+ public static int STATE_FINISHED;
+ public static int STATE_SHOWING_SAVE_UI;
+ public static int STATE_UNKNOWN;
+ public static int STATE_UNKNOWN_COMPAT_MODE;
+}
+
+-keep class android.view.autofill.AutofillManager$AutofillCallback {
+ <init>();
+
+ public void onAutofillEvent(android.view.View, int);
+ public void onAutofillEvent(android.view.View, int, int);
+
+
+ public static int EVENT_INPUT_HIDDEN;
+ public static int EVENT_INPUT_SHOWN;
+ public static int EVENT_INPUT_UNAVAILABLE;
+}
+
+-keep class android.view.autofill.AutofillManager$AutofillClient {
+
+ public abstract void autofillClientAuthenticate(int, android.content.IntentSender, android.content.Intent);
+ public abstract void autofillClientDispatchUnhandledKey(android.view.View, android.view.KeyEvent);
+ public abstract android.view.View autofillClientFindViewByAccessibilityIdTraversal(int, int);
+ public abstract android.view.View autofillClientFindViewByAutofillIdTraversal(android.view.autofill.AutofillId);
+ public abstract android.view.View[] autofillClientFindViewsByAutofillIdTraversal(android.view.autofill.AutofillId[]);
+ public abstract android.os.IBinder autofillClientGetActivityToken();
+ public abstract android.content.ComponentName autofillClientGetComponentName();
+ public abstract android.view.autofill.AutofillId autofillClientGetNextAutofillId();
+ public abstract boolean[] autofillClientGetViewVisibility(android.view.autofill.AutofillId[]);
+ public abstract boolean autofillClientIsCompatibilityModeEnabled();
+ public abstract boolean autofillClientIsFillUiShowing();
+ public abstract boolean autofillClientIsVisibleForAutofill();
+ public abstract boolean autofillClientRequestHideFillUi();
+ public abstract boolean autofillClientRequestShowFillUi(android.view.View, int, int, android.graphics.Rect, android.view.autofill.IAutofillWindowPresenter);
+ public abstract void autofillClientResetableStateAvailable();
+ public abstract void autofillClientRunOnUiThread(java.lang.Runnable);
+ public abstract boolean isDisablingEnterExitEventForAutofill();
+
+
+}
+
+-keep class android.view.autofill.AutofillValue {
+
+ public int describeContents();
+ public boolean equals(java.lang.Object);
+ public static android.view.autofill.AutofillValue forDate(long);
+ public static android.view.autofill.AutofillValue forList(int);
+ public static android.view.autofill.AutofillValue forText(java.lang.CharSequence);
+ public static android.view.autofill.AutofillValue forToggle(boolean);
+ public long getDateValue();
+ public int getListValue();
+ public java.lang.CharSequence getTextValue();
+ public boolean getToggleValue();
+ public int hashCode();
+ public boolean isDate();
+ public boolean isEmpty();
+ public boolean isList();
+ public boolean isText();
+ public boolean isToggle();
+ public java.lang.String toString();
+ public void writeToParcel(android.os.Parcel, int);
+
+
+ public static android.os.Parcelable$Creator CREATOR;
+}
+
+-keep class android.view.autofill.IAutoFillManager {
+
+ public abstract int addClient(android.view.autofill.IAutoFillManagerClient, int);
+ public abstract void cancelSession(int, int);
+ public abstract void disableOwnedAutofillServices(int);
+ public abstract void finishSession(int, int);
+ public abstract android.content.ComponentName getAutofillServiceComponentName();
+ public abstract java.lang.String[] getAvailableFieldClassificationAlgorithms();
+ public abstract java.lang.String getDefaultFieldClassificationAlgorithm();
+ public abstract android.service.autofill.FillEventHistory getFillEventHistory();
+ public abstract android.service.autofill.UserData getUserData();
+ public abstract java.lang.String getUserDataId();
+ public abstract boolean isFieldClassificationEnabled();
+ public abstract boolean isServiceEnabled(int, java.lang.String);
+ public abstract boolean isServiceSupported(int);
+ public abstract void onPendingSaveUi(int, android.os.IBinder);
+ public abstract void removeClient(android.view.autofill.IAutoFillManagerClient, int);
+ public abstract boolean restoreSession(int, android.os.IBinder, android.os.IBinder);
+ public abstract void setAuthenticationResult(android.os.Bundle, int, int, int);
+ public abstract void setAutofillFailure(int, java.util.List, int);
+ public abstract void setHasCallback(int, int, boolean);
+ public abstract void setUserData(android.service.autofill.UserData);
+ public abstract int startSession(android.os.IBinder, android.os.IBinder, android.view.autofill.AutofillId, android.graphics.Rect, android.view.autofill.AutofillValue, int, boolean, int, android.content.ComponentName, boolean);
+ public abstract int updateOrRestartSession(android.os.IBinder, android.os.IBinder, android.view.autofill.AutofillId, android.graphics.Rect, android.view.autofill.AutofillValue, int, boolean, int, android.content.ComponentName, int, int, boolean);
+ public abstract void updateSession(int, android.view.autofill.AutofillId, android.graphics.Rect, android.view.autofill.AutofillValue, int, int, int);
+
+
+}
+
+-keep class android.view.autofill.IAutoFillManagerClient {
+
+ public abstract void authenticate(int, int, android.content.IntentSender, android.content.Intent);
+ public abstract void autofill(int, java.util.List, java.util.List);
+ public abstract void dispatchUnhandledKey(int, android.view.autofill.AutofillId, android.view.KeyEvent);
+ public abstract void notifyNoFillUi(int, android.view.autofill.AutofillId, int);
+ public abstract void requestHideFillUi(int, android.view.autofill.AutofillId);
+ public abstract void requestShowFillUi(int, android.view.autofill.AutofillId, int, int, android.graphics.Rect, android.view.autofill.IAutofillWindowPresenter);
+ public abstract void setSaveUiState(int, boolean);
+ public abstract void setSessionFinished(int);
+ public abstract void setState(int);
+ public abstract void setTrackedViews(int, android.view.autofill.AutofillId[], boolean, boolean, android.view.autofill.AutofillId[], android.view.autofill.AutofillId);
+ public abstract void startIntentSender(android.content.IntentSender, android.content.Intent);
+
+
+}
+
+-keep class android.view.autofill.IAutofillWindowPresenter {
+
+ public abstract void hide(android.graphics.Rect);
+ public abstract void show(android.view.WindowManager$LayoutParams, android.graphics.Rect, boolean, int);
+
+
+}
+
+-keep class android.view.inputmethod.CompletionInfo {
+ <init>(long, int, java.lang.CharSequence);
+ <init>(long, int, java.lang.CharSequence, java.lang.CharSequence);
+
+ public int describeContents();
+ public long getId();
+ public java.lang.CharSequence getLabel();
+ public int getPosition();
+ public java.lang.CharSequence getText();
+ public java.lang.String toString();
+ public void writeToParcel(android.os.Parcel, int);
+
+
+ public static android.os.Parcelable$Creator CREATOR;
+}
+
+-keep class android.view.inputmethod.CorrectionInfo {
+ <init>(int, java.lang.CharSequence, java.lang.CharSequence);
+
+ public int describeContents();
+ public java.lang.CharSequence getNewText();
+ public int getOffset();
+ public java.lang.CharSequence getOldText();
+ public java.lang.String toString();
+ public void writeToParcel(android.os.Parcel, int);
+
+
+ public static android.os.Parcelable$Creator CREATOR;
+}
+
+-keep class android.view.inputmethod.EditorInfo {
+ <init>();
+
+ public int describeContents();
+ public void dump(android.util.Printer, java.lang.String);
+ public void makeCompatible(int);
+ public void writeToParcel(android.os.Parcel, int);
+
+
+ public static android.os.Parcelable$Creator CREATOR;
+ public static int IME_ACTION_DONE;
+ public static int IME_ACTION_GO;
+ public static int IME_ACTION_NEXT;
+ public static int IME_ACTION_NONE;
+ public static int IME_ACTION_PREVIOUS;
+ public static int IME_ACTION_SEARCH;
+ public static int IME_ACTION_SEND;
+ public static int IME_ACTION_UNSPECIFIED;
+ public static int IME_FLAG_FORCE_ASCII;
+ public static int IME_FLAG_NAVIGATE_NEXT;
+ public static int IME_FLAG_NAVIGATE_PREVIOUS;
+ public static int IME_FLAG_NO_ACCESSORY_ACTION;
+ public static int IME_FLAG_NO_ENTER_ACTION;
+ public static int IME_FLAG_NO_EXTRACT_UI;
+ public static int IME_FLAG_NO_FULLSCREEN;
+ public static int IME_FLAG_NO_PERSONALIZED_LEARNING;
+ public static int IME_MASK_ACTION;
+ public static int IME_NULL;
+ public int actionId;
+ public java.lang.CharSequence actionLabel;
+ public java.lang.String[] contentMimeTypes;
+ public android.os.Bundle extras;
+ public int fieldId;
+ public java.lang.String fieldName;
+ public android.os.LocaleList hintLocales;
+ public java.lang.CharSequence hintText;
+ public int imeOptions;
+ public int initialCapsMode;
+ public int initialSelEnd;
+ public int initialSelStart;
+ public int inputType;
+ public java.lang.CharSequence label;
+ public java.lang.String packageName;
+ public java.lang.String privateImeOptions;
+}
+
+-keep class android.view.inputmethod.ExtractedText {
+ <init>();
+
+ public int describeContents();
+ public void writeToParcel(android.os.Parcel, int);
+
+
+ public static android.os.Parcelable$Creator CREATOR;
+ public static int FLAG_SELECTING;
+ public static int FLAG_SINGLE_LINE;
+ public int flags;
+ public java.lang.CharSequence hint;
+ public int partialEndOffset;
+ public int partialStartOffset;
+ public int selectionEnd;
+ public int selectionStart;
+ public int startOffset;
+ public java.lang.CharSequence text;
+}
+
+-keep class android.view.inputmethod.ExtractedTextRequest {
+ <init>();
+
+ public int describeContents();
+ public void writeToParcel(android.os.Parcel, int);
+
+
+ public static android.os.Parcelable$Creator CREATOR;
+ public int flags;
+ public int hintMaxChars;
+ public int hintMaxLines;
+ public int token;
+}
+
+-keep class android.view.inputmethod.InputConnection {
+
+ public abstract boolean beginBatchEdit();
+ public abstract boolean clearMetaKeyStates(int);
+ public abstract void closeConnection();
+ public abstract boolean commitCompletion(android.view.inputmethod.CompletionInfo);
+ public abstract boolean commitContent(android.view.inputmethod.InputContentInfo, int, android.os.Bundle);
+ public abstract boolean commitCorrection(android.view.inputmethod.CorrectionInfo);
+ public abstract boolean commitText(java.lang.CharSequence, int);
+ public abstract boolean deleteSurroundingText(int, int);
+ public abstract boolean deleteSurroundingTextInCodePoints(int, int);
+ public abstract boolean endBatchEdit();
+ public abstract boolean finishComposingText();
+ public abstract int getCursorCapsMode(int);
+ public abstract android.view.inputmethod.ExtractedText getExtractedText(android.view.inputmethod.ExtractedTextRequest, int);
+ public abstract android.os.Handler getHandler();
+ public abstract java.lang.CharSequence getSelectedText(int);
+ public abstract java.lang.CharSequence getTextAfterCursor(int, int);
+ public abstract java.lang.CharSequence getTextBeforeCursor(int, int);
+ public abstract boolean performContextMenuAction(int);
+ public abstract boolean performEditorAction(int);
+ public abstract boolean performPrivateCommand(java.lang.String, android.os.Bundle);
+ public abstract boolean reportFullscreenMode(boolean);
+ public abstract boolean requestCursorUpdates(int);
+ public abstract boolean sendKeyEvent(android.view.KeyEvent);
+ public abstract boolean setComposingRegion(int, int);
+ public abstract boolean setComposingText(java.lang.CharSequence, int);
+ public abstract boolean setSelection(int, int);
+
+
+ public static int CURSOR_UPDATE_IMMEDIATE;
+ public static int CURSOR_UPDATE_MONITOR;
+ public static int GET_EXTRACTED_TEXT_MONITOR;
+ public static int GET_TEXT_WITH_STYLES;
+ public static int INPUT_CONTENT_GRANT_READ_URI_PERMISSION;
+}
+
+-keep class android.view.inputmethod.InputContentInfo {
+ <init>(android.net.Uri, android.content.ClipDescription);
+ <init>(android.net.Uri, android.content.ClipDescription, android.net.Uri);
+
+ public int describeContents();
+ public android.net.Uri getContentUri();
+ public android.content.ClipDescription getDescription();
+ public android.net.Uri getLinkUri();
+ public void releasePermission();
+ public void requestPermission();
+ public boolean validate();
+ public void writeToParcel(android.os.Parcel, int);
+
+
+ public static android.os.Parcelable$Creator CREATOR;
+}
+
+-keep class android.widget.ActionMenuPresenter {
+ <init>(android.content.Context);
+
+ public void bindItemView(com.android.internal.view.menu.MenuItemImpl, com.android.internal.view.menu.MenuView$ItemView);
+ public boolean dismissPopupMenus();
+ public boolean filterLeftoverView(android.view.ViewGroup, int);
+ public boolean flagActionItems();
+ public android.view.View getItemView(com.android.internal.view.menu.MenuItemImpl, android.view.View, android.view.ViewGroup);
+ public com.android.internal.view.menu.MenuView getMenuView(android.view.ViewGroup);
+ public android.graphics.drawable.Drawable getOverflowIcon();
+ public boolean hideOverflowMenu();
+ public boolean hideSubMenus();
+ public void initForMenu(android.content.Context, com.android.internal.view.menu.MenuBuilder);
+ public boolean isOverflowMenuShowPending();
+ public boolean isOverflowMenuShowing();
+ public boolean isOverflowReserved();
+ public void onCloseMenu(com.android.internal.view.menu.MenuBuilder, boolean);
+ public void onConfigurationChanged(android.content.res.Configuration);
+ public void onRestoreInstanceState(android.os.Parcelable);
+ public android.os.Parcelable onSaveInstanceState();
+ public boolean onSubMenuSelected(com.android.internal.view.menu.SubMenuBuilder);
+ public void onSubUiVisibilityChanged(boolean);
+ public void setExpandedActionViewsExclusive(boolean);
+ public void setItemLimit(int);
+ public void setMenuView(android.widget.ActionMenuView);
+ public void setOverflowIcon(android.graphics.drawable.Drawable);
+ public void setReserveOverflow(boolean);
+ public void setWidthLimit(int, boolean);
+ public boolean shouldIncludeItem(int, com.android.internal.view.menu.MenuItemImpl);
+ public boolean showOverflowMenu();
+ public void updateMenuView(boolean);
+
+
+}
+
+-keep class android.widget.ActionMenuView {
+ <init>(android.content.Context);
+ <init>(android.content.Context, android.util.AttributeSet);
+
+ protected boolean checkLayoutParams(android.view.ViewGroup$LayoutParams);
+ public void dismissPopupMenus();
+ public boolean dispatchPopulateAccessibilityEventInternal(android.view.accessibility.AccessibilityEvent);
+ protected android.widget.ActionMenuView$LayoutParams generateDefaultLayoutParams();
+ protected android.widget.LinearLayout$LayoutParams generateDefaultLayoutParams();
+ protected android.view.ViewGroup$LayoutParams generateDefaultLayoutParams();
+ public android.widget.ActionMenuView$LayoutParams generateLayoutParams(android.util.AttributeSet);
+ protected android.widget.ActionMenuView$LayoutParams generateLayoutParams(android.view.ViewGroup$LayoutParams);
+ protected android.widget.LinearLayout$LayoutParams generateLayoutParams(android.view.ViewGroup$LayoutParams);
+ public android.widget.LinearLayout$LayoutParams generateLayoutParams(android.util.AttributeSet);
+ protected android.view.ViewGroup$LayoutParams generateLayoutParams(android.view.ViewGroup$LayoutParams);
+ public android.view.ViewGroup$LayoutParams generateLayoutParams(android.util.AttributeSet);
+ public android.widget.ActionMenuView$LayoutParams generateOverflowButtonLayoutParams();
+ public android.view.Menu getMenu();
+ public android.graphics.drawable.Drawable getOverflowIcon();
+ public int getPopupTheme();
+ public int getWindowAnimations();
+ protected boolean hasDividerBeforeChildAt(int);
+ public boolean hideOverflowMenu();
+ public void initialize(com.android.internal.view.menu.MenuBuilder);
+ public boolean invokeItem(com.android.internal.view.menu.MenuItemImpl);
+ public boolean isOverflowMenuShowPending();
+ public boolean isOverflowMenuShowing();
+ public boolean isOverflowReserved();
+ public void onConfigurationChanged(android.content.res.Configuration);
+ public void onDetachedFromWindow();
+ protected void onLayout(boolean, int, int, int, int);
+ protected void onMeasure(int, int);
+ public com.android.internal.view.menu.MenuBuilder peekMenu();
+ public void setExpandedActionViewsExclusive(boolean);
+ public void setMenuCallbacks(com.android.internal.view.menu.MenuPresenter$Callback, com.android.internal.view.menu.MenuBuilder$Callback);
+ public void setOnMenuItemClickListener(android.widget.ActionMenuView$OnMenuItemClickListener);
+ public void setOverflowIcon(android.graphics.drawable.Drawable);
+ public void setOverflowReserved(boolean);
+ public void setPopupTheme(int);
+ public void setPresenter(android.widget.ActionMenuPresenter);
+ public boolean showOverflowMenu();
+
+
+}
+
+-keep class android.widget.ActionMenuView$LayoutParams {
+ <init>(android.content.Context, android.util.AttributeSet);
+ <init>(android.view.ViewGroup$LayoutParams);
+ <init>(android.widget.ActionMenuView$LayoutParams);
+ <init>(int, int);
+ <init>(int, int, boolean);
+
+ protected void encodeProperties(android.view.ViewHierarchyEncoder);
+
+
+ public int cellsUsed;
+ public boolean expandable;
+ public boolean expanded;
+ public int extraPixels;
+ public boolean isOverflowButton;
+ public boolean preventEdgeOffset;
+}
+
+-keep class android.widget.ActionMenuView$OnMenuItemClickListener {
+
+ public abstract boolean onMenuItemClick(android.view.MenuItem);
+
+
+}
+
+-keep class android.widget.Adapter {
+
+ public java.lang.CharSequence[] getAutofillOptions();
+ public abstract int getCount();
+ public abstract java.lang.Object getItem(int);
+ public abstract long getItemId(int);
+ public abstract int getItemViewType(int);
+ public abstract android.view.View getView(int, android.view.View, android.view.ViewGroup);
+ public abstract int getViewTypeCount();
+ public abstract boolean hasStableIds();
+ public abstract boolean isEmpty();
+ public abstract void registerDataSetObserver(android.database.DataSetObserver);
+ public abstract void unregisterDataSetObserver(android.database.DataSetObserver);
+
+
+ public static int IGNORE_ITEM_VIEW_TYPE;
+ public static int NO_SELECTION;
+}
+
+-keep class android.widget.AdapterView {
+ <init>(android.content.Context);
+ <init>(android.content.Context, android.util.AttributeSet);
+ <init>(android.content.Context, android.util.AttributeSet, int);
+ <init>(android.content.Context, android.util.AttributeSet, int, int);
+
+ public void addView(android.view.View);
+ public void addView(android.view.View, int);
+ public void addView(android.view.View, android.view.ViewGroup$LayoutParams);
+ public void addView(android.view.View, int, android.view.ViewGroup$LayoutParams);
+ protected boolean canAnimate();
+ public boolean dispatchPopulateAccessibilityEventInternal(android.view.accessibility.AccessibilityEvent);
+ protected void dispatchRestoreInstanceState(android.util.SparseArray);
+ protected void dispatchSaveInstanceState(android.util.SparseArray);
+ protected void encodeProperties(android.view.ViewHierarchyEncoder);
+ public java.lang.CharSequence getAccessibilityClassName();
+ public abstract android.widget.Adapter getAdapter();
+ public int getCount();
+ public android.view.View getEmptyView();
+ public int getFirstVisiblePosition();
+ public java.lang.Object getItemAtPosition(int);
+ public long getItemIdAtPosition(int);
+ public int getLastVisiblePosition();
+ public android.widget.AdapterView$OnItemClickListener getOnItemClickListener();
+ public android.widget.AdapterView$OnItemLongClickListener getOnItemLongClickListener();
+ public android.widget.AdapterView$OnItemSelectedListener getOnItemSelectedListener();
+ public int getPositionForView(android.view.View);
+ public java.lang.Object getSelectedItem();
+ public long getSelectedItemId();
+ public int getSelectedItemPosition();
+ public abstract android.view.View getSelectedView();
+ protected void onDetachedFromWindow();
+ public void onInitializeAccessibilityEventInternal(android.view.accessibility.AccessibilityEvent);
+ public void onInitializeAccessibilityNodeInfoInternal(android.view.accessibility.AccessibilityNodeInfo);
+ protected void onLayout(boolean, int, int, int, int);
+ public void onProvideAutofillStructure(android.view.ViewStructure, int);
+ public boolean onRequestSendAccessibilityEventInternal(android.view.View, android.view.accessibility.AccessibilityEvent);
+ public boolean performItemClick(android.view.View, int, long);
+ public void removeAllViews();
+ public void removeView(android.view.View);
+ public void removeViewAt(int);
+ public abstract void setAdapter(android.widget.Adapter);
+ public void setEmptyView(android.view.View);
+ public void setFocusable(int);
+ public void setFocusableInTouchMode(boolean);
+ public void setOnClickListener(android.view.View$OnClickListener);
+ public void setOnItemClickListener(android.widget.AdapterView$OnItemClickListener);
+ public void setOnItemLongClickListener(android.widget.AdapterView$OnItemLongClickListener);
+ public void setOnItemSelectedListener(android.widget.AdapterView$OnItemSelectedListener);
+ public abstract void setSelection(int);
+
+
+ public static int INVALID_POSITION;
+ public static long INVALID_ROW_ID;
+ public static int ITEM_VIEW_TYPE_HEADER_OR_FOOTER;
+ public static int ITEM_VIEW_TYPE_IGNORE;
+}
+
+-keep class android.widget.AdapterView$OnItemClickListener {
+
+ public abstract void onItemClick(android.widget.AdapterView, android.view.View, int, long);
+
+
+}
+
+-keep class android.widget.AdapterView$OnItemLongClickListener {
+
+ public abstract boolean onItemLongClick(android.widget.AdapterView, android.view.View, int, long);
+
+
+}
+
+-keep class android.widget.AdapterView$OnItemSelectedListener {
+
+ public abstract void onItemSelected(android.widget.AdapterView, android.view.View, int, long);
+ public abstract void onNothingSelected(android.widget.AdapterView);
+
+
+}
+
+-keep class android.widget.FrameLayout {
+ <init>(android.content.Context);
+ <init>(android.content.Context, android.util.AttributeSet);
+ <init>(android.content.Context, android.util.AttributeSet, int);
+ <init>(android.content.Context, android.util.AttributeSet, int, int);
+
+ protected boolean checkLayoutParams(android.view.ViewGroup$LayoutParams);
+ protected void encodeProperties(android.view.ViewHierarchyEncoder);
+ protected android.widget.FrameLayout$LayoutParams generateDefaultLayoutParams();
+ protected android.view.ViewGroup$LayoutParams generateDefaultLayoutParams();
+ public android.widget.FrameLayout$LayoutParams generateLayoutParams(android.util.AttributeSet);
+ protected android.view.ViewGroup$LayoutParams generateLayoutParams(android.view.ViewGroup$LayoutParams);
+ public android.view.ViewGroup$LayoutParams generateLayoutParams(android.util.AttributeSet);
+ public java.lang.CharSequence getAccessibilityClassName();
+ public boolean getConsiderGoneChildrenWhenMeasuring();
+ public boolean getMeasureAllChildren();
+ protected void onLayout(boolean, int, int, int, int);
+ protected void onMeasure(int, int);
+ public void setForegroundGravity(int);
+ public void setMeasureAllChildren(boolean);
+ public boolean shouldDelayChildPressedState();
+
+
+}
+
+-keep class android.widget.FrameLayout$LayoutParams {
+ <init>(android.content.Context, android.util.AttributeSet);
+ <init>(int, int);
+ <init>(int, int, int);
+ <init>(android.view.ViewGroup$LayoutParams);
+ <init>(android.view.ViewGroup$MarginLayoutParams);
+ <init>(android.widget.FrameLayout$LayoutParams);
+
+
+
+ public static int UNSPECIFIED_GRAVITY;
+ public int gravity;
+}
+
+-keep class android.widget.HorizontalScrollView {
+ <init>(android.content.Context);
+ <init>(android.content.Context, android.util.AttributeSet);
+ <init>(android.content.Context, android.util.AttributeSet, int);
+ <init>(android.content.Context, android.util.AttributeSet, int, int);
+
+ public void addView(android.view.View);
+ public void addView(android.view.View, int);
+ public void addView(android.view.View, android.view.ViewGroup$LayoutParams);
+ public void addView(android.view.View, int, android.view.ViewGroup$LayoutParams);
+ public boolean arrowScroll(int);
+ protected int computeHorizontalScrollOffset();
+ protected int computeHorizontalScrollRange();
+ public void computeScroll();
+ protected int computeScrollDeltaToGetChildRectOnScreen(android.graphics.Rect);
+ public boolean dispatchKeyEvent(android.view.KeyEvent);
+ public void draw(android.graphics.Canvas);
+ protected void encodeProperties(android.view.ViewHierarchyEncoder);
+ public boolean executeKeyEvent(android.view.KeyEvent);
+ public void fling(int);
+ public boolean fullScroll(int);
+ public java.lang.CharSequence getAccessibilityClassName();
+ protected float getLeftFadingEdgeStrength();
+ public int getMaxScrollAmount();
+ protected float getRightFadingEdgeStrength();
+ public boolean isFillViewport();
+ public boolean isSmoothScrollingEnabled();
+ protected void measureChild(android.view.View, int, int);
+ protected void measureChildWithMargins(android.view.View, int, int, int, int);
+ public boolean onGenericMotionEvent(android.view.MotionEvent);
+ public void onInitializeAccessibilityEventInternal(android.view.accessibility.AccessibilityEvent);
+ public void onInitializeAccessibilityNodeInfoInternal(android.view.accessibility.AccessibilityNodeInfo);
+ public boolean onInterceptTouchEvent(android.view.MotionEvent);
+ protected void onLayout(boolean, int, int, int, int);
+ protected void onMeasure(int, int);
+ protected void onOverScrolled(int, int, boolean, boolean);
+ protected boolean onRequestFocusInDescendants(int, android.graphics.Rect);
+ protected void onRestoreInstanceState(android.os.Parcelable);
+ protected android.os.Parcelable onSaveInstanceState();
+ protected void onSizeChanged(int, int, int, int);
+ public boolean onTouchEvent(android.view.MotionEvent);
+ public boolean pageScroll(int);
+ public boolean performAccessibilityActionInternal(int, android.os.Bundle);
+ public void requestChildFocus(android.view.View, android.view.View);
+ public boolean requestChildRectangleOnScreen(android.view.View, android.graphics.Rect, boolean);
+ public void requestDisallowInterceptTouchEvent(boolean);
+ public void requestLayout();
+ public void scrollTo(int, int);
+ public void setFillViewport(boolean);
+ public void setOverScrollMode(int);
+ public void setSmoothScrollingEnabled(boolean);
+ public boolean shouldDelayChildPressedState();
+ public void smoothScrollBy(int, int);
+ public void smoothScrollTo(int, int);
+
+
+}
+
+-keep class android.widget.LinearLayout {
+ <init>(android.content.Context);
+ <init>(android.content.Context, android.util.AttributeSet);
+ <init>(android.content.Context, android.util.AttributeSet, int);
+ <init>(android.content.Context, android.util.AttributeSet, int, int);
+
+ protected boolean checkLayoutParams(android.view.ViewGroup$LayoutParams);
+ protected void encodeProperties(android.view.ViewHierarchyEncoder);
+ protected android.widget.LinearLayout$LayoutParams generateDefaultLayoutParams();
+ protected android.view.ViewGroup$LayoutParams generateDefaultLayoutParams();
+ public android.widget.LinearLayout$LayoutParams generateLayoutParams(android.util.AttributeSet);
+ protected android.widget.LinearLayout$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 getAccessibilityClassName();
+ public int getBaseline();
+ public int getBaselineAlignedChildIndex();
+ public android.graphics.drawable.Drawable getDividerDrawable();
+ public int getDividerPadding();
+ public int getDividerWidth();
+ public int getGravity();
+ public int getOrientation();
+ public int getShowDividers();
+ public float getWeightSum();
+ protected boolean hasDividerBeforeChildAt(int);
+ public boolean isBaselineAligned();
+ public boolean isMeasureWithLargestChildEnabled();
+ protected void onDraw(android.graphics.Canvas);
+ protected void onLayout(boolean, int, int, int, int);
+ protected void onMeasure(int, int);
+ public void onRtlPropertiesChanged(int);
+ public void setBaselineAligned(boolean);
+ public void setBaselineAlignedChildIndex(int);
+ public void setDividerDrawable(android.graphics.drawable.Drawable);
+ public void setDividerPadding(int);
+ public void setGravity(int);
+ public void setHorizontalGravity(int);
+ public void setMeasureWithLargestChildEnabled(boolean);
+ public void setOrientation(int);
+ public void setShowDividers(int);
+ public void setVerticalGravity(int);
+ public void setWeightSum(float);
+ public boolean shouldDelayChildPressedState();
+
+
+ public static int HORIZONTAL;
+ public static int SHOW_DIVIDER_BEGINNING;
+ public static int SHOW_DIVIDER_END;
+ public static int SHOW_DIVIDER_MIDDLE;
+ public static int SHOW_DIVIDER_NONE;
+ public static int VERTICAL;
+}
+
+-keep class android.widget.LinearLayout$LayoutParams {
+ <init>(android.content.Context, android.util.AttributeSet);
+ <init>(int, int);
+ <init>(int, int, float);
+ <init>(android.view.ViewGroup$LayoutParams);
+ <init>(android.view.ViewGroup$MarginLayoutParams);
+ <init>(android.widget.LinearLayout$LayoutParams);
+
+ public java.lang.String debug(java.lang.String);
+ protected void encodeProperties(android.view.ViewHierarchyEncoder);
+
+
+ public int gravity;
+ public float weight;
+}
+
+-keep class android.widget.RemoteViews {
+ <init>(java.lang.String, int);
+ <init>(java.lang.String, int, int);
+ <init>(android.content.pm.ApplicationInfo, int);
+ <init>(android.widget.RemoteViews, android.widget.RemoteViews);
+ <init>(android.widget.RemoteViews);
+ <init>(android.os.Parcel);
+
+ public void addView(int, android.widget.RemoteViews);
+ public void addView(int, android.widget.RemoteViews, int);
+ public android.view.View apply(android.content.Context, android.view.ViewGroup);
+ public android.view.View apply(android.content.Context, android.view.ViewGroup, android.widget.RemoteViews$OnClickHandler);
+ public android.os.CancellationSignal applyAsync(android.content.Context, android.view.ViewGroup, java.util.concurrent.Executor, android.widget.RemoteViews$OnViewAppliedListener);
+ public android.os.CancellationSignal applyAsync(android.content.Context, android.view.ViewGroup, java.util.concurrent.Executor, android.widget.RemoteViews$OnViewAppliedListener, android.widget.RemoteViews$OnClickHandler);
+ public android.widget.RemoteViews clone();
+ public java.lang.Object clone();
+ public int describeContents();
+ public int estimateMemoryUsage();
+ public int getLayoutId();
+ public java.lang.String getPackage();
+ public int getSequenceNumber();
+ public boolean hasSameAppInfo(android.content.pm.ApplicationInfo);
+ public boolean isReapplyDisallowed();
+ public void mergeRemoteViews(android.widget.RemoteViews);
+ public boolean onLoadClass(java.lang.Class);
+ public void overrideTextColors(int);
+ public boolean prefersAsyncApply();
+ public void reapply(android.content.Context, android.view.View);
+ public void reapply(android.content.Context, android.view.View, android.widget.RemoteViews$OnClickHandler);
+ public android.os.CancellationSignal reapplyAsync(android.content.Context, android.view.View, java.util.concurrent.Executor, android.widget.RemoteViews$OnViewAppliedListener);
+ public android.os.CancellationSignal reapplyAsync(android.content.Context, android.view.View, java.util.concurrent.Executor, android.widget.RemoteViews$OnViewAppliedListener, android.widget.RemoteViews$OnClickHandler);
+ public void reduceImageSizes(int, int);
+ public void removeAllViews(int);
+ public void removeAllViewsExceptId(int, int);
+ public void setAccessibilityTraversalAfter(int, int);
+ public void setAccessibilityTraversalBefore(int, int);
+ public void setApplyTheme(int);
+ public void setBitmap(int, java.lang.String, android.graphics.Bitmap);
+ public void setBoolean(int, java.lang.String, boolean);
+ public void setBundle(int, java.lang.String, android.os.Bundle);
+ public void setByte(int, java.lang.String, byte);
+ public void setChar(int, java.lang.String, char);
+ public void setCharSequence(int, java.lang.String, java.lang.CharSequence);
+ public void setChronometer(int, long, java.lang.String, boolean);
+ public void setChronometerCountDown(int, boolean);
+ public void setColorStateList(int, java.lang.String, android.content.res.ColorStateList);
+ public void setContentDescription(int, java.lang.CharSequence);
+ public void setDisplayedChild(int, int);
+ public void setDouble(int, java.lang.String, double);
+ public void setDrawableTint(int, boolean, int, android.graphics.PorterDuff$Mode);
+ public void setEmptyView(int, int);
+ public void setFloat(int, java.lang.String, float);
+ public void setIcon(int, java.lang.String, android.graphics.drawable.Icon);
+ public void setImageViewBitmap(int, android.graphics.Bitmap);
+ public void setImageViewIcon(int, android.graphics.drawable.Icon);
+ public void setImageViewResource(int, int);
+ public void setImageViewUri(int, android.net.Uri);
+ public void setInt(int, java.lang.String, int);
+ public void setIntent(int, java.lang.String, android.content.Intent);
+ public void setLabelFor(int, int);
+ public void setLong(int, java.lang.String, long);
+ public void setOnClickFillInIntent(int, android.content.Intent);
+ public void setOnClickPendingIntent(int, android.app.PendingIntent);
+ public void setPendingIntentTemplate(int, android.app.PendingIntent);
+ public void setProgressBackgroundTintList(int, android.content.res.ColorStateList);
+ public void setProgressBar(int, int, int, boolean);
+ public void setProgressIndeterminateTintList(int, android.content.res.ColorStateList);
+ public void setProgressTintList(int, android.content.res.ColorStateList);
+ public void setReapplyDisallowed();
+ public void setRelativeScrollPosition(int, int);
+ public void setRemoteAdapter(int, int, android.content.Intent);
+ public void setRemoteAdapter(int, android.content.Intent);
+ public void setRemoteAdapter(int, java.util.ArrayList, int);
+ public void setRemoteInputs(int, android.app.RemoteInput[]);
+ public void setScrollPosition(int, int);
+ public void setShort(int, java.lang.String, short);
+ public void setString(int, java.lang.String, java.lang.String);
+ public void setTextColor(int, int);
+ public void setTextColor(int, android.content.res.ColorStateList);
+ public void setTextViewCompoundDrawables(int, int, int, int, int);
+ public void setTextViewCompoundDrawables(int, android.graphics.drawable.Icon, android.graphics.drawable.Icon, android.graphics.drawable.Icon, android.graphics.drawable.Icon);
+ public void setTextViewCompoundDrawablesRelative(int, int, int, int, int);
+ public void setTextViewCompoundDrawablesRelative(int, android.graphics.drawable.Icon, android.graphics.drawable.Icon, android.graphics.drawable.Icon, android.graphics.drawable.Icon);
+ public void setTextViewText(int, java.lang.CharSequence);
+ public void setTextViewTextSize(int, int, float);
+ public void setUri(int, java.lang.String, android.net.Uri);
+ public void setViewLayoutMarginBottomDimen(int, int);
+ public void setViewLayoutMarginEnd(int, int);
+ public void setViewLayoutMarginEndDimen(int, int);
+ public void setViewLayoutWidth(int, int);
+ public void setViewPadding(int, int, int, int, int);
+ public void setViewVisibility(int, int);
+ public void showNext(int);
+ public void showPrevious(int);
+ public void visitUris(java.util.function.Consumer);
+ public void writeToParcel(android.os.Parcel, int);
+
+
+ public static android.os.Parcelable$Creator CREATOR;
+ public android.content.pm.ApplicationInfo mApplication;
+}
+
+-keep class android.widget.RemoteViews$OnClickHandler {
+ <init>();
+
+ public boolean onClickHandler(android.view.View, android.app.PendingIntent, android.content.Intent);
+ public boolean onClickHandler(android.view.View, android.app.PendingIntent, android.content.Intent, int);
+ public void setEnterAnimationId(int);
+
+
+}
+
+-keep class android.widget.RemoteViews$OnViewAppliedListener {
+
+ public abstract void onError(java.lang.Exception);
+ public abstract void onViewApplied(android.view.View);
+
+
+}
+
+-keep class android.widget.SpinnerAdapter {
+
+ public abstract android.view.View getDropDownView(int, android.view.View, android.view.ViewGroup);
+
+
+}
+
+-keep class android.widget.Toolbar {
+ <init>(android.content.Context);
+ <init>(android.content.Context, android.util.AttributeSet);
+ <init>(android.content.Context, android.util.AttributeSet, int);
+ <init>(android.content.Context, android.util.AttributeSet, int, int);
+
+ public boolean canShowOverflowMenu();
+ protected boolean checkLayoutParams(android.view.ViewGroup$LayoutParams);
+ public void collapseActionView();
+ public void dismissPopupMenus();
+ protected android.widget.Toolbar$LayoutParams generateDefaultLayoutParams();
+ protected android.view.ViewGroup$LayoutParams generateDefaultLayoutParams();
+ public android.widget.Toolbar$LayoutParams generateLayoutParams(android.util.AttributeSet);
+ 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 int getContentInsetEnd();
+ public int getContentInsetEndWithActions();
+ public int getContentInsetLeft();
+ public int getContentInsetRight();
+ public int getContentInsetStart();
+ public int getContentInsetStartWithNavigation();
+ public int getCurrentContentInsetEnd();
+ public int getCurrentContentInsetLeft();
+ public int getCurrentContentInsetRight();
+ public int getCurrentContentInsetStart();
+ public android.graphics.drawable.Drawable getLogo();
+ public java.lang.CharSequence getLogoDescription();
+ public android.view.Menu getMenu();
+ public java.lang.CharSequence getNavigationContentDescription();
+ public android.graphics.drawable.Drawable getNavigationIcon();
+ public android.view.View getNavigationView();
+ public android.graphics.drawable.Drawable getOverflowIcon();
+ public int getPopupTheme();
+ public java.lang.CharSequence getSubtitle();
+ public java.lang.CharSequence getTitle();
+ public int getTitleMarginBottom();
+ public int getTitleMarginEnd();
+ public int getTitleMarginStart();
+ public int getTitleMarginTop();
+ public com.android.internal.widget.DecorToolbar getWrapper();
+ public boolean hasExpandedActionView();
+ public boolean hideOverflowMenu();
+ public void inflateMenu(int);
+ public boolean isOverflowMenuShowPending();
+ public boolean isOverflowMenuShowing();
+ public boolean isTitleTruncated();
+ protected void onAttachedToWindow();
+ protected void onDetachedFromWindow();
+ protected void onLayout(boolean, int, int, int, int);
+ protected void onMeasure(int, int);
+ protected void onRestoreInstanceState(android.os.Parcelable);
+ public void onRtlPropertiesChanged(int);
+ protected android.os.Parcelable onSaveInstanceState();
+ protected void onSetLayoutParams(android.view.View, android.view.ViewGroup$LayoutParams);
+ public boolean onTouchEvent(android.view.MotionEvent);
+ public void setCollapsible(boolean);
+ public void setContentInsetEndWithActions(int);
+ public void setContentInsetStartWithNavigation(int);
+ public void setContentInsetsAbsolute(int, int);
+ public void setContentInsetsRelative(int, int);
+ public void setLogo(int);
+ public void setLogo(android.graphics.drawable.Drawable);
+ public void setLogoDescription(int);
+ public void setLogoDescription(java.lang.CharSequence);
+ public void setMenu(com.android.internal.view.menu.MenuBuilder, android.widget.ActionMenuPresenter);
+ public void setMenuCallbacks(com.android.internal.view.menu.MenuPresenter$Callback, com.android.internal.view.menu.MenuBuilder$Callback);
+ public void setNavigationContentDescription(int);
+ public void setNavigationContentDescription(java.lang.CharSequence);
+ public void setNavigationIcon(int);
+ public void setNavigationIcon(android.graphics.drawable.Drawable);
+ public void setNavigationOnClickListener(android.view.View$OnClickListener);
+ public void setOnMenuItemClickListener(android.widget.Toolbar$OnMenuItemClickListener);
+ public void setOverflowIcon(android.graphics.drawable.Drawable);
+ public void setPopupTheme(int);
+ public void setSubtitle(int);
+ public void setSubtitle(java.lang.CharSequence);
+ public void setSubtitleTextAppearance(android.content.Context, int);
+ public void setSubtitleTextColor(int);
+ public void setTitle(int);
+ public void setTitle(java.lang.CharSequence);
+ public void setTitleMargin(int, int, int, int);
+ public void setTitleMarginBottom(int);
+ public void setTitleMarginEnd(int);
+ public void setTitleMarginStart(int);
+ public void setTitleMarginTop(int);
+ public void setTitleTextAppearance(android.content.Context, int);
+ public void setTitleTextColor(int);
+ public boolean showOverflowMenu();
+
+
+}
+
+-keep class android.widget.Toolbar$LayoutParams {
+ <init>(android.content.Context, android.util.AttributeSet);
+ <init>(int, int);
+ <init>(int, int, int);
+ <init>(int);
+ <init>(android.widget.Toolbar$LayoutParams);
+ <init>(android.app.ActionBar$LayoutParams);
+ <init>(android.view.ViewGroup$MarginLayoutParams);
+ <init>(android.view.ViewGroup$LayoutParams);
+
+
+
+}
+
+-keep class android.widget.Toolbar$OnMenuItemClickListener {
+
+ public abstract boolean onMenuItemClick(android.view.MenuItem);
+
+
+}
+
+-keep class com.android.internal.app.IAppOpsActiveCallback {
+
+ public abstract void opActiveChanged(int, int, java.lang.String, boolean);
+
+
+}
+
+-keep class com.android.internal.app.IAppOpsCallback {
+
+ public abstract void opChanged(int, int, java.lang.String);
+
+
+}
+
+-keep class com.android.internal.app.IAppOpsService {
+
+ public abstract int checkAudioOperation(int, int, int, java.lang.String);
+ public abstract int checkOperation(int, int, java.lang.String);
+ public abstract int checkPackage(int, java.lang.String);
+ public abstract void finishOperation(android.os.IBinder, int, int, java.lang.String);
+ public abstract java.util.List getOpsForPackage(int, java.lang.String, int[]);
+ public abstract java.util.List getPackagesForOps(int[]);
+ public abstract android.os.IBinder getToken(android.os.IBinder);
+ public abstract java.util.List getUidOps(int, int[]);
+ public abstract boolean isOperationActive(int, int, java.lang.String);
+ public abstract int noteOperation(int, int, java.lang.String);
+ public abstract int noteProxyOperation(int, java.lang.String, int, java.lang.String);
+ public abstract int permissionToOpCode(java.lang.String);
+ public abstract void removeUser(int);
+ public abstract void resetAllModes(int, java.lang.String);
+ public abstract void setAudioRestriction(int, int, int, int, java.lang.String[]);
+ public abstract void setMode(int, int, java.lang.String, int);
+ public abstract void setUidMode(int, int, int);
+ public abstract void setUserRestriction(int, boolean, android.os.IBinder, int, java.lang.String[]);
+ public abstract void setUserRestrictions(android.os.Bundle, android.os.IBinder, int);
+ public abstract int startOperation(android.os.IBinder, int, int, java.lang.String, boolean);
+ public abstract void startWatchingActive(int[], com.android.internal.app.IAppOpsActiveCallback);
+ public abstract void startWatchingMode(int, java.lang.String, com.android.internal.app.IAppOpsCallback);
+ public abstract void startWatchingModeWithFlags(int, java.lang.String, int, com.android.internal.app.IAppOpsCallback);
+ public abstract void stopWatchingActive(com.android.internal.app.IAppOpsActiveCallback);
+ public abstract void stopWatchingMode(com.android.internal.app.IAppOpsCallback);
+
+
+}
+
+-keep class com.android.internal.app.IVoiceInteractionSessionShowCallback {
+
+ public abstract void onFailed();
+ public abstract void onShown();
+
+
+}
+
+-keep class com.android.internal.app.IVoiceInteractor {
+
+ public abstract com.android.internal.app.IVoiceInteractorRequest startAbortVoice(java.lang.String, com.android.internal.app.IVoiceInteractorCallback, android.app.VoiceInteractor$Prompt, android.os.Bundle);
+ public abstract com.android.internal.app.IVoiceInteractorRequest startCommand(java.lang.String, com.android.internal.app.IVoiceInteractorCallback, java.lang.String, android.os.Bundle);
+ public abstract com.android.internal.app.IVoiceInteractorRequest startCompleteVoice(java.lang.String, com.android.internal.app.IVoiceInteractorCallback, android.app.VoiceInteractor$Prompt, android.os.Bundle);
+ public abstract com.android.internal.app.IVoiceInteractorRequest startConfirmation(java.lang.String, com.android.internal.app.IVoiceInteractorCallback, android.app.VoiceInteractor$Prompt, android.os.Bundle);
+ public abstract com.android.internal.app.IVoiceInteractorRequest startPickOption(java.lang.String, com.android.internal.app.IVoiceInteractorCallback, android.app.VoiceInteractor$Prompt, android.app.VoiceInteractor$PickOptionRequest$Option[], android.os.Bundle);
+ public abstract boolean[] supportsCommands(java.lang.String, java.lang.String[]);
+
+
+}
+
+-keep class com.android.internal.app.IVoiceInteractorCallback {
+
+ public abstract void deliverAbortVoiceResult(com.android.internal.app.IVoiceInteractorRequest, android.os.Bundle);
+ public abstract void deliverCancel(com.android.internal.app.IVoiceInteractorRequest);
+ public abstract void deliverCommandResult(com.android.internal.app.IVoiceInteractorRequest, boolean, android.os.Bundle);
+ public abstract void deliverCompleteVoiceResult(com.android.internal.app.IVoiceInteractorRequest, android.os.Bundle);
+ public abstract void deliverConfirmationResult(com.android.internal.app.IVoiceInteractorRequest, boolean, android.os.Bundle);
+ public abstract void deliverPickOptionResult(com.android.internal.app.IVoiceInteractorRequest, boolean, android.app.VoiceInteractor$PickOptionRequest$Option[], android.os.Bundle);
+
+
+}
+
+-keep class com.android.internal.app.IVoiceInteractorRequest {
+
+ public abstract void cancel();
+
+
+}
+
+-keep class com.android.internal.content.ReferrerIntent {
+ <init>(android.content.Intent, java.lang.String);
+
+ public boolean equals(java.lang.Object);
+ public int hashCode();
+ public void writeToParcel(android.os.Parcel, int);
+
+
+ public static android.os.Parcelable$Creator CREATOR;
+ public java.lang.String mReferrer;
+}
+
+-keep class com.android.internal.os.IResultReceiver {
+
+ public abstract void send(int, android.os.Bundle);
+
+
+}
+
+-keep class com.android.internal.policy.IKeyguardDismissCallback {
+
+ public abstract void onDismissCancelled();
+ public abstract void onDismissError();
+ public abstract void onDismissSucceeded();
+
+
+}
+
+-keep class com.android.internal.util.FunctionalUtils {
+
+ public static java.lang.Runnable handleExceptions(com.android.internal.util.FunctionalUtils$ThrowingRunnable, java.util.function.Consumer);
+ public static java.util.function.Consumer ignoreRemoteException(com.android.internal.util.FunctionalUtils$RemoteExceptionIgnoringConsumer);
+ public static java.util.function.Consumer uncheckExceptions(com.android.internal.util.FunctionalUtils$ThrowingConsumer);
+
+
+}
+
+-keep class com.android.internal.util.FunctionalUtils$RemoteExceptionIgnoringConsumer {
+
+ public void accept(java.lang.Object);
+ public abstract void acceptOrThrow(java.lang.Object);
+
+
+}
+
+-keep class com.android.internal.util.FunctionalUtils$ThrowingConsumer {
+
+ public void accept(java.lang.Object);
+ public abstract void acceptOrThrow(java.lang.Object);
+
+
+}
+
+-keep class com.android.internal.util.FunctionalUtils$ThrowingRunnable {
+
+ public void run();
+ public abstract void runOrThrow();
+
+
+}
+
+-keep class com.android.internal.util.FunctionalUtils$ThrowingSupplier {
+
+ public abstract java.lang.Object getOrThrow();
+
+
+}
+
+-keep class com.android.internal.util.IndentingPrintWriter {
+ <init>(java.io.Writer, java.lang.String);
+ <init>(java.io.Writer, java.lang.String, int);
+
+ public com.android.internal.util.IndentingPrintWriter decreaseIndent();
+ public com.android.internal.util.IndentingPrintWriter increaseIndent();
+ public com.android.internal.util.IndentingPrintWriter printHexPair(java.lang.String, int);
+ public com.android.internal.util.IndentingPrintWriter printPair(java.lang.String, java.lang.Object);
+ public com.android.internal.util.IndentingPrintWriter printPair(java.lang.String, java.lang.Object[]);
+ public void println();
+ public com.android.internal.util.IndentingPrintWriter setIndent(java.lang.String);
+ public com.android.internal.util.IndentingPrintWriter setIndent(int);
+ public void write(int);
+ public void write(java.lang.String, int, int);
+ public void write(char[], int, int);
+
+
+}
+
+-keep class com.android.internal.view.IDragAndDropPermissions {
+
+ public abstract void release();
+ public abstract void take(android.os.IBinder);
+ public abstract void takeTransient(android.os.IBinder);
+
+
+}
+
+-keep class com.android.internal.view.menu.BaseMenuPresenter {
+ <init>(android.content.Context, int, int);
+
+ protected void addItemView(android.view.View, int);
+ public abstract void bindItemView(com.android.internal.view.menu.MenuItemImpl, com.android.internal.view.menu.MenuView$ItemView);
+ public boolean collapseItemActionView(com.android.internal.view.menu.MenuBuilder, com.android.internal.view.menu.MenuItemImpl);
+ public com.android.internal.view.menu.MenuView$ItemView createItemView(android.view.ViewGroup);
+ public boolean expandItemActionView(com.android.internal.view.menu.MenuBuilder, com.android.internal.view.menu.MenuItemImpl);
+ protected boolean filterLeftoverView(android.view.ViewGroup, int);
+ public boolean flagActionItems();
+ public com.android.internal.view.menu.MenuPresenter$Callback getCallback();
+ public int getId();
+ public android.view.View getItemView(com.android.internal.view.menu.MenuItemImpl, android.view.View, android.view.ViewGroup);
+ public com.android.internal.view.menu.MenuView getMenuView(android.view.ViewGroup);
+ public void initForMenu(android.content.Context, com.android.internal.view.menu.MenuBuilder);
+ public void onCloseMenu(com.android.internal.view.menu.MenuBuilder, boolean);
+ public boolean onSubMenuSelected(com.android.internal.view.menu.SubMenuBuilder);
+ public void setCallback(com.android.internal.view.menu.MenuPresenter$Callback);
+ public void setId(int);
+ public boolean shouldIncludeItem(int, com.android.internal.view.menu.MenuItemImpl);
+ public void updateMenuView(boolean);
+
+
+ protected android.content.Context mContext;
+ protected android.view.LayoutInflater mInflater;
+ protected com.android.internal.view.menu.MenuBuilder mMenu;
+ protected com.android.internal.view.menu.MenuView mMenuView;
+ protected android.content.Context mSystemContext;
+ protected android.view.LayoutInflater mSystemInflater;
+}
+
+-keep class com.android.internal.view.menu.MenuBuilder {
+ <init>(android.content.Context);
+
+ public android.view.MenuItem add(java.lang.CharSequence);
+ public android.view.MenuItem add(int);
+ public android.view.MenuItem add(int, int, int, java.lang.CharSequence);
+ public android.view.MenuItem add(int, int, int, int);
+ public int addIntentOptions(int, int, int, android.content.ComponentName, android.content.Intent[], android.content.Intent, int, android.view.MenuItem[]);
+ public void addMenuPresenter(com.android.internal.view.menu.MenuPresenter);
+ public void addMenuPresenter(com.android.internal.view.menu.MenuPresenter, android.content.Context);
+ public android.view.SubMenu addSubMenu(java.lang.CharSequence);
+ public android.view.SubMenu addSubMenu(int);
+ public android.view.SubMenu addSubMenu(int, int, int, java.lang.CharSequence);
+ public android.view.SubMenu addSubMenu(int, int, int, int);
+ public void changeMenuMode();
+ public void clear();
+ public void clearAll();
+ public void clearHeader();
+ public void close(boolean);
+ public void close();
+ public boolean collapseItemActionView(com.android.internal.view.menu.MenuItemImpl);
+ public boolean expandItemActionView(com.android.internal.view.menu.MenuItemImpl);
+ public int findGroupIndex(int);
+ public int findGroupIndex(int, int);
+ public android.view.MenuItem findItem(int);
+ public int findItemIndex(int);
+ public void flagActionItems();
+ public java.util.ArrayList getActionItems();
+ protected java.lang.String getActionViewStatesKey();
+ public android.content.Context getContext();
+ public com.android.internal.view.menu.MenuItemImpl getExpandedItem();
+ public android.graphics.drawable.Drawable getHeaderIcon();
+ public java.lang.CharSequence getHeaderTitle();
+ public android.view.View getHeaderView();
+ public android.view.MenuItem getItem(int);
+ public java.util.ArrayList getNonActionItems();
+ public com.android.internal.view.menu.MenuBuilder getRootMenu();
+ public java.util.ArrayList getVisibleItems();
+ public boolean hasVisibleItems();
+ public boolean isGroupDividerEnabled();
+ public boolean isShortcutKey(int, android.view.KeyEvent);
+ public boolean isShortcutsVisible();
+ public void onItemsChanged(boolean);
+ public boolean performIdentifierAction(int, int);
+ public boolean performItemAction(android.view.MenuItem, int);
+ public boolean performItemAction(android.view.MenuItem, com.android.internal.view.menu.MenuPresenter, int);
+ public boolean performShortcut(int, android.view.KeyEvent, int);
+ public void removeGroup(int);
+ public void removeItem(int);
+ public void removeItemAt(int);
+ public void removeMenuPresenter(com.android.internal.view.menu.MenuPresenter);
+ public void restoreActionViewStates(android.os.Bundle);
+ public void restorePresenterStates(android.os.Bundle);
+ public void saveActionViewStates(android.os.Bundle);
+ public void savePresenterStates(android.os.Bundle);
+ public void setCallback(com.android.internal.view.menu.MenuBuilder$Callback);
+ public void setCurrentMenuInfo(android.view.ContextMenu$ContextMenuInfo);
+ public com.android.internal.view.menu.MenuBuilder setDefaultShowAsAction(int);
+ public void setGroupCheckable(int, boolean, boolean);
+ public void setGroupDividerEnabled(boolean);
+ public void setGroupEnabled(int, boolean);
+ public void setGroupVisible(int, boolean);
+ protected com.android.internal.view.menu.MenuBuilder setHeaderIconInt(android.graphics.drawable.Drawable);
+ protected com.android.internal.view.menu.MenuBuilder setHeaderIconInt(int);
+ protected com.android.internal.view.menu.MenuBuilder setHeaderTitleInt(java.lang.CharSequence);
+ protected com.android.internal.view.menu.MenuBuilder setHeaderTitleInt(int);
+ protected com.android.internal.view.menu.MenuBuilder setHeaderViewInt(android.view.View);
+ public void setQwertyMode(boolean);
+ public void setShortcutsVisible(boolean);
+ public int size();
+ public void startDispatchingItemsChanged();
+ public void stopDispatchingItemsChanged();
+
+
+}
+
+-keep class com.android.internal.view.menu.MenuBuilder$Callback {
+
+ public abstract boolean onMenuItemSelected(com.android.internal.view.menu.MenuBuilder, android.view.MenuItem);
+ public abstract void onMenuModeChange(com.android.internal.view.menu.MenuBuilder);
+
+
+}
+
+-keep class com.android.internal.view.menu.MenuItemImpl {
+
+ public void actionFormatChanged();
+ public boolean collapseActionView();
+ public boolean expandActionView();
+ public android.view.ActionProvider getActionProvider();
+ public android.view.View getActionView();
+ public int getAlphabeticModifiers();
+ public char getAlphabeticShortcut();
+ public java.lang.CharSequence getContentDescription();
+ public int getGroupId();
+ public android.graphics.drawable.Drawable getIcon();
+ public android.content.res.ColorStateList getIconTintList();
+ public android.graphics.PorterDuff$Mode getIconTintMode();
+ public android.content.Intent getIntent();
+ public int getItemId();
+ public android.view.ContextMenu$ContextMenuInfo getMenuInfo();
+ public int getNumericModifiers();
+ public char getNumericShortcut();
+ public int getOrder();
+ public int getOrdering();
+ public android.view.SubMenu getSubMenu();
+ public java.lang.CharSequence getTitle();
+ public java.lang.CharSequence getTitleCondensed();
+ public java.lang.CharSequence getTooltipText();
+ public boolean hasCollapsibleActionView();
+ public boolean hasSubMenu();
+ public boolean invoke();
+ public boolean isActionButton();
+ public boolean isActionViewExpanded();
+ public boolean isCheckable();
+ public boolean isChecked();
+ public boolean isEnabled();
+ public boolean isExclusiveCheckable();
+ public boolean isVisible();
+ public boolean requestsActionButton();
+ public boolean requiresActionButton();
+ public boolean requiresOverflow();
+ public android.view.MenuItem setActionProvider(android.view.ActionProvider);
+ public android.view.MenuItem setActionView(android.view.View);
+ public android.view.MenuItem setActionView(int);
+ public void setActionViewExpanded(boolean);
+ public android.view.MenuItem setAlphabeticShortcut(char);
+ public android.view.MenuItem setAlphabeticShortcut(char, int);
+ public android.view.MenuItem setCallback(java.lang.Runnable);
+ public android.view.MenuItem setCheckable(boolean);
+ public android.view.MenuItem setChecked(boolean);
+ public android.view.MenuItem setContentDescription(java.lang.CharSequence);
+ public android.view.MenuItem setEnabled(boolean);
+ public void setExclusiveCheckable(boolean);
+ public android.view.MenuItem setIcon(android.graphics.drawable.Drawable);
+ public android.view.MenuItem setIcon(int);
+ public android.view.MenuItem setIconTintList(android.content.res.ColorStateList);
+ public android.view.MenuItem setIconTintMode(android.graphics.PorterDuff$Mode);
+ public android.view.MenuItem setIntent(android.content.Intent);
+ public void setIsActionButton(boolean);
+ public android.view.MenuItem setNumericShortcut(char);
+ public android.view.MenuItem setNumericShortcut(char, int);
+ public android.view.MenuItem setOnActionExpandListener(android.view.MenuItem$OnActionExpandListener);
+ public android.view.MenuItem setOnMenuItemClickListener(android.view.MenuItem$OnMenuItemClickListener);
+ public android.view.MenuItem setShortcut(char, char);
+ public android.view.MenuItem setShortcut(char, char, int, int);
+ public void setShowAsAction(int);
+ public android.view.MenuItem setShowAsActionFlags(int);
+ public android.view.MenuItem setTitle(java.lang.CharSequence);
+ public android.view.MenuItem setTitle(int);
+ public android.view.MenuItem setTitleCondensed(java.lang.CharSequence);
+ public android.view.MenuItem setTooltipText(java.lang.CharSequence);
+ public android.view.MenuItem setVisible(boolean);
+ public boolean shouldShowIcon();
+ public boolean showsTextAsAction();
+ public java.lang.String toString();
+
+
+}
+
+-keep class com.android.internal.view.menu.MenuPresenter {
+
+ public abstract boolean collapseItemActionView(com.android.internal.view.menu.MenuBuilder, com.android.internal.view.menu.MenuItemImpl);
+ public abstract boolean expandItemActionView(com.android.internal.view.menu.MenuBuilder, com.android.internal.view.menu.MenuItemImpl);
+ public abstract boolean flagActionItems();
+ public abstract int getId();
+ public abstract com.android.internal.view.menu.MenuView getMenuView(android.view.ViewGroup);
+ public abstract void initForMenu(android.content.Context, com.android.internal.view.menu.MenuBuilder);
+ public abstract void onCloseMenu(com.android.internal.view.menu.MenuBuilder, boolean);
+ public abstract void onRestoreInstanceState(android.os.Parcelable);
+ public abstract android.os.Parcelable onSaveInstanceState();
+ public abstract boolean onSubMenuSelected(com.android.internal.view.menu.SubMenuBuilder);
+ public abstract void setCallback(com.android.internal.view.menu.MenuPresenter$Callback);
+ public abstract void updateMenuView(boolean);
+
+
+}
+
+-keep class com.android.internal.view.menu.MenuPresenter$Callback {
+
+ public abstract void onCloseMenu(com.android.internal.view.menu.MenuBuilder, boolean);
+ public abstract boolean onOpenSubMenu(com.android.internal.view.menu.MenuBuilder);
+
+
+}
+
+-keep class com.android.internal.view.menu.MenuView {
+
+ public abstract int getWindowAnimations();
+ public abstract void initialize(com.android.internal.view.menu.MenuBuilder);
+
+
+}
+
+-keep class com.android.internal.view.menu.MenuView$ItemView {
+
+ public abstract com.android.internal.view.menu.MenuItemImpl getItemData();
+ public abstract void initialize(com.android.internal.view.menu.MenuItemImpl, int);
+ public abstract boolean prefersCondensedTitle();
+ public abstract void setCheckable(boolean);
+ public abstract void setChecked(boolean);
+ public abstract void setEnabled(boolean);
+ public abstract void setIcon(android.graphics.drawable.Drawable);
+ public abstract void setShortcut(boolean, char);
+ public abstract void setTitle(java.lang.CharSequence);
+ public abstract boolean showsIcon();
+
+
+}
+
+-keep class com.android.internal.view.menu.SubMenuBuilder {
+ <init>(android.content.Context, com.android.internal.view.menu.MenuBuilder, com.android.internal.view.menu.MenuItemImpl);
+
+ public boolean collapseItemActionView(com.android.internal.view.menu.MenuItemImpl);
+ public boolean expandItemActionView(com.android.internal.view.menu.MenuItemImpl);
+ public java.lang.String getActionViewStatesKey();
+ public android.view.MenuItem getItem();
+ public android.view.Menu getParentMenu();
+ public com.android.internal.view.menu.MenuBuilder getRootMenu();
+ public boolean isGroupDividerEnabled();
+ public boolean isQwertyMode();
+ public boolean isShortcutsVisible();
+ public void setCallback(com.android.internal.view.menu.MenuBuilder$Callback);
+ public void setGroupDividerEnabled(boolean);
+ public android.view.SubMenu setHeaderIcon(android.graphics.drawable.Drawable);
+ public android.view.SubMenu setHeaderIcon(int);
+ public android.view.SubMenu setHeaderTitle(java.lang.CharSequence);
+ public android.view.SubMenu setHeaderTitle(int);
+ public android.view.SubMenu setHeaderView(android.view.View);
+ public android.view.SubMenu setIcon(android.graphics.drawable.Drawable);
+ public android.view.SubMenu setIcon(int);
+ public void setQwertyMode(boolean);
+ public void setShortcutsVisible(boolean);
+
+
+}
+
+-keep class com.android.internal.widget.DecorToolbar {
+
+ public abstract void animateToVisibility(int);
+ public abstract boolean canShowOverflowMenu();
+ public abstract boolean canSplit();
+ public abstract void collapseActionView();
+ public abstract void dismissPopupMenus();
+ public abstract android.content.Context getContext();
+ public abstract android.view.View getCustomView();
+ public abstract int getDisplayOptions();
+ public abstract int getDropdownItemCount();
+ public abstract int getDropdownSelectedPosition();
+ public abstract int getHeight();
+ public abstract android.view.Menu getMenu();
+ public abstract int getNavigationMode();
+ public abstract java.lang.CharSequence getSubtitle();
+ public abstract java.lang.CharSequence getTitle();
+ public abstract android.view.ViewGroup getViewGroup();
+ public abstract int getVisibility();
+ public abstract boolean hasEmbeddedTabs();
+ public abstract boolean hasExpandedActionView();
+ public abstract boolean hasIcon();
+ public abstract boolean hasLogo();
+ public abstract boolean hideOverflowMenu();
+ public abstract void initIndeterminateProgress();
+ public abstract void initProgress();
+ public abstract boolean isOverflowMenuShowPending();
+ public abstract boolean isOverflowMenuShowing();
+ public abstract boolean isSplit();
+ public abstract boolean isTitleTruncated();
+ public abstract void restoreHierarchyState(android.util.SparseArray);
+ public abstract void saveHierarchyState(android.util.SparseArray);
+ public abstract void setBackgroundDrawable(android.graphics.drawable.Drawable);
+ public abstract void setCollapsible(boolean);
+ public abstract void setCustomView(android.view.View);
+ public abstract void setDefaultNavigationContentDescription(int);
+ public abstract void setDefaultNavigationIcon(android.graphics.drawable.Drawable);
+ public abstract void setDisplayOptions(int);
+ public abstract void setDropdownParams(android.widget.SpinnerAdapter, android.widget.AdapterView$OnItemSelectedListener);
+ public abstract void setDropdownSelectedPosition(int);
+ public abstract void setEmbeddedTabView(com.android.internal.widget.ScrollingTabContainerView);
+ public abstract void setHomeButtonEnabled(boolean);
+ public abstract void setIcon(int);
+ public abstract void setIcon(android.graphics.drawable.Drawable);
+ public abstract void setLogo(int);
+ public abstract void setLogo(android.graphics.drawable.Drawable);
+ public abstract void setMenu(android.view.Menu, com.android.internal.view.menu.MenuPresenter$Callback);
+ public abstract void setMenuCallbacks(com.android.internal.view.menu.MenuPresenter$Callback, com.android.internal.view.menu.MenuBuilder$Callback);
+ public abstract void setMenuPrepared();
+ public abstract void setNavigationContentDescription(java.lang.CharSequence);
+ public abstract void setNavigationContentDescription(int);
+ public abstract void setNavigationIcon(android.graphics.drawable.Drawable);
+ public abstract void setNavigationIcon(int);
+ public abstract void setNavigationMode(int);
+ public abstract void setSplitToolbar(boolean);
+ public abstract void setSplitView(android.view.ViewGroup);
+ public abstract void setSplitWhenNarrow(boolean);
+ public abstract void setSubtitle(java.lang.CharSequence);
+ public abstract void setTitle(java.lang.CharSequence);
+ public abstract void setVisibility(int);
+ public abstract void setWindowCallback(android.view.Window$Callback);
+ public abstract void setWindowTitle(java.lang.CharSequence);
+ public abstract android.animation.Animator setupAnimatorToVisibility(int, long);
+ public abstract boolean showOverflowMenu();
+
+
+}
+
+-keep class com.android.internal.widget.ScrollingTabContainerView {
+ <init>(android.content.Context);
+
+ public void addTab(android.app.ActionBar$Tab, boolean);
+ public void addTab(android.app.ActionBar$Tab, int, boolean);
+ public void animateToTab(int);
+ public void animateToVisibility(int);
+ public void onAttachedToWindow();
+ protected void onConfigurationChanged(android.content.res.Configuration);
+ public void onDetachedFromWindow();
+ public void onItemClick(android.widget.AdapterView, android.view.View, int, long);
+ public void onMeasure(int, int);
+ public void removeAllTabs();
+ public void removeTabAt(int);
+ public void setAllowCollapse(boolean);
+ public void setContentHeight(int);
+ public void setTabSelected(int);
+ public void updateTab(int);
+
+
+ protected com.android.internal.widget.ScrollingTabContainerView$VisibilityAnimListener mVisAnimListener;
+ protected android.animation.Animator mVisibilityAnim;
+}
+
+-keep class com.android.internal.widget.ScrollingTabContainerView$VisibilityAnimListener {
+ <init>();
+
+ public void onAnimationCancel(android.animation.Animator);
+ public void onAnimationEnd(android.animation.Animator);
+ public void onAnimationRepeat(android.animation.Animator);
+ public void onAnimationStart(android.animation.Animator);
+ public com.android.internal.widget.ScrollingTabContainerView$VisibilityAnimListener withFinalVisibility(int);
+
+
+}
+
+-keep class java.io.BufferedWriter {
+ <init>(java.io.Writer);
+ <init>(java.io.Writer, int);
+
+ public void close();
+ public void flush();
+ public void newLine();
+ public void write(int);
+ public void write(char[], int, int);
+ public void write(java.lang.String, int, int);
+
+
+}
+
+-keep class java.io.ByteArrayOutputStream {
+ <init>();
+ <init>(int);
+
+ public void close();
+ public synchronized void reset();
+ public synchronized int size();
+ public synchronized byte[] toByteArray();
+ public synchronized java.lang.String toString();
+ public synchronized java.lang.String toString(java.lang.String);
+ public synchronized java.lang.String toString(int);
+ public synchronized void write(int);
+ public synchronized void write(byte[], int, int);
+ public synchronized void writeTo(java.io.OutputStream);
+
+
+ protected byte[] buf;
+ protected int count;
+}
+
+-keep class java.io.DataOutputStream {
+ <init>(java.io.OutputStream);
+
+ public void flush();
+ public int size();
+ public synchronized void write(int);
+ public synchronized void write(byte[], int, int);
+ public void writeBoolean(boolean);
+ public void writeByte(int);
+ public void writeBytes(java.lang.String);
+ public void writeChar(int);
+ public void writeChars(java.lang.String);
+ public void writeDouble(double);
+ public void writeFloat(float);
+ public void writeInt(int);
+ public void writeLong(long);
+ public void writeShort(int);
+ public void writeUTF(java.lang.String);
+
+
+ protected int written;
+}
+
-keep class java.io.File {
- <init>(java.io.File, java.lang.String);
<init>(java.lang.String);
<init>(java.lang.String, java.lang.String);
+ <init>(java.io.File, java.lang.String);
<init>(java.net.URI);
public boolean canExecute();
@@ -6250,8 +24124,8 @@
public int compareTo(java.io.File);
public int compareTo(java.lang.Object);
public boolean createNewFile();
- public static java.io.File createTempFile(java.lang.String, java.lang.String);
public static java.io.File createTempFile(java.lang.String, java.lang.String, java.io.File);
+ public static java.io.File createTempFile(java.lang.String, java.lang.String);
public boolean delete();
public void deleteOnExit();
public boolean equals(java.lang.Object);
@@ -6291,6 +24165,7 @@
public boolean setReadable(boolean);
public boolean setWritable(boolean, boolean);
public boolean setWritable(boolean);
+ public java.nio.file.Path toPath();
public java.lang.String toString();
public java.net.URI toURI();
public java.net.URL toURL();
@@ -6305,8 +24180,10 @@
-keep class java.io.FileDescriptor {
<init>();
+ public int getInt$();
+ public boolean isSocket$();
+ public void setInt$(int);
public void sync();
- public java.lang.String toString();
public boolean valid();
@@ -6323,9 +24200,10 @@
}
-keep class java.io.FileInputStream {
+ <init>(java.lang.String);
<init>(java.io.File);
<init>(java.io.FileDescriptor);
- <init>(java.lang.String);
+ <init>(java.io.FileDescriptor, boolean);
public int available();
public void close();
@@ -6333,6 +24211,7 @@
public java.nio.channels.FileChannel getChannel();
public java.io.FileDescriptor getFD();
public int read();
+ public int read(byte[]);
public int read(byte[], int, int);
public long skip(long);
@@ -6348,18 +24227,20 @@
}
-keep class java.io.FileOutputStream {
+ <init>(java.lang.String);
+ <init>(java.lang.String, boolean);
<init>(java.io.File);
<init>(java.io.File, boolean);
<init>(java.io.FileDescriptor);
- <init>(java.lang.String);
- <init>(java.lang.String, boolean);
+ <init>(java.io.FileDescriptor, boolean);
public void close();
protected void finalize();
public java.nio.channels.FileChannel getChannel();
public java.io.FileDescriptor getFD();
- public void write(byte[], int, int);
public void write(int);
+ public void write(byte[]);
+ public void write(byte[], int, int);
}
@@ -6376,8 +24257,9 @@
public void close();
public void flush();
- public void write(byte[], int, int);
public void write(int);
+ public void write(byte[]);
+ public void write(byte[], int, int);
protected java.io.OutputStream out;
@@ -6398,7 +24280,7 @@
public int available();
public void close();
- public void mark(int);
+ public synchronized void mark(int);
public boolean markSupported();
public abstract int read();
public int read(byte[]);
@@ -6409,22 +24291,29 @@
}
--keep class java.io.ObjectStreamException {
- <init>();
+-keep class java.io.InvalidObjectException {
<init>(java.lang.String);
}
+-keep class java.io.ObjectStreamException {
+ <init>(java.lang.String);
+ <init>();
+
+
+
+}
+
-keep class java.io.OutputStream {
<init>();
public void close();
public void flush();
+ public abstract void write(int);
public void write(byte[]);
public void write(byte[], int, int);
- public abstract void write(int);
}
@@ -6433,103 +24322,103 @@
<init>(java.io.OutputStream);
<init>(java.io.OutputStream, boolean);
<init>(java.io.OutputStream, boolean, java.lang.String);
- <init>(java.io.File);
- <init>(java.io.File, java.lang.String);
<init>(java.lang.String);
<init>(java.lang.String, java.lang.String);
+ <init>(java.io.File);
+ <init>(java.io.File, java.lang.String);
- public java.io.PrintStream append(char);
public java.io.PrintStream append(java.lang.CharSequence);
public java.io.PrintStream append(java.lang.CharSequence, int, int);
+ public java.io.PrintStream append(char);
+ public java.lang.Appendable append(char);
public java.lang.Appendable append(java.lang.CharSequence, int, int);
public java.lang.Appendable append(java.lang.CharSequence);
- public java.lang.Appendable append(char);
public boolean checkError();
protected void clearError();
- public synchronized void close();
- public synchronized void flush();
+ public void close();
+ public void flush();
public java.io.PrintStream format(java.lang.String, java.lang.Object[]);
public java.io.PrintStream format(java.util.Locale, java.lang.String, java.lang.Object[]);
- public void print(char[]);
+ public void print(boolean);
public void print(char);
- public void print(double);
- public void print(float);
public void print(int);
public void print(long);
+ public void print(float);
+ public void print(double);
+ public void print(char[]);
+ public void print(java.lang.String);
public void print(java.lang.Object);
- public synchronized void print(java.lang.String);
- public void print(boolean);
public java.io.PrintStream printf(java.lang.String, java.lang.Object[]);
public java.io.PrintStream printf(java.util.Locale, java.lang.String, java.lang.Object[]);
public void println();
- public void println(char[]);
+ public void println(boolean);
public void println(char);
- public void println(double);
- public void println(float);
public void println(int);
public void println(long);
+ public void println(float);
+ public void println(double);
+ public void println(char[]);
+ public void println(java.lang.String);
public void println(java.lang.Object);
- public synchronized void println(java.lang.String);
- public void println(boolean);
protected void setError();
+ public void write(int);
public void write(byte[], int, int);
- public synchronized void write(int);
}
-keep class java.io.PrintWriter {
- <init>(java.io.OutputStream);
- <init>(java.io.OutputStream, boolean);
<init>(java.io.Writer);
<init>(java.io.Writer, boolean);
- <init>(java.io.File);
- <init>(java.io.File, java.lang.String);
+ <init>(java.io.OutputStream);
+ <init>(java.io.OutputStream, boolean);
<init>(java.lang.String);
<init>(java.lang.String, java.lang.String);
+ <init>(java.io.File);
+ <init>(java.io.File, java.lang.String);
- public java.io.PrintWriter append(char);
public java.io.PrintWriter append(java.lang.CharSequence);
public java.io.PrintWriter append(java.lang.CharSequence, int, int);
+ public java.io.PrintWriter append(char);
+ public java.io.Writer append(char);
public java.io.Writer append(java.lang.CharSequence, int, int);
public java.io.Writer append(java.lang.CharSequence);
- public java.io.Writer append(char);
+ public java.lang.Appendable append(char);
public java.lang.Appendable append(java.lang.CharSequence, int, int);
public java.lang.Appendable append(java.lang.CharSequence);
- public java.lang.Appendable append(char);
public boolean checkError();
protected void clearError();
public void close();
public void flush();
public java.io.PrintWriter format(java.lang.String, java.lang.Object[]);
public java.io.PrintWriter format(java.util.Locale, java.lang.String, java.lang.Object[]);
- public void print(char[]);
+ public void print(boolean);
public void print(char);
- public void print(double);
- public void print(float);
public void print(int);
public void print(long);
- public void print(java.lang.Object);
+ public void print(float);
+ public void print(double);
+ public void print(char[]);
public void print(java.lang.String);
- public void print(boolean);
+ public void print(java.lang.Object);
public java.io.PrintWriter printf(java.lang.String, java.lang.Object[]);
public java.io.PrintWriter printf(java.util.Locale, java.lang.String, java.lang.Object[]);
public void println();
- public void println(char[]);
+ public void println(boolean);
public void println(char);
- public void println(double);
- public void println(float);
public void println(int);
public void println(long);
- public void println(java.lang.Object);
+ public void println(float);
+ public void println(double);
+ public void println(char[]);
public void println(java.lang.String);
- public void println(boolean);
+ public void println(java.lang.Object);
protected void setError();
- public void write(char[]);
- public void write(char[], int, int);
public void write(int);
- public void write(java.lang.String);
+ public void write(char[], int, int);
+ public void write(char[]);
public void write(java.lang.String, int, int);
+ public void write(java.lang.String);
protected java.io.Writer out;
@@ -6542,10 +24431,10 @@
public abstract void close();
public void mark(int);
public boolean markSupported();
+ public int read(java.nio.CharBuffer);
public int read();
public int read(char[]);
public abstract int read(char[], int, int);
- public int read(java.nio.CharBuffer);
public boolean ready();
public void reset();
public long skip(long);
@@ -6579,17 +24468,17 @@
<init>();
<init>(java.lang.Object);
- public java.io.Writer append(char);
public java.io.Writer append(java.lang.CharSequence);
public java.io.Writer append(java.lang.CharSequence, int, int);
+ public java.io.Writer append(char);
+ public java.lang.Appendable append(char);
public java.lang.Appendable append(java.lang.CharSequence, int, int);
public java.lang.Appendable append(java.lang.CharSequence);
- public java.lang.Appendable append(char);
public abstract void close();
public abstract void flush();
+ public void write(int);
public void write(char[]);
public abstract void write(char[], int, int);
- public void write(int);
public void write(java.lang.String);
public void write(java.lang.String, int, int);
@@ -6599,25 +24488,58 @@
-keep class java.lang.AbstractStringBuilder {
+ public java.lang.AbstractStringBuilder append(java.lang.Object);
+ public java.lang.AbstractStringBuilder append(java.lang.String);
+ public java.lang.AbstractStringBuilder append(java.lang.StringBuffer);
+ public java.lang.AbstractStringBuilder append(java.lang.CharSequence);
+ public java.lang.AbstractStringBuilder append(java.lang.CharSequence, int, int);
+ public java.lang.AbstractStringBuilder append(char[]);
+ public java.lang.AbstractStringBuilder append(char[], int, int);
+ public java.lang.AbstractStringBuilder append(boolean);
+ public java.lang.AbstractStringBuilder append(char);
+ public java.lang.AbstractStringBuilder append(int);
+ public java.lang.AbstractStringBuilder append(long);
+ public java.lang.AbstractStringBuilder append(float);
+ public java.lang.AbstractStringBuilder append(double);
+ public java.lang.Appendable append(char);
+ public java.lang.Appendable append(java.lang.CharSequence, int, int);
+ public java.lang.Appendable append(java.lang.CharSequence);
+ public java.lang.AbstractStringBuilder appendCodePoint(int);
public int capacity();
public char charAt(int);
public int codePointAt(int);
public int codePointBefore(int);
public int codePointCount(int, int);
+ public java.lang.AbstractStringBuilder delete(int, int);
+ public java.lang.AbstractStringBuilder deleteCharAt(int);
public void ensureCapacity(int);
public void getChars(int, int, char[], int);
public int indexOf(java.lang.String);
public int indexOf(java.lang.String, int);
+ public java.lang.AbstractStringBuilder insert(int, char[], int, int);
+ public java.lang.AbstractStringBuilder insert(int, java.lang.Object);
+ public java.lang.AbstractStringBuilder insert(int, java.lang.String);
+ public java.lang.AbstractStringBuilder insert(int, char[]);
+ public java.lang.AbstractStringBuilder insert(int, java.lang.CharSequence);
+ public java.lang.AbstractStringBuilder insert(int, java.lang.CharSequence, int, int);
+ public java.lang.AbstractStringBuilder insert(int, boolean);
+ public java.lang.AbstractStringBuilder insert(int, char);
+ public java.lang.AbstractStringBuilder insert(int, int);
+ public java.lang.AbstractStringBuilder insert(int, long);
+ public java.lang.AbstractStringBuilder insert(int, float);
+ public java.lang.AbstractStringBuilder insert(int, double);
public int lastIndexOf(java.lang.String);
public int lastIndexOf(java.lang.String, int);
public int length();
public int offsetByCodePoints(int, int);
+ public java.lang.AbstractStringBuilder replace(int, int, java.lang.String);
+ public java.lang.AbstractStringBuilder reverse();
public void setCharAt(int, char);
public void setLength(int);
public java.lang.CharSequence subSequence(int, int);
public java.lang.String substring(int);
public java.lang.String substring(int, int);
- public java.lang.String toString();
+ public abstract java.lang.String toString();
public void trimToSize();
@@ -6625,16 +24547,16 @@
-keep class java.lang.Appendable {
- public abstract java.lang.Appendable append(char);
public abstract java.lang.Appendable append(java.lang.CharSequence);
public abstract java.lang.Appendable append(java.lang.CharSequence, int, int);
+ public abstract java.lang.Appendable append(char);
}
-keep class java.lang.Boolean {
- <init>(java.lang.String);
<init>(boolean);
+ <init>(java.lang.String);
public boolean booleanValue();
public static int compare(boolean, boolean);
@@ -6643,11 +24565,15 @@
public boolean equals(java.lang.Object);
public static boolean getBoolean(java.lang.String);
public int hashCode();
+ public static int hashCode(boolean);
+ public static boolean logicalAnd(boolean, boolean);
+ public static boolean logicalOr(boolean, boolean);
+ public static boolean logicalXor(boolean, boolean);
public static boolean parseBoolean(java.lang.String);
- public java.lang.String toString();
public static java.lang.String toString(boolean);
- public static java.lang.Boolean valueOf(java.lang.String);
+ public java.lang.String toString();
public static java.lang.Boolean valueOf(boolean);
+ public static java.lang.Boolean valueOf(java.lang.String);
public static java.lang.Boolean FALSE;
@@ -6668,18 +24594,23 @@
public boolean equals(java.lang.Object);
public float floatValue();
public int hashCode();
+ public static int hashCode(byte);
public int intValue();
public long longValue();
- public static byte parseByte(java.lang.String);
public static byte parseByte(java.lang.String, int);
+ public static byte parseByte(java.lang.String);
public short shortValue();
- public java.lang.String toString();
+ public static java.lang.String toHexString(byte, boolean);
public static java.lang.String toString(byte);
- public static java.lang.Byte valueOf(java.lang.String);
- public static java.lang.Byte valueOf(java.lang.String, int);
+ public java.lang.String toString();
+ public static int toUnsignedInt(byte);
+ public static long toUnsignedLong(byte);
public static java.lang.Byte valueOf(byte);
+ public static java.lang.Byte valueOf(java.lang.String, int);
+ public static java.lang.Byte valueOf(java.lang.String);
+ public static int BYTES;
public static byte MAX_VALUE;
public static byte MIN_VALUE;
public static int SIZE;
@@ -6689,6 +24620,8 @@
-keep class java.lang.CharSequence {
public abstract char charAt(int);
+ public java.util.stream.IntStream chars();
+ public java.util.stream.IntStream codePoints();
public abstract int length();
public abstract java.lang.CharSequence subSequence(int, int);
public abstract java.lang.String toString();
@@ -6724,6 +24657,7 @@
public static int getType(char);
public static int getType(int);
public int hashCode();
+ public static int hashCode(char);
public static char highSurrogate(int);
public static boolean isAlphabetic(int);
public static boolean isBmpCodePoint(int);
@@ -6787,6 +24721,7 @@
public static java.lang.Character valueOf(char);
+ public static int BYTES;
public static byte COMBINING_SPACING_MARK;
public static byte CONNECTOR_PUNCTUATION;
public static byte CONTROL;
@@ -6861,43 +24796,52 @@
public boolean desiredAssertionStatus();
public static java.lang.Class forName(java.lang.String);
public static java.lang.Class forName(java.lang.String, boolean, java.lang.ClassLoader);
+ public int getAccessFlags();
public java.lang.annotation.Annotation getAnnotation(java.lang.Class);
public java.lang.annotation.Annotation[] getAnnotations();
+ public java.lang.annotation.Annotation[] getAnnotationsByType(java.lang.Class);
public java.lang.String getCanonicalName();
public java.lang.ClassLoader getClassLoader();
public java.lang.Class[] getClasses();
public java.lang.Class getComponentType();
public java.lang.reflect.Constructor getConstructor(java.lang.Class[]);
public java.lang.reflect.Constructor[] getConstructors();
+ public java.lang.annotation.Annotation getDeclaredAnnotation(java.lang.Class);
public java.lang.annotation.Annotation[] getDeclaredAnnotations();
public java.lang.Class[] getDeclaredClasses();
public java.lang.reflect.Constructor getDeclaredConstructor(java.lang.Class[]);
public java.lang.reflect.Constructor[] getDeclaredConstructors();
public java.lang.reflect.Field getDeclaredField(java.lang.String);
public java.lang.reflect.Field[] getDeclaredFields();
+ public java.lang.reflect.Field[] getDeclaredFieldsUnchecked(boolean);
public java.lang.reflect.Method getDeclaredMethod(java.lang.String, java.lang.Class[]);
public java.lang.reflect.Method[] getDeclaredMethods();
+ public java.lang.reflect.Method[] getDeclaredMethodsUnchecked(boolean);
public java.lang.Class getDeclaringClass();
public java.lang.Class getEnclosingClass();
public java.lang.reflect.Constructor getEnclosingConstructor();
public java.lang.reflect.Method getEnclosingMethod();
public java.lang.Object[] getEnumConstants();
+ public java.lang.Object[] getEnumConstantsShared();
public java.lang.reflect.Field getField(java.lang.String);
public java.lang.reflect.Field[] getFields();
public java.lang.reflect.Type[] getGenericInterfaces();
public java.lang.reflect.Type getGenericSuperclass();
+ public java.lang.reflect.Method getInstanceMethod(java.lang.String, java.lang.Class[]);
public java.lang.Class[] getInterfaces();
public java.lang.reflect.Method getMethod(java.lang.String, java.lang.Class[]);
public java.lang.reflect.Method[] getMethods();
public int getModifiers();
public java.lang.String getName();
public java.lang.Package getPackage();
+ public java.lang.String getPackageName$();
public java.security.ProtectionDomain getProtectionDomain();
public java.net.URL getResource(java.lang.String);
public java.io.InputStream getResourceAsStream(java.lang.String);
public java.lang.Object[] getSigners();
public java.lang.String getSimpleName();
public java.lang.Class getSuperclass();
+ public java.lang.String getTypeName();
public synchronized java.lang.reflect.TypeVariable[] getTypeParameters();
public boolean isAnnotation();
public boolean isAnnotationPresent(java.lang.Class);
@@ -6905,13 +24849,16 @@
public boolean isArray();
public boolean isAssignableFrom(java.lang.Class);
public boolean isEnum();
+ public boolean isFinalizable();
public boolean isInstance(java.lang.Object);
public boolean isInterface();
public boolean isLocalClass();
public boolean isMemberClass();
public boolean isPrimitive();
+ public boolean isProxy();
public boolean isSynthetic();
public java.lang.Object newInstance();
+ public java.lang.String toGenericString();
public java.lang.String toString();
@@ -6926,8 +24873,8 @@
}
-keep class java.lang.ClassLoader {
- <init>();
<init>(java.lang.ClassLoader);
+ <init>();
public void clearAssertionStatus();
protected java.lang.Class defineClass(byte[], int, int);
@@ -6953,6 +24900,7 @@
public static java.util.Enumeration getSystemResources(java.lang.String);
public java.lang.Class loadClass(java.lang.String);
protected java.lang.Class loadClass(java.lang.String, boolean);
+ protected static boolean registerAsParallelCapable();
protected void resolveClass(java.lang.Class);
public void setClassAssertionStatus(java.lang.String, boolean);
public void setDefaultAssertionStatus(boolean);
@@ -6960,6 +24908,7 @@
protected void setSigners(java.lang.Class, java.lang.Object[]);
+ public java.util.Map proxyCache;
}
-keep class java.lang.ClassNotFoundException {
@@ -6981,6 +24930,13 @@
}
+-keep class java.lang.Comparable {
+
+ public abstract int compareTo(java.lang.Object);
+
+
+}
+
-keep class java.lang.Double {
<init>(double);
<init>(java.lang.String);
@@ -6995,22 +24951,28 @@
public boolean equals(java.lang.Object);
public float floatValue();
public int hashCode();
+ public static int hashCode(double);
public int intValue();
- public boolean isInfinite();
+ public static boolean isFinite(double);
public static boolean isInfinite(double);
- public boolean isNaN();
+ public boolean isInfinite();
public static boolean isNaN(double);
+ public boolean isNaN();
public static double longBitsToDouble(long);
public long longValue();
+ public static double max(double, double);
+ public static double min(double, double);
public static double parseDouble(java.lang.String);
public short shortValue();
+ public static double sum(double, double);
public static java.lang.String toHexString(double);
- public java.lang.String toString();
public static java.lang.String toString(double);
+ public java.lang.String toString();
public static java.lang.Double valueOf(java.lang.String);
public static java.lang.Double valueOf(double);
+ public static int BYTES;
public static int MAX_EXPONENT;
public static double MAX_VALUE;
public static int MIN_EXPONENT;
@@ -7032,6 +24994,7 @@
public boolean equals(java.lang.Object);
protected void finalize();
public java.lang.Class getDeclaringClass();
+ public static java.lang.Enum[] getSharedConstants(java.lang.Class);
public int hashCode();
public java.lang.String name();
public int ordinal();
@@ -7046,6 +25009,7 @@
<init>(java.lang.String);
<init>(java.lang.String, java.lang.Throwable);
<init>(java.lang.Throwable);
+ <init>(java.lang.String, java.lang.Throwable, boolean, boolean);
@@ -7056,6 +25020,7 @@
<init>(java.lang.String);
<init>(java.lang.String, java.lang.Throwable);
<init>(java.lang.Throwable);
+ <init>(java.lang.String, java.lang.Throwable, boolean, boolean);
@@ -7076,22 +25041,28 @@
public static int floatToRawIntBits(float);
public float floatValue();
public int hashCode();
+ public static int hashCode(float);
public static float intBitsToFloat(int);
public int intValue();
- public boolean isInfinite();
+ public static boolean isFinite(float);
public static boolean isInfinite(float);
- public boolean isNaN();
+ public boolean isInfinite();
public static boolean isNaN(float);
+ public boolean isNaN();
public long longValue();
+ public static float max(float, float);
+ public static float min(float, float);
public static float parseFloat(java.lang.String);
public short shortValue();
+ public static float sum(float, float);
public static java.lang.String toHexString(float);
- public java.lang.String toString();
public static java.lang.String toString(float);
+ public java.lang.String toString();
public static java.lang.Float valueOf(java.lang.String);
public static java.lang.Float valueOf(float);
+ public static int BYTES;
public static int MAX_EXPONENT;
public static float MAX_VALUE;
public static int MIN_EXPONENT;
@@ -7149,7 +25120,9 @@
public static int compare(int, int);
public int compareTo(java.lang.Integer);
public int compareTo(java.lang.Object);
+ public static int compareUnsigned(int, int);
public static java.lang.Integer decode(java.lang.String);
+ public static int divideUnsigned(int, int);
public double doubleValue();
public boolean equals(java.lang.Object);
public float floatValue();
@@ -7157,31 +25130,42 @@
public static java.lang.Integer getInteger(java.lang.String, int);
public static java.lang.Integer getInteger(java.lang.String, java.lang.Integer);
public int hashCode();
+ public static int hashCode(int);
public static int highestOneBit(int);
public int intValue();
public long longValue();
public static int lowestOneBit(int);
+ public static int max(int, int);
+ public static int min(int, int);
public static int numberOfLeadingZeros(int);
public static int numberOfTrailingZeros(int);
- public static int parseInt(java.lang.String);
public static int parseInt(java.lang.String, int);
+ public static int parseInt(java.lang.String);
+ public static int parseUnsignedInt(java.lang.String, int);
+ public static int parseUnsignedInt(java.lang.String);
+ public static int remainderUnsigned(int, int);
public static int reverse(int);
public static int reverseBytes(int);
public static int rotateLeft(int, int);
public static int rotateRight(int, int);
public short shortValue();
public static int signum(int);
+ public static int sum(int, int);
public static java.lang.String toBinaryString(int);
public static java.lang.String toHexString(int);
public static java.lang.String toOctalString(int);
- public java.lang.String toString();
- public static java.lang.String toString(int);
public static java.lang.String toString(int, int);
- public static java.lang.Integer valueOf(java.lang.String);
+ public static java.lang.String toString(int);
+ public java.lang.String toString();
+ public static long toUnsignedLong(int);
+ public static java.lang.String toUnsignedString(int, int);
+ public static java.lang.String toUnsignedString(int);
public static java.lang.Integer valueOf(java.lang.String, int);
+ public static java.lang.Integer valueOf(java.lang.String);
public static java.lang.Integer valueOf(int);
+ public static int BYTES;
public static int MAX_VALUE;
public static int MIN_VALUE;
public static int SIZE;
@@ -7196,6 +25180,15 @@
}
+-keep class java.lang.Iterable {
+
+ public void forEach(java.util.function.Consumer);
+ public abstract java.util.Iterator iterator();
+ public java.util.Spliterator spliterator();
+
+
+}
+
-keep class java.lang.LinkageError {
<init>();
<init>(java.lang.String);
@@ -7214,7 +25207,9 @@
public static int compare(long, long);
public int compareTo(java.lang.Long);
public int compareTo(java.lang.Object);
+ public static int compareUnsigned(long, long);
public static java.lang.Long decode(java.lang.String);
+ public static long divideUnsigned(long, long);
public double doubleValue();
public boolean equals(java.lang.Object);
public float floatValue();
@@ -7222,31 +25217,41 @@
public static java.lang.Long getLong(java.lang.String, long);
public static java.lang.Long getLong(java.lang.String, java.lang.Long);
public int hashCode();
+ public static int hashCode(long);
public static long highestOneBit(long);
public int intValue();
public long longValue();
public static long lowestOneBit(long);
+ public static long max(long, long);
+ public static long min(long, long);
public static int numberOfLeadingZeros(long);
public static int numberOfTrailingZeros(long);
- public static long parseLong(java.lang.String);
public static long parseLong(java.lang.String, int);
+ public static long parseLong(java.lang.String);
+ public static long parseUnsignedLong(java.lang.String, int);
+ public static long parseUnsignedLong(java.lang.String);
+ public static long remainderUnsigned(long, long);
public static long reverse(long);
public static long reverseBytes(long);
public static long rotateLeft(long, int);
public static long rotateRight(long, int);
public short shortValue();
public static int signum(long);
+ public static long sum(long, long);
public static java.lang.String toBinaryString(long);
public static java.lang.String toHexString(long);
public static java.lang.String toOctalString(long);
- public java.lang.String toString();
- public static java.lang.String toString(long);
public static java.lang.String toString(long, int);
- public static java.lang.Long valueOf(java.lang.String);
+ public static java.lang.String toString(long);
+ public java.lang.String toString();
+ public static java.lang.String toUnsignedString(long, int);
+ public static java.lang.String toUnsignedString(long);
public static java.lang.Long valueOf(java.lang.String, int);
+ public static java.lang.Long valueOf(java.lang.String);
public static java.lang.Long valueOf(long);
+ public static int BYTES;
public static long MAX_VALUE;
public static long MIN_VALUE;
public static int SIZE;
@@ -7301,9 +25306,9 @@
public void notify();
public void notifyAll();
public java.lang.String toString();
- public void wait();
public void wait(long);
public void wait(long, int);
+ public void wait();
}
@@ -7312,7 +25317,10 @@
public java.lang.annotation.Annotation getAnnotation(java.lang.Class);
public java.lang.annotation.Annotation[] getAnnotations();
+ public java.lang.annotation.Annotation[] getAnnotationsByType(java.lang.Class);
+ public java.lang.annotation.Annotation getDeclaredAnnotation(java.lang.Class);
public java.lang.annotation.Annotation[] getDeclaredAnnotations();
+ public java.lang.annotation.Annotation[] getDeclaredAnnotationsByType(java.lang.Class);
public java.lang.String getImplementationTitle();
public java.lang.String getImplementationVendor();
public java.lang.String getImplementationVersion();
@@ -7335,8 +25343,8 @@
-keep class java.lang.ReflectiveOperationException {
<init>();
<init>(java.lang.String);
- <init>(java.lang.Throwable);
<init>(java.lang.String, java.lang.Throwable);
+ <init>(java.lang.Throwable);
@@ -7354,6 +25362,7 @@
<init>(java.lang.String);
<init>(java.lang.String, java.lang.Throwable);
<init>(java.lang.Throwable);
+ <init>(java.lang.String, java.lang.Throwable, boolean, boolean);
@@ -7370,8 +25379,8 @@
}
-keep class java.lang.Short {
- <init>(java.lang.String);
<init>(short);
+ <init>(java.lang.String);
public byte byteValue();
public static int compare(short, short);
@@ -7382,19 +25391,23 @@
public boolean equals(java.lang.Object);
public float floatValue();
public int hashCode();
+ public static int hashCode(short);
public int intValue();
public long longValue();
- public static short parseShort(java.lang.String);
public static short parseShort(java.lang.String, int);
+ public static short parseShort(java.lang.String);
public static short reverseBytes(short);
public short shortValue();
- public java.lang.String toString();
public static java.lang.String toString(short);
- public static java.lang.Short valueOf(java.lang.String);
+ public java.lang.String toString();
+ public static int toUnsignedInt(short);
+ public static long toUnsignedLong(short);
public static java.lang.Short valueOf(java.lang.String, int);
+ public static java.lang.Short valueOf(java.lang.String);
public static java.lang.Short valueOf(short);
+ public static int BYTES;
public static short MAX_VALUE;
public static short MIN_VALUE;
public static int SIZE;
@@ -7418,19 +25431,19 @@
-keep class java.lang.String {
<init>();
- <init>(byte[]);
- <init>(byte[], int);
- <init>(byte[], int, int);
- <init>(byte[], int, int, int);
- <init>(byte[], int, int, java.lang.String);
- <init>(byte[], java.lang.String);
- <init>(byte[], int, int, java.nio.charset.Charset);
- <init>(byte[], java.nio.charset.Charset);
+ <init>(java.lang.String);
<init>(char[]);
<init>(char[], int, int);
- <init>(java.lang.String);
- <init>(java.lang.StringBuffer);
<init>(int[], int, int);
+ <init>(byte[], int, int, int);
+ <init>(byte[], int);
+ <init>(byte[], int, int, java.lang.String);
+ <init>(byte[], int, int, java.nio.charset.Charset);
+ <init>(byte[], java.lang.String);
+ <init>(byte[], java.nio.charset.Charset);
+ <init>(byte[], int, int);
+ <init>(byte[]);
+ <init>(java.lang.StringBuffer);
<init>(java.lang.StringBuilder);
public char charAt(int);
@@ -7444,17 +25457,17 @@
public boolean contains(java.lang.CharSequence);
public boolean contentEquals(java.lang.StringBuffer);
public boolean contentEquals(java.lang.CharSequence);
- public static java.lang.String copyValueOf(char[]);
public static java.lang.String copyValueOf(char[], int, int);
+ public static java.lang.String copyValueOf(char[]);
public boolean endsWith(java.lang.String);
public boolean equals(java.lang.Object);
public boolean equalsIgnoreCase(java.lang.String);
public static java.lang.String format(java.lang.String, java.lang.Object[]);
public static java.lang.String format(java.util.Locale, java.lang.String, java.lang.Object[]);
public void getBytes(int, int, byte[], int);
- public byte[] getBytes();
public byte[] getBytes(java.lang.String);
public byte[] getBytes(java.nio.charset.Charset);
+ public byte[] getBytes();
public void getChars(int, int, char[], int);
public int hashCode();
public int indexOf(int);
@@ -7463,6 +25476,8 @@
public int indexOf(java.lang.String, int);
public java.lang.String intern();
public boolean isEmpty();
+ public static java.lang.String join(java.lang.CharSequence, java.lang.CharSequence[]);
+ public static java.lang.String join(java.lang.CharSequence, java.lang.Iterable);
public int lastIndexOf(int);
public int lastIndexOf(int, int);
public int lastIndexOf(java.lang.String);
@@ -7476,29 +25491,29 @@
public java.lang.String replace(java.lang.CharSequence, java.lang.CharSequence);
public java.lang.String replaceAll(java.lang.String, java.lang.String);
public java.lang.String replaceFirst(java.lang.String, java.lang.String);
- public java.lang.String[] split(java.lang.String);
public java.lang.String[] split(java.lang.String, int);
- public boolean startsWith(java.lang.String);
+ public java.lang.String[] split(java.lang.String);
public boolean startsWith(java.lang.String, int);
+ public boolean startsWith(java.lang.String);
public java.lang.CharSequence subSequence(int, int);
public java.lang.String substring(int);
public java.lang.String substring(int, int);
public char[] toCharArray();
- public java.lang.String toLowerCase();
public java.lang.String toLowerCase(java.util.Locale);
+ public java.lang.String toLowerCase();
public java.lang.String toString();
- public java.lang.String toUpperCase();
public java.lang.String toUpperCase(java.util.Locale);
+ public java.lang.String toUpperCase();
public java.lang.String trim();
+ public static java.lang.String valueOf(java.lang.Object);
public static java.lang.String valueOf(char[]);
public static java.lang.String valueOf(char[], int, int);
+ public static java.lang.String valueOf(boolean);
public static java.lang.String valueOf(char);
- public static java.lang.String valueOf(double);
- public static java.lang.String valueOf(float);
public static java.lang.String valueOf(int);
public static java.lang.String valueOf(long);
- public static java.lang.String valueOf(java.lang.Object);
- public static java.lang.String valueOf(boolean);
+ public static java.lang.String valueOf(float);
+ public static java.lang.String valueOf(double);
public static java.util.Comparator CASE_INSENSITIVE_ORDER;
@@ -7510,52 +25525,82 @@
<init>(java.lang.String);
<init>(java.lang.CharSequence);
- public java.lang.StringBuffer append(boolean);
- public synchronized java.lang.StringBuffer append(char);
- public java.lang.StringBuffer append(double);
- public java.lang.StringBuffer append(float);
- public java.lang.StringBuffer append(int);
- public java.lang.StringBuffer append(long);
public synchronized java.lang.StringBuffer append(java.lang.Object);
public synchronized java.lang.StringBuffer append(java.lang.String);
public synchronized java.lang.StringBuffer append(java.lang.StringBuffer);
- public synchronized java.lang.StringBuffer append(char[]);
- public synchronized java.lang.StringBuffer append(char[], int, int);
public synchronized java.lang.StringBuffer append(java.lang.CharSequence);
public synchronized java.lang.StringBuffer append(java.lang.CharSequence, int, int);
+ public synchronized java.lang.StringBuffer append(char[]);
+ public synchronized java.lang.StringBuffer append(char[], int, int);
+ public synchronized java.lang.StringBuffer append(boolean);
+ public synchronized java.lang.StringBuffer append(char);
+ public synchronized java.lang.StringBuffer append(int);
+ public synchronized java.lang.StringBuffer append(long);
+ public synchronized java.lang.StringBuffer append(float);
+ public synchronized java.lang.StringBuffer append(double);
+ public java.lang.AbstractStringBuilder append(double);
+ public java.lang.AbstractStringBuilder append(float);
+ public java.lang.AbstractStringBuilder append(long);
+ public java.lang.AbstractStringBuilder append(int);
+ public java.lang.AbstractStringBuilder append(char);
+ public java.lang.AbstractStringBuilder append(boolean);
+ public java.lang.AbstractStringBuilder append(char[], int, int);
+ public java.lang.AbstractStringBuilder append(char[]);
+ public java.lang.AbstractStringBuilder append(java.lang.CharSequence, int, int);
+ public java.lang.AbstractStringBuilder append(java.lang.CharSequence);
+ public java.lang.AbstractStringBuilder append(java.lang.StringBuffer);
+ public java.lang.AbstractStringBuilder append(java.lang.String);
+ public java.lang.AbstractStringBuilder append(java.lang.Object);
+ public java.lang.Appendable append(char);
public java.lang.Appendable append(java.lang.CharSequence, int, int);
public java.lang.Appendable append(java.lang.CharSequence);
- public java.lang.Appendable append(char);
- public java.lang.StringBuffer appendCodePoint(int);
- public int capacity();
+ public synchronized java.lang.StringBuffer appendCodePoint(int);
+ public java.lang.AbstractStringBuilder appendCodePoint(int);
+ public synchronized int capacity();
public synchronized char charAt(int);
public synchronized int codePointAt(int);
public synchronized int codePointBefore(int);
public synchronized int codePointCount(int, int);
public synchronized java.lang.StringBuffer delete(int, int);
+ public java.lang.AbstractStringBuilder delete(int, int);
public synchronized java.lang.StringBuffer deleteCharAt(int);
+ public java.lang.AbstractStringBuilder deleteCharAt(int);
public synchronized void ensureCapacity(int);
public synchronized void getChars(int, int, char[], int);
- public synchronized int indexOf(java.lang.String, int);
public int indexOf(java.lang.String);
- public synchronized java.lang.StringBuffer insert(int, char);
- public java.lang.StringBuffer insert(int, boolean);
- public java.lang.StringBuffer insert(int, int);
- public java.lang.StringBuffer insert(int, long);
- public java.lang.StringBuffer insert(int, double);
- public java.lang.StringBuffer insert(int, float);
- public java.lang.StringBuffer insert(int, java.lang.Object);
+ public synchronized int indexOf(java.lang.String, int);
+ public synchronized java.lang.StringBuffer insert(int, char[], int, int);
+ public synchronized java.lang.StringBuffer insert(int, java.lang.Object);
public synchronized java.lang.StringBuffer insert(int, java.lang.String);
public synchronized java.lang.StringBuffer insert(int, char[]);
- public synchronized java.lang.StringBuffer insert(int, char[], int, int);
- public synchronized java.lang.StringBuffer insert(int, java.lang.CharSequence);
+ public java.lang.StringBuffer insert(int, java.lang.CharSequence);
public synchronized java.lang.StringBuffer insert(int, java.lang.CharSequence, int, int);
- public synchronized int lastIndexOf(java.lang.String, int);
+ public java.lang.StringBuffer insert(int, boolean);
+ public synchronized java.lang.StringBuffer insert(int, char);
+ public java.lang.StringBuffer insert(int, int);
+ public java.lang.StringBuffer insert(int, long);
+ public java.lang.StringBuffer insert(int, float);
+ public java.lang.StringBuffer insert(int, double);
+ public java.lang.AbstractStringBuilder insert(int, double);
+ public java.lang.AbstractStringBuilder insert(int, float);
+ public java.lang.AbstractStringBuilder insert(int, long);
+ public java.lang.AbstractStringBuilder insert(int, int);
+ public java.lang.AbstractStringBuilder insert(int, char);
+ public java.lang.AbstractStringBuilder insert(int, boolean);
+ public java.lang.AbstractStringBuilder insert(int, java.lang.CharSequence, int, int);
+ public java.lang.AbstractStringBuilder insert(int, java.lang.CharSequence);
+ public java.lang.AbstractStringBuilder insert(int, char[]);
+ public java.lang.AbstractStringBuilder insert(int, java.lang.String);
+ public java.lang.AbstractStringBuilder insert(int, java.lang.Object);
+ public java.lang.AbstractStringBuilder insert(int, char[], int, int);
public int lastIndexOf(java.lang.String);
- public int length();
+ public synchronized int lastIndexOf(java.lang.String, int);
+ public synchronized int length();
public synchronized int offsetByCodePoints(int, int);
public synchronized java.lang.StringBuffer replace(int, int, java.lang.String);
+ public java.lang.AbstractStringBuilder replace(int, int, java.lang.String);
public synchronized java.lang.StringBuffer reverse();
+ public java.lang.AbstractStringBuilder reverse();
public synchronized void setCharAt(int, char);
public synchronized void setLength(int);
public synchronized java.lang.CharSequence subSequence(int, int);
@@ -7570,55 +25615,85 @@
-keep class java.lang.StringBuilder {
<init>();
<init>(int);
- <init>(java.lang.CharSequence);
<init>(java.lang.String);
+ <init>(java.lang.CharSequence);
+ public java.lang.StringBuilder append(java.lang.Object);
+ public java.lang.StringBuilder append(java.lang.String);
+ public java.lang.StringBuilder append(java.lang.StringBuffer);
+ public java.lang.StringBuilder append(java.lang.CharSequence);
+ public java.lang.StringBuilder append(java.lang.CharSequence, int, int);
+ public java.lang.StringBuilder append(char[]);
+ public java.lang.StringBuilder append(char[], int, int);
public java.lang.StringBuilder append(boolean);
public java.lang.StringBuilder append(char);
public java.lang.StringBuilder append(int);
public java.lang.StringBuilder append(long);
public java.lang.StringBuilder append(float);
public java.lang.StringBuilder append(double);
- public java.lang.StringBuilder append(java.lang.Object);
- public java.lang.StringBuilder append(java.lang.String);
- public java.lang.StringBuilder append(java.lang.StringBuffer);
- public java.lang.StringBuilder append(char[]);
- public java.lang.StringBuilder append(char[], int, int);
- public java.lang.StringBuilder append(java.lang.CharSequence);
- public java.lang.StringBuilder append(java.lang.CharSequence, int, int);
+ public java.lang.AbstractStringBuilder append(double);
+ public java.lang.AbstractStringBuilder append(float);
+ public java.lang.AbstractStringBuilder append(long);
+ public java.lang.AbstractStringBuilder append(int);
+ public java.lang.AbstractStringBuilder append(char);
+ public java.lang.AbstractStringBuilder append(boolean);
+ public java.lang.AbstractStringBuilder append(char[], int, int);
+ public java.lang.AbstractStringBuilder append(char[]);
+ public java.lang.AbstractStringBuilder append(java.lang.CharSequence, int, int);
+ public java.lang.AbstractStringBuilder append(java.lang.CharSequence);
+ public java.lang.AbstractStringBuilder append(java.lang.StringBuffer);
+ public java.lang.AbstractStringBuilder append(java.lang.String);
+ public java.lang.AbstractStringBuilder append(java.lang.Object);
+ public java.lang.Appendable append(char);
public java.lang.Appendable append(java.lang.CharSequence, int, int);
public java.lang.Appendable append(java.lang.CharSequence);
- public java.lang.Appendable append(char);
public java.lang.StringBuilder appendCodePoint(int);
+ public java.lang.AbstractStringBuilder appendCodePoint(int);
public int capacity();
public char charAt(int);
public int codePointAt(int);
public int codePointBefore(int);
public int codePointCount(int, int);
public java.lang.StringBuilder delete(int, int);
+ public java.lang.AbstractStringBuilder delete(int, int);
public java.lang.StringBuilder deleteCharAt(int);
+ public java.lang.AbstractStringBuilder deleteCharAt(int);
public void ensureCapacity(int);
public void getChars(int, int, char[], int);
- public int indexOf(java.lang.String, int);
public int indexOf(java.lang.String);
+ public int indexOf(java.lang.String, int);
+ public java.lang.StringBuilder insert(int, char[], int, int);
+ public java.lang.StringBuilder insert(int, java.lang.Object);
+ public java.lang.StringBuilder insert(int, java.lang.String);
+ public java.lang.StringBuilder insert(int, char[]);
+ public java.lang.StringBuilder insert(int, java.lang.CharSequence);
+ public java.lang.StringBuilder insert(int, java.lang.CharSequence, int, int);
public java.lang.StringBuilder insert(int, boolean);
public java.lang.StringBuilder insert(int, char);
public java.lang.StringBuilder insert(int, int);
public java.lang.StringBuilder insert(int, long);
public java.lang.StringBuilder insert(int, float);
public java.lang.StringBuilder insert(int, double);
- public java.lang.StringBuilder insert(int, java.lang.Object);
- public java.lang.StringBuilder insert(int, java.lang.String);
- public java.lang.StringBuilder insert(int, char[]);
- public java.lang.StringBuilder insert(int, char[], int, int);
- public java.lang.StringBuilder insert(int, java.lang.CharSequence);
- public java.lang.StringBuilder insert(int, java.lang.CharSequence, int, int);
- public int lastIndexOf(java.lang.String, int);
+ public java.lang.AbstractStringBuilder insert(int, double);
+ public java.lang.AbstractStringBuilder insert(int, float);
+ public java.lang.AbstractStringBuilder insert(int, long);
+ public java.lang.AbstractStringBuilder insert(int, int);
+ public java.lang.AbstractStringBuilder insert(int, char);
+ public java.lang.AbstractStringBuilder insert(int, boolean);
+ public java.lang.AbstractStringBuilder insert(int, java.lang.CharSequence, int, int);
+ public java.lang.AbstractStringBuilder insert(int, java.lang.CharSequence);
+ public java.lang.AbstractStringBuilder insert(int, char[]);
+ public java.lang.AbstractStringBuilder insert(int, java.lang.String);
+ public java.lang.AbstractStringBuilder insert(int, java.lang.Object);
+ public java.lang.AbstractStringBuilder insert(int, char[], int, int);
public int lastIndexOf(java.lang.String);
+ public int lastIndexOf(java.lang.String, int);
public int length();
public int offsetByCodePoints(int, int);
public java.lang.StringBuilder replace(int, int, java.lang.String);
+ public java.lang.AbstractStringBuilder replace(int, int, java.lang.String);
public java.lang.StringBuilder reverse();
+ public java.lang.AbstractStringBuilder reverse();
public void setCharAt(int, char);
public void setLength(int);
public java.lang.CharSequence subSequence(int, int);
@@ -7633,18 +25708,21 @@
-keep class java.lang.Thread {
<init>();
<init>(java.lang.Runnable);
- <init>(java.lang.Runnable, java.lang.String);
- <init>(java.lang.String);
<init>(java.lang.ThreadGroup, java.lang.Runnable);
- <init>(java.lang.ThreadGroup, java.lang.Runnable, java.lang.String);
+ <init>(java.lang.String);
<init>(java.lang.ThreadGroup, java.lang.String);
+ <init>(java.lang.Runnable, java.lang.String);
+ <init>(java.lang.ThreadGroup, java.lang.Runnable, java.lang.String);
<init>(java.lang.ThreadGroup, java.lang.Runnable, java.lang.String, long);
public static int activeCount();
+ public void blockedOn(sun.nio.ch.Interruptible);
public void checkAccess();
+ protected java.lang.Object clone();
public int countStackFrames();
public static java.lang.Thread currentThread();
public void destroy();
+ public void dispatchUncaughtException(java.lang.Throwable);
public static void dumpStack();
public static int enumerate(java.lang.Thread[]);
public static java.util.Map getAllStackTraces();
@@ -7657,15 +25735,18 @@
public java.lang.Thread$State getState();
public java.lang.ThreadGroup getThreadGroup();
public java.lang.Thread$UncaughtExceptionHandler getUncaughtExceptionHandler();
+ public static java.lang.Thread$UncaughtExceptionHandler getUncaughtExceptionPreHandler();
public static boolean holdsLock(java.lang.Object);
public void interrupt();
public static boolean interrupted();
public boolean isAlive();
public boolean isDaemon();
public boolean isInterrupted();
- public void join();
public void join(long);
public void join(long, int);
+ public void join();
+ public void parkFor$(long);
+ public void parkUntil$(long);
public void resume();
public void run();
public void setContextClassLoader(java.lang.ClassLoader);
@@ -7674,13 +25755,15 @@
public void setName(java.lang.String);
public void setPriority(int);
public void setUncaughtExceptionHandler(java.lang.Thread$UncaughtExceptionHandler);
+ public static void setUncaughtExceptionPreHandler(java.lang.Thread$UncaughtExceptionHandler);
public static void sleep(long);
public static void sleep(long, int);
public synchronized void start();
public void stop();
- public synchronized void stop(java.lang.Throwable);
+ public void stop(java.lang.Throwable);
public void suspend();
public java.lang.String toString();
+ public void unpark$();
public static void yield();
@@ -7742,6 +25825,18 @@
}
+-keep class java.lang.ThreadLocal {
+ <init>();
+
+ public java.lang.Object get();
+ protected java.lang.Object initialValue();
+ public void remove();
+ public void set(java.lang.Object);
+ public static java.lang.ThreadLocal withInitial(java.util.function.Supplier);
+
+
+}
+
-keep class java.lang.Throwable {
<init>();
<init>(java.lang.String);
@@ -7749,14 +25844,14 @@
<init>(java.lang.Throwable);
<init>(java.lang.String, java.lang.Throwable, boolean, boolean);
- public void addSuppressed(java.lang.Throwable);
- public java.lang.Throwable fillInStackTrace();
- public java.lang.Throwable getCause();
+ public synchronized void addSuppressed(java.lang.Throwable);
+ public synchronized java.lang.Throwable fillInStackTrace();
+ public synchronized java.lang.Throwable getCause();
public java.lang.String getLocalizedMessage();
public java.lang.String getMessage();
public java.lang.StackTraceElement[] getStackTrace();
- public java.lang.Throwable[] getSuppressed();
- public java.lang.Throwable initCause(java.lang.Throwable);
+ public synchronized java.lang.Throwable[] getSuppressed();
+ public synchronized java.lang.Throwable initCause(java.lang.Throwable);
public void printStackTrace();
public void printStackTrace(java.io.PrintStream);
public void printStackTrace(java.io.PrintWriter);
@@ -7766,16 +25861,6 @@
}
--keep class java.lang.UnsupportedOperationException {
- <init>();
- <init>(java.lang.String);
- <init>(java.lang.String, java.lang.Throwable);
- <init>(java.lang.Throwable);
-
-
-
-}
-
-keep class java.lang.annotation.Annotation {
public abstract java.lang.Class annotationType();
@@ -7791,11 +25876,14 @@
public java.lang.annotation.Annotation getAnnotation(java.lang.Class);
public java.lang.annotation.Annotation[] getAnnotations();
+ public java.lang.annotation.Annotation[] getAnnotationsByType(java.lang.Class);
+ public java.lang.annotation.Annotation getDeclaredAnnotation(java.lang.Class);
public java.lang.annotation.Annotation[] getDeclaredAnnotations();
+ public java.lang.annotation.Annotation[] getDeclaredAnnotationsByType(java.lang.Class);
public boolean isAccessible();
public boolean isAnnotationPresent(java.lang.Class);
- public void setAccessible(boolean);
public static void setAccessible(java.lang.reflect.AccessibleObject[], boolean);
+ public void setAccessible(boolean);
}
@@ -7804,7 +25892,6 @@
public boolean equals(java.lang.Object);
public java.lang.annotation.Annotation getAnnotation(java.lang.Class);
- public java.lang.annotation.Annotation[] getAnnotations();
public java.lang.annotation.Annotation[] getDeclaredAnnotations();
public java.lang.Class getDeclaringClass();
public java.lang.Class[] getExceptionTypes();
@@ -7813,30 +25900,59 @@
public int getModifiers();
public java.lang.String getName();
public java.lang.annotation.Annotation[][] getParameterAnnotations();
+ public int getParameterCount();
public java.lang.Class[] getParameterTypes();
public java.lang.reflect.TypeVariable[] getTypeParameters();
public int hashCode();
- public boolean isAnnotationPresent(java.lang.Class);
public boolean isSynthetic();
public boolean isVarArgs();
public java.lang.Object newInstance(java.lang.Object[]);
- public void setAccessible(boolean);
+ public java.lang.reflect.Constructor serializationCopy(java.lang.Class, java.lang.Class);
public java.lang.String toGenericString();
public java.lang.String toString();
}
+-keep class java.lang.reflect.Executable {
+
+ public int getAccessFlags();
+ public java.lang.annotation.Annotation getAnnotation(java.lang.Class);
+ public java.lang.annotation.Annotation[] getAnnotationsByType(java.lang.Class);
+ public long getArtMethod();
+ public java.lang.annotation.Annotation[] getDeclaredAnnotations();
+ public abstract java.lang.Class getDeclaringClass();
+ public abstract java.lang.Class[] getExceptionTypes();
+ public java.lang.reflect.Type[] getGenericExceptionTypes();
+ public java.lang.reflect.Type[] getGenericParameterTypes();
+ public abstract int getModifiers();
+ public abstract java.lang.String getName();
+ public abstract java.lang.annotation.Annotation[][] getParameterAnnotations();
+ public int getParameterCount();
+ public abstract java.lang.Class[] getParameterTypes();
+ public java.lang.reflect.Parameter[] getParameters();
+ public abstract java.lang.reflect.TypeVariable[] getTypeParameters();
+ public boolean isAnnotationPresent(java.lang.Class);
+ public boolean isSynthetic();
+ public boolean isVarArgs();
+ public abstract java.lang.String toGenericString();
+
+
+}
+
-keep class java.lang.reflect.Field {
public boolean equals(java.lang.Object);
public java.lang.Object get(java.lang.Object);
public java.lang.annotation.Annotation getAnnotation(java.lang.Class);
+ public java.lang.annotation.Annotation[] getAnnotationsByType(java.lang.Class);
+ public long getArtField();
public boolean getBoolean(java.lang.Object);
public byte getByte(java.lang.Object);
public char getChar(java.lang.Object);
public java.lang.annotation.Annotation[] getDeclaredAnnotations();
public java.lang.Class getDeclaringClass();
+ public int getDexFieldIndex();
public double getDouble(java.lang.Object);
public float getFloat(java.lang.Object);
public java.lang.reflect.Type getGenericType();
@@ -7844,6 +25960,7 @@
public long getLong(java.lang.Object);
public int getModifiers();
public java.lang.String getName();
+ public int getOffset();
public short getShort(java.lang.Object);
public java.lang.Class getType();
public int hashCode();
@@ -7887,7 +26004,6 @@
public boolean equals(java.lang.Object);
public java.lang.annotation.Annotation getAnnotation(java.lang.Class);
- public java.lang.annotation.Annotation[] getAnnotations();
public java.lang.annotation.Annotation[] getDeclaredAnnotations();
public java.lang.Class getDeclaringClass();
public java.lang.Object getDefaultValue();
@@ -7898,23 +26014,50 @@
public int getModifiers();
public java.lang.String getName();
public java.lang.annotation.Annotation[][] getParameterAnnotations();
+ public int getParameterCount();
public java.lang.Class[] getParameterTypes();
public java.lang.Class getReturnType();
public java.lang.reflect.TypeVariable[] getTypeParameters();
public int hashCode();
public java.lang.Object invoke(java.lang.Object, java.lang.Object[]);
- public boolean isAnnotationPresent(java.lang.Class);
public boolean isBridge();
+ public boolean isDefault();
public boolean isSynthetic();
public boolean isVarArgs();
public java.lang.String toGenericString();
public java.lang.String toString();
+ public static java.util.Comparator ORDER_BY_SIGNATURE;
+}
+
+-keep class java.lang.reflect.Parameter {
+
+ public boolean equals(java.lang.Object);
+ public java.lang.annotation.Annotation getAnnotation(java.lang.Class);
+ public java.lang.annotation.Annotation[] getAnnotations();
+ public java.lang.annotation.Annotation[] getAnnotationsByType(java.lang.Class);
+ public java.lang.annotation.Annotation getDeclaredAnnotation(java.lang.Class);
+ public java.lang.annotation.Annotation[] getDeclaredAnnotations();
+ public java.lang.annotation.Annotation[] getDeclaredAnnotationsByType(java.lang.Class);
+ public java.lang.reflect.Executable getDeclaringExecutable();
+ public int getModifiers();
+ public java.lang.String getName();
+ public java.lang.reflect.Type getParameterizedType();
+ public java.lang.Class getType();
+ public int hashCode();
+ public boolean isImplicit();
+ public boolean isNamePresent();
+ public boolean isSynthetic();
+ public boolean isVarArgs();
+ public java.lang.String toString();
+
+
}
-keep class java.lang.reflect.Type {
+ public java.lang.String getTypeName();
}
@@ -7945,12 +26088,12 @@
}
-keep class java.net.DatagramPacket {
- <init>(byte[], int);
<init>(byte[], int, int);
+ <init>(byte[], int);
<init>(byte[], int, int, java.net.InetAddress, int);
+ <init>(byte[], int, int, java.net.SocketAddress);
<init>(byte[], int, java.net.InetAddress, int);
<init>(byte[], int, java.net.SocketAddress);
- <init>(byte[], int, int, java.net.SocketAddress);
public synchronized java.net.InetAddress getAddress();
public synchronized byte[] getData();
@@ -7963,6 +26106,7 @@
public synchronized void setData(byte[]);
public synchronized void setLength(int);
public synchronized void setPort(int);
+ public void setReceivedLength(int);
public synchronized void setSocketAddress(java.net.SocketAddress);
@@ -7970,18 +26114,19 @@
-keep class java.net.DatagramSocket {
<init>();
- <init>(int);
- <init>(int, java.net.InetAddress);
<init>(java.net.DatagramSocketImpl);
<init>(java.net.SocketAddress);
+ <init>(int);
+ <init>(int, java.net.InetAddress);
- public void bind(java.net.SocketAddress);
+ public synchronized void bind(java.net.SocketAddress);
public void close();
- public void connect(java.net.SocketAddress);
public void connect(java.net.InetAddress, int);
+ public void connect(java.net.SocketAddress);
public void disconnect();
- public boolean getBroadcast();
+ public synchronized boolean getBroadcast();
public java.nio.channels.DatagramChannel getChannel();
+ public java.io.FileDescriptor getFileDescriptor$();
public java.net.InetAddress getInetAddress();
public java.net.InetAddress getLocalAddress();
public int getLocalPort();
@@ -7989,22 +26134,22 @@
public int getPort();
public synchronized int getReceiveBufferSize();
public java.net.SocketAddress getRemoteSocketAddress();
- public boolean getReuseAddress();
+ public synchronized boolean getReuseAddress();
public synchronized int getSendBufferSize();
public synchronized int getSoTimeout();
- public int getTrafficClass();
+ public synchronized int getTrafficClass();
public boolean isBound();
public boolean isClosed();
public boolean isConnected();
public synchronized void receive(java.net.DatagramPacket);
public void send(java.net.DatagramPacket);
- public void setBroadcast(boolean);
+ public synchronized void setBroadcast(boolean);
public static synchronized void setDatagramSocketImplFactory(java.net.DatagramSocketImplFactory);
public synchronized void setReceiveBufferSize(int);
- public void setReuseAddress(boolean);
+ public synchronized void setReuseAddress(boolean);
public synchronized void setSendBufferSize(int);
public synchronized void setSoTimeout(int);
- public void setTrafficClass(int);
+ public synchronized void setTrafficClass(int);
}
@@ -8053,12 +26198,15 @@
-keep class java.net.InetAddress {
+ public static void clearDnsCache();
public boolean equals(java.lang.Object);
public byte[] getAddress();
public static java.net.InetAddress[] getAllByName(java.lang.String);
- public static java.net.InetAddress getByAddress(byte[]);
+ public static java.net.InetAddress[] getAllByNameOnNet(java.lang.String, int);
public static java.net.InetAddress getByAddress(java.lang.String, byte[]);
+ public static java.net.InetAddress getByAddress(byte[]);
public static java.net.InetAddress getByName(java.lang.String);
+ public static java.net.InetAddress getByNameOnNet(java.lang.String, int);
public java.lang.String getCanonicalHostName();
public java.lang.String getHostAddress();
public java.lang.String getHostName();
@@ -8074,9 +26222,12 @@
public boolean isMCOrgLocal();
public boolean isMCSiteLocal();
public boolean isMulticastAddress();
+ public static boolean isNumeric(java.lang.String);
public boolean isReachable(int);
public boolean isReachable(java.net.NetworkInterface, int, int);
+ public boolean isReachableByICMP(int);
public boolean isSiteLocalAddress();
+ public static java.net.InetAddress parseNumericAddress(java.lang.String);
public java.lang.String toString();
@@ -8129,6 +26280,13 @@
}
+-keep class java.net.ProtocolFamily {
+
+ public abstract java.lang.String name();
+
+
+}
+
-keep class java.net.Proxy {
<init>(java.net.Proxy$Type, java.net.SocketAddress);
@@ -8164,17 +26322,19 @@
public void bind(java.net.SocketAddress, int);
public void close();
public java.nio.channels.ServerSocketChannel getChannel();
+ public java.io.FileDescriptor getFileDescriptor$();
+ public java.net.SocketImpl getImpl();
public java.net.InetAddress getInetAddress();
public int getLocalPort();
public java.net.SocketAddress getLocalSocketAddress();
- public int getReceiveBufferSize();
+ public synchronized int getReceiveBufferSize();
public boolean getReuseAddress();
public synchronized int getSoTimeout();
protected void implAccept(java.net.Socket);
public boolean isBound();
public boolean isClosed();
public void setPerformancePreferences(int, int, int);
- public void setReceiveBufferSize(int);
+ public synchronized void setReceiveBufferSize(int);
public void setReuseAddress(boolean);
public synchronized void setSoTimeout(int);
public static synchronized void setSocketFactory(java.net.SocketImplFactory);
@@ -8186,19 +26346,20 @@
-keep class java.net.Socket {
<init>();
<init>(java.net.Proxy);
- <init>(java.lang.String, int);
- <init>(java.lang.String, int, java.net.InetAddress, int);
- <init>(java.lang.String, int, boolean);
- <init>(java.net.InetAddress, int);
- <init>(java.net.InetAddress, int, java.net.InetAddress, int);
- <init>(java.net.InetAddress, int, boolean);
<init>(java.net.SocketImpl);
+ <init>(java.lang.String, int);
+ <init>(java.net.InetAddress, int);
+ <init>(java.lang.String, int, java.net.InetAddress, int);
+ <init>(java.net.InetAddress, int, java.net.InetAddress, int);
+ <init>(java.lang.String, int, boolean);
+ <init>(java.net.InetAddress, int, boolean);
public void bind(java.net.SocketAddress);
public synchronized void close();
public void connect(java.net.SocketAddress);
public void connect(java.net.SocketAddress, int);
public java.nio.channels.SocketChannel getChannel();
+ public java.io.FileDescriptor getFileDescriptor$();
public java.net.InetAddress getInetAddress();
public java.io.InputStream getInputStream();
public boolean getKeepAlive();
@@ -8248,8 +26409,10 @@
}
-keep class java.net.SocketException {
- <init>();
<init>(java.lang.String);
+ <init>();
+ <init>(java.lang.Throwable);
+ <init>(java.lang.String, java.lang.Throwable);
@@ -8266,6 +26429,7 @@
protected abstract void connect(java.net.InetAddress, int);
protected abstract void connect(java.net.SocketAddress, int);
protected abstract void create(boolean);
+ public java.io.FileDescriptor getFD$();
protected java.io.FileDescriptor getFileDescriptor();
protected java.net.InetAddress getInetAddress();
protected abstract java.io.InputStream getInputStream();
@@ -8294,12 +26458,20 @@
}
+-keep class java.net.SocketOption {
+
+ public abstract java.lang.String name();
+ public abstract java.lang.Class type();
+
+
+}
+
-keep class java.net.URI {
<init>(java.lang.String);
- <init>(java.lang.String, java.lang.String, java.lang.String);
<init>(java.lang.String, java.lang.String, java.lang.String, int, java.lang.String, java.lang.String, java.lang.String);
- <init>(java.lang.String, java.lang.String, java.lang.String, java.lang.String);
<init>(java.lang.String, java.lang.String, java.lang.String, java.lang.String, java.lang.String);
+ <init>(java.lang.String, java.lang.String, java.lang.String, java.lang.String);
+ <init>(java.lang.String, java.lang.String, java.lang.String);
public int compareTo(java.net.URI);
public int compareTo(java.lang.Object);
@@ -8348,12 +26520,12 @@
}
-keep class java.net.URL {
+ <init>(java.lang.String, java.lang.String, int, java.lang.String);
+ <init>(java.lang.String, java.lang.String, java.lang.String);
+ <init>(java.lang.String, java.lang.String, int, java.lang.String, java.net.URLStreamHandler);
<init>(java.lang.String);
<init>(java.net.URL, java.lang.String);
<init>(java.net.URL, java.lang.String, java.net.URLStreamHandler);
- <init>(java.lang.String, java.lang.String, java.lang.String);
- <init>(java.lang.String, java.lang.String, int, java.lang.String);
- <init>(java.lang.String, java.lang.String, int, java.lang.String, java.net.URLStreamHandler);
public boolean equals(java.lang.Object);
public java.lang.String getAuthority();
@@ -8368,14 +26540,12 @@
public java.lang.String getQuery();
public java.lang.String getRef();
public java.lang.String getUserInfo();
- public int hashCode();
+ public synchronized int hashCode();
public java.net.URLConnection openConnection();
public java.net.URLConnection openConnection(java.net.Proxy);
public java.io.InputStream openStream();
public boolean sameFile(java.net.URL);
- protected void set(java.lang.String, java.lang.String, int, java.lang.String, java.lang.String);
- protected void set(java.lang.String, java.lang.String, int, java.lang.String, java.lang.String, java.lang.String, java.lang.String, java.lang.String);
- public static synchronized void setURLStreamHandlerFactory(java.net.URLStreamHandlerFactory);
+ public static void setURLStreamHandlerFactory(java.net.URLStreamHandlerFactory);
public java.lang.String toExternalForm();
public java.lang.String toString();
public java.net.URI toURI();
@@ -8394,6 +26564,7 @@
public java.lang.Object getContent(java.lang.Class[]);
public java.lang.String getContentEncoding();
public int getContentLength();
+ public long getContentLengthLong();
public java.lang.String getContentType();
public long getDate();
public static boolean getDefaultAllowUserInteraction();
@@ -8402,12 +26573,13 @@
public boolean getDoInput();
public boolean getDoOutput();
public long getExpiration();
- public static java.net.FileNameMap getFileNameMap();
- public java.lang.String getHeaderField(int);
+ public static synchronized java.net.FileNameMap getFileNameMap();
public java.lang.String getHeaderField(java.lang.String);
+ public java.lang.String getHeaderField(int);
public long getHeaderFieldDate(java.lang.String, long);
public int getHeaderFieldInt(java.lang.String, int);
public java.lang.String getHeaderFieldKey(int);
+ public long getHeaderFieldLong(java.lang.String, long);
public java.util.Map getHeaderFields();
public long getIfModifiedSince();
public java.io.InputStream getInputStream();
@@ -8451,15 +26623,15 @@
protected boolean equals(java.net.URL, java.net.URL);
protected int getDefaultPort();
- protected java.net.InetAddress getHostAddress(java.net.URL);
+ protected synchronized java.net.InetAddress getHostAddress(java.net.URL);
protected int hashCode(java.net.URL);
protected boolean hostsEqual(java.net.URL, java.net.URL);
protected abstract java.net.URLConnection openConnection(java.net.URL);
protected java.net.URLConnection openConnection(java.net.URL, java.net.Proxy);
protected void parseURL(java.net.URL, java.lang.String, int, int);
protected boolean sameFile(java.net.URL, java.net.URL);
- protected void setURL(java.net.URL, java.lang.String, java.lang.String, int, java.lang.String, java.lang.String);
protected void setURL(java.net.URL, java.lang.String, java.lang.String, int, java.lang.String, java.lang.String, java.lang.String, java.lang.String, java.lang.String);
+ protected void setURL(java.net.URL, java.lang.String, java.lang.String, int, java.lang.String, java.lang.String);
protected java.lang.String toExternalForm(java.net.URL);
@@ -8473,8 +26645,8 @@
}
-keep class java.net.UnknownHostException {
- <init>();
<init>(java.lang.String);
+ <init>();
@@ -8487,6 +26659,7 @@
public int capacity();
public java.nio.Buffer clear();
public java.nio.Buffer flip();
+ public int getElementSizeShift();
public abstract boolean hasArray();
public boolean hasRemaining();
public abstract boolean isDirect();
@@ -8499,21 +26672,6 @@
public int remaining();
public java.nio.Buffer reset();
public java.nio.Buffer rewind();
- public java.lang.String toString();
-
-
-}
-
--keep class java.nio.BufferOverflowException {
- <init>();
-
-
-
-}
-
--keep class java.nio.BufferUnderflowException {
- <init>();
-
}
@@ -8538,9 +26696,9 @@
public abstract java.nio.ByteBuffer duplicate();
public boolean equals(java.lang.Object);
public abstract byte get();
- public java.nio.ByteBuffer get(byte[]);
- public java.nio.ByteBuffer get(byte[], int, int);
public abstract byte get(int);
+ public java.nio.ByteBuffer get(byte[], int, int);
+ public java.nio.ByteBuffer get(byte[]);
public abstract char getChar();
public abstract char getChar(int);
public abstract double getDouble();
@@ -8555,14 +26713,15 @@
public abstract short getShort(int);
public boolean hasArray();
public int hashCode();
+ public boolean isAccessible();
public abstract boolean isDirect();
public java.nio.ByteOrder order();
public java.nio.ByteBuffer order(java.nio.ByteOrder);
public abstract java.nio.ByteBuffer put(byte);
- public java.nio.ByteBuffer put(byte[]);
- public java.nio.ByteBuffer put(byte[], int, int);
- public java.nio.ByteBuffer put(java.nio.ByteBuffer);
public abstract java.nio.ByteBuffer put(int, byte);
+ public java.nio.ByteBuffer put(java.nio.ByteBuffer);
+ public java.nio.ByteBuffer put(byte[], int, int);
+ public java.nio.ByteBuffer put(byte[]);
public abstract java.nio.ByteBuffer putChar(char);
public abstract java.nio.ByteBuffer putChar(int, char);
public abstract java.nio.ByteBuffer putDouble(double);
@@ -8575,9 +26734,11 @@
public abstract java.nio.ByteBuffer putLong(int, long);
public abstract java.nio.ByteBuffer putShort(short);
public abstract java.nio.ByteBuffer putShort(int, short);
+ public void setAccessible(boolean);
public abstract java.nio.ByteBuffer slice();
- public static java.nio.ByteBuffer wrap(byte[]);
+ public java.lang.String toString();
public static java.nio.ByteBuffer wrap(byte[], int, int);
+ public static java.nio.ByteBuffer wrap(byte[]);
}
@@ -8595,47 +26756,48 @@
-keep class java.nio.CharBuffer {
public static java.nio.CharBuffer allocate(int);
- public java.nio.CharBuffer append(char);
public java.nio.CharBuffer append(java.lang.CharSequence);
public java.nio.CharBuffer append(java.lang.CharSequence, int, int);
+ public java.nio.CharBuffer append(char);
+ public java.lang.Appendable append(char);
public java.lang.Appendable append(java.lang.CharSequence, int, int);
public java.lang.Appendable append(java.lang.CharSequence);
- public java.lang.Appendable append(char);
public char[] array();
public java.lang.Object array();
public int arrayOffset();
public abstract java.nio.CharBuffer asReadOnlyBuffer();
public char charAt(int);
+ public java.util.stream.IntStream chars();
public abstract java.nio.CharBuffer compact();
public int compareTo(java.nio.CharBuffer);
public int compareTo(java.lang.Object);
public abstract java.nio.CharBuffer duplicate();
public boolean equals(java.lang.Object);
public abstract char get();
- public java.nio.CharBuffer get(char[]);
- public java.nio.CharBuffer get(char[], int, int);
public abstract char get(int);
+ public java.nio.CharBuffer get(char[], int, int);
+ public java.nio.CharBuffer get(char[]);
public boolean hasArray();
public int hashCode();
public abstract boolean isDirect();
public int length();
public abstract java.nio.ByteOrder order();
public abstract java.nio.CharBuffer put(char);
- public java.nio.CharBuffer put(char[]);
- public java.nio.CharBuffer put(char[], int, int);
- public java.nio.CharBuffer put(java.nio.CharBuffer);
public abstract java.nio.CharBuffer put(int, char);
- public java.nio.CharBuffer put(java.lang.String);
+ public java.nio.CharBuffer put(java.nio.CharBuffer);
+ public java.nio.CharBuffer put(char[], int, int);
+ public java.nio.CharBuffer put(char[]);
public java.nio.CharBuffer put(java.lang.String, int, int);
+ public java.nio.CharBuffer put(java.lang.String);
public int read(java.nio.CharBuffer);
public abstract java.nio.CharBuffer slice();
public abstract java.nio.CharBuffer subSequence(int, int);
public java.lang.CharSequence subSequence(int, int);
public java.lang.String toString();
- public static java.nio.CharBuffer wrap(char[]);
public static java.nio.CharBuffer wrap(char[], int, int);
- public static java.nio.CharBuffer wrap(java.lang.CharSequence);
+ public static java.nio.CharBuffer wrap(char[]);
public static java.nio.CharBuffer wrap(java.lang.CharSequence, int, int);
+ public static java.nio.CharBuffer wrap(java.lang.CharSequence);
}
@@ -8653,21 +26815,22 @@
public abstract java.nio.DoubleBuffer duplicate();
public boolean equals(java.lang.Object);
public abstract double get();
- public java.nio.DoubleBuffer get(double[]);
- public java.nio.DoubleBuffer get(double[], int, int);
public abstract double get(int);
+ public java.nio.DoubleBuffer get(double[], int, int);
+ public java.nio.DoubleBuffer get(double[]);
public boolean hasArray();
public int hashCode();
public abstract boolean isDirect();
public abstract java.nio.ByteOrder order();
public abstract java.nio.DoubleBuffer put(double);
- public java.nio.DoubleBuffer put(double[]);
- public java.nio.DoubleBuffer put(double[], int, int);
- public java.nio.DoubleBuffer put(java.nio.DoubleBuffer);
public abstract java.nio.DoubleBuffer put(int, double);
+ public java.nio.DoubleBuffer put(java.nio.DoubleBuffer);
+ public java.nio.DoubleBuffer put(double[], int, int);
+ public java.nio.DoubleBuffer put(double[]);
public abstract java.nio.DoubleBuffer slice();
- public static java.nio.DoubleBuffer wrap(double[]);
+ public java.lang.String toString();
public static java.nio.DoubleBuffer wrap(double[], int, int);
+ public static java.nio.DoubleBuffer wrap(double[]);
}
@@ -8685,21 +26848,22 @@
public abstract java.nio.FloatBuffer duplicate();
public boolean equals(java.lang.Object);
public abstract float get();
- public java.nio.FloatBuffer get(float[]);
- public java.nio.FloatBuffer get(float[], int, int);
public abstract float get(int);
+ public java.nio.FloatBuffer get(float[], int, int);
+ public java.nio.FloatBuffer get(float[]);
public boolean hasArray();
public int hashCode();
public abstract boolean isDirect();
public abstract java.nio.ByteOrder order();
public abstract java.nio.FloatBuffer put(float);
- public java.nio.FloatBuffer put(float[]);
- public java.nio.FloatBuffer put(float[], int, int);
- public java.nio.FloatBuffer put(java.nio.FloatBuffer);
public abstract java.nio.FloatBuffer put(int, float);
+ public java.nio.FloatBuffer put(java.nio.FloatBuffer);
+ public java.nio.FloatBuffer put(float[], int, int);
+ public java.nio.FloatBuffer put(float[]);
public abstract java.nio.FloatBuffer slice();
- public static java.nio.FloatBuffer wrap(float[]);
+ public java.lang.String toString();
public static java.nio.FloatBuffer wrap(float[], int, int);
+ public static java.nio.FloatBuffer wrap(float[]);
}
@@ -8717,21 +26881,22 @@
public abstract java.nio.IntBuffer duplicate();
public boolean equals(java.lang.Object);
public abstract int get();
- public java.nio.IntBuffer get(int[]);
- public java.nio.IntBuffer get(int[], int, int);
public abstract int get(int);
+ public java.nio.IntBuffer get(int[], int, int);
+ public java.nio.IntBuffer get(int[]);
public boolean hasArray();
public int hashCode();
public abstract boolean isDirect();
public abstract java.nio.ByteOrder order();
public abstract java.nio.IntBuffer put(int);
- public java.nio.IntBuffer put(int[]);
- public java.nio.IntBuffer put(int[], int, int);
- public java.nio.IntBuffer put(java.nio.IntBuffer);
public abstract java.nio.IntBuffer put(int, int);
+ public java.nio.IntBuffer put(java.nio.IntBuffer);
+ public java.nio.IntBuffer put(int[], int, int);
+ public java.nio.IntBuffer put(int[]);
public abstract java.nio.IntBuffer slice();
- public static java.nio.IntBuffer wrap(int[]);
+ public java.lang.String toString();
public static java.nio.IntBuffer wrap(int[], int, int);
+ public static java.nio.IntBuffer wrap(int[]);
}
@@ -8749,21 +26914,22 @@
public abstract java.nio.LongBuffer duplicate();
public boolean equals(java.lang.Object);
public abstract long get();
- public java.nio.LongBuffer get(long[]);
- public java.nio.LongBuffer get(long[], int, int);
public abstract long get(int);
+ public java.nio.LongBuffer get(long[], int, int);
+ public java.nio.LongBuffer get(long[]);
public boolean hasArray();
public int hashCode();
public abstract boolean isDirect();
public abstract java.nio.ByteOrder order();
public abstract java.nio.LongBuffer put(long);
- public java.nio.LongBuffer put(long[]);
- public java.nio.LongBuffer put(long[], int, int);
- public java.nio.LongBuffer put(java.nio.LongBuffer);
public abstract java.nio.LongBuffer put(int, long);
+ public java.nio.LongBuffer put(java.nio.LongBuffer);
+ public java.nio.LongBuffer put(long[], int, int);
+ public java.nio.LongBuffer put(long[]);
public abstract java.nio.LongBuffer slice();
- public static java.nio.LongBuffer wrap(long[]);
+ public java.lang.String toString();
public static java.nio.LongBuffer wrap(long[], int, int);
+ public static java.nio.LongBuffer wrap(long[]);
}
@@ -8790,21 +26956,22 @@
public abstract java.nio.ShortBuffer duplicate();
public boolean equals(java.lang.Object);
public abstract short get();
- public java.nio.ShortBuffer get(short[]);
- public java.nio.ShortBuffer get(short[], int, int);
public abstract short get(int);
+ public java.nio.ShortBuffer get(short[], int, int);
+ public java.nio.ShortBuffer get(short[]);
public boolean hasArray();
public int hashCode();
public abstract boolean isDirect();
public abstract java.nio.ByteOrder order();
public abstract java.nio.ShortBuffer put(short);
- public java.nio.ShortBuffer put(short[]);
- public java.nio.ShortBuffer put(short[], int, int);
- public java.nio.ShortBuffer put(java.nio.ShortBuffer);
public abstract java.nio.ShortBuffer put(int, short);
+ public java.nio.ShortBuffer put(java.nio.ShortBuffer);
+ public java.nio.ShortBuffer put(short[], int, int);
+ public java.nio.ShortBuffer put(short[]);
public abstract java.nio.ShortBuffer slice();
- public static java.nio.ShortBuffer wrap(short[]);
+ public java.lang.String toString();
public static java.nio.ShortBuffer wrap(short[], int, int);
+ public static java.nio.ShortBuffer wrap(short[]);
}
@@ -8816,6 +26983,28 @@
}
+-keep class java.nio.channels.AsynchronousFileChannel {
+ <init>();
+
+ public abstract void force(boolean);
+ public abstract void lock(long, long, boolean, java.lang.Object, java.nio.channels.CompletionHandler);
+ public void lock(java.lang.Object, java.nio.channels.CompletionHandler);
+ public abstract java.util.concurrent.Future lock(long, long, boolean);
+ public java.util.concurrent.Future lock();
+ public static java.nio.channels.AsynchronousFileChannel open(java.nio.file.Path, java.util.Set, java.util.concurrent.ExecutorService, java.nio.file.attribute.FileAttribute[]);
+ public static java.nio.channels.AsynchronousFileChannel open(java.nio.file.Path, java.nio.file.OpenOption[]);
+ public abstract void read(java.nio.ByteBuffer, long, java.lang.Object, java.nio.channels.CompletionHandler);
+ public abstract java.util.concurrent.Future read(java.nio.ByteBuffer, long);
+ public abstract long size();
+ public abstract java.nio.channels.AsynchronousFileChannel truncate(long);
+ public abstract java.nio.channels.FileLock tryLock(long, long, boolean);
+ public java.nio.channels.FileLock tryLock();
+ public abstract void write(java.nio.ByteBuffer, long, java.lang.Object, java.nio.channels.CompletionHandler);
+ public abstract java.util.concurrent.Future write(java.nio.ByteBuffer, long);
+
+
+}
+
-keep class java.nio.channels.Channel {
public abstract void close();
@@ -8831,23 +27020,38 @@
}
+-keep class java.nio.channels.CompletionHandler {
+
+ public abstract void completed(java.lang.Object, java.lang.Object);
+ public abstract void failed(java.lang.Throwable, java.lang.Object);
+
+
+}
+
-keep class java.nio.channels.DatagramChannel {
<init>(java.nio.channels.spi.SelectorProvider);
+ public abstract java.nio.channels.DatagramChannel bind(java.net.SocketAddress);
+ public java.nio.channels.NetworkChannel bind(java.net.SocketAddress);
public abstract java.nio.channels.DatagramChannel connect(java.net.SocketAddress);
public abstract java.nio.channels.DatagramChannel disconnect();
+ public abstract java.net.SocketAddress getLocalAddress();
+ public abstract java.net.SocketAddress getRemoteAddress();
public abstract boolean isConnected();
public static java.nio.channels.DatagramChannel open();
+ public static java.nio.channels.DatagramChannel open(java.net.ProtocolFamily);
public abstract int read(java.nio.ByteBuffer);
public abstract long read(java.nio.ByteBuffer[], int, int);
- public synchronized long read(java.nio.ByteBuffer[]);
+ public long read(java.nio.ByteBuffer[]);
public abstract java.net.SocketAddress receive(java.nio.ByteBuffer);
public abstract int send(java.nio.ByteBuffer, java.net.SocketAddress);
+ public abstract java.nio.channels.DatagramChannel setOption(java.net.SocketOption, java.lang.Object);
+ public java.nio.channels.NetworkChannel setOption(java.net.SocketOption, java.lang.Object);
public abstract java.net.DatagramSocket socket();
public int validOps();
public abstract int write(java.nio.ByteBuffer);
public abstract long write(java.nio.ByteBuffer[], int, int);
- public synchronized long write(java.nio.ByteBuffer[]);
+ public long write(java.nio.ByteBuffer[]);
}
@@ -8856,25 +27060,29 @@
<init>();
public abstract void force(boolean);
- public java.nio.channels.FileLock lock();
public abstract java.nio.channels.FileLock lock(long, long, boolean);
+ public java.nio.channels.FileLock lock();
public abstract java.nio.MappedByteBuffer map(java.nio.channels.FileChannel$MapMode, long, long);
+ public static java.nio.channels.FileChannel open(java.nio.file.Path, java.util.Set, java.nio.file.attribute.FileAttribute[]);
+ public static java.nio.channels.FileChannel open(java.nio.file.Path, java.nio.file.OpenOption[]);
public abstract long position();
public abstract java.nio.channels.FileChannel position(long);
+ public java.nio.channels.SeekableByteChannel position(long);
public abstract int read(java.nio.ByteBuffer);
- public abstract int read(java.nio.ByteBuffer, long);
- public long read(java.nio.ByteBuffer[]);
public abstract long read(java.nio.ByteBuffer[], int, int);
+ public long read(java.nio.ByteBuffer[]);
+ public abstract int read(java.nio.ByteBuffer, long);
public abstract long size();
public abstract long transferFrom(java.nio.channels.ReadableByteChannel, long, long);
public abstract long transferTo(long, long, java.nio.channels.WritableByteChannel);
public abstract java.nio.channels.FileChannel truncate(long);
- public java.nio.channels.FileLock tryLock();
+ public java.nio.channels.SeekableByteChannel truncate(long);
public abstract java.nio.channels.FileLock tryLock(long, long, boolean);
+ public java.nio.channels.FileLock tryLock();
public abstract int write(java.nio.ByteBuffer);
- public abstract int write(java.nio.ByteBuffer, long);
- public long write(java.nio.ByteBuffer[]);
public abstract long write(java.nio.ByteBuffer[], int, int);
+ public long write(java.nio.ByteBuffer[]);
+ public abstract int write(java.nio.ByteBuffer, long);
}
@@ -8891,7 +27099,9 @@
-keep class java.nio.channels.FileLock {
<init>(java.nio.channels.FileChannel, long, long, boolean);
+ <init>(java.nio.channels.AsynchronousFileChannel, long, long, boolean);
+ public java.nio.channels.Channel acquiredBy();
public java.nio.channels.FileChannel channel();
public void close();
public boolean isShared();
@@ -8905,6 +27115,17 @@
}
+-keep class java.nio.channels.NetworkChannel {
+
+ public abstract java.nio.channels.NetworkChannel bind(java.net.SocketAddress);
+ public abstract java.net.SocketAddress getLocalAddress();
+ public abstract java.lang.Object getOption(java.net.SocketOption);
+ public abstract java.nio.channels.NetworkChannel setOption(java.net.SocketOption, java.lang.Object);
+ public abstract java.util.Set supportedOptions();
+
+
+}
+
-keep class java.nio.channels.Pipe {
<init>();
@@ -8938,6 +27159,18 @@
}
+-keep class java.nio.channels.SeekableByteChannel {
+
+ public abstract long position();
+ public abstract java.nio.channels.SeekableByteChannel position(long);
+ public abstract int read(java.nio.ByteBuffer);
+ public abstract long size();
+ public abstract java.nio.channels.SeekableByteChannel truncate(long);
+ public abstract int write(java.nio.ByteBuffer);
+
+
+}
+
-keep class java.nio.channels.SelectableChannel {
<init>();
@@ -8947,8 +27180,8 @@
public abstract boolean isRegistered();
public abstract java.nio.channels.SelectionKey keyFor(java.nio.channels.Selector);
public abstract java.nio.channels.spi.SelectorProvider provider();
- public java.nio.channels.SelectionKey register(java.nio.channels.Selector, int);
public abstract java.nio.channels.SelectionKey register(java.nio.channels.Selector, int, java.lang.Object);
+ public java.nio.channels.SelectionKey register(java.nio.channels.Selector, int);
public abstract int validOps();
@@ -8986,8 +27219,8 @@
public abstract java.util.Set keys();
public static java.nio.channels.Selector open();
public abstract java.nio.channels.spi.SelectorProvider provider();
- public abstract int select();
public abstract int select(long);
+ public abstract int select();
public abstract int selectNow();
public abstract java.util.Set selectedKeys();
public abstract java.nio.channels.Selector wakeup();
@@ -8999,7 +27232,13 @@
<init>(java.nio.channels.spi.SelectorProvider);
public abstract java.nio.channels.SocketChannel accept();
+ public java.nio.channels.ServerSocketChannel bind(java.net.SocketAddress);
+ public abstract java.nio.channels.ServerSocketChannel bind(java.net.SocketAddress, int);
+ public java.nio.channels.NetworkChannel bind(java.net.SocketAddress);
+ public abstract java.net.SocketAddress getLocalAddress();
public static java.nio.channels.ServerSocketChannel open();
+ public abstract java.nio.channels.ServerSocketChannel setOption(java.net.SocketOption, java.lang.Object);
+ public java.nio.channels.NetworkChannel setOption(java.net.SocketOption, java.lang.Object);
public abstract java.net.ServerSocket socket();
public int validOps();
@@ -9009,20 +27248,28 @@
-keep class java.nio.channels.SocketChannel {
<init>(java.nio.channels.spi.SelectorProvider);
+ public abstract java.nio.channels.SocketChannel bind(java.net.SocketAddress);
+ public java.nio.channels.NetworkChannel bind(java.net.SocketAddress);
public abstract boolean connect(java.net.SocketAddress);
public abstract boolean finishConnect();
+ public abstract java.net.SocketAddress getLocalAddress();
+ public abstract java.net.SocketAddress getRemoteAddress();
public abstract boolean isConnected();
public abstract boolean isConnectionPending();
public static java.nio.channels.SocketChannel open();
public static java.nio.channels.SocketChannel open(java.net.SocketAddress);
public abstract int read(java.nio.ByteBuffer);
public abstract long read(java.nio.ByteBuffer[], int, int);
- public synchronized long read(java.nio.ByteBuffer[]);
+ public long read(java.nio.ByteBuffer[]);
+ public abstract java.nio.channels.SocketChannel setOption(java.net.SocketOption, java.lang.Object);
+ public java.nio.channels.NetworkChannel setOption(java.net.SocketOption, java.lang.Object);
+ public abstract java.nio.channels.SocketChannel shutdownInput();
+ public abstract java.nio.channels.SocketChannel shutdownOutput();
public abstract java.net.Socket socket();
public int validOps();
public abstract int write(java.nio.ByteBuffer);
public abstract long write(java.nio.ByteBuffer[], int, int);
- public synchronized long write(java.nio.ByteBuffer[]);
+ public long write(java.nio.ByteBuffer[]);
}
@@ -9041,7 +27288,7 @@
public void close();
protected void end(boolean);
protected abstract void implCloseChannel();
- public synchronized boolean isOpen();
+ public boolean isOpen();
}
@@ -9051,12 +27298,12 @@
public java.lang.Object blockingLock();
public java.nio.channels.SelectableChannel configureBlocking(boolean);
- protected synchronized void implCloseChannel();
+ protected void implCloseChannel();
protected abstract void implCloseSelectableChannel();
protected abstract void implConfigureBlocking(boolean);
public boolean isBlocking();
- public synchronized boolean isRegistered();
- public synchronized java.nio.channels.SelectionKey keyFor(java.nio.channels.Selector);
+ public boolean isRegistered();
+ public java.nio.channels.SelectionKey keyFor(java.nio.channels.Selector);
public java.nio.channels.spi.SelectorProvider provider();
public java.nio.channels.SelectionKey register(java.nio.channels.Selector, int, java.lang.Object);
@@ -9093,11 +27340,12 @@
public java.nio.channels.Channel inheritedChannel();
public abstract java.nio.channels.DatagramChannel openDatagramChannel();
+ public abstract java.nio.channels.DatagramChannel openDatagramChannel(java.net.ProtocolFamily);
public abstract java.nio.channels.Pipe openPipe();
public abstract java.nio.channels.spi.AbstractSelector openSelector();
public abstract java.nio.channels.ServerSocketChannel openServerSocketChannel();
public abstract java.nio.channels.SocketChannel openSocketChannel();
- public static synchronized java.nio.channels.spi.SelectorProvider provider();
+ public static java.nio.channels.spi.SelectorProvider provider();
}
@@ -9126,6 +27374,7 @@
public java.nio.ByteBuffer encode(java.lang.String);
public boolean equals(java.lang.Object);
public static java.nio.charset.Charset forName(java.lang.String);
+ public static java.nio.charset.Charset forNameUEE(java.lang.String);
public int hashCode();
public boolean isRegistered();
public static boolean isSupported(java.lang.String);
@@ -9142,8 +27391,8 @@
public float averageCharsPerByte();
public java.nio.charset.Charset charset();
- public java.nio.CharBuffer decode(java.nio.ByteBuffer);
public java.nio.charset.CoderResult decode(java.nio.ByteBuffer, java.nio.CharBuffer, boolean);
+ public java.nio.CharBuffer decode(java.nio.ByteBuffer);
protected abstract java.nio.charset.CoderResult decodeLoop(java.nio.ByteBuffer, java.nio.CharBuffer);
public java.nio.charset.Charset detectedCharset();
public java.nio.charset.CoderResult flush(java.nio.CharBuffer);
@@ -9167,15 +27416,15 @@
}
-keep class java.nio.charset.CharsetEncoder {
- <init>(java.nio.charset.Charset, float, float);
<init>(java.nio.charset.Charset, float, float, byte[]);
+ <init>(java.nio.charset.Charset, float, float);
public float averageBytesPerChar();
public boolean canEncode(char);
public boolean canEncode(java.lang.CharSequence);
public java.nio.charset.Charset charset();
- public java.nio.ByteBuffer encode(java.nio.CharBuffer);
public java.nio.charset.CoderResult encode(java.nio.CharBuffer, java.nio.ByteBuffer, boolean);
+ public java.nio.ByteBuffer encode(java.nio.CharBuffer);
protected abstract java.nio.charset.CoderResult encodeLoop(java.nio.CharBuffer, java.nio.ByteBuffer);
public java.nio.charset.CoderResult flush(java.nio.ByteBuffer);
protected java.nio.charset.CoderResult implFlush(java.nio.ByteBuffer);
@@ -9204,10 +27453,10 @@
public boolean isUnderflow();
public boolean isUnmappable();
public int length();
- public static synchronized java.nio.charset.CoderResult malformedForLength(int);
+ public static java.nio.charset.CoderResult malformedForLength(int);
public void throwException();
public java.lang.String toString();
- public static synchronized java.nio.charset.CoderResult unmappableForLength(int);
+ public static java.nio.charset.CoderResult unmappableForLength(int);
public static java.nio.charset.CoderResult OVERFLOW;
@@ -9224,20 +27473,307 @@
public static java.nio.charset.CodingErrorAction REPORT;
}
--keep class java.nio.charset.MalformedInputException {
- <init>(int);
+-keep class java.nio.file.AccessMode {
- public int getInputLength();
- public java.lang.String getMessage();
+ public static java.nio.file.AccessMode valueOf(java.lang.String);
+ public static java.nio.file.AccessMode[] values();
+
+ public static java.nio.file.AccessMode EXECUTE;
+ public static java.nio.file.AccessMode READ;
+ public static java.nio.file.AccessMode WRITE;
+
+}
+
+-keep class java.nio.file.CopyOption {
+
}
--keep class java.nio.charset.UnmappableCharacterException {
- <init>(int);
+-keep class java.nio.file.DirectoryStream {
- public int getInputLength();
- public java.lang.String getMessage();
+ public abstract java.util.Iterator iterator();
+
+
+}
+
+-keep class java.nio.file.DirectoryStream$Filter {
+
+ public abstract boolean accept(java.lang.Object);
+
+
+}
+
+-keep class java.nio.file.FileStore {
+ <init>();
+
+ public abstract java.lang.Object getAttribute(java.lang.String);
+ public abstract java.nio.file.attribute.FileStoreAttributeView getFileStoreAttributeView(java.lang.Class);
+ public abstract long getTotalSpace();
+ public abstract long getUnallocatedSpace();
+ public abstract long getUsableSpace();
+ public abstract boolean isReadOnly();
+ public abstract java.lang.String name();
+ public abstract boolean supportsFileAttributeView(java.lang.Class);
+ public abstract boolean supportsFileAttributeView(java.lang.String);
+ public abstract java.lang.String type();
+
+
+}
+
+-keep class java.nio.file.FileSystem {
+ <init>();
+
+ public abstract void close();
+ public abstract java.lang.Iterable getFileStores();
+ public abstract java.nio.file.Path getPath(java.lang.String, java.lang.String[]);
+ public abstract java.nio.file.PathMatcher getPathMatcher(java.lang.String);
+ public abstract java.lang.Iterable getRootDirectories();
+ public abstract java.lang.String getSeparator();
+ public abstract java.nio.file.attribute.UserPrincipalLookupService getUserPrincipalLookupService();
+ public abstract boolean isOpen();
+ public abstract boolean isReadOnly();
+ public abstract java.nio.file.WatchService newWatchService();
+ public abstract java.nio.file.spi.FileSystemProvider provider();
+ public abstract java.util.Set supportedFileAttributeViews();
+
+
+}
+
+-keep class java.nio.file.LinkOption {
+
+ public static java.nio.file.LinkOption valueOf(java.lang.String);
+ public static java.nio.file.LinkOption[] values();
+
+ public static java.nio.file.LinkOption NOFOLLOW_LINKS;
+
+}
+
+-keep class java.nio.file.OpenOption {
+
+
+
+}
+
+-keep class java.nio.file.Path {
+
+ public abstract int compareTo(java.nio.file.Path);
+ public int compareTo(java.lang.Object);
+ public abstract boolean endsWith(java.nio.file.Path);
+ public abstract boolean endsWith(java.lang.String);
+ public abstract boolean equals(java.lang.Object);
+ public abstract java.nio.file.Path getFileName();
+ public abstract java.nio.file.FileSystem getFileSystem();
+ public abstract java.nio.file.Path getName(int);
+ public abstract int getNameCount();
+ public abstract java.nio.file.Path getParent();
+ public abstract java.nio.file.Path getRoot();
+ public abstract int hashCode();
+ public abstract boolean isAbsolute();
+ public abstract java.util.Iterator iterator();
+ public abstract java.nio.file.Path normalize();
+ public abstract java.nio.file.WatchKey register(java.nio.file.WatchService, java.nio.file.WatchEvent$Kind[], java.nio.file.WatchEvent$Modifier[]);
+ public abstract java.nio.file.WatchKey register(java.nio.file.WatchService, java.nio.file.WatchEvent$Kind[]);
+ public abstract java.nio.file.Path relativize(java.nio.file.Path);
+ public abstract java.nio.file.Path resolve(java.nio.file.Path);
+ public abstract java.nio.file.Path resolve(java.lang.String);
+ public abstract java.nio.file.Path resolveSibling(java.nio.file.Path);
+ public abstract java.nio.file.Path resolveSibling(java.lang.String);
+ public abstract boolean startsWith(java.nio.file.Path);
+ public abstract boolean startsWith(java.lang.String);
+ public abstract java.nio.file.Path subpath(int, int);
+ public abstract java.nio.file.Path toAbsolutePath();
+ public abstract java.io.File toFile();
+ public abstract java.nio.file.Path toRealPath(java.nio.file.LinkOption[]);
+ public abstract java.lang.String toString();
+ public abstract java.net.URI toUri();
+
+
+}
+
+-keep class java.nio.file.PathMatcher {
+
+ public abstract boolean matches(java.nio.file.Path);
+
+
+}
+
+-keep class java.nio.file.WatchEvent {
+
+ public abstract java.lang.Object context();
+ public abstract int count();
+ public abstract java.nio.file.WatchEvent$Kind kind();
+
+
+}
+
+-keep class java.nio.file.WatchEvent$Kind {
+
+ public abstract java.lang.String name();
+ public abstract java.lang.Class type();
+
+
+}
+
+-keep class java.nio.file.WatchEvent$Modifier {
+
+ public abstract java.lang.String name();
+
+
+}
+
+-keep class java.nio.file.WatchKey {
+
+ public abstract void cancel();
+ public abstract boolean isValid();
+ public abstract java.util.List pollEvents();
+ public abstract boolean reset();
+ public abstract java.nio.file.Watchable watchable();
+
+
+}
+
+-keep class java.nio.file.WatchService {
+
+ public abstract void close();
+ public abstract java.nio.file.WatchKey poll();
+ public abstract java.nio.file.WatchKey poll(long, java.util.concurrent.TimeUnit);
+ public abstract java.nio.file.WatchKey take();
+
+
+}
+
+-keep class java.nio.file.Watchable {
+
+ public abstract java.nio.file.WatchKey register(java.nio.file.WatchService, java.nio.file.WatchEvent$Kind[], java.nio.file.WatchEvent$Modifier[]);
+ public abstract java.nio.file.WatchKey register(java.nio.file.WatchService, java.nio.file.WatchEvent$Kind[]);
+
+
+}
+
+-keep class java.nio.file.attribute.BasicFileAttributes {
+
+ public abstract java.nio.file.attribute.FileTime creationTime();
+ public abstract java.lang.Object fileKey();
+ public abstract boolean isDirectory();
+ public abstract boolean isOther();
+ public abstract boolean isRegularFile();
+ public abstract boolean isSymbolicLink();
+ public abstract java.nio.file.attribute.FileTime lastAccessTime();
+ public abstract java.nio.file.attribute.FileTime lastModifiedTime();
+ public abstract long size();
+
+
+}
+
+-keep class java.nio.file.attribute.FileAttribute {
+
+ public abstract java.lang.String name();
+ public abstract java.lang.Object value();
+
+
+}
+
+-keep class java.nio.file.attribute.FileAttributeView {
+
+
+
+}
+
+-keep class java.nio.file.attribute.FileStoreAttributeView {
+
+
+
+}
+
+-keep class java.nio.file.attribute.FileTime {
+
+ public int compareTo(java.nio.file.attribute.FileTime);
+ public int compareTo(java.lang.Object);
+ public boolean equals(java.lang.Object);
+ public static java.nio.file.attribute.FileTime from(long, java.util.concurrent.TimeUnit);
+ public static java.nio.file.attribute.FileTime from(java.time.Instant);
+ public static java.nio.file.attribute.FileTime fromMillis(long);
+ public int hashCode();
+ public long to(java.util.concurrent.TimeUnit);
+ public java.time.Instant toInstant();
+ public long toMillis();
+ public java.lang.String toString();
+
+
+}
+
+-keep class java.nio.file.attribute.GroupPrincipal {
+
+
+
+}
+
+-keep class java.nio.file.attribute.UserPrincipal {
+
+
+
+}
+
+-keep class java.nio.file.attribute.UserPrincipalLookupService {
+ <init>();
+
+ public abstract java.nio.file.attribute.GroupPrincipal lookupPrincipalByGroupName(java.lang.String);
+ public abstract java.nio.file.attribute.UserPrincipal lookupPrincipalByName(java.lang.String);
+
+
+}
+
+-keep class java.nio.file.spi.FileSystemProvider {
+ <init>();
+
+ public abstract void checkAccess(java.nio.file.Path, java.nio.file.AccessMode[]);
+ public abstract void copy(java.nio.file.Path, java.nio.file.Path, java.nio.file.CopyOption[]);
+ public abstract void createDirectory(java.nio.file.Path, java.nio.file.attribute.FileAttribute[]);
+ public void createLink(java.nio.file.Path, java.nio.file.Path);
+ public void createSymbolicLink(java.nio.file.Path, java.nio.file.Path, java.nio.file.attribute.FileAttribute[]);
+ public abstract void delete(java.nio.file.Path);
+ public boolean deleteIfExists(java.nio.file.Path);
+ public abstract java.nio.file.attribute.FileAttributeView getFileAttributeView(java.nio.file.Path, java.lang.Class, java.nio.file.LinkOption[]);
+ public abstract java.nio.file.FileStore getFileStore(java.nio.file.Path);
+ public abstract java.nio.file.FileSystem getFileSystem(java.net.URI);
+ public abstract java.nio.file.Path getPath(java.net.URI);
+ public abstract java.lang.String getScheme();
+ public static java.util.List installedProviders();
+ public abstract boolean isHidden(java.nio.file.Path);
+ public abstract boolean isSameFile(java.nio.file.Path, java.nio.file.Path);
+ public abstract void move(java.nio.file.Path, java.nio.file.Path, java.nio.file.CopyOption[]);
+ public java.nio.channels.AsynchronousFileChannel newAsynchronousFileChannel(java.nio.file.Path, java.util.Set, java.util.concurrent.ExecutorService, java.nio.file.attribute.FileAttribute[]);
+ public abstract java.nio.channels.SeekableByteChannel newByteChannel(java.nio.file.Path, java.util.Set, java.nio.file.attribute.FileAttribute[]);
+ public abstract java.nio.file.DirectoryStream newDirectoryStream(java.nio.file.Path, java.nio.file.DirectoryStream$Filter);
+ public java.nio.channels.FileChannel newFileChannel(java.nio.file.Path, java.util.Set, java.nio.file.attribute.FileAttribute[]);
+ public abstract java.nio.file.FileSystem newFileSystem(java.net.URI, java.util.Map);
+ public java.nio.file.FileSystem newFileSystem(java.nio.file.Path, java.util.Map);
+ public java.io.InputStream newInputStream(java.nio.file.Path, java.nio.file.OpenOption[]);
+ public java.io.OutputStream newOutputStream(java.nio.file.Path, java.nio.file.OpenOption[]);
+ public abstract java.nio.file.attribute.BasicFileAttributes readAttributes(java.nio.file.Path, java.lang.Class, java.nio.file.LinkOption[]);
+ public abstract java.util.Map readAttributes(java.nio.file.Path, java.lang.String, java.nio.file.LinkOption[]);
+ public java.nio.file.Path readSymbolicLink(java.nio.file.Path);
+ public abstract void setAttribute(java.nio.file.Path, java.lang.String, java.lang.Object, java.nio.file.LinkOption[]);
+
+
+}
+
+-keep class java.security.AccessControlContext {
+ <init>(java.security.ProtectionDomain[]);
+ <init>(java.security.AccessControlContext, java.security.DomainCombiner);
+
+ public void checkPermission(java.security.Permission);
+ public java.security.DomainCombiner getDomainCombiner();
+
+
+}
+
+-keep class java.security.AccessControlException {
+ <init>(java.lang.String);
+ <init>(java.lang.String, java.security.Permission);
+
+ public java.security.Permission getPermission();
}
@@ -9266,9 +27802,16 @@
}
+-keep class java.security.DomainCombiner {
+
+ public abstract java.security.ProtectionDomain[] combine(java.security.ProtectionDomain[], java.security.ProtectionDomain[]);
+
+
+}
+
-keep class java.security.GeneralSecurityException {
- <init>(java.lang.String);
<init>();
+ <init>(java.lang.String);
<init>(java.lang.String, java.lang.Throwable);
<init>(java.lang.Throwable);
@@ -9277,8 +27820,8 @@
}
-keep class java.security.InvalidKeyException {
- <init>(java.lang.String);
<init>();
+ <init>(java.lang.String);
<init>(java.lang.String, java.lang.Throwable);
<init>(java.lang.Throwable);
@@ -9287,8 +27830,8 @@
}
-keep class java.security.KeyException {
- <init>(java.lang.String);
<init>();
+ <init>(java.lang.String);
<init>(java.lang.String, java.lang.Throwable);
<init>(java.lang.Throwable);
@@ -9297,8 +27840,8 @@
}
-keep class java.security.NoSuchAlgorithmException {
- <init>(java.lang.String);
<init>();
+ <init>(java.lang.String);
<init>(java.lang.String, java.lang.Throwable);
<init>(java.lang.Throwable);
@@ -9307,8 +27850,8 @@
}
-keep class java.security.NoSuchProviderException {
- <init>(java.lang.String);
<init>();
+ <init>(java.lang.String);
@@ -9343,11 +27886,36 @@
public abstract boolean equals(java.lang.Object);
public abstract java.lang.String getName();
public abstract int hashCode();
+ public boolean implies(javax.security.auth.Subject);
public abstract java.lang.String toString();
}
+-keep class java.security.PrivilegedAction {
+
+ public abstract java.lang.Object run();
+
+
+}
+
+-keep class java.security.PrivilegedActionException {
+ <init>(java.lang.Exception);
+
+ public java.lang.Throwable getCause();
+ public java.lang.Exception getException();
+ public java.lang.String toString();
+
+
+}
+
+-keep class java.security.PrivilegedExceptionAction {
+
+ public abstract java.lang.Object run();
+
+
+}
+
-keep class java.security.ProtectionDomain {
<init>(java.security.CodeSource, java.security.PermissionCollection);
<init>(java.security.CodeSource, java.security.PermissionCollection, java.lang.ClassLoader, java.security.Principal[]);
@@ -9361,6 +27929,63 @@
}
+-keep class java.security.Provider {
+ <init>(java.lang.String, double, java.lang.String);
+
+ public synchronized void clear();
+ public synchronized java.lang.Object compute(java.lang.Object, java.util.function.BiFunction);
+ public synchronized java.lang.Object computeIfAbsent(java.lang.Object, java.util.function.Function);
+ public synchronized java.lang.Object computeIfPresent(java.lang.Object, java.util.function.BiFunction);
+ public java.util.Enumeration elements();
+ public synchronized java.util.Set entrySet();
+ public synchronized void forEach(java.util.function.BiConsumer);
+ public java.lang.Object get(java.lang.Object);
+ public java.lang.String getInfo();
+ public java.lang.String getName();
+ public synchronized java.lang.Object getOrDefault(java.lang.Object, java.lang.Object);
+ public java.lang.String getProperty(java.lang.String);
+ public synchronized java.security.Provider$Service getService(java.lang.String, java.lang.String);
+ public synchronized java.util.Set getServices();
+ public double getVersion();
+ public boolean isRegistered();
+ public java.util.Set keySet();
+ public java.util.Enumeration keys();
+ public synchronized void load(java.io.InputStream);
+ public synchronized java.lang.Object merge(java.lang.Object, java.lang.Object, java.util.function.BiFunction);
+ public synchronized java.lang.Object put(java.lang.Object, java.lang.Object);
+ public synchronized void putAll(java.util.Map);
+ public synchronized java.lang.Object putIfAbsent(java.lang.Object, java.lang.Object);
+ protected synchronized void putService(java.security.Provider$Service);
+ public synchronized java.lang.Object remove(java.lang.Object);
+ public synchronized boolean remove(java.lang.Object, java.lang.Object);
+ protected synchronized void removeService(java.security.Provider$Service);
+ public synchronized boolean replace(java.lang.Object, java.lang.Object, java.lang.Object);
+ public synchronized java.lang.Object replace(java.lang.Object, java.lang.Object);
+ public synchronized void replaceAll(java.util.function.BiFunction);
+ public void setRegistered();
+ public void setUnregistered();
+ public java.lang.String toString();
+ public java.util.Collection values();
+ public synchronized void warmUpServiceProvision();
+
+
+}
+
+-keep class java.security.Provider$Service {
+ <init>(java.security.Provider, java.lang.String, java.lang.String, java.lang.String, java.util.List, java.util.Map);
+
+ public java.lang.String getAlgorithm();
+ public java.lang.String getAttribute(java.lang.String);
+ public java.lang.String getClassName();
+ public java.security.Provider getProvider();
+ public java.lang.String getType();
+ public java.lang.Object newInstance(java.lang.Object);
+ public boolean supportsParameter(java.lang.Object);
+ public java.lang.String toString();
+
+
+}
+
-keep class java.security.PublicKey {
@@ -9369,8 +27994,8 @@
}
-keep class java.security.SignatureException {
- <init>(java.lang.String);
<init>();
+ <init>(java.lang.String);
<init>(java.lang.String, java.lang.Throwable);
<init>(java.lang.Throwable);
@@ -9390,6 +28015,26 @@
}
+-keep class java.security.cert.CRL {
+ <init>(java.lang.String);
+
+ public java.lang.String getType();
+ public abstract boolean isRevoked(java.security.cert.Certificate);
+ public abstract java.lang.String toString();
+
+
+}
+
+-keep class java.security.cert.CRLException {
+ <init>();
+ <init>(java.lang.String);
+ <init>(java.lang.String, java.lang.Throwable);
+ <init>(java.lang.Throwable);
+
+
+
+}
+
-keep class java.security.cert.CertPath {
<init>(java.lang.String);
@@ -9417,14 +28062,15 @@
public abstract java.lang.String toString();
public abstract void verify(java.security.PublicKey);
public abstract void verify(java.security.PublicKey, java.lang.String);
+ public void verify(java.security.PublicKey, java.security.Provider);
protected java.lang.Object writeReplace();
}
-keep class java.security.cert.CertificateEncodingException {
- <init>(java.lang.String);
<init>();
+ <init>(java.lang.String);
<init>(java.lang.String, java.lang.Throwable);
<init>(java.lang.Throwable);
@@ -9433,8 +28079,8 @@
}
-keep class java.security.cert.CertificateException {
- <init>(java.lang.String);
<init>();
+ <init>(java.lang.String);
<init>(java.lang.String, java.lang.Throwable);
<init>(java.lang.Throwable);
@@ -9442,6 +28088,1561 @@
}
+-keep class java.security.cert.CertificateFactory {
+ <init>(java.security.cert.CertificateFactorySpi, java.security.Provider, java.lang.String);
+
+ public java.security.cert.CRL generateCRL(java.io.InputStream);
+ public java.util.Collection generateCRLs(java.io.InputStream);
+ public java.security.cert.CertPath generateCertPath(java.io.InputStream);
+ public java.security.cert.CertPath generateCertPath(java.io.InputStream, java.lang.String);
+ public java.security.cert.CertPath generateCertPath(java.util.List);
+ public java.security.cert.Certificate generateCertificate(java.io.InputStream);
+ public java.util.Collection generateCertificates(java.io.InputStream);
+ public java.util.Iterator getCertPathEncodings();
+ public static java.security.cert.CertificateFactory getInstance(java.lang.String);
+ public static java.security.cert.CertificateFactory getInstance(java.lang.String, java.lang.String);
+ public static java.security.cert.CertificateFactory getInstance(java.lang.String, java.security.Provider);
+ public java.security.Provider getProvider();
+ public java.lang.String getType();
+
+
+}
+
+-keep class java.security.cert.CertificateFactorySpi {
+ <init>();
+
+ public abstract java.security.cert.CRL engineGenerateCRL(java.io.InputStream);
+ public abstract java.util.Collection engineGenerateCRLs(java.io.InputStream);
+ public java.security.cert.CertPath engineGenerateCertPath(java.io.InputStream);
+ public java.security.cert.CertPath engineGenerateCertPath(java.io.InputStream, java.lang.String);
+ public java.security.cert.CertPath engineGenerateCertPath(java.util.List);
+ public abstract java.security.cert.Certificate engineGenerateCertificate(java.io.InputStream);
+ public abstract java.util.Collection engineGenerateCertificates(java.io.InputStream);
+ public java.util.Iterator engineGetCertPathEncodings();
+
+
+}
+
+-keep class java.text.AttributedCharacterIterator {
+
+ public abstract java.util.Set getAllAttributeKeys();
+ public abstract java.lang.Object getAttribute(java.text.AttributedCharacterIterator$Attribute);
+ public abstract java.util.Map getAttributes();
+ public abstract int getRunLimit();
+ public abstract int getRunLimit(java.text.AttributedCharacterIterator$Attribute);
+ public abstract int getRunLimit(java.util.Set);
+ public abstract int getRunStart();
+ public abstract int getRunStart(java.text.AttributedCharacterIterator$Attribute);
+ public abstract int getRunStart(java.util.Set);
+
+
+}
+
+-keep class java.text.AttributedCharacterIterator$Attribute {
+ <init>(java.lang.String);
+
+ public boolean equals(java.lang.Object);
+ protected java.lang.String getName();
+ public int hashCode();
+ protected java.lang.Object readResolve();
+ public java.lang.String toString();
+
+
+ public static java.text.AttributedCharacterIterator$Attribute INPUT_METHOD_SEGMENT;
+ public static java.text.AttributedCharacterIterator$Attribute LANGUAGE;
+ public static java.text.AttributedCharacterIterator$Attribute READING;
+}
+
+-keep class java.text.FieldPosition {
+ <init>(int);
+ <init>(java.text.Format$Field);
+ <init>(java.text.Format$Field, int);
+
+ public boolean equals(java.lang.Object);
+ public int getBeginIndex();
+ public int getEndIndex();
+ public int getField();
+ public java.text.Format$Field getFieldAttribute();
+ public int hashCode();
+ public void setBeginIndex(int);
+ public void setEndIndex(int);
+ public java.lang.String toString();
+
+
+}
+
+-keep class java.text.Format {
+ <init>();
+
+ public java.lang.Object clone();
+ public java.lang.String format(java.lang.Object);
+ public abstract java.lang.StringBuffer format(java.lang.Object, java.lang.StringBuffer, java.text.FieldPosition);
+ public java.text.AttributedCharacterIterator formatToCharacterIterator(java.lang.Object);
+ public abstract java.lang.Object parseObject(java.lang.String, java.text.ParsePosition);
+ public java.lang.Object parseObject(java.lang.String);
+
+
+}
+
+-keep class java.text.Format$Field {
+ <init>(java.lang.String);
+
+
+
+}
+
+-keep class java.text.ParseException {
+ <init>(java.lang.String, int);
+
+ public int getErrorOffset();
+
+
+}
+
+-keep class java.text.ParsePosition {
+ <init>(int);
+
+ public boolean equals(java.lang.Object);
+ public int getErrorIndex();
+ public int getIndex();
+ public int hashCode();
+ public void setErrorIndex(int);
+ public void setIndex(int);
+ public java.lang.String toString();
+
+
+}
+
+-keep class java.time.Clock {
+ <init>();
+
+ public boolean equals(java.lang.Object);
+ public static java.time.Clock fixed(java.time.Instant, java.time.ZoneId);
+ public abstract java.time.ZoneId getZone();
+ public int hashCode();
+ public abstract java.time.Instant instant();
+ public long millis();
+ public static java.time.Clock offset(java.time.Clock, java.time.Duration);
+ public static java.time.Clock system(java.time.ZoneId);
+ public static java.time.Clock systemDefaultZone();
+ public static java.time.Clock systemUTC();
+ public static java.time.Clock tick(java.time.Clock, java.time.Duration);
+ public static java.time.Clock tickMinutes(java.time.ZoneId);
+ public static java.time.Clock tickSeconds(java.time.ZoneId);
+ public abstract java.time.Clock withZone(java.time.ZoneId);
+
+
+}
+
+-keep class java.time.DayOfWeek {
+
+ public java.time.temporal.Temporal adjustInto(java.time.temporal.Temporal);
+ public static java.time.DayOfWeek from(java.time.temporal.TemporalAccessor);
+ public int get(java.time.temporal.TemporalField);
+ public java.lang.String getDisplayName(java.time.format.TextStyle, java.util.Locale);
+ public long getLong(java.time.temporal.TemporalField);
+ public int getValue();
+ public boolean isSupported(java.time.temporal.TemporalField);
+ public java.time.DayOfWeek minus(long);
+ public static java.time.DayOfWeek of(int);
+ public java.time.DayOfWeek plus(long);
+ public java.lang.Object query(java.time.temporal.TemporalQuery);
+ public java.time.temporal.ValueRange range(java.time.temporal.TemporalField);
+ public static java.time.DayOfWeek valueOf(java.lang.String);
+ public static java.time.DayOfWeek[] values();
+
+ public static java.time.DayOfWeek FRIDAY;
+ public static java.time.DayOfWeek MONDAY;
+ public static java.time.DayOfWeek SATURDAY;
+ public static java.time.DayOfWeek SUNDAY;
+ public static java.time.DayOfWeek THURSDAY;
+ public static java.time.DayOfWeek TUESDAY;
+ public static java.time.DayOfWeek WEDNESDAY;
+
+}
+
+-keep class java.time.Duration {
+
+ public java.time.Duration abs();
+ public java.time.temporal.Temporal addTo(java.time.temporal.Temporal);
+ public static java.time.Duration between(java.time.temporal.Temporal, java.time.temporal.Temporal);
+ public int compareTo(java.time.Duration);
+ public int compareTo(java.lang.Object);
+ public java.time.Duration dividedBy(long);
+ public boolean equals(java.lang.Object);
+ public static java.time.Duration from(java.time.temporal.TemporalAmount);
+ public long get(java.time.temporal.TemporalUnit);
+ public int getNano();
+ public long getSeconds();
+ public java.util.List getUnits();
+ public int hashCode();
+ public boolean isNegative();
+ public boolean isZero();
+ public java.time.Duration minus(java.time.Duration);
+ public java.time.Duration minus(long, java.time.temporal.TemporalUnit);
+ public java.time.Duration minusDays(long);
+ public java.time.Duration minusHours(long);
+ public java.time.Duration minusMillis(long);
+ public java.time.Duration minusMinutes(long);
+ public java.time.Duration minusNanos(long);
+ public java.time.Duration minusSeconds(long);
+ public java.time.Duration multipliedBy(long);
+ public java.time.Duration negated();
+ public static java.time.Duration of(long, java.time.temporal.TemporalUnit);
+ public static java.time.Duration ofDays(long);
+ public static java.time.Duration ofHours(long);
+ public static java.time.Duration ofMillis(long);
+ public static java.time.Duration ofMinutes(long);
+ public static java.time.Duration ofNanos(long);
+ public static java.time.Duration ofSeconds(long);
+ public static java.time.Duration ofSeconds(long, long);
+ public static java.time.Duration parse(java.lang.CharSequence);
+ public java.time.Duration plus(java.time.Duration);
+ public java.time.Duration plus(long, java.time.temporal.TemporalUnit);
+ public java.time.Duration plusDays(long);
+ public java.time.Duration plusHours(long);
+ public java.time.Duration plusMillis(long);
+ public java.time.Duration plusMinutes(long);
+ public java.time.Duration plusNanos(long);
+ public java.time.Duration plusSeconds(long);
+ public java.time.temporal.Temporal subtractFrom(java.time.temporal.Temporal);
+ public long toDays();
+ public long toHours();
+ public long toMillis();
+ public long toMinutes();
+ public long toNanos();
+ public java.lang.String toString();
+ public java.time.Duration withNanos(int);
+ public java.time.Duration withSeconds(long);
+
+
+ public static java.time.Duration ZERO;
+}
+
+-keep class java.time.Instant {
+
+ public java.time.temporal.Temporal adjustInto(java.time.temporal.Temporal);
+ public java.time.OffsetDateTime atOffset(java.time.ZoneOffset);
+ public java.time.ZonedDateTime atZone(java.time.ZoneId);
+ public int compareTo(java.time.Instant);
+ public int compareTo(java.lang.Object);
+ public boolean equals(java.lang.Object);
+ public static java.time.Instant from(java.time.temporal.TemporalAccessor);
+ public int get(java.time.temporal.TemporalField);
+ public long getEpochSecond();
+ public long getLong(java.time.temporal.TemporalField);
+ public int getNano();
+ public int hashCode();
+ public boolean isAfter(java.time.Instant);
+ public boolean isBefore(java.time.Instant);
+ public boolean isSupported(java.time.temporal.TemporalField);
+ public boolean isSupported(java.time.temporal.TemporalUnit);
+ public java.time.Instant minus(java.time.temporal.TemporalAmount);
+ public java.time.Instant minus(long, java.time.temporal.TemporalUnit);
+ public java.time.temporal.Temporal minus(long, java.time.temporal.TemporalUnit);
+ public java.time.temporal.Temporal minus(java.time.temporal.TemporalAmount);
+ public java.time.Instant minusMillis(long);
+ public java.time.Instant minusNanos(long);
+ public java.time.Instant minusSeconds(long);
+ public static java.time.Instant now();
+ public static java.time.Instant now(java.time.Clock);
+ public static java.time.Instant ofEpochMilli(long);
+ public static java.time.Instant ofEpochSecond(long);
+ public static java.time.Instant ofEpochSecond(long, long);
+ public static java.time.Instant parse(java.lang.CharSequence);
+ public java.time.Instant plus(java.time.temporal.TemporalAmount);
+ public java.time.Instant plus(long, java.time.temporal.TemporalUnit);
+ public java.time.temporal.Temporal plus(long, java.time.temporal.TemporalUnit);
+ public java.time.temporal.Temporal plus(java.time.temporal.TemporalAmount);
+ public java.time.Instant plusMillis(long);
+ public java.time.Instant plusNanos(long);
+ public java.time.Instant plusSeconds(long);
+ public java.lang.Object query(java.time.temporal.TemporalQuery);
+ public java.time.temporal.ValueRange range(java.time.temporal.TemporalField);
+ public long toEpochMilli();
+ public java.lang.String toString();
+ public java.time.Instant truncatedTo(java.time.temporal.TemporalUnit);
+ public long until(java.time.temporal.Temporal, java.time.temporal.TemporalUnit);
+ public java.time.Instant with(java.time.temporal.TemporalAdjuster);
+ public java.time.Instant with(java.time.temporal.TemporalField, long);
+ public java.time.temporal.Temporal with(java.time.temporal.TemporalField, long);
+ public java.time.temporal.Temporal with(java.time.temporal.TemporalAdjuster);
+
+
+ public static java.time.Instant EPOCH;
+ public static java.time.Instant MAX;
+ public static java.time.Instant MIN;
+}
+
+-keep class java.time.LocalDate {
+
+ public java.time.temporal.Temporal adjustInto(java.time.temporal.Temporal);
+ public java.time.LocalDateTime atStartOfDay();
+ public java.time.ZonedDateTime atStartOfDay(java.time.ZoneId);
+ public java.time.LocalDateTime atTime(java.time.LocalTime);
+ public java.time.LocalDateTime atTime(int, int);
+ public java.time.LocalDateTime atTime(int, int, int);
+ public java.time.LocalDateTime atTime(int, int, int, int);
+ public java.time.OffsetDateTime atTime(java.time.OffsetTime);
+ public java.time.chrono.ChronoLocalDateTime atTime(java.time.LocalTime);
+ public int compareTo(java.time.chrono.ChronoLocalDate);
+ public int compareTo(java.lang.Object);
+ public boolean equals(java.lang.Object);
+ public java.lang.String format(java.time.format.DateTimeFormatter);
+ public static java.time.LocalDate from(java.time.temporal.TemporalAccessor);
+ public int get(java.time.temporal.TemporalField);
+ public java.time.chrono.IsoChronology getChronology();
+ public java.time.chrono.Chronology getChronology();
+ public int getDayOfMonth();
+ public java.time.DayOfWeek getDayOfWeek();
+ public int getDayOfYear();
+ public java.time.chrono.Era getEra();
+ public long getLong(java.time.temporal.TemporalField);
+ public java.time.Month getMonth();
+ public int getMonthValue();
+ public int getYear();
+ public int hashCode();
+ public boolean isAfter(java.time.chrono.ChronoLocalDate);
+ public boolean isBefore(java.time.chrono.ChronoLocalDate);
+ public boolean isEqual(java.time.chrono.ChronoLocalDate);
+ public boolean isLeapYear();
+ public boolean isSupported(java.time.temporal.TemporalField);
+ public boolean isSupported(java.time.temporal.TemporalUnit);
+ public int lengthOfMonth();
+ public int lengthOfYear();
+ public java.time.LocalDate minus(java.time.temporal.TemporalAmount);
+ public java.time.LocalDate minus(long, java.time.temporal.TemporalUnit);
+ public java.time.temporal.Temporal minus(long, java.time.temporal.TemporalUnit);
+ public java.time.temporal.Temporal minus(java.time.temporal.TemporalAmount);
+ public java.time.chrono.ChronoLocalDate minus(long, java.time.temporal.TemporalUnit);
+ public java.time.chrono.ChronoLocalDate minus(java.time.temporal.TemporalAmount);
+ public java.time.LocalDate minusDays(long);
+ public java.time.LocalDate minusMonths(long);
+ public java.time.LocalDate minusWeeks(long);
+ public java.time.LocalDate minusYears(long);
+ public static java.time.LocalDate now();
+ public static java.time.LocalDate now(java.time.ZoneId);
+ public static java.time.LocalDate now(java.time.Clock);
+ public static java.time.LocalDate of(int, java.time.Month, int);
+ public static java.time.LocalDate of(int, int, int);
+ public static java.time.LocalDate ofEpochDay(long);
+ public static java.time.LocalDate ofYearDay(int, int);
+ public static java.time.LocalDate parse(java.lang.CharSequence);
+ public static java.time.LocalDate parse(java.lang.CharSequence, java.time.format.DateTimeFormatter);
+ public java.time.LocalDate plus(java.time.temporal.TemporalAmount);
+ public java.time.LocalDate plus(long, java.time.temporal.TemporalUnit);
+ public java.time.temporal.Temporal plus(long, java.time.temporal.TemporalUnit);
+ public java.time.temporal.Temporal plus(java.time.temporal.TemporalAmount);
+ public java.time.chrono.ChronoLocalDate plus(long, java.time.temporal.TemporalUnit);
+ public java.time.chrono.ChronoLocalDate plus(java.time.temporal.TemporalAmount);
+ public java.time.LocalDate plusDays(long);
+ public java.time.LocalDate plusMonths(long);
+ public java.time.LocalDate plusWeeks(long);
+ public java.time.LocalDate plusYears(long);
+ public java.lang.Object query(java.time.temporal.TemporalQuery);
+ public java.time.temporal.ValueRange range(java.time.temporal.TemporalField);
+ public long toEpochDay();
+ public java.lang.String toString();
+ public long until(java.time.temporal.Temporal, java.time.temporal.TemporalUnit);
+ public java.time.Period until(java.time.chrono.ChronoLocalDate);
+ public java.time.chrono.ChronoPeriod until(java.time.chrono.ChronoLocalDate);
+ public java.time.LocalDate with(java.time.temporal.TemporalAdjuster);
+ public java.time.LocalDate with(java.time.temporal.TemporalField, long);
+ public java.time.temporal.Temporal with(java.time.temporal.TemporalField, long);
+ public java.time.temporal.Temporal with(java.time.temporal.TemporalAdjuster);
+ public java.time.chrono.ChronoLocalDate with(java.time.temporal.TemporalField, long);
+ public java.time.chrono.ChronoLocalDate with(java.time.temporal.TemporalAdjuster);
+ public java.time.LocalDate withDayOfMonth(int);
+ public java.time.LocalDate withDayOfYear(int);
+ public java.time.LocalDate withMonth(int);
+ public java.time.LocalDate withYear(int);
+
+
+ public static java.time.LocalDate MAX;
+ public static java.time.LocalDate MIN;
+}
+
+-keep class java.time.LocalDateTime {
+
+ public java.time.temporal.Temporal adjustInto(java.time.temporal.Temporal);
+ public java.time.OffsetDateTime atOffset(java.time.ZoneOffset);
+ public java.time.ZonedDateTime atZone(java.time.ZoneId);
+ public java.time.chrono.ChronoZonedDateTime atZone(java.time.ZoneId);
+ public int compareTo(java.time.chrono.ChronoLocalDateTime);
+ public int compareTo(java.lang.Object);
+ public boolean equals(java.lang.Object);
+ public java.lang.String format(java.time.format.DateTimeFormatter);
+ public static java.time.LocalDateTime from(java.time.temporal.TemporalAccessor);
+ public int get(java.time.temporal.TemporalField);
+ public int getDayOfMonth();
+ public java.time.DayOfWeek getDayOfWeek();
+ public int getDayOfYear();
+ public int getHour();
+ public long getLong(java.time.temporal.TemporalField);
+ public int getMinute();
+ public java.time.Month getMonth();
+ public int getMonthValue();
+ public int getNano();
+ public int getSecond();
+ public int getYear();
+ public int hashCode();
+ public boolean isAfter(java.time.chrono.ChronoLocalDateTime);
+ public boolean isBefore(java.time.chrono.ChronoLocalDateTime);
+ public boolean isEqual(java.time.chrono.ChronoLocalDateTime);
+ public boolean isSupported(java.time.temporal.TemporalField);
+ public boolean isSupported(java.time.temporal.TemporalUnit);
+ public java.time.LocalDateTime minus(java.time.temporal.TemporalAmount);
+ public java.time.LocalDateTime minus(long, java.time.temporal.TemporalUnit);
+ public java.time.temporal.Temporal minus(long, java.time.temporal.TemporalUnit);
+ public java.time.temporal.Temporal minus(java.time.temporal.TemporalAmount);
+ public java.time.chrono.ChronoLocalDateTime minus(long, java.time.temporal.TemporalUnit);
+ public java.time.chrono.ChronoLocalDateTime minus(java.time.temporal.TemporalAmount);
+ public java.time.LocalDateTime minusDays(long);
+ public java.time.LocalDateTime minusHours(long);
+ public java.time.LocalDateTime minusMinutes(long);
+ public java.time.LocalDateTime minusMonths(long);
+ public java.time.LocalDateTime minusNanos(long);
+ public java.time.LocalDateTime minusSeconds(long);
+ public java.time.LocalDateTime minusWeeks(long);
+ public java.time.LocalDateTime minusYears(long);
+ public static java.time.LocalDateTime now();
+ public static java.time.LocalDateTime now(java.time.ZoneId);
+ public static java.time.LocalDateTime now(java.time.Clock);
+ public static java.time.LocalDateTime of(int, java.time.Month, int, int, int);
+ public static java.time.LocalDateTime of(int, java.time.Month, int, int, int, int);
+ public static java.time.LocalDateTime of(int, java.time.Month, int, int, int, int, int);
+ public static java.time.LocalDateTime of(int, int, int, int, int);
+ public static java.time.LocalDateTime of(int, int, int, int, int, int);
+ public static java.time.LocalDateTime of(int, int, int, int, int, int, int);
+ public static java.time.LocalDateTime of(java.time.LocalDate, java.time.LocalTime);
+ public static java.time.LocalDateTime ofEpochSecond(long, int, java.time.ZoneOffset);
+ public static java.time.LocalDateTime ofInstant(java.time.Instant, java.time.ZoneId);
+ public static java.time.LocalDateTime parse(java.lang.CharSequence);
+ public static java.time.LocalDateTime parse(java.lang.CharSequence, java.time.format.DateTimeFormatter);
+ public java.time.LocalDateTime plus(java.time.temporal.TemporalAmount);
+ public java.time.LocalDateTime plus(long, java.time.temporal.TemporalUnit);
+ public java.time.temporal.Temporal plus(long, java.time.temporal.TemporalUnit);
+ public java.time.temporal.Temporal plus(java.time.temporal.TemporalAmount);
+ public java.time.chrono.ChronoLocalDateTime plus(long, java.time.temporal.TemporalUnit);
+ public java.time.chrono.ChronoLocalDateTime plus(java.time.temporal.TemporalAmount);
+ public java.time.LocalDateTime plusDays(long);
+ public java.time.LocalDateTime plusHours(long);
+ public java.time.LocalDateTime plusMinutes(long);
+ public java.time.LocalDateTime plusMonths(long);
+ public java.time.LocalDateTime plusNanos(long);
+ public java.time.LocalDateTime plusSeconds(long);
+ public java.time.LocalDateTime plusWeeks(long);
+ public java.time.LocalDateTime plusYears(long);
+ public java.lang.Object query(java.time.temporal.TemporalQuery);
+ public java.time.temporal.ValueRange range(java.time.temporal.TemporalField);
+ public java.time.LocalDate toLocalDate();
+ public java.time.chrono.ChronoLocalDate toLocalDate();
+ public java.time.LocalTime toLocalTime();
+ public java.lang.String toString();
+ public java.time.LocalDateTime truncatedTo(java.time.temporal.TemporalUnit);
+ public long until(java.time.temporal.Temporal, java.time.temporal.TemporalUnit);
+ public java.time.LocalDateTime with(java.time.temporal.TemporalAdjuster);
+ public java.time.LocalDateTime with(java.time.temporal.TemporalField, long);
+ public java.time.temporal.Temporal with(java.time.temporal.TemporalField, long);
+ public java.time.temporal.Temporal with(java.time.temporal.TemporalAdjuster);
+ public java.time.chrono.ChronoLocalDateTime with(java.time.temporal.TemporalField, long);
+ public java.time.chrono.ChronoLocalDateTime with(java.time.temporal.TemporalAdjuster);
+ public java.time.LocalDateTime withDayOfMonth(int);
+ public java.time.LocalDateTime withDayOfYear(int);
+ public java.time.LocalDateTime withHour(int);
+ public java.time.LocalDateTime withMinute(int);
+ public java.time.LocalDateTime withMonth(int);
+ public java.time.LocalDateTime withNano(int);
+ public java.time.LocalDateTime withSecond(int);
+ public java.time.LocalDateTime withYear(int);
+
+
+ public static java.time.LocalDateTime MAX;
+ public static java.time.LocalDateTime MIN;
+}
+
+-keep class java.time.LocalTime {
+
+ public java.time.temporal.Temporal adjustInto(java.time.temporal.Temporal);
+ public java.time.LocalDateTime atDate(java.time.LocalDate);
+ public java.time.OffsetTime atOffset(java.time.ZoneOffset);
+ public int compareTo(java.time.LocalTime);
+ public int compareTo(java.lang.Object);
+ public boolean equals(java.lang.Object);
+ public java.lang.String format(java.time.format.DateTimeFormatter);
+ public static java.time.LocalTime from(java.time.temporal.TemporalAccessor);
+ public int get(java.time.temporal.TemporalField);
+ public int getHour();
+ public long getLong(java.time.temporal.TemporalField);
+ public int getMinute();
+ public int getNano();
+ public int getSecond();
+ public int hashCode();
+ public boolean isAfter(java.time.LocalTime);
+ public boolean isBefore(java.time.LocalTime);
+ public boolean isSupported(java.time.temporal.TemporalField);
+ public boolean isSupported(java.time.temporal.TemporalUnit);
+ public java.time.LocalTime minus(java.time.temporal.TemporalAmount);
+ public java.time.LocalTime minus(long, java.time.temporal.TemporalUnit);
+ public java.time.temporal.Temporal minus(long, java.time.temporal.TemporalUnit);
+ public java.time.temporal.Temporal minus(java.time.temporal.TemporalAmount);
+ public java.time.LocalTime minusHours(long);
+ public java.time.LocalTime minusMinutes(long);
+ public java.time.LocalTime minusNanos(long);
+ public java.time.LocalTime minusSeconds(long);
+ public static java.time.LocalTime now();
+ public static java.time.LocalTime now(java.time.ZoneId);
+ public static java.time.LocalTime now(java.time.Clock);
+ public static java.time.LocalTime of(int, int);
+ public static java.time.LocalTime of(int, int, int);
+ public static java.time.LocalTime of(int, int, int, int);
+ public static java.time.LocalTime ofNanoOfDay(long);
+ public static java.time.LocalTime ofSecondOfDay(long);
+ public static java.time.LocalTime parse(java.lang.CharSequence);
+ public static java.time.LocalTime parse(java.lang.CharSequence, java.time.format.DateTimeFormatter);
+ public java.time.LocalTime plus(java.time.temporal.TemporalAmount);
+ public java.time.LocalTime plus(long, java.time.temporal.TemporalUnit);
+ public java.time.temporal.Temporal plus(long, java.time.temporal.TemporalUnit);
+ public java.time.temporal.Temporal plus(java.time.temporal.TemporalAmount);
+ public java.time.LocalTime plusHours(long);
+ public java.time.LocalTime plusMinutes(long);
+ public java.time.LocalTime plusNanos(long);
+ public java.time.LocalTime plusSeconds(long);
+ public java.lang.Object query(java.time.temporal.TemporalQuery);
+ public java.time.temporal.ValueRange range(java.time.temporal.TemporalField);
+ public long toNanoOfDay();
+ public int toSecondOfDay();
+ public java.lang.String toString();
+ public java.time.LocalTime truncatedTo(java.time.temporal.TemporalUnit);
+ public long until(java.time.temporal.Temporal, java.time.temporal.TemporalUnit);
+ public java.time.LocalTime with(java.time.temporal.TemporalAdjuster);
+ public java.time.LocalTime with(java.time.temporal.TemporalField, long);
+ public java.time.temporal.Temporal with(java.time.temporal.TemporalField, long);
+ public java.time.temporal.Temporal with(java.time.temporal.TemporalAdjuster);
+ public java.time.LocalTime withHour(int);
+ public java.time.LocalTime withMinute(int);
+ public java.time.LocalTime withNano(int);
+ public java.time.LocalTime withSecond(int);
+
+
+ public static java.time.LocalTime MAX;
+ public static java.time.LocalTime MIDNIGHT;
+ public static java.time.LocalTime MIN;
+ public static java.time.LocalTime NOON;
+}
+
+-keep class java.time.Month {
+
+ public java.time.temporal.Temporal adjustInto(java.time.temporal.Temporal);
+ public int firstDayOfYear(boolean);
+ public java.time.Month firstMonthOfQuarter();
+ public static java.time.Month from(java.time.temporal.TemporalAccessor);
+ public int get(java.time.temporal.TemporalField);
+ public java.lang.String getDisplayName(java.time.format.TextStyle, java.util.Locale);
+ public long getLong(java.time.temporal.TemporalField);
+ public int getValue();
+ public boolean isSupported(java.time.temporal.TemporalField);
+ public int length(boolean);
+ public int maxLength();
+ public int minLength();
+ public java.time.Month minus(long);
+ public static java.time.Month of(int);
+ public java.time.Month plus(long);
+ public java.lang.Object query(java.time.temporal.TemporalQuery);
+ public java.time.temporal.ValueRange range(java.time.temporal.TemporalField);
+ public static java.time.Month valueOf(java.lang.String);
+ public static java.time.Month[] values();
+
+ public static java.time.Month APRIL;
+ public static java.time.Month AUGUST;
+ public static java.time.Month DECEMBER;
+ public static java.time.Month FEBRUARY;
+ public static java.time.Month JANUARY;
+ public static java.time.Month JULY;
+ public static java.time.Month JUNE;
+ public static java.time.Month MARCH;
+ public static java.time.Month MAY;
+ public static java.time.Month NOVEMBER;
+ public static java.time.Month OCTOBER;
+ public static java.time.Month SEPTEMBER;
+
+}
+
+-keep class java.time.OffsetDateTime {
+
+ public java.time.temporal.Temporal adjustInto(java.time.temporal.Temporal);
+ public java.time.ZonedDateTime atZoneSameInstant(java.time.ZoneId);
+ public java.time.ZonedDateTime atZoneSimilarLocal(java.time.ZoneId);
+ public int compareTo(java.time.OffsetDateTime);
+ public int compareTo(java.lang.Object);
+ public boolean equals(java.lang.Object);
+ public java.lang.String format(java.time.format.DateTimeFormatter);
+ public static java.time.OffsetDateTime from(java.time.temporal.TemporalAccessor);
+ public int get(java.time.temporal.TemporalField);
+ public int getDayOfMonth();
+ public java.time.DayOfWeek getDayOfWeek();
+ public int getDayOfYear();
+ public int getHour();
+ public long getLong(java.time.temporal.TemporalField);
+ public int getMinute();
+ public java.time.Month getMonth();
+ public int getMonthValue();
+ public int getNano();
+ public java.time.ZoneOffset getOffset();
+ public int getSecond();
+ public int getYear();
+ public int hashCode();
+ public boolean isAfter(java.time.OffsetDateTime);
+ public boolean isBefore(java.time.OffsetDateTime);
+ public boolean isEqual(java.time.OffsetDateTime);
+ public boolean isSupported(java.time.temporal.TemporalField);
+ public boolean isSupported(java.time.temporal.TemporalUnit);
+ public java.time.OffsetDateTime minus(java.time.temporal.TemporalAmount);
+ public java.time.OffsetDateTime minus(long, java.time.temporal.TemporalUnit);
+ public java.time.temporal.Temporal minus(long, java.time.temporal.TemporalUnit);
+ public java.time.temporal.Temporal minus(java.time.temporal.TemporalAmount);
+ public java.time.OffsetDateTime minusDays(long);
+ public java.time.OffsetDateTime minusHours(long);
+ public java.time.OffsetDateTime minusMinutes(long);
+ public java.time.OffsetDateTime minusMonths(long);
+ public java.time.OffsetDateTime minusNanos(long);
+ public java.time.OffsetDateTime minusSeconds(long);
+ public java.time.OffsetDateTime minusWeeks(long);
+ public java.time.OffsetDateTime minusYears(long);
+ public static java.time.OffsetDateTime now();
+ public static java.time.OffsetDateTime now(java.time.ZoneId);
+ public static java.time.OffsetDateTime now(java.time.Clock);
+ public static java.time.OffsetDateTime of(java.time.LocalDate, java.time.LocalTime, java.time.ZoneOffset);
+ public static java.time.OffsetDateTime of(java.time.LocalDateTime, java.time.ZoneOffset);
+ public static java.time.OffsetDateTime of(int, int, int, int, int, int, int, java.time.ZoneOffset);
+ public static java.time.OffsetDateTime ofInstant(java.time.Instant, java.time.ZoneId);
+ public static java.time.OffsetDateTime parse(java.lang.CharSequence);
+ public static java.time.OffsetDateTime parse(java.lang.CharSequence, java.time.format.DateTimeFormatter);
+ public java.time.OffsetDateTime plus(java.time.temporal.TemporalAmount);
+ public java.time.OffsetDateTime plus(long, java.time.temporal.TemporalUnit);
+ public java.time.temporal.Temporal plus(long, java.time.temporal.TemporalUnit);
+ public java.time.temporal.Temporal plus(java.time.temporal.TemporalAmount);
+ public java.time.OffsetDateTime plusDays(long);
+ public java.time.OffsetDateTime plusHours(long);
+ public java.time.OffsetDateTime plusMinutes(long);
+ public java.time.OffsetDateTime plusMonths(long);
+ public java.time.OffsetDateTime plusNanos(long);
+ public java.time.OffsetDateTime plusSeconds(long);
+ public java.time.OffsetDateTime plusWeeks(long);
+ public java.time.OffsetDateTime plusYears(long);
+ public java.lang.Object query(java.time.temporal.TemporalQuery);
+ public java.time.temporal.ValueRange range(java.time.temporal.TemporalField);
+ public static java.util.Comparator timeLineOrder();
+ public long toEpochSecond();
+ public java.time.Instant toInstant();
+ public java.time.LocalDate toLocalDate();
+ public java.time.LocalDateTime toLocalDateTime();
+ public java.time.LocalTime toLocalTime();
+ public java.time.OffsetTime toOffsetTime();
+ public java.lang.String toString();
+ public java.time.ZonedDateTime toZonedDateTime();
+ public java.time.OffsetDateTime truncatedTo(java.time.temporal.TemporalUnit);
+ public long until(java.time.temporal.Temporal, java.time.temporal.TemporalUnit);
+ public java.time.OffsetDateTime with(java.time.temporal.TemporalAdjuster);
+ public java.time.OffsetDateTime with(java.time.temporal.TemporalField, long);
+ public java.time.temporal.Temporal with(java.time.temporal.TemporalField, long);
+ public java.time.temporal.Temporal with(java.time.temporal.TemporalAdjuster);
+ public java.time.OffsetDateTime withDayOfMonth(int);
+ public java.time.OffsetDateTime withDayOfYear(int);
+ public java.time.OffsetDateTime withHour(int);
+ public java.time.OffsetDateTime withMinute(int);
+ public java.time.OffsetDateTime withMonth(int);
+ public java.time.OffsetDateTime withNano(int);
+ public java.time.OffsetDateTime withOffsetSameInstant(java.time.ZoneOffset);
+ public java.time.OffsetDateTime withOffsetSameLocal(java.time.ZoneOffset);
+ public java.time.OffsetDateTime withSecond(int);
+ public java.time.OffsetDateTime withYear(int);
+
+
+ public static java.time.OffsetDateTime MAX;
+ public static java.time.OffsetDateTime MIN;
+}
+
+-keep class java.time.OffsetTime {
+
+ public java.time.temporal.Temporal adjustInto(java.time.temporal.Temporal);
+ public java.time.OffsetDateTime atDate(java.time.LocalDate);
+ public int compareTo(java.time.OffsetTime);
+ public int compareTo(java.lang.Object);
+ public boolean equals(java.lang.Object);
+ public java.lang.String format(java.time.format.DateTimeFormatter);
+ public static java.time.OffsetTime from(java.time.temporal.TemporalAccessor);
+ public int get(java.time.temporal.TemporalField);
+ public int getHour();
+ public long getLong(java.time.temporal.TemporalField);
+ public int getMinute();
+ public int getNano();
+ public java.time.ZoneOffset getOffset();
+ public int getSecond();
+ public int hashCode();
+ public boolean isAfter(java.time.OffsetTime);
+ public boolean isBefore(java.time.OffsetTime);
+ public boolean isEqual(java.time.OffsetTime);
+ public boolean isSupported(java.time.temporal.TemporalField);
+ public boolean isSupported(java.time.temporal.TemporalUnit);
+ public java.time.OffsetTime minus(java.time.temporal.TemporalAmount);
+ public java.time.OffsetTime minus(long, java.time.temporal.TemporalUnit);
+ public java.time.temporal.Temporal minus(long, java.time.temporal.TemporalUnit);
+ public java.time.temporal.Temporal minus(java.time.temporal.TemporalAmount);
+ public java.time.OffsetTime minusHours(long);
+ public java.time.OffsetTime minusMinutes(long);
+ public java.time.OffsetTime minusNanos(long);
+ public java.time.OffsetTime minusSeconds(long);
+ public static java.time.OffsetTime now();
+ public static java.time.OffsetTime now(java.time.ZoneId);
+ public static java.time.OffsetTime now(java.time.Clock);
+ public static java.time.OffsetTime of(java.time.LocalTime, java.time.ZoneOffset);
+ public static java.time.OffsetTime of(int, int, int, int, java.time.ZoneOffset);
+ public static java.time.OffsetTime ofInstant(java.time.Instant, java.time.ZoneId);
+ public static java.time.OffsetTime parse(java.lang.CharSequence);
+ public static java.time.OffsetTime parse(java.lang.CharSequence, java.time.format.DateTimeFormatter);
+ public java.time.OffsetTime plus(java.time.temporal.TemporalAmount);
+ public java.time.OffsetTime plus(long, java.time.temporal.TemporalUnit);
+ public java.time.temporal.Temporal plus(long, java.time.temporal.TemporalUnit);
+ public java.time.temporal.Temporal plus(java.time.temporal.TemporalAmount);
+ public java.time.OffsetTime plusHours(long);
+ public java.time.OffsetTime plusMinutes(long);
+ public java.time.OffsetTime plusNanos(long);
+ public java.time.OffsetTime plusSeconds(long);
+ public java.lang.Object query(java.time.temporal.TemporalQuery);
+ public java.time.temporal.ValueRange range(java.time.temporal.TemporalField);
+ public java.time.LocalTime toLocalTime();
+ public java.lang.String toString();
+ public java.time.OffsetTime truncatedTo(java.time.temporal.TemporalUnit);
+ public long until(java.time.temporal.Temporal, java.time.temporal.TemporalUnit);
+ public java.time.OffsetTime with(java.time.temporal.TemporalAdjuster);
+ public java.time.OffsetTime with(java.time.temporal.TemporalField, long);
+ public java.time.temporal.Temporal with(java.time.temporal.TemporalField, long);
+ public java.time.temporal.Temporal with(java.time.temporal.TemporalAdjuster);
+ public java.time.OffsetTime withHour(int);
+ public java.time.OffsetTime withMinute(int);
+ public java.time.OffsetTime withNano(int);
+ public java.time.OffsetTime withOffsetSameInstant(java.time.ZoneOffset);
+ public java.time.OffsetTime withOffsetSameLocal(java.time.ZoneOffset);
+ public java.time.OffsetTime withSecond(int);
+
+
+ public static java.time.OffsetTime MAX;
+ public static java.time.OffsetTime MIN;
+}
+
+-keep class java.time.Period {
+
+ public java.time.temporal.Temporal addTo(java.time.temporal.Temporal);
+ public static java.time.Period between(java.time.LocalDate, java.time.LocalDate);
+ public boolean equals(java.lang.Object);
+ public static java.time.Period from(java.time.temporal.TemporalAmount);
+ public long get(java.time.temporal.TemporalUnit);
+ public java.time.chrono.IsoChronology getChronology();
+ public java.time.chrono.Chronology getChronology();
+ public int getDays();
+ public int getMonths();
+ public java.util.List getUnits();
+ public int getYears();
+ public int hashCode();
+ public boolean isNegative();
+ public boolean isZero();
+ public java.time.Period minus(java.time.temporal.TemporalAmount);
+ public java.time.chrono.ChronoPeriod minus(java.time.temporal.TemporalAmount);
+ public java.time.Period minusDays(long);
+ public java.time.Period minusMonths(long);
+ public java.time.Period minusYears(long);
+ public java.time.Period multipliedBy(int);
+ public java.time.chrono.ChronoPeriod multipliedBy(int);
+ public java.time.Period negated();
+ public java.time.chrono.ChronoPeriod negated();
+ public java.time.Period normalized();
+ public java.time.chrono.ChronoPeriod normalized();
+ public static java.time.Period of(int, int, int);
+ public static java.time.Period ofDays(int);
+ public static java.time.Period ofMonths(int);
+ public static java.time.Period ofWeeks(int);
+ public static java.time.Period ofYears(int);
+ public static java.time.Period parse(java.lang.CharSequence);
+ public java.time.Period plus(java.time.temporal.TemporalAmount);
+ public java.time.chrono.ChronoPeriod plus(java.time.temporal.TemporalAmount);
+ public java.time.Period plusDays(long);
+ public java.time.Period plusMonths(long);
+ public java.time.Period plusYears(long);
+ public java.time.temporal.Temporal subtractFrom(java.time.temporal.Temporal);
+ public java.lang.String toString();
+ public long toTotalMonths();
+ public java.time.Period withDays(int);
+ public java.time.Period withMonths(int);
+ public java.time.Period withYears(int);
+
+
+ public static java.time.Period ZERO;
+}
+
+-keep class java.time.ZoneId {
+
+ public boolean equals(java.lang.Object);
+ public static java.time.ZoneId from(java.time.temporal.TemporalAccessor);
+ public static java.util.Set getAvailableZoneIds();
+ public java.lang.String getDisplayName(java.time.format.TextStyle, java.util.Locale);
+ public abstract java.lang.String getId();
+ public abstract java.time.zone.ZoneRules getRules();
+ public int hashCode();
+ public java.time.ZoneId normalized();
+ public static java.time.ZoneId of(java.lang.String, java.util.Map);
+ public static java.time.ZoneId of(java.lang.String);
+ public static java.time.ZoneId ofOffset(java.lang.String, java.time.ZoneOffset);
+ public static java.time.ZoneId systemDefault();
+ public java.lang.String toString();
+
+
+ public static java.util.Map SHORT_IDS;
+}
+
+-keep class java.time.ZoneOffset {
+
+ public java.time.temporal.Temporal adjustInto(java.time.temporal.Temporal);
+ public int compareTo(java.time.ZoneOffset);
+ public int compareTo(java.lang.Object);
+ public boolean equals(java.lang.Object);
+ public static java.time.ZoneOffset from(java.time.temporal.TemporalAccessor);
+ public int get(java.time.temporal.TemporalField);
+ public java.lang.String getId();
+ public long getLong(java.time.temporal.TemporalField);
+ public java.time.zone.ZoneRules getRules();
+ public int getTotalSeconds();
+ public int hashCode();
+ public boolean isSupported(java.time.temporal.TemporalField);
+ public static java.time.ZoneOffset of(java.lang.String);
+ public static java.time.ZoneOffset ofHours(int);
+ public static java.time.ZoneOffset ofHoursMinutes(int, int);
+ public static java.time.ZoneOffset ofHoursMinutesSeconds(int, int, int);
+ public static java.time.ZoneOffset ofTotalSeconds(int);
+ public java.lang.Object query(java.time.temporal.TemporalQuery);
+ public java.time.temporal.ValueRange range(java.time.temporal.TemporalField);
+ public java.lang.String toString();
+
+
+ public static java.time.ZoneOffset MAX;
+ public static java.time.ZoneOffset MIN;
+ public static java.time.ZoneOffset UTC;
+}
+
+-keep class java.time.ZonedDateTime {
+
+ public boolean equals(java.lang.Object);
+ public java.lang.String format(java.time.format.DateTimeFormatter);
+ public static java.time.ZonedDateTime from(java.time.temporal.TemporalAccessor);
+ public int get(java.time.temporal.TemporalField);
+ public int getDayOfMonth();
+ public java.time.DayOfWeek getDayOfWeek();
+ public int getDayOfYear();
+ public int getHour();
+ public long getLong(java.time.temporal.TemporalField);
+ public int getMinute();
+ public java.time.Month getMonth();
+ public int getMonthValue();
+ public int getNano();
+ public java.time.ZoneOffset getOffset();
+ public int getSecond();
+ public int getYear();
+ public java.time.ZoneId getZone();
+ public int hashCode();
+ public boolean isSupported(java.time.temporal.TemporalField);
+ public boolean isSupported(java.time.temporal.TemporalUnit);
+ public java.time.ZonedDateTime minus(java.time.temporal.TemporalAmount);
+ public java.time.ZonedDateTime minus(long, java.time.temporal.TemporalUnit);
+ public java.time.temporal.Temporal minus(long, java.time.temporal.TemporalUnit);
+ public java.time.temporal.Temporal minus(java.time.temporal.TemporalAmount);
+ public java.time.chrono.ChronoZonedDateTime minus(long, java.time.temporal.TemporalUnit);
+ public java.time.chrono.ChronoZonedDateTime minus(java.time.temporal.TemporalAmount);
+ public java.time.ZonedDateTime minusDays(long);
+ public java.time.ZonedDateTime minusHours(long);
+ public java.time.ZonedDateTime minusMinutes(long);
+ public java.time.ZonedDateTime minusMonths(long);
+ public java.time.ZonedDateTime minusNanos(long);
+ public java.time.ZonedDateTime minusSeconds(long);
+ public java.time.ZonedDateTime minusWeeks(long);
+ public java.time.ZonedDateTime minusYears(long);
+ public static java.time.ZonedDateTime now();
+ public static java.time.ZonedDateTime now(java.time.ZoneId);
+ public static java.time.ZonedDateTime now(java.time.Clock);
+ public static java.time.ZonedDateTime of(java.time.LocalDate, java.time.LocalTime, java.time.ZoneId);
+ public static java.time.ZonedDateTime of(java.time.LocalDateTime, java.time.ZoneId);
+ public static java.time.ZonedDateTime of(int, int, int, int, int, int, int, java.time.ZoneId);
+ public static java.time.ZonedDateTime ofInstant(java.time.Instant, java.time.ZoneId);
+ public static java.time.ZonedDateTime ofInstant(java.time.LocalDateTime, java.time.ZoneOffset, java.time.ZoneId);
+ public static java.time.ZonedDateTime ofLocal(java.time.LocalDateTime, java.time.ZoneId, java.time.ZoneOffset);
+ public static java.time.ZonedDateTime ofStrict(java.time.LocalDateTime, java.time.ZoneOffset, java.time.ZoneId);
+ public static java.time.ZonedDateTime parse(java.lang.CharSequence);
+ public static java.time.ZonedDateTime parse(java.lang.CharSequence, java.time.format.DateTimeFormatter);
+ public java.time.ZonedDateTime plus(java.time.temporal.TemporalAmount);
+ public java.time.ZonedDateTime plus(long, java.time.temporal.TemporalUnit);
+ public java.time.temporal.Temporal plus(long, java.time.temporal.TemporalUnit);
+ public java.time.temporal.Temporal plus(java.time.temporal.TemporalAmount);
+ public java.time.chrono.ChronoZonedDateTime plus(long, java.time.temporal.TemporalUnit);
+ public java.time.chrono.ChronoZonedDateTime plus(java.time.temporal.TemporalAmount);
+ public java.time.ZonedDateTime plusDays(long);
+ public java.time.ZonedDateTime plusHours(long);
+ public java.time.ZonedDateTime plusMinutes(long);
+ public java.time.ZonedDateTime plusMonths(long);
+ public java.time.ZonedDateTime plusNanos(long);
+ public java.time.ZonedDateTime plusSeconds(long);
+ public java.time.ZonedDateTime plusWeeks(long);
+ public java.time.ZonedDateTime plusYears(long);
+ public java.lang.Object query(java.time.temporal.TemporalQuery);
+ public java.time.temporal.ValueRange range(java.time.temporal.TemporalField);
+ public java.time.LocalDate toLocalDate();
+ public java.time.chrono.ChronoLocalDate toLocalDate();
+ public java.time.LocalDateTime toLocalDateTime();
+ public java.time.chrono.ChronoLocalDateTime toLocalDateTime();
+ public java.time.LocalTime toLocalTime();
+ public java.time.OffsetDateTime toOffsetDateTime();
+ public java.lang.String toString();
+ public java.time.ZonedDateTime truncatedTo(java.time.temporal.TemporalUnit);
+ public long until(java.time.temporal.Temporal, java.time.temporal.TemporalUnit);
+ public java.time.ZonedDateTime with(java.time.temporal.TemporalAdjuster);
+ public java.time.ZonedDateTime with(java.time.temporal.TemporalField, long);
+ public java.time.temporal.Temporal with(java.time.temporal.TemporalField, long);
+ public java.time.temporal.Temporal with(java.time.temporal.TemporalAdjuster);
+ public java.time.chrono.ChronoZonedDateTime with(java.time.temporal.TemporalField, long);
+ public java.time.chrono.ChronoZonedDateTime with(java.time.temporal.TemporalAdjuster);
+ public java.time.ZonedDateTime withDayOfMonth(int);
+ public java.time.ZonedDateTime withDayOfYear(int);
+ public java.time.ZonedDateTime withEarlierOffsetAtOverlap();
+ public java.time.chrono.ChronoZonedDateTime withEarlierOffsetAtOverlap();
+ public java.time.ZonedDateTime withFixedOffsetZone();
+ public java.time.ZonedDateTime withHour(int);
+ public java.time.ZonedDateTime withLaterOffsetAtOverlap();
+ public java.time.chrono.ChronoZonedDateTime withLaterOffsetAtOverlap();
+ public java.time.ZonedDateTime withMinute(int);
+ public java.time.ZonedDateTime withMonth(int);
+ public java.time.ZonedDateTime withNano(int);
+ public java.time.ZonedDateTime withSecond(int);
+ public java.time.ZonedDateTime withYear(int);
+ public java.time.ZonedDateTime withZoneSameInstant(java.time.ZoneId);
+ public java.time.chrono.ChronoZonedDateTime withZoneSameInstant(java.time.ZoneId);
+ public java.time.ZonedDateTime withZoneSameLocal(java.time.ZoneId);
+ public java.time.chrono.ChronoZonedDateTime withZoneSameLocal(java.time.ZoneId);
+
+
+}
+
+-keep class java.time.chrono.AbstractChronology {
+ <init>();
+
+ public int compareTo(java.time.chrono.Chronology);
+ public int compareTo(java.lang.Object);
+ public boolean equals(java.lang.Object);
+ public int hashCode();
+ public java.time.chrono.ChronoLocalDate resolveDate(java.util.Map, java.time.format.ResolverStyle);
+ public java.lang.String toString();
+
+
+}
+
+-keep class java.time.chrono.ChronoLocalDate {
+
+ public java.time.temporal.Temporal adjustInto(java.time.temporal.Temporal);
+ public java.time.chrono.ChronoLocalDateTime atTime(java.time.LocalTime);
+ public int compareTo(java.time.chrono.ChronoLocalDate);
+ public int compareTo(java.lang.Object);
+ public abstract boolean equals(java.lang.Object);
+ public java.lang.String format(java.time.format.DateTimeFormatter);
+ public static java.time.chrono.ChronoLocalDate from(java.time.temporal.TemporalAccessor);
+ public abstract java.time.chrono.Chronology getChronology();
+ public java.time.chrono.Era getEra();
+ public abstract int hashCode();
+ public boolean isAfter(java.time.chrono.ChronoLocalDate);
+ public boolean isBefore(java.time.chrono.ChronoLocalDate);
+ public boolean isEqual(java.time.chrono.ChronoLocalDate);
+ public boolean isLeapYear();
+ public boolean isSupported(java.time.temporal.TemporalField);
+ public boolean isSupported(java.time.temporal.TemporalUnit);
+ public abstract int lengthOfMonth();
+ public int lengthOfYear();
+ public java.time.chrono.ChronoLocalDate minus(java.time.temporal.TemporalAmount);
+ public java.time.chrono.ChronoLocalDate minus(long, java.time.temporal.TemporalUnit);
+ public java.time.temporal.Temporal minus(long, java.time.temporal.TemporalUnit);
+ public java.time.temporal.Temporal minus(java.time.temporal.TemporalAmount);
+ public java.time.chrono.ChronoLocalDate plus(java.time.temporal.TemporalAmount);
+ public java.time.chrono.ChronoLocalDate plus(long, java.time.temporal.TemporalUnit);
+ public java.time.temporal.Temporal plus(long, java.time.temporal.TemporalUnit);
+ public java.time.temporal.Temporal plus(java.time.temporal.TemporalAmount);
+ public java.lang.Object query(java.time.temporal.TemporalQuery);
+ public static java.util.Comparator timeLineOrder();
+ public long toEpochDay();
+ public abstract java.lang.String toString();
+ public abstract long until(java.time.temporal.Temporal, java.time.temporal.TemporalUnit);
+ public abstract java.time.chrono.ChronoPeriod until(java.time.chrono.ChronoLocalDate);
+ public java.time.chrono.ChronoLocalDate with(java.time.temporal.TemporalAdjuster);
+ public java.time.chrono.ChronoLocalDate with(java.time.temporal.TemporalField, long);
+ public java.time.temporal.Temporal with(java.time.temporal.TemporalField, long);
+ public java.time.temporal.Temporal with(java.time.temporal.TemporalAdjuster);
+
+
+}
+
+-keep class java.time.chrono.ChronoLocalDateTime {
+
+ public java.time.temporal.Temporal adjustInto(java.time.temporal.Temporal);
+ public abstract java.time.chrono.ChronoZonedDateTime atZone(java.time.ZoneId);
+ public int compareTo(java.time.chrono.ChronoLocalDateTime);
+ public int compareTo(java.lang.Object);
+ public abstract boolean equals(java.lang.Object);
+ public java.lang.String format(java.time.format.DateTimeFormatter);
+ public static java.time.chrono.ChronoLocalDateTime from(java.time.temporal.TemporalAccessor);
+ public java.time.chrono.Chronology getChronology();
+ public abstract int hashCode();
+ public boolean isAfter(java.time.chrono.ChronoLocalDateTime);
+ public boolean isBefore(java.time.chrono.ChronoLocalDateTime);
+ public boolean isEqual(java.time.chrono.ChronoLocalDateTime);
+ public abstract boolean isSupported(java.time.temporal.TemporalField);
+ public boolean isSupported(java.time.temporal.TemporalUnit);
+ public java.time.chrono.ChronoLocalDateTime minus(java.time.temporal.TemporalAmount);
+ public java.time.chrono.ChronoLocalDateTime minus(long, java.time.temporal.TemporalUnit);
+ public java.time.temporal.Temporal minus(long, java.time.temporal.TemporalUnit);
+ public java.time.temporal.Temporal minus(java.time.temporal.TemporalAmount);
+ public java.time.chrono.ChronoLocalDateTime plus(java.time.temporal.TemporalAmount);
+ public abstract java.time.chrono.ChronoLocalDateTime plus(long, java.time.temporal.TemporalUnit);
+ public java.time.temporal.Temporal plus(long, java.time.temporal.TemporalUnit);
+ public java.time.temporal.Temporal plus(java.time.temporal.TemporalAmount);
+ public java.lang.Object query(java.time.temporal.TemporalQuery);
+ public static java.util.Comparator timeLineOrder();
+ public long toEpochSecond(java.time.ZoneOffset);
+ public java.time.Instant toInstant(java.time.ZoneOffset);
+ public abstract java.time.chrono.ChronoLocalDate toLocalDate();
+ public abstract java.time.LocalTime toLocalTime();
+ public abstract java.lang.String toString();
+ public java.time.chrono.ChronoLocalDateTime with(java.time.temporal.TemporalAdjuster);
+ public abstract java.time.chrono.ChronoLocalDateTime with(java.time.temporal.TemporalField, long);
+ public java.time.temporal.Temporal with(java.time.temporal.TemporalField, long);
+ public java.time.temporal.Temporal with(java.time.temporal.TemporalAdjuster);
+
+
+}
+
+-keep class java.time.chrono.ChronoPeriod {
+
+ public abstract java.time.temporal.Temporal addTo(java.time.temporal.Temporal);
+ public static java.time.chrono.ChronoPeriod between(java.time.chrono.ChronoLocalDate, java.time.chrono.ChronoLocalDate);
+ public abstract boolean equals(java.lang.Object);
+ public abstract long get(java.time.temporal.TemporalUnit);
+ public abstract java.time.chrono.Chronology getChronology();
+ public abstract java.util.List getUnits();
+ public abstract int hashCode();
+ public boolean isNegative();
+ public boolean isZero();
+ public abstract java.time.chrono.ChronoPeriod minus(java.time.temporal.TemporalAmount);
+ public abstract java.time.chrono.ChronoPeriod multipliedBy(int);
+ public java.time.chrono.ChronoPeriod negated();
+ public abstract java.time.chrono.ChronoPeriod normalized();
+ public abstract java.time.chrono.ChronoPeriod plus(java.time.temporal.TemporalAmount);
+ public abstract java.time.temporal.Temporal subtractFrom(java.time.temporal.Temporal);
+ public abstract java.lang.String toString();
+
+
+}
+
+-keep class java.time.chrono.ChronoZonedDateTime {
+
+ public int compareTo(java.time.chrono.ChronoZonedDateTime);
+ public int compareTo(java.lang.Object);
+ public abstract boolean equals(java.lang.Object);
+ public java.lang.String format(java.time.format.DateTimeFormatter);
+ public static java.time.chrono.ChronoZonedDateTime from(java.time.temporal.TemporalAccessor);
+ public int get(java.time.temporal.TemporalField);
+ public java.time.chrono.Chronology getChronology();
+ public long getLong(java.time.temporal.TemporalField);
+ public abstract java.time.ZoneOffset getOffset();
+ public abstract java.time.ZoneId getZone();
+ public abstract int hashCode();
+ public boolean isAfter(java.time.chrono.ChronoZonedDateTime);
+ public boolean isBefore(java.time.chrono.ChronoZonedDateTime);
+ public boolean isEqual(java.time.chrono.ChronoZonedDateTime);
+ public abstract boolean isSupported(java.time.temporal.TemporalField);
+ public boolean isSupported(java.time.temporal.TemporalUnit);
+ public java.time.chrono.ChronoZonedDateTime minus(java.time.temporal.TemporalAmount);
+ public java.time.chrono.ChronoZonedDateTime minus(long, java.time.temporal.TemporalUnit);
+ public java.time.temporal.Temporal minus(long, java.time.temporal.TemporalUnit);
+ public java.time.temporal.Temporal minus(java.time.temporal.TemporalAmount);
+ public java.time.chrono.ChronoZonedDateTime plus(java.time.temporal.TemporalAmount);
+ public abstract java.time.chrono.ChronoZonedDateTime plus(long, java.time.temporal.TemporalUnit);
+ public java.time.temporal.Temporal plus(long, java.time.temporal.TemporalUnit);
+ public java.time.temporal.Temporal plus(java.time.temporal.TemporalAmount);
+ public java.lang.Object query(java.time.temporal.TemporalQuery);
+ public java.time.temporal.ValueRange range(java.time.temporal.TemporalField);
+ public static java.util.Comparator timeLineOrder();
+ public long toEpochSecond();
+ public java.time.Instant toInstant();
+ public java.time.chrono.ChronoLocalDate toLocalDate();
+ public abstract java.time.chrono.ChronoLocalDateTime toLocalDateTime();
+ public java.time.LocalTime toLocalTime();
+ public abstract java.lang.String toString();
+ public java.time.chrono.ChronoZonedDateTime with(java.time.temporal.TemporalAdjuster);
+ public abstract java.time.chrono.ChronoZonedDateTime with(java.time.temporal.TemporalField, long);
+ public java.time.temporal.Temporal with(java.time.temporal.TemporalField, long);
+ public java.time.temporal.Temporal with(java.time.temporal.TemporalAdjuster);
+ public abstract java.time.chrono.ChronoZonedDateTime withEarlierOffsetAtOverlap();
+ public abstract java.time.chrono.ChronoZonedDateTime withLaterOffsetAtOverlap();
+ public abstract java.time.chrono.ChronoZonedDateTime withZoneSameInstant(java.time.ZoneId);
+ public abstract java.time.chrono.ChronoZonedDateTime withZoneSameLocal(java.time.ZoneId);
+
+
+}
+
+-keep class java.time.chrono.Chronology {
+
+ public abstract int compareTo(java.time.chrono.Chronology);
+ public int compareTo(java.lang.Object);
+ public java.time.chrono.ChronoLocalDate date(java.time.chrono.Era, int, int, int);
+ public abstract java.time.chrono.ChronoLocalDate date(int, int, int);
+ public abstract java.time.chrono.ChronoLocalDate date(java.time.temporal.TemporalAccessor);
+ public abstract java.time.chrono.ChronoLocalDate dateEpochDay(long);
+ public java.time.chrono.ChronoLocalDate dateNow();
+ public java.time.chrono.ChronoLocalDate dateNow(java.time.ZoneId);
+ public java.time.chrono.ChronoLocalDate dateNow(java.time.Clock);
+ public java.time.chrono.ChronoLocalDate dateYearDay(java.time.chrono.Era, int, int);
+ public abstract java.time.chrono.ChronoLocalDate dateYearDay(int, int);
+ public abstract boolean equals(java.lang.Object);
+ public abstract java.time.chrono.Era eraOf(int);
+ public abstract java.util.List eras();
+ public static java.time.chrono.Chronology from(java.time.temporal.TemporalAccessor);
+ public static java.util.Set getAvailableChronologies();
+ public abstract java.lang.String getCalendarType();
+ public java.lang.String getDisplayName(java.time.format.TextStyle, java.util.Locale);
+ public abstract java.lang.String getId();
+ public abstract int hashCode();
+ public abstract boolean isLeapYear(long);
+ public java.time.chrono.ChronoLocalDateTime localDateTime(java.time.temporal.TemporalAccessor);
+ public static java.time.chrono.Chronology of(java.lang.String);
+ public static java.time.chrono.Chronology ofLocale(java.util.Locale);
+ public java.time.chrono.ChronoPeriod period(int, int, int);
+ public abstract int prolepticYear(java.time.chrono.Era, int);
+ public abstract java.time.temporal.ValueRange range(java.time.temporal.ChronoField);
+ public abstract java.time.chrono.ChronoLocalDate resolveDate(java.util.Map, java.time.format.ResolverStyle);
+ public abstract java.lang.String toString();
+ public java.time.chrono.ChronoZonedDateTime zonedDateTime(java.time.temporal.TemporalAccessor);
+ public java.time.chrono.ChronoZonedDateTime zonedDateTime(java.time.Instant, java.time.ZoneId);
+
+
+}
+
+-keep class java.time.chrono.Era {
+
+ public java.time.temporal.Temporal adjustInto(java.time.temporal.Temporal);
+ public int get(java.time.temporal.TemporalField);
+ public java.lang.String getDisplayName(java.time.format.TextStyle, java.util.Locale);
+ public long getLong(java.time.temporal.TemporalField);
+ public abstract int getValue();
+ public boolean isSupported(java.time.temporal.TemporalField);
+ public java.lang.Object query(java.time.temporal.TemporalQuery);
+ public java.time.temporal.ValueRange range(java.time.temporal.TemporalField);
+
+
+}
+
+-keep class java.time.chrono.IsoChronology {
+
+ public java.time.LocalDate date(java.time.chrono.Era, int, int, int);
+ public java.time.LocalDate date(int, int, int);
+ public java.time.LocalDate date(java.time.temporal.TemporalAccessor);
+ public java.time.chrono.ChronoLocalDate date(java.time.temporal.TemporalAccessor);
+ public java.time.chrono.ChronoLocalDate date(int, int, int);
+ public java.time.chrono.ChronoLocalDate date(java.time.chrono.Era, int, int, int);
+ public java.time.LocalDate dateEpochDay(long);
+ public java.time.chrono.ChronoLocalDate dateEpochDay(long);
+ public java.time.LocalDate dateNow();
+ public java.time.LocalDate dateNow(java.time.ZoneId);
+ public java.time.LocalDate dateNow(java.time.Clock);
+ public java.time.chrono.ChronoLocalDate dateNow(java.time.Clock);
+ public java.time.chrono.ChronoLocalDate dateNow(java.time.ZoneId);
+ public java.time.chrono.ChronoLocalDate dateNow();
+ public java.time.LocalDate dateYearDay(java.time.chrono.Era, int, int);
+ public java.time.LocalDate dateYearDay(int, int);
+ public java.time.chrono.ChronoLocalDate dateYearDay(int, int);
+ public java.time.chrono.ChronoLocalDate dateYearDay(java.time.chrono.Era, int, int);
+ public java.time.chrono.IsoEra eraOf(int);
+ public java.time.chrono.Era eraOf(int);
+ public java.util.List eras();
+ public java.lang.String getCalendarType();
+ public java.lang.String getId();
+ public boolean isLeapYear(long);
+ public java.time.LocalDateTime localDateTime(java.time.temporal.TemporalAccessor);
+ public java.time.chrono.ChronoLocalDateTime localDateTime(java.time.temporal.TemporalAccessor);
+ public java.time.Period period(int, int, int);
+ public java.time.chrono.ChronoPeriod period(int, int, int);
+ public int prolepticYear(java.time.chrono.Era, int);
+ public java.time.temporal.ValueRange range(java.time.temporal.ChronoField);
+ public java.time.LocalDate resolveDate(java.util.Map, java.time.format.ResolverStyle);
+ public java.time.chrono.ChronoLocalDate resolveDate(java.util.Map, java.time.format.ResolverStyle);
+ public java.time.ZonedDateTime zonedDateTime(java.time.temporal.TemporalAccessor);
+ public java.time.ZonedDateTime zonedDateTime(java.time.Instant, java.time.ZoneId);
+ public java.time.chrono.ChronoZonedDateTime zonedDateTime(java.time.Instant, java.time.ZoneId);
+ public java.time.chrono.ChronoZonedDateTime zonedDateTime(java.time.temporal.TemporalAccessor);
+
+
+ public static java.time.chrono.IsoChronology INSTANCE;
+}
+
+-keep class java.time.chrono.IsoEra {
+
+ public int getValue();
+ public static java.time.chrono.IsoEra of(int);
+ public static java.time.chrono.IsoEra valueOf(java.lang.String);
+ public static java.time.chrono.IsoEra[] values();
+
+ public static java.time.chrono.IsoEra BCE;
+ public static java.time.chrono.IsoEra CE;
+
+}
+
+-keep class java.time.format.DateTimeFormatter {
+
+ public java.lang.String format(java.time.temporal.TemporalAccessor);
+ public void formatTo(java.time.temporal.TemporalAccessor, java.lang.Appendable);
+ public java.time.chrono.Chronology getChronology();
+ public java.time.format.DecimalStyle getDecimalStyle();
+ public java.util.Locale getLocale();
+ public java.util.Set getResolverFields();
+ public java.time.format.ResolverStyle getResolverStyle();
+ public java.time.ZoneId getZone();
+ public static java.time.format.DateTimeFormatter ofLocalizedDate(java.time.format.FormatStyle);
+ public static java.time.format.DateTimeFormatter ofLocalizedDateTime(java.time.format.FormatStyle);
+ public static java.time.format.DateTimeFormatter ofLocalizedDateTime(java.time.format.FormatStyle, java.time.format.FormatStyle);
+ public static java.time.format.DateTimeFormatter ofLocalizedTime(java.time.format.FormatStyle);
+ public static java.time.format.DateTimeFormatter ofPattern(java.lang.String);
+ public static java.time.format.DateTimeFormatter ofPattern(java.lang.String, java.util.Locale);
+ public java.time.temporal.TemporalAccessor parse(java.lang.CharSequence);
+ public java.time.temporal.TemporalAccessor parse(java.lang.CharSequence, java.text.ParsePosition);
+ public java.lang.Object parse(java.lang.CharSequence, java.time.temporal.TemporalQuery);
+ public java.time.temporal.TemporalAccessor parseBest(java.lang.CharSequence, java.time.temporal.TemporalQuery[]);
+ public java.time.temporal.TemporalAccessor parseUnresolved(java.lang.CharSequence, java.text.ParsePosition);
+ public static java.time.temporal.TemporalQuery parsedExcessDays();
+ public static java.time.temporal.TemporalQuery parsedLeapSecond();
+ public java.text.Format toFormat();
+ public java.text.Format toFormat(java.time.temporal.TemporalQuery);
+ public java.lang.String toString();
+ public java.time.format.DateTimeFormatter withChronology(java.time.chrono.Chronology);
+ public java.time.format.DateTimeFormatter withDecimalStyle(java.time.format.DecimalStyle);
+ public java.time.format.DateTimeFormatter withLocale(java.util.Locale);
+ public java.time.format.DateTimeFormatter withResolverFields(java.time.temporal.TemporalField[]);
+ public java.time.format.DateTimeFormatter withResolverFields(java.util.Set);
+ public java.time.format.DateTimeFormatter withResolverStyle(java.time.format.ResolverStyle);
+ public java.time.format.DateTimeFormatter withZone(java.time.ZoneId);
+
+
+ public static java.time.format.DateTimeFormatter BASIC_ISO_DATE;
+ public static java.time.format.DateTimeFormatter ISO_DATE;
+ public static java.time.format.DateTimeFormatter ISO_DATE_TIME;
+ public static java.time.format.DateTimeFormatter ISO_INSTANT;
+ public static java.time.format.DateTimeFormatter ISO_LOCAL_DATE;
+ public static java.time.format.DateTimeFormatter ISO_LOCAL_DATE_TIME;
+ public static java.time.format.DateTimeFormatter ISO_LOCAL_TIME;
+ public static java.time.format.DateTimeFormatter ISO_OFFSET_DATE;
+ public static java.time.format.DateTimeFormatter ISO_OFFSET_DATE_TIME;
+ public static java.time.format.DateTimeFormatter ISO_OFFSET_TIME;
+ public static java.time.format.DateTimeFormatter ISO_ORDINAL_DATE;
+ public static java.time.format.DateTimeFormatter ISO_TIME;
+ public static java.time.format.DateTimeFormatter ISO_WEEK_DATE;
+ public static java.time.format.DateTimeFormatter ISO_ZONED_DATE_TIME;
+ public static java.time.format.DateTimeFormatter RFC_1123_DATE_TIME;
+}
+
+-keep class java.time.format.DecimalStyle {
+
+ public boolean equals(java.lang.Object);
+ public static java.util.Set getAvailableLocales();
+ public char getDecimalSeparator();
+ public char getNegativeSign();
+ public char getPositiveSign();
+ public char getZeroDigit();
+ public int hashCode();
+ public static java.time.format.DecimalStyle of(java.util.Locale);
+ public static java.time.format.DecimalStyle ofDefaultLocale();
+ public java.lang.String toString();
+ public java.time.format.DecimalStyle withDecimalSeparator(char);
+ public java.time.format.DecimalStyle withNegativeSign(char);
+ public java.time.format.DecimalStyle withPositiveSign(char);
+ public java.time.format.DecimalStyle withZeroDigit(char);
+
+
+ public static java.time.format.DecimalStyle STANDARD;
+}
+
+-keep class java.time.format.FormatStyle {
+
+ public static java.time.format.FormatStyle valueOf(java.lang.String);
+ public static java.time.format.FormatStyle[] values();
+
+ public static java.time.format.FormatStyle FULL;
+ public static java.time.format.FormatStyle LONG;
+ public static java.time.format.FormatStyle MEDIUM;
+ public static java.time.format.FormatStyle SHORT;
+
+}
+
+-keep class java.time.format.ResolverStyle {
+
+ public static java.time.format.ResolverStyle valueOf(java.lang.String);
+ public static java.time.format.ResolverStyle[] values();
+
+ public static java.time.format.ResolverStyle LENIENT;
+ public static java.time.format.ResolverStyle SMART;
+ public static java.time.format.ResolverStyle STRICT;
+
+}
+
+-keep class java.time.format.TextStyle {
+
+ public java.time.format.TextStyle asNormal();
+ public java.time.format.TextStyle asStandalone();
+ public boolean isStandalone();
+ public static java.time.format.TextStyle valueOf(java.lang.String);
+ public static java.time.format.TextStyle[] values();
+
+ public static java.time.format.TextStyle FULL;
+ public static java.time.format.TextStyle FULL_STANDALONE;
+ public static java.time.format.TextStyle NARROW;
+ public static java.time.format.TextStyle NARROW_STANDALONE;
+ public static java.time.format.TextStyle SHORT;
+ public static java.time.format.TextStyle SHORT_STANDALONE;
+
+}
+
+-keep class java.time.temporal.ChronoField {
+
+ public java.time.temporal.Temporal adjustInto(java.time.temporal.Temporal, long);
+ public int checkValidIntValue(long);
+ public long checkValidValue(long);
+ public java.time.temporal.TemporalUnit getBaseUnit();
+ public java.lang.String getDisplayName(java.util.Locale);
+ public long getFrom(java.time.temporal.TemporalAccessor);
+ public java.time.temporal.TemporalUnit getRangeUnit();
+ public boolean isDateBased();
+ public boolean isSupportedBy(java.time.temporal.TemporalAccessor);
+ public boolean isTimeBased();
+ public java.time.temporal.ValueRange range();
+ public java.time.temporal.ValueRange rangeRefinedBy(java.time.temporal.TemporalAccessor);
+ public java.lang.String toString();
+ public static java.time.temporal.ChronoField valueOf(java.lang.String);
+ public static java.time.temporal.ChronoField[] values();
+
+ public static java.time.temporal.ChronoField ALIGNED_DAY_OF_WEEK_IN_MONTH;
+ public static java.time.temporal.ChronoField ALIGNED_DAY_OF_WEEK_IN_YEAR;
+ public static java.time.temporal.ChronoField ALIGNED_WEEK_OF_MONTH;
+ public static java.time.temporal.ChronoField ALIGNED_WEEK_OF_YEAR;
+ public static java.time.temporal.ChronoField AMPM_OF_DAY;
+ public static java.time.temporal.ChronoField CLOCK_HOUR_OF_AMPM;
+ public static java.time.temporal.ChronoField CLOCK_HOUR_OF_DAY;
+ public static java.time.temporal.ChronoField DAY_OF_MONTH;
+ public static java.time.temporal.ChronoField DAY_OF_WEEK;
+ public static java.time.temporal.ChronoField DAY_OF_YEAR;
+ public static java.time.temporal.ChronoField EPOCH_DAY;
+ public static java.time.temporal.ChronoField ERA;
+ public static java.time.temporal.ChronoField HOUR_OF_AMPM;
+ public static java.time.temporal.ChronoField HOUR_OF_DAY;
+ public static java.time.temporal.ChronoField INSTANT_SECONDS;
+ public static java.time.temporal.ChronoField MICRO_OF_DAY;
+ public static java.time.temporal.ChronoField MICRO_OF_SECOND;
+ public static java.time.temporal.ChronoField MILLI_OF_DAY;
+ public static java.time.temporal.ChronoField MILLI_OF_SECOND;
+ public static java.time.temporal.ChronoField MINUTE_OF_DAY;
+ public static java.time.temporal.ChronoField MINUTE_OF_HOUR;
+ public static java.time.temporal.ChronoField MONTH_OF_YEAR;
+ public static java.time.temporal.ChronoField NANO_OF_DAY;
+ public static java.time.temporal.ChronoField NANO_OF_SECOND;
+ public static java.time.temporal.ChronoField OFFSET_SECONDS;
+ public static java.time.temporal.ChronoField PROLEPTIC_MONTH;
+ public static java.time.temporal.ChronoField SECOND_OF_DAY;
+ public static java.time.temporal.ChronoField SECOND_OF_MINUTE;
+ public static java.time.temporal.ChronoField YEAR;
+ public static java.time.temporal.ChronoField YEAR_OF_ERA;
+
+}
+
+-keep class java.time.temporal.Temporal {
+
+ public abstract boolean isSupported(java.time.temporal.TemporalUnit);
+ public java.time.temporal.Temporal minus(java.time.temporal.TemporalAmount);
+ public java.time.temporal.Temporal minus(long, java.time.temporal.TemporalUnit);
+ public java.time.temporal.Temporal plus(java.time.temporal.TemporalAmount);
+ public abstract java.time.temporal.Temporal plus(long, java.time.temporal.TemporalUnit);
+ public abstract long until(java.time.temporal.Temporal, java.time.temporal.TemporalUnit);
+ public java.time.temporal.Temporal with(java.time.temporal.TemporalAdjuster);
+ public abstract java.time.temporal.Temporal with(java.time.temporal.TemporalField, long);
+
+
+}
+
+-keep class java.time.temporal.TemporalAccessor {
+
+ public int get(java.time.temporal.TemporalField);
+ public abstract long getLong(java.time.temporal.TemporalField);
+ public abstract boolean isSupported(java.time.temporal.TemporalField);
+ public java.lang.Object query(java.time.temporal.TemporalQuery);
+ public java.time.temporal.ValueRange range(java.time.temporal.TemporalField);
+
+
+}
+
+-keep class java.time.temporal.TemporalAdjuster {
+
+ public abstract java.time.temporal.Temporal adjustInto(java.time.temporal.Temporal);
+
+
+}
+
+-keep class java.time.temporal.TemporalAmount {
+
+ public abstract java.time.temporal.Temporal addTo(java.time.temporal.Temporal);
+ public abstract long get(java.time.temporal.TemporalUnit);
+ public abstract java.util.List getUnits();
+ public abstract java.time.temporal.Temporal subtractFrom(java.time.temporal.Temporal);
+
+
+}
+
+-keep class java.time.temporal.TemporalField {
+
+ public abstract java.time.temporal.Temporal adjustInto(java.time.temporal.Temporal, long);
+ public abstract java.time.temporal.TemporalUnit getBaseUnit();
+ public java.lang.String getDisplayName(java.util.Locale);
+ public abstract long getFrom(java.time.temporal.TemporalAccessor);
+ public abstract java.time.temporal.TemporalUnit getRangeUnit();
+ public abstract boolean isDateBased();
+ public abstract boolean isSupportedBy(java.time.temporal.TemporalAccessor);
+ public abstract boolean isTimeBased();
+ public abstract java.time.temporal.ValueRange range();
+ public abstract java.time.temporal.ValueRange rangeRefinedBy(java.time.temporal.TemporalAccessor);
+ public java.time.temporal.TemporalAccessor resolve(java.util.Map, java.time.temporal.TemporalAccessor, java.time.format.ResolverStyle);
+ public abstract java.lang.String toString();
+
+
+}
+
+-keep class java.time.temporal.TemporalQuery {
+
+ public abstract java.lang.Object queryFrom(java.time.temporal.TemporalAccessor);
+
+
+}
+
+-keep class java.time.temporal.TemporalUnit {
+
+ public abstract java.time.temporal.Temporal addTo(java.time.temporal.Temporal, long);
+ public abstract long between(java.time.temporal.Temporal, java.time.temporal.Temporal);
+ public abstract java.time.Duration getDuration();
+ public abstract boolean isDateBased();
+ public abstract boolean isDurationEstimated();
+ public boolean isSupportedBy(java.time.temporal.Temporal);
+ public abstract boolean isTimeBased();
+ public abstract java.lang.String toString();
+
+
+}
+
+-keep class java.time.temporal.ValueRange {
+
+ public int checkValidIntValue(long, java.time.temporal.TemporalField);
+ public long checkValidValue(long, java.time.temporal.TemporalField);
+ public boolean equals(java.lang.Object);
+ public long getLargestMinimum();
+ public long getMaximum();
+ public long getMinimum();
+ public long getSmallestMaximum();
+ public int hashCode();
+ public boolean isFixed();
+ public boolean isIntValue();
+ public boolean isValidIntValue(long);
+ public boolean isValidValue(long);
+ public static java.time.temporal.ValueRange of(long, long);
+ public static java.time.temporal.ValueRange of(long, long, long);
+ public static java.time.temporal.ValueRange of(long, long, long, long);
+ public java.lang.String toString();
+
+
+}
+
+-keep class java.time.zone.ZoneOffsetTransition {
+
+ public int compareTo(java.time.zone.ZoneOffsetTransition);
+ public int compareTo(java.lang.Object);
+ public boolean equals(java.lang.Object);
+ public java.time.LocalDateTime getDateTimeAfter();
+ public java.time.LocalDateTime getDateTimeBefore();
+ public java.time.Duration getDuration();
+ public java.time.Instant getInstant();
+ public java.time.ZoneOffset getOffsetAfter();
+ public java.time.ZoneOffset getOffsetBefore();
+ public int hashCode();
+ public boolean isGap();
+ public boolean isOverlap();
+ public boolean isValidOffset(java.time.ZoneOffset);
+ public static java.time.zone.ZoneOffsetTransition of(java.time.LocalDateTime, java.time.ZoneOffset, java.time.ZoneOffset);
+ public long toEpochSecond();
+ public java.lang.String toString();
+
+
+}
+
+-keep class java.time.zone.ZoneOffsetTransitionRule {
+
+ public java.time.zone.ZoneOffsetTransition createTransition(int);
+ public boolean equals(java.lang.Object);
+ public int getDayOfMonthIndicator();
+ public java.time.DayOfWeek getDayOfWeek();
+ public java.time.LocalTime getLocalTime();
+ public java.time.Month getMonth();
+ public java.time.ZoneOffset getOffsetAfter();
+ public java.time.ZoneOffset getOffsetBefore();
+ public java.time.ZoneOffset getStandardOffset();
+ public java.time.zone.ZoneOffsetTransitionRule$TimeDefinition getTimeDefinition();
+ public int hashCode();
+ public boolean isMidnightEndOfDay();
+ public static java.time.zone.ZoneOffsetTransitionRule of(java.time.Month, int, java.time.DayOfWeek, java.time.LocalTime, boolean, java.time.zone.ZoneOffsetTransitionRule$TimeDefinition, java.time.ZoneOffset, java.time.ZoneOffset, java.time.ZoneOffset);
+ public java.lang.String toString();
+
+
+}
+
+-keep class java.time.zone.ZoneOffsetTransitionRule$TimeDefinition {
+
+ public java.time.LocalDateTime createDateTime(java.time.LocalDateTime, java.time.ZoneOffset, java.time.ZoneOffset);
+ public static java.time.zone.ZoneOffsetTransitionRule$TimeDefinition valueOf(java.lang.String);
+ public static java.time.zone.ZoneOffsetTransitionRule$TimeDefinition[] values();
+
+ public static java.time.zone.ZoneOffsetTransitionRule$TimeDefinition STANDARD;
+ public static java.time.zone.ZoneOffsetTransitionRule$TimeDefinition UTC;
+ public static java.time.zone.ZoneOffsetTransitionRule$TimeDefinition WALL;
+
+}
+
+-keep class java.time.zone.ZoneRules {
+
+ public boolean equals(java.lang.Object);
+ public java.time.Duration getDaylightSavings(java.time.Instant);
+ public java.time.ZoneOffset getOffset(java.time.Instant);
+ public java.time.ZoneOffset getOffset(java.time.LocalDateTime);
+ public java.time.ZoneOffset getStandardOffset(java.time.Instant);
+ public java.time.zone.ZoneOffsetTransition getTransition(java.time.LocalDateTime);
+ public java.util.List getTransitionRules();
+ public java.util.List getTransitions();
+ public java.util.List getValidOffsets(java.time.LocalDateTime);
+ public int hashCode();
+ public boolean isDaylightSavings(java.time.Instant);
+ public boolean isFixedOffset();
+ public boolean isValidOffset(java.time.LocalDateTime, java.time.ZoneOffset);
+ public java.time.zone.ZoneOffsetTransition nextTransition(java.time.Instant);
+ public static java.time.zone.ZoneRules of(java.time.ZoneOffset, java.time.ZoneOffset, java.util.List, java.util.List, java.util.List);
+ public static java.time.zone.ZoneRules of(java.time.ZoneOffset);
+ public java.time.zone.ZoneOffsetTransition previousTransition(java.time.Instant);
+ public java.lang.String toString();
+
+
+}
+
-keep class java.util.AbstractCollection {
<init>();
@@ -9466,8 +29667,8 @@
-keep class java.util.AbstractList {
<init>();
- public void add(int, java.lang.Object);
public boolean add(java.lang.Object);
+ public void add(int, java.lang.Object);
public boolean addAll(int, java.util.Collection);
public void clear();
public boolean equals(java.lang.Object);
@@ -9523,18 +29724,26 @@
public java.lang.Object clone();
public boolean contains(java.lang.Object);
public void ensureCapacity(int);
- public boolean equals(java.lang.Object);
+ public void forEach(java.util.function.Consumer);
public java.lang.Object get(int);
- public int hashCode();
public int indexOf(java.lang.Object);
public boolean isEmpty();
public java.util.Iterator iterator();
public int lastIndexOf(java.lang.Object);
+ public java.util.ListIterator listIterator(int);
+ public java.util.ListIterator listIterator();
public java.lang.Object remove(int);
public boolean remove(java.lang.Object);
+ public boolean removeAll(java.util.Collection);
+ public boolean removeIf(java.util.function.Predicate);
protected void removeRange(int, int);
+ public void replaceAll(java.util.function.UnaryOperator);
+ public boolean retainAll(java.util.Collection);
public java.lang.Object set(int, java.lang.Object);
public int size();
+ public void sort(java.util.Comparator);
+ public java.util.Spliterator spliterator();
+ public java.util.List subList(int, int);
public java.lang.Object[] toArray();
public java.lang.Object[] toArray(java.lang.Object[]);
public void trimToSize();
@@ -9553,10 +29762,14 @@
public abstract int hashCode();
public abstract boolean isEmpty();
public abstract java.util.Iterator iterator();
+ public java.util.stream.Stream parallelStream();
public abstract boolean remove(java.lang.Object);
public abstract boolean removeAll(java.util.Collection);
+ public boolean removeIf(java.util.function.Predicate);
public abstract boolean retainAll(java.util.Collection);
public abstract int size();
+ public java.util.Spliterator spliterator();
+ public java.util.stream.Stream stream();
public abstract java.lang.Object[] toArray();
public abstract java.lang.Object[] toArray(java.lang.Object[]);
@@ -9566,17 +29779,33 @@
-keep class java.util.Comparator {
public abstract int compare(java.lang.Object, java.lang.Object);
+ public static java.util.Comparator comparing(java.util.function.Function, java.util.Comparator);
+ public static java.util.Comparator comparing(java.util.function.Function);
+ public static java.util.Comparator comparingDouble(java.util.function.ToDoubleFunction);
+ public static java.util.Comparator comparingInt(java.util.function.ToIntFunction);
+ public static java.util.Comparator comparingLong(java.util.function.ToLongFunction);
public abstract boolean equals(java.lang.Object);
+ public static java.util.Comparator naturalOrder();
+ public static java.util.Comparator nullsFirst(java.util.Comparator);
+ public static java.util.Comparator nullsLast(java.util.Comparator);
+ public static java.util.Comparator reverseOrder();
+ public java.util.Comparator reversed();
+ public java.util.Comparator thenComparing(java.util.Comparator);
+ public java.util.Comparator thenComparing(java.util.function.Function, java.util.Comparator);
+ public java.util.Comparator thenComparing(java.util.function.Function);
+ public java.util.Comparator thenComparingDouble(java.util.function.ToDoubleFunction);
+ public java.util.Comparator thenComparingInt(java.util.function.ToIntFunction);
+ public java.util.Comparator thenComparingLong(java.util.function.ToLongFunction);
}
-keep class java.util.Date {
<init>();
+ <init>(long);
<init>(int, int, int);
<init>(int, int, int, int, int);
<init>(int, int, int, int, int, int);
- <init>(long);
<init>(java.lang.String);
public static long UTC(int, int, int, int, int, int);
@@ -9586,6 +29815,7 @@
public int compareTo(java.util.Date);
public int compareTo(java.lang.Object);
public boolean equals(java.lang.Object);
+ public static java.util.Date from(java.time.Instant);
public int getDate();
public int getDay();
public int getHours();
@@ -9605,12 +29835,42 @@
public void setTime(long);
public void setYear(int);
public java.lang.String toGMTString();
+ public java.time.Instant toInstant();
public java.lang.String toLocaleString();
public java.lang.String toString();
}
+-keep class java.util.Dictionary {
+ <init>();
+
+ public abstract java.util.Enumeration elements();
+ public abstract java.lang.Object get(java.lang.Object);
+ public abstract boolean isEmpty();
+ public abstract java.util.Enumeration keys();
+ public abstract java.lang.Object put(java.lang.Object, java.lang.Object);
+ public abstract java.lang.Object remove(java.lang.Object);
+ public abstract int size();
+
+
+}
+
+-keep class java.util.DoubleSummaryStatistics {
+ <init>();
+
+ public void accept(double);
+ public void combine(java.util.DoubleSummaryStatistics);
+ public double getAverage();
+ public long getCount();
+ public double getMax();
+ public double getMin();
+ public double getSum();
+ public java.lang.String toString();
+
+
+}
+
-keep class java.util.Enumeration {
public abstract boolean hasMoreElements();
@@ -9620,43 +29880,119 @@
}
-keep class java.util.HashMap {
- <init>();
- <init>(int);
<init>(int, float);
+ <init>(int);
+ <init>();
<init>(java.util.Map);
public void clear();
public java.lang.Object clone();
+ public java.lang.Object compute(java.lang.Object, java.util.function.BiFunction);
+ public java.lang.Object computeIfAbsent(java.lang.Object, java.util.function.Function);
+ public java.lang.Object computeIfPresent(java.lang.Object, java.util.function.BiFunction);
public boolean containsKey(java.lang.Object);
public boolean containsValue(java.lang.Object);
public java.util.Set entrySet();
+ public void forEach(java.util.function.BiConsumer);
public java.lang.Object get(java.lang.Object);
+ public java.lang.Object getOrDefault(java.lang.Object, java.lang.Object);
public boolean isEmpty();
public java.util.Set keySet();
+ public java.lang.Object merge(java.lang.Object, java.lang.Object, java.util.function.BiFunction);
public java.lang.Object put(java.lang.Object, java.lang.Object);
public void putAll(java.util.Map);
+ public java.lang.Object putIfAbsent(java.lang.Object, java.lang.Object);
public java.lang.Object remove(java.lang.Object);
+ public boolean remove(java.lang.Object, java.lang.Object);
+ public boolean replace(java.lang.Object, java.lang.Object, java.lang.Object);
+ public java.lang.Object replace(java.lang.Object, java.lang.Object);
+ public void replaceAll(java.util.function.BiFunction);
public int size();
public java.util.Collection values();
}
+-keep class java.util.Hashtable {
+ <init>(int, float);
+ <init>(int);
+ <init>();
+ <init>(java.util.Map);
+
+ public synchronized void clear();
+ public synchronized java.lang.Object clone();
+ public synchronized java.lang.Object compute(java.lang.Object, java.util.function.BiFunction);
+ public synchronized java.lang.Object computeIfAbsent(java.lang.Object, java.util.function.Function);
+ public synchronized java.lang.Object computeIfPresent(java.lang.Object, java.util.function.BiFunction);
+ public synchronized boolean contains(java.lang.Object);
+ public synchronized boolean containsKey(java.lang.Object);
+ public boolean containsValue(java.lang.Object);
+ public synchronized java.util.Enumeration elements();
+ public java.util.Set entrySet();
+ public synchronized boolean equals(java.lang.Object);
+ public synchronized void forEach(java.util.function.BiConsumer);
+ public synchronized java.lang.Object get(java.lang.Object);
+ public synchronized java.lang.Object getOrDefault(java.lang.Object, java.lang.Object);
+ public synchronized int hashCode();
+ public synchronized boolean isEmpty();
+ public java.util.Set keySet();
+ public synchronized java.util.Enumeration keys();
+ public synchronized java.lang.Object merge(java.lang.Object, java.lang.Object, java.util.function.BiFunction);
+ public synchronized java.lang.Object put(java.lang.Object, java.lang.Object);
+ public synchronized void putAll(java.util.Map);
+ public synchronized java.lang.Object putIfAbsent(java.lang.Object, java.lang.Object);
+ protected void rehash();
+ public synchronized java.lang.Object remove(java.lang.Object);
+ public synchronized boolean remove(java.lang.Object, java.lang.Object);
+ public synchronized boolean replace(java.lang.Object, java.lang.Object, java.lang.Object);
+ public synchronized java.lang.Object replace(java.lang.Object, java.lang.Object);
+ public synchronized void replaceAll(java.util.function.BiFunction);
+ public synchronized int size();
+ public synchronized java.lang.String toString();
+ public java.util.Collection values();
+
+
+}
+
+-keep class java.util.IntSummaryStatistics {
+ <init>();
+
+ public void accept(int);
+ public void combine(java.util.IntSummaryStatistics);
+ public double getAverage();
+ public long getCount();
+ public int getMax();
+ public int getMin();
+ public long getSum();
+ public java.lang.String toString();
+
+
+}
+
+-keep class java.util.InvalidPropertiesFormatException {
+ <init>(java.lang.Throwable);
+ <init>(java.lang.String);
+
+
+
+}
+
-keep class java.util.Iterator {
+ public void forEachRemaining(java.util.function.Consumer);
public abstract boolean hasNext();
public abstract java.lang.Object next();
- public abstract void remove();
+ public void remove();
}
-keep class java.util.List {
- public abstract void add(int, java.lang.Object);
public abstract boolean add(java.lang.Object);
- public abstract boolean addAll(int, java.util.Collection);
+ public abstract void add(int, java.lang.Object);
public abstract boolean addAll(java.util.Collection);
+ public abstract boolean addAll(int, java.util.Collection);
public abstract void clear();
public abstract boolean contains(java.lang.Object);
public abstract boolean containsAll(java.util.Collection);
@@ -9669,12 +30005,15 @@
public abstract int lastIndexOf(java.lang.Object);
public abstract java.util.ListIterator listIterator();
public abstract java.util.ListIterator listIterator(int);
- public abstract java.lang.Object remove(int);
public abstract boolean remove(java.lang.Object);
+ public abstract java.lang.Object remove(int);
public abstract boolean removeAll(java.util.Collection);
+ public void replaceAll(java.util.function.UnaryOperator);
public abstract boolean retainAll(java.util.Collection);
public abstract java.lang.Object set(int, java.lang.Object);
public abstract int size();
+ public void sort(java.util.Comparator);
+ public java.util.Spliterator spliterator();
public abstract java.util.List subList(int, int);
public abstract java.lang.Object[] toArray();
public abstract java.lang.Object[] toArray(java.lang.Object[]);
@@ -9698,16 +30037,22 @@
}
-keep class java.util.Locale {
- <init>(java.lang.String);
- <init>(java.lang.String, java.lang.String);
<init>(java.lang.String, java.lang.String, java.lang.String);
+ <init>(java.lang.String, java.lang.String);
+ <init>(java.lang.String);
+ public static java.lang.String adjustLanguageCode(java.lang.String);
public java.lang.Object clone();
public boolean equals(java.lang.Object);
+ public static java.util.List filter(java.util.List, java.util.Collection, java.util.Locale$FilteringMode);
+ public static java.util.List filter(java.util.List, java.util.Collection);
+ public static java.util.List filterTags(java.util.List, java.util.Collection, java.util.Locale$FilteringMode);
+ public static java.util.List filterTags(java.util.List, java.util.Collection);
public static java.util.Locale forLanguageTag(java.lang.String);
public static java.util.Locale[] getAvailableLocales();
public java.lang.String getCountry();
public static java.util.Locale getDefault();
+ public static java.util.Locale getDefault(java.util.Locale$Category);
public java.lang.String getDisplayCountry();
public java.lang.String getDisplayCountry(java.util.Locale);
public java.lang.String getDisplayLanguage();
@@ -9730,8 +30075,14 @@
public java.util.Set getUnicodeLocaleKeys();
public java.lang.String getUnicodeLocaleType(java.lang.String);
public java.lang.String getVariant();
- public synchronized int hashCode();
+ public boolean hasExtensions();
+ public int hashCode();
+ public static java.util.Locale initDefault();
+ public static java.util.Locale lookup(java.util.List, java.util.Collection);
+ public static java.lang.String lookupTag(java.util.List, java.util.Collection);
public static synchronized void setDefault(java.util.Locale);
+ public static synchronized void setDefault(java.util.Locale$Category, java.util.Locale);
+ public java.util.Locale stripExtensions();
public java.lang.String toLanguageTag();
public java.lang.String toString();
@@ -9762,20 +30113,87 @@
public static java.util.Locale US;
}
+-keep class java.util.Locale$Category {
+
+ public static java.util.Locale$Category valueOf(java.lang.String);
+ public static java.util.Locale$Category[] values();
+
+ public static java.util.Locale$Category DISPLAY;
+ public static java.util.Locale$Category FORMAT;
+
+}
+
+-keep class java.util.Locale$FilteringMode {
+
+ public static java.util.Locale$FilteringMode valueOf(java.lang.String);
+ public static java.util.Locale$FilteringMode[] values();
+
+ public static java.util.Locale$FilteringMode AUTOSELECT_FILTERING;
+ public static java.util.Locale$FilteringMode EXTENDED_FILTERING;
+ public static java.util.Locale$FilteringMode IGNORE_EXTENDED_RANGES;
+ public static java.util.Locale$FilteringMode MAP_EXTENDED_RANGES;
+ public static java.util.Locale$FilteringMode REJECT_EXTENDED_RANGES;
+
+}
+
+-keep class java.util.Locale$LanguageRange {
+ <init>(java.lang.String);
+ <init>(java.lang.String, double);
+
+ public boolean equals(java.lang.Object);
+ public java.lang.String getRange();
+ public double getWeight();
+ public int hashCode();
+ public static java.util.List mapEquivalents(java.util.List, java.util.Map);
+ public static java.util.List parse(java.lang.String);
+ public static java.util.List parse(java.lang.String, java.util.Map);
+
+
+ public static double MAX_WEIGHT;
+ public static double MIN_WEIGHT;
+}
+
+-keep class java.util.LongSummaryStatistics {
+ <init>();
+
+ public void accept(int);
+ public void accept(long);
+ public void combine(java.util.LongSummaryStatistics);
+ public double getAverage();
+ public long getCount();
+ public long getMax();
+ public long getMin();
+ public long getSum();
+ public java.lang.String toString();
+
+
+}
+
-keep class java.util.Map {
public abstract void clear();
+ public java.lang.Object compute(java.lang.Object, java.util.function.BiFunction);
+ public java.lang.Object computeIfAbsent(java.lang.Object, java.util.function.Function);
+ public java.lang.Object computeIfPresent(java.lang.Object, java.util.function.BiFunction);
public abstract boolean containsKey(java.lang.Object);
public abstract boolean containsValue(java.lang.Object);
public abstract java.util.Set entrySet();
public abstract boolean equals(java.lang.Object);
+ public void forEach(java.util.function.BiConsumer);
public abstract java.lang.Object get(java.lang.Object);
+ public java.lang.Object getOrDefault(java.lang.Object, java.lang.Object);
public abstract int hashCode();
public abstract boolean isEmpty();
public abstract java.util.Set keySet();
+ public java.lang.Object merge(java.lang.Object, java.lang.Object, java.util.function.BiFunction);
public abstract java.lang.Object put(java.lang.Object, java.lang.Object);
public abstract void putAll(java.util.Map);
+ public java.lang.Object putIfAbsent(java.lang.Object, java.lang.Object);
public abstract java.lang.Object remove(java.lang.Object);
+ public boolean remove(java.lang.Object, java.lang.Object);
+ public boolean replace(java.lang.Object, java.lang.Object, java.lang.Object);
+ public java.lang.Object replace(java.lang.Object, java.lang.Object);
+ public void replaceAll(java.util.function.BiFunction);
public abstract int size();
public abstract java.util.Collection values();
@@ -9784,6 +30202,10 @@
-keep class java.util.Map$Entry {
+ public static java.util.Comparator comparingByKey();
+ public static java.util.Comparator comparingByKey(java.util.Comparator);
+ public static java.util.Comparator comparingByValue();
+ public static java.util.Comparator comparingByValue(java.util.Comparator);
public abstract boolean equals(java.lang.Object);
public abstract java.lang.Object getKey();
public abstract java.lang.Object getValue();
@@ -9793,6 +30215,184 @@
}
+-keep class java.util.MissingResourceException {
+ <init>(java.lang.String, java.lang.String, java.lang.String);
+
+ public java.lang.String getClassName();
+ public java.lang.String getKey();
+
+
+}
+
+-keep class java.util.Optional {
+
+ public static java.util.Optional empty();
+ public boolean equals(java.lang.Object);
+ public java.util.Optional filter(java.util.function.Predicate);
+ public java.util.Optional flatMap(java.util.function.Function);
+ public java.lang.Object get();
+ public int hashCode();
+ public void ifPresent(java.util.function.Consumer);
+ public boolean isPresent();
+ public java.util.Optional map(java.util.function.Function);
+ public static java.util.Optional of(java.lang.Object);
+ public static java.util.Optional ofNullable(java.lang.Object);
+ public java.lang.Object orElse(java.lang.Object);
+ public java.lang.Object orElseGet(java.util.function.Supplier);
+ public java.lang.Object orElseThrow(java.util.function.Supplier);
+ public java.lang.String toString();
+
+
+}
+
+-keep class java.util.OptionalDouble {
+
+ public static java.util.OptionalDouble empty();
+ public boolean equals(java.lang.Object);
+ public double getAsDouble();
+ public int hashCode();
+ public void ifPresent(java.util.function.DoubleConsumer);
+ public boolean isPresent();
+ public static java.util.OptionalDouble of(double);
+ public double orElse(double);
+ public double orElseGet(java.util.function.DoubleSupplier);
+ public double orElseThrow(java.util.function.Supplier);
+ public java.lang.String toString();
+
+
+}
+
+-keep class java.util.OptionalInt {
+
+ public static java.util.OptionalInt empty();
+ public boolean equals(java.lang.Object);
+ public int getAsInt();
+ public int hashCode();
+ public void ifPresent(java.util.function.IntConsumer);
+ public boolean isPresent();
+ public static java.util.OptionalInt of(int);
+ public int orElse(int);
+ public int orElseGet(java.util.function.IntSupplier);
+ public int orElseThrow(java.util.function.Supplier);
+ public java.lang.String toString();
+
+
+}
+
+-keep class java.util.OptionalLong {
+
+ public static java.util.OptionalLong empty();
+ public boolean equals(java.lang.Object);
+ public long getAsLong();
+ public int hashCode();
+ public void ifPresent(java.util.function.LongConsumer);
+ public boolean isPresent();
+ public static java.util.OptionalLong of(long);
+ public long orElse(long);
+ public long orElseGet(java.util.function.LongSupplier);
+ public long orElseThrow(java.util.function.Supplier);
+ public java.lang.String toString();
+
+
+}
+
+-keep class java.util.PrimitiveIterator {
+
+ public abstract void forEachRemaining(java.lang.Object);
+
+
+}
+
+-keep class java.util.PrimitiveIterator$OfDouble {
+
+ public void forEachRemaining(java.util.function.DoubleConsumer);
+ public void forEachRemaining(java.util.function.Consumer);
+ public void forEachRemaining(java.lang.Object);
+ public java.lang.Double next();
+ public java.lang.Object next();
+ public abstract double nextDouble();
+
+
+}
+
+-keep class java.util.PrimitiveIterator$OfInt {
+
+ public void forEachRemaining(java.util.function.IntConsumer);
+ public void forEachRemaining(java.util.function.Consumer);
+ public void forEachRemaining(java.lang.Object);
+ public java.lang.Integer next();
+ public java.lang.Object next();
+ public abstract int nextInt();
+
+
+}
+
+-keep class java.util.PrimitiveIterator$OfLong {
+
+ public void forEachRemaining(java.util.function.LongConsumer);
+ public void forEachRemaining(java.util.function.Consumer);
+ public void forEachRemaining(java.lang.Object);
+ public java.lang.Long next();
+ public java.lang.Object next();
+ public abstract long nextLong();
+
+
+}
+
+-keep class java.util.Properties {
+ <init>();
+ <init>(java.util.Properties);
+
+ public java.lang.String getProperty(java.lang.String);
+ public java.lang.String getProperty(java.lang.String, java.lang.String);
+ public void list(java.io.PrintStream);
+ public void list(java.io.PrintWriter);
+ public synchronized void load(java.io.Reader);
+ public synchronized void load(java.io.InputStream);
+ public synchronized void loadFromXML(java.io.InputStream);
+ public java.util.Enumeration propertyNames();
+ public void save(java.io.OutputStream, java.lang.String);
+ public synchronized java.lang.Object setProperty(java.lang.String, java.lang.String);
+ public void store(java.io.Writer, java.lang.String);
+ public void store(java.io.OutputStream, java.lang.String);
+ public void storeToXML(java.io.OutputStream, java.lang.String);
+ public void storeToXML(java.io.OutputStream, java.lang.String, java.lang.String);
+ public java.util.Set stringPropertyNames();
+
+
+ protected java.util.Properties defaults;
+}
+
+-keep class java.util.Random {
+ <init>();
+ <init>(long);
+
+ public java.util.stream.DoubleStream doubles(long);
+ public java.util.stream.DoubleStream doubles();
+ public java.util.stream.DoubleStream doubles(long, double, double);
+ public java.util.stream.DoubleStream doubles(double, double);
+ public java.util.stream.IntStream ints(long);
+ public java.util.stream.IntStream ints();
+ public java.util.stream.IntStream ints(long, int, int);
+ public java.util.stream.IntStream ints(int, int);
+ public java.util.stream.LongStream longs(long);
+ public java.util.stream.LongStream longs();
+ public java.util.stream.LongStream longs(long, long, long);
+ public java.util.stream.LongStream longs(long, long);
+ protected int next(int);
+ public boolean nextBoolean();
+ public void nextBytes(byte[]);
+ public double nextDouble();
+ public float nextFloat();
+ public synchronized double nextGaussian();
+ public int nextInt();
+ public int nextInt(int);
+ public long nextLong();
+ public synchronized void setSeed(long);
+
+
+}
+
-keep class java.util.Set {
public abstract boolean add(java.lang.Object);
@@ -9808,6 +30408,7 @@
public abstract boolean removeAll(java.util.Collection);
public abstract boolean retainAll(java.util.Collection);
public abstract int size();
+ public java.util.Spliterator spliterator();
public abstract java.lang.Object[] toArray();
public abstract java.lang.Object[] toArray(java.lang.Object[]);
@@ -9817,11 +30418,850 @@
-keep class java.util.SortedMap {
public abstract java.util.Comparator comparator();
+ public abstract java.util.Set entrySet();
public abstract java.lang.Object firstKey();
public abstract java.util.SortedMap headMap(java.lang.Object);
+ public abstract java.util.Set keySet();
public abstract java.lang.Object lastKey();
public abstract java.util.SortedMap subMap(java.lang.Object, java.lang.Object);
public abstract java.util.SortedMap tailMap(java.lang.Object);
+ public abstract java.util.Collection values();
+
+
+}
+
+-keep class java.util.Spliterator {
+
+ public abstract int characteristics();
+ public abstract long estimateSize();
+ public void forEachRemaining(java.util.function.Consumer);
+ public java.util.Comparator getComparator();
+ public long getExactSizeIfKnown();
+ public boolean hasCharacteristics(int);
+ public abstract boolean tryAdvance(java.util.function.Consumer);
+ public abstract java.util.Spliterator trySplit();
+
+
+ public static int CONCURRENT;
+ public static int DISTINCT;
+ public static int IMMUTABLE;
+ public static int NONNULL;
+ public static int ORDERED;
+ public static int SIZED;
+ public static int SORTED;
+ public static int SUBSIZED;
+}
+
+-keep class java.util.Spliterator$OfDouble {
+
+ public void forEachRemaining(java.util.function.DoubleConsumer);
+ public void forEachRemaining(java.util.function.Consumer);
+ public void forEachRemaining(java.lang.Object);
+ public abstract boolean tryAdvance(java.util.function.DoubleConsumer);
+ public boolean tryAdvance(java.util.function.Consumer);
+ public boolean tryAdvance(java.lang.Object);
+ public abstract java.util.Spliterator$OfDouble trySplit();
+ public java.util.Spliterator$OfPrimitive trySplit();
+ public java.util.Spliterator trySplit();
+
+
+}
+
+-keep class java.util.Spliterator$OfInt {
+
+ public void forEachRemaining(java.util.function.IntConsumer);
+ public void forEachRemaining(java.util.function.Consumer);
+ public void forEachRemaining(java.lang.Object);
+ public abstract boolean tryAdvance(java.util.function.IntConsumer);
+ public boolean tryAdvance(java.util.function.Consumer);
+ public boolean tryAdvance(java.lang.Object);
+ public abstract java.util.Spliterator$OfInt trySplit();
+ public java.util.Spliterator$OfPrimitive trySplit();
+ public java.util.Spliterator trySplit();
+
+
+}
+
+-keep class java.util.Spliterator$OfLong {
+
+ public void forEachRemaining(java.util.function.LongConsumer);
+ public void forEachRemaining(java.util.function.Consumer);
+ public void forEachRemaining(java.lang.Object);
+ public abstract boolean tryAdvance(java.util.function.LongConsumer);
+ public boolean tryAdvance(java.util.function.Consumer);
+ public boolean tryAdvance(java.lang.Object);
+ public abstract java.util.Spliterator$OfLong trySplit();
+ public java.util.Spliterator$OfPrimitive trySplit();
+ public java.util.Spliterator trySplit();
+
+
+}
+
+-keep class java.util.Spliterator$OfPrimitive {
+
+ public void forEachRemaining(java.lang.Object);
+ public abstract boolean tryAdvance(java.lang.Object);
+ public abstract java.util.Spliterator$OfPrimitive trySplit();
+ public java.util.Spliterator trySplit();
+
+
+}
+
+-keep class java.util.UUID {
+ <init>(long, long);
+
+ public int clockSequence();
+ public int compareTo(java.util.UUID);
+ public int compareTo(java.lang.Object);
+ public boolean equals(java.lang.Object);
+ public static java.util.UUID fromString(java.lang.String);
+ public long getLeastSignificantBits();
+ public long getMostSignificantBits();
+ public int hashCode();
+ public static java.util.UUID nameUUIDFromBytes(byte[]);
+ public long node();
+ public static java.util.UUID randomUUID();
+ public long timestamp();
+ public java.lang.String toString();
+ public int variant();
+ public int version();
+
+
+}
+
+-keep class java.util.concurrent.Callable {
+
+ public abstract java.lang.Object call();
+
+
+}
+
+-keep class java.util.concurrent.ExecutionException {
+ <init>();
+ <init>(java.lang.String);
+ <init>(java.lang.String, java.lang.Throwable);
+ <init>(java.lang.Throwable);
+
+
+
+}
+
+-keep class java.util.concurrent.Executor {
+
+ public abstract void execute(java.lang.Runnable);
+
+
+}
+
+-keep class java.util.concurrent.ExecutorService {
+
+ public abstract boolean awaitTermination(long, java.util.concurrent.TimeUnit);
+ public abstract java.util.List invokeAll(java.util.Collection);
+ public abstract java.util.List invokeAll(java.util.Collection, long, java.util.concurrent.TimeUnit);
+ public abstract java.lang.Object invokeAny(java.util.Collection);
+ public abstract java.lang.Object invokeAny(java.util.Collection, long, java.util.concurrent.TimeUnit);
+ public abstract boolean isShutdown();
+ public abstract boolean isTerminated();
+ public abstract void shutdown();
+ public abstract java.util.List shutdownNow();
+ public abstract java.util.concurrent.Future submit(java.util.concurrent.Callable);
+ public abstract java.util.concurrent.Future submit(java.lang.Runnable, java.lang.Object);
+ public abstract java.util.concurrent.Future submit(java.lang.Runnable);
+
+
+}
+
+-keep class java.util.concurrent.Future {
+
+ public abstract boolean cancel(boolean);
+ public abstract java.lang.Object get();
+ public abstract java.lang.Object get(long, java.util.concurrent.TimeUnit);
+ public abstract boolean isCancelled();
+ public abstract boolean isDone();
+
+
+}
+
+-keep class java.util.concurrent.TimeUnit {
+
+ public long convert(long, java.util.concurrent.TimeUnit);
+ public void sleep(long);
+ public void timedJoin(java.lang.Thread, long);
+ public void timedWait(java.lang.Object, long);
+ public long toDays(long);
+ public long toHours(long);
+ public long toMicros(long);
+ public long toMillis(long);
+ public long toMinutes(long);
+ public long toNanos(long);
+ public long toSeconds(long);
+ public static java.util.concurrent.TimeUnit valueOf(java.lang.String);
+ public static java.util.concurrent.TimeUnit[] values();
+
+ public static java.util.concurrent.TimeUnit DAYS;
+ public static java.util.concurrent.TimeUnit HOURS;
+ public static java.util.concurrent.TimeUnit MICROSECONDS;
+ public static java.util.concurrent.TimeUnit MILLISECONDS;
+ public static java.util.concurrent.TimeUnit MINUTES;
+ public static java.util.concurrent.TimeUnit NANOSECONDS;
+ public static java.util.concurrent.TimeUnit SECONDS;
+
+}
+
+-keep class java.util.concurrent.TimeoutException {
+ <init>();
+ <init>(java.lang.String);
+
+
+
+}
+
+-keep class java.util.concurrent.atomic.AtomicInteger {
+ <init>(int);
+ <init>();
+
+ public int accumulateAndGet(int, java.util.function.IntBinaryOperator);
+ public int addAndGet(int);
+ public boolean compareAndSet(int, int);
+ public int decrementAndGet();
+ public double doubleValue();
+ public float floatValue();
+ public int get();
+ public int getAndAccumulate(int, java.util.function.IntBinaryOperator);
+ public int getAndAdd(int);
+ public int getAndDecrement();
+ public int getAndIncrement();
+ public int getAndSet(int);
+ public int getAndUpdate(java.util.function.IntUnaryOperator);
+ public int incrementAndGet();
+ public int intValue();
+ public void lazySet(int);
+ public long longValue();
+ public void set(int);
+ public java.lang.String toString();
+ public int updateAndGet(java.util.function.IntUnaryOperator);
+ public boolean weakCompareAndSet(int, int);
+
+
+}
+
+-keep class java.util.function.BiConsumer {
+
+ public abstract void accept(java.lang.Object, java.lang.Object);
+ public java.util.function.BiConsumer andThen(java.util.function.BiConsumer);
+
+
+}
+
+-keep class java.util.function.BiFunction {
+
+ public java.util.function.BiFunction andThen(java.util.function.Function);
+ public abstract java.lang.Object apply(java.lang.Object, java.lang.Object);
+
+
+}
+
+-keep class java.util.function.BinaryOperator {
+
+ public static java.util.function.BinaryOperator maxBy(java.util.Comparator);
+ public static java.util.function.BinaryOperator minBy(java.util.Comparator);
+
+
+}
+
+-keep class java.util.function.Consumer {
+
+ public abstract void accept(java.lang.Object);
+ public java.util.function.Consumer andThen(java.util.function.Consumer);
+
+
+}
+
+-keep class java.util.function.DoubleBinaryOperator {
+
+ public abstract double applyAsDouble(double, double);
+
+
+}
+
+-keep class java.util.function.DoubleConsumer {
+
+ public abstract void accept(double);
+ public java.util.function.DoubleConsumer andThen(java.util.function.DoubleConsumer);
+
+
+}
+
+-keep class java.util.function.DoubleFunction {
+
+ public abstract java.lang.Object apply(double);
+
+
+}
+
+-keep class java.util.function.DoublePredicate {
+
+ public java.util.function.DoublePredicate and(java.util.function.DoublePredicate);
+ public java.util.function.DoublePredicate negate();
+ public java.util.function.DoublePredicate or(java.util.function.DoublePredicate);
+ public abstract boolean test(double);
+
+
+}
+
+-keep class java.util.function.DoubleSupplier {
+
+ public abstract double getAsDouble();
+
+
+}
+
+-keep class java.util.function.DoubleToIntFunction {
+
+ public abstract int applyAsInt(double);
+
+
+}
+
+-keep class java.util.function.DoubleToLongFunction {
+
+ public abstract long applyAsLong(double);
+
+
+}
+
+-keep class java.util.function.DoubleUnaryOperator {
+
+ public java.util.function.DoubleUnaryOperator andThen(java.util.function.DoubleUnaryOperator);
+ public abstract double applyAsDouble(double);
+ public java.util.function.DoubleUnaryOperator compose(java.util.function.DoubleUnaryOperator);
+ public static java.util.function.DoubleUnaryOperator identity();
+
+
+}
+
+-keep class java.util.function.Function {
+
+ public java.util.function.Function andThen(java.util.function.Function);
+ public abstract java.lang.Object apply(java.lang.Object);
+ public java.util.function.Function compose(java.util.function.Function);
+ public static java.util.function.Function identity();
+
+
+}
+
+-keep class java.util.function.IntBinaryOperator {
+
+ public abstract int applyAsInt(int, int);
+
+
+}
+
+-keep class java.util.function.IntConsumer {
+
+ public abstract void accept(int);
+ public java.util.function.IntConsumer andThen(java.util.function.IntConsumer);
+
+
+}
+
+-keep class java.util.function.IntFunction {
+
+ public abstract java.lang.Object apply(int);
+
+
+}
+
+-keep class java.util.function.IntPredicate {
+
+ public java.util.function.IntPredicate and(java.util.function.IntPredicate);
+ public java.util.function.IntPredicate negate();
+ public java.util.function.IntPredicate or(java.util.function.IntPredicate);
+ public abstract boolean test(int);
+
+
+}
+
+-keep class java.util.function.IntSupplier {
+
+ public abstract int getAsInt();
+
+
+}
+
+-keep class java.util.function.IntToDoubleFunction {
+
+ public abstract double applyAsDouble(int);
+
+
+}
+
+-keep class java.util.function.IntToLongFunction {
+
+ public abstract long applyAsLong(int);
+
+
+}
+
+-keep class java.util.function.IntUnaryOperator {
+
+ public java.util.function.IntUnaryOperator andThen(java.util.function.IntUnaryOperator);
+ public abstract int applyAsInt(int);
+ public java.util.function.IntUnaryOperator compose(java.util.function.IntUnaryOperator);
+ public static java.util.function.IntUnaryOperator identity();
+
+
+}
+
+-keep class java.util.function.LongBinaryOperator {
+
+ public abstract long applyAsLong(long, long);
+
+
+}
+
+-keep class java.util.function.LongConsumer {
+
+ public abstract void accept(long);
+ public java.util.function.LongConsumer andThen(java.util.function.LongConsumer);
+
+
+}
+
+-keep class java.util.function.LongFunction {
+
+ public abstract java.lang.Object apply(long);
+
+
+}
+
+-keep class java.util.function.LongPredicate {
+
+ public java.util.function.LongPredicate and(java.util.function.LongPredicate);
+ public java.util.function.LongPredicate negate();
+ public java.util.function.LongPredicate or(java.util.function.LongPredicate);
+ public abstract boolean test(long);
+
+
+}
+
+-keep class java.util.function.LongSupplier {
+
+ public abstract long getAsLong();
+
+
+}
+
+-keep class java.util.function.LongToDoubleFunction {
+
+ public abstract double applyAsDouble(long);
+
+
+}
+
+-keep class java.util.function.LongToIntFunction {
+
+ public abstract int applyAsInt(long);
+
+
+}
+
+-keep class java.util.function.LongUnaryOperator {
+
+ public java.util.function.LongUnaryOperator andThen(java.util.function.LongUnaryOperator);
+ public abstract long applyAsLong(long);
+ public java.util.function.LongUnaryOperator compose(java.util.function.LongUnaryOperator);
+ public static java.util.function.LongUnaryOperator identity();
+
+
+}
+
+-keep class java.util.function.ObjDoubleConsumer {
+
+ public abstract void accept(java.lang.Object, double);
+
+
+}
+
+-keep class java.util.function.ObjIntConsumer {
+
+ public abstract void accept(java.lang.Object, int);
+
+
+}
+
+-keep class java.util.function.ObjLongConsumer {
+
+ public abstract void accept(java.lang.Object, long);
+
+
+}
+
+-keep class java.util.function.Predicate {
+
+ public java.util.function.Predicate and(java.util.function.Predicate);
+ public static java.util.function.Predicate isEqual(java.lang.Object);
+ public java.util.function.Predicate negate();
+ public java.util.function.Predicate or(java.util.function.Predicate);
+ public abstract boolean test(java.lang.Object);
+
+
+}
+
+-keep class java.util.function.Supplier {
+
+ public abstract java.lang.Object get();
+
+
+}
+
+-keep class java.util.function.ToDoubleFunction {
+
+ public abstract double applyAsDouble(java.lang.Object);
+
+
+}
+
+-keep class java.util.function.ToIntFunction {
+
+ public abstract int applyAsInt(java.lang.Object);
+
+
+}
+
+-keep class java.util.function.ToLongFunction {
+
+ public abstract long applyAsLong(java.lang.Object);
+
+
+}
+
+-keep class java.util.function.UnaryOperator {
+
+ public static java.util.function.UnaryOperator identity();
+
+
+}
+
+-keep class java.util.stream.BaseStream {
+
+ public abstract void close();
+ public abstract boolean isParallel();
+ public abstract java.util.Iterator iterator();
+ public abstract java.util.stream.BaseStream onClose(java.lang.Runnable);
+ public abstract java.util.stream.BaseStream parallel();
+ public abstract java.util.stream.BaseStream sequential();
+ public abstract java.util.Spliterator spliterator();
+ public abstract java.util.stream.BaseStream unordered();
+
+
+}
+
+-keep class java.util.stream.Collector {
+
+ public abstract java.util.function.BiConsumer accumulator();
+ public abstract java.util.Set characteristics();
+ public abstract java.util.function.BinaryOperator combiner();
+ public abstract java.util.function.Function finisher();
+ public static java.util.stream.Collector of(java.util.function.Supplier, java.util.function.BiConsumer, java.util.function.BinaryOperator, java.util.stream.Collector$Characteristics[]);
+ public static java.util.stream.Collector of(java.util.function.Supplier, java.util.function.BiConsumer, java.util.function.BinaryOperator, java.util.function.Function, java.util.stream.Collector$Characteristics[]);
+ public abstract java.util.function.Supplier supplier();
+
+
+}
+
+-keep class java.util.stream.Collector$Characteristics {
+
+ public static java.util.stream.Collector$Characteristics valueOf(java.lang.String);
+ public static java.util.stream.Collector$Characteristics[] values();
+
+ public static java.util.stream.Collector$Characteristics CONCURRENT;
+ public static java.util.stream.Collector$Characteristics IDENTITY_FINISH;
+ public static java.util.stream.Collector$Characteristics UNORDERED;
+
+}
+
+-keep class java.util.stream.DoubleStream {
+
+ public abstract boolean allMatch(java.util.function.DoublePredicate);
+ public abstract boolean anyMatch(java.util.function.DoublePredicate);
+ public abstract java.util.OptionalDouble average();
+ public abstract java.util.stream.Stream boxed();
+ public static java.util.stream.DoubleStream$Builder builder();
+ public abstract java.lang.Object collect(java.util.function.Supplier, java.util.function.ObjDoubleConsumer, java.util.function.BiConsumer);
+ public static java.util.stream.DoubleStream concat(java.util.stream.DoubleStream, java.util.stream.DoubleStream);
+ public abstract long count();
+ public abstract java.util.stream.DoubleStream distinct();
+ public static java.util.stream.DoubleStream empty();
+ public abstract java.util.stream.DoubleStream filter(java.util.function.DoublePredicate);
+ public abstract java.util.OptionalDouble findAny();
+ public abstract java.util.OptionalDouble findFirst();
+ public abstract java.util.stream.DoubleStream flatMap(java.util.function.DoubleFunction);
+ public abstract void forEach(java.util.function.DoubleConsumer);
+ public abstract void forEachOrdered(java.util.function.DoubleConsumer);
+ public static java.util.stream.DoubleStream generate(java.util.function.DoubleSupplier);
+ public static java.util.stream.DoubleStream iterate(double, java.util.function.DoubleUnaryOperator);
+ public abstract java.util.PrimitiveIterator$OfDouble iterator();
+ public java.util.Iterator iterator();
+ public abstract java.util.stream.DoubleStream limit(long);
+ public abstract java.util.stream.DoubleStream map(java.util.function.DoubleUnaryOperator);
+ public abstract java.util.stream.IntStream mapToInt(java.util.function.DoubleToIntFunction);
+ public abstract java.util.stream.LongStream mapToLong(java.util.function.DoubleToLongFunction);
+ public abstract java.util.stream.Stream mapToObj(java.util.function.DoubleFunction);
+ public abstract java.util.OptionalDouble max();
+ public abstract java.util.OptionalDouble min();
+ public abstract boolean noneMatch(java.util.function.DoublePredicate);
+ public static java.util.stream.DoubleStream of(double);
+ public static java.util.stream.DoubleStream of(double[]);
+ public abstract java.util.stream.DoubleStream parallel();
+ public java.util.stream.BaseStream parallel();
+ public abstract java.util.stream.DoubleStream peek(java.util.function.DoubleConsumer);
+ public abstract double reduce(double, java.util.function.DoubleBinaryOperator);
+ public abstract java.util.OptionalDouble reduce(java.util.function.DoubleBinaryOperator);
+ public abstract java.util.stream.DoubleStream sequential();
+ public java.util.stream.BaseStream sequential();
+ public abstract java.util.stream.DoubleStream skip(long);
+ public abstract java.util.stream.DoubleStream sorted();
+ public abstract java.util.Spliterator$OfDouble spliterator();
+ public java.util.Spliterator spliterator();
+ public abstract double sum();
+ public abstract java.util.DoubleSummaryStatistics summaryStatistics();
+ public abstract double[] toArray();
+
+
+}
+
+-keep class java.util.stream.DoubleStream$Builder {
+
+ public abstract void accept(double);
+ public java.util.stream.DoubleStream$Builder add(double);
+ public abstract java.util.stream.DoubleStream build();
+
+
+}
+
+-keep class java.util.stream.IntStream {
+
+ public abstract boolean allMatch(java.util.function.IntPredicate);
+ public abstract boolean anyMatch(java.util.function.IntPredicate);
+ public abstract java.util.stream.DoubleStream asDoubleStream();
+ public abstract java.util.stream.LongStream asLongStream();
+ public abstract java.util.OptionalDouble average();
+ public abstract java.util.stream.Stream boxed();
+ public static java.util.stream.IntStream$Builder builder();
+ public abstract java.lang.Object collect(java.util.function.Supplier, java.util.function.ObjIntConsumer, java.util.function.BiConsumer);
+ public static java.util.stream.IntStream concat(java.util.stream.IntStream, java.util.stream.IntStream);
+ public abstract long count();
+ public abstract java.util.stream.IntStream distinct();
+ public static java.util.stream.IntStream empty();
+ public abstract java.util.stream.IntStream filter(java.util.function.IntPredicate);
+ public abstract java.util.OptionalInt findAny();
+ public abstract java.util.OptionalInt findFirst();
+ public abstract java.util.stream.IntStream flatMap(java.util.function.IntFunction);
+ public abstract void forEach(java.util.function.IntConsumer);
+ public abstract void forEachOrdered(java.util.function.IntConsumer);
+ public static java.util.stream.IntStream generate(java.util.function.IntSupplier);
+ public static java.util.stream.IntStream iterate(int, java.util.function.IntUnaryOperator);
+ public abstract java.util.PrimitiveIterator$OfInt iterator();
+ public java.util.Iterator iterator();
+ public abstract java.util.stream.IntStream limit(long);
+ public abstract java.util.stream.IntStream map(java.util.function.IntUnaryOperator);
+ public abstract java.util.stream.DoubleStream mapToDouble(java.util.function.IntToDoubleFunction);
+ public abstract java.util.stream.LongStream mapToLong(java.util.function.IntToLongFunction);
+ public abstract java.util.stream.Stream mapToObj(java.util.function.IntFunction);
+ public abstract java.util.OptionalInt max();
+ public abstract java.util.OptionalInt min();
+ public abstract boolean noneMatch(java.util.function.IntPredicate);
+ public static java.util.stream.IntStream of(int);
+ public static java.util.stream.IntStream of(int[]);
+ public abstract java.util.stream.IntStream parallel();
+ public java.util.stream.BaseStream parallel();
+ public abstract java.util.stream.IntStream peek(java.util.function.IntConsumer);
+ public static java.util.stream.IntStream range(int, int);
+ public static java.util.stream.IntStream rangeClosed(int, int);
+ public abstract int reduce(int, java.util.function.IntBinaryOperator);
+ public abstract java.util.OptionalInt reduce(java.util.function.IntBinaryOperator);
+ public abstract java.util.stream.IntStream sequential();
+ public java.util.stream.BaseStream sequential();
+ public abstract java.util.stream.IntStream skip(long);
+ public abstract java.util.stream.IntStream sorted();
+ public abstract java.util.Spliterator$OfInt spliterator();
+ public java.util.Spliterator spliterator();
+ public abstract int sum();
+ public abstract java.util.IntSummaryStatistics summaryStatistics();
+ public abstract int[] toArray();
+
+
+}
+
+-keep class java.util.stream.IntStream$Builder {
+
+ public abstract void accept(int);
+ public java.util.stream.IntStream$Builder add(int);
+ public abstract java.util.stream.IntStream build();
+
+
+}
+
+-keep class java.util.stream.LongStream {
+
+ public abstract boolean allMatch(java.util.function.LongPredicate);
+ public abstract boolean anyMatch(java.util.function.LongPredicate);
+ public abstract java.util.stream.DoubleStream asDoubleStream();
+ public abstract java.util.OptionalDouble average();
+ public abstract java.util.stream.Stream boxed();
+ public static java.util.stream.LongStream$Builder builder();
+ public abstract java.lang.Object collect(java.util.function.Supplier, java.util.function.ObjLongConsumer, java.util.function.BiConsumer);
+ public static java.util.stream.LongStream concat(java.util.stream.LongStream, java.util.stream.LongStream);
+ public abstract long count();
+ public abstract java.util.stream.LongStream distinct();
+ public static java.util.stream.LongStream empty();
+ public abstract java.util.stream.LongStream filter(java.util.function.LongPredicate);
+ public abstract java.util.OptionalLong findAny();
+ public abstract java.util.OptionalLong findFirst();
+ public abstract java.util.stream.LongStream flatMap(java.util.function.LongFunction);
+ public abstract void forEach(java.util.function.LongConsumer);
+ public abstract void forEachOrdered(java.util.function.LongConsumer);
+ public static java.util.stream.LongStream generate(java.util.function.LongSupplier);
+ public static java.util.stream.LongStream iterate(long, java.util.function.LongUnaryOperator);
+ public abstract java.util.PrimitiveIterator$OfLong iterator();
+ public java.util.Iterator iterator();
+ public abstract java.util.stream.LongStream limit(long);
+ public abstract java.util.stream.LongStream map(java.util.function.LongUnaryOperator);
+ public abstract java.util.stream.DoubleStream mapToDouble(java.util.function.LongToDoubleFunction);
+ public abstract java.util.stream.IntStream mapToInt(java.util.function.LongToIntFunction);
+ public abstract java.util.stream.Stream mapToObj(java.util.function.LongFunction);
+ public abstract java.util.OptionalLong max();
+ public abstract java.util.OptionalLong min();
+ public abstract boolean noneMatch(java.util.function.LongPredicate);
+ public static java.util.stream.LongStream of(long);
+ public static java.util.stream.LongStream of(long[]);
+ public abstract java.util.stream.LongStream parallel();
+ public java.util.stream.BaseStream parallel();
+ public abstract java.util.stream.LongStream peek(java.util.function.LongConsumer);
+ public static java.util.stream.LongStream range(long, long);
+ public static java.util.stream.LongStream rangeClosed(long, long);
+ public abstract long reduce(long, java.util.function.LongBinaryOperator);
+ public abstract java.util.OptionalLong reduce(java.util.function.LongBinaryOperator);
+ public abstract java.util.stream.LongStream sequential();
+ public java.util.stream.BaseStream sequential();
+ public abstract java.util.stream.LongStream skip(long);
+ public abstract java.util.stream.LongStream sorted();
+ public abstract java.util.Spliterator$OfLong spliterator();
+ public java.util.Spliterator spliterator();
+ public abstract long sum();
+ public abstract java.util.LongSummaryStatistics summaryStatistics();
+ public abstract long[] toArray();
+
+
+}
+
+-keep class java.util.stream.LongStream$Builder {
+
+ public abstract void accept(long);
+ public java.util.stream.LongStream$Builder add(long);
+ public abstract java.util.stream.LongStream build();
+
+
+}
+
+-keep class java.util.stream.Stream {
+
+ public abstract boolean allMatch(java.util.function.Predicate);
+ public abstract boolean anyMatch(java.util.function.Predicate);
+ public static java.util.stream.Stream$Builder builder();
+ public abstract java.lang.Object collect(java.util.function.Supplier, java.util.function.BiConsumer, java.util.function.BiConsumer);
+ public abstract java.lang.Object collect(java.util.stream.Collector);
+ public static java.util.stream.Stream concat(java.util.stream.Stream, java.util.stream.Stream);
+ public abstract long count();
+ public abstract java.util.stream.Stream distinct();
+ public static java.util.stream.Stream empty();
+ public abstract java.util.stream.Stream filter(java.util.function.Predicate);
+ public abstract java.util.Optional findAny();
+ public abstract java.util.Optional findFirst();
+ public abstract java.util.stream.Stream flatMap(java.util.function.Function);
+ public abstract java.util.stream.DoubleStream flatMapToDouble(java.util.function.Function);
+ public abstract java.util.stream.IntStream flatMapToInt(java.util.function.Function);
+ public abstract java.util.stream.LongStream flatMapToLong(java.util.function.Function);
+ public abstract void forEach(java.util.function.Consumer);
+ public abstract void forEachOrdered(java.util.function.Consumer);
+ public static java.util.stream.Stream generate(java.util.function.Supplier);
+ public static java.util.stream.Stream iterate(java.lang.Object, java.util.function.UnaryOperator);
+ public abstract java.util.stream.Stream limit(long);
+ public abstract java.util.stream.Stream map(java.util.function.Function);
+ public abstract java.util.stream.DoubleStream mapToDouble(java.util.function.ToDoubleFunction);
+ public abstract java.util.stream.IntStream mapToInt(java.util.function.ToIntFunction);
+ public abstract java.util.stream.LongStream mapToLong(java.util.function.ToLongFunction);
+ public abstract java.util.Optional max(java.util.Comparator);
+ public abstract java.util.Optional min(java.util.Comparator);
+ public abstract boolean noneMatch(java.util.function.Predicate);
+ public static java.util.stream.Stream of(java.lang.Object);
+ public static java.util.stream.Stream of(java.lang.Object[]);
+ public abstract java.util.stream.Stream peek(java.util.function.Consumer);
+ public abstract java.lang.Object reduce(java.lang.Object, java.util.function.BinaryOperator);
+ public abstract java.util.Optional reduce(java.util.function.BinaryOperator);
+ public abstract java.lang.Object reduce(java.lang.Object, java.util.function.BiFunction, java.util.function.BinaryOperator);
+ public abstract java.util.stream.Stream skip(long);
+ public abstract java.util.stream.Stream sorted();
+ public abstract java.util.stream.Stream sorted(java.util.Comparator);
+ public abstract java.lang.Object[] toArray();
+ public abstract java.lang.Object[] toArray(java.util.function.IntFunction);
+
+
+}
+
+-keep class java.util.stream.Stream$Builder {
+
+ public abstract void accept(java.lang.Object);
+ public java.util.stream.Stream$Builder add(java.lang.Object);
+ public abstract java.util.stream.Stream build();
+
+
+}
+
+-keep class javax.microedition.khronos.opengles.GL {
+
+
+
+}
+
+-keep class javax.security.auth.Subject {
+ <init>();
+ <init>(boolean, java.util.Set, java.util.Set, java.util.Set);
+
+ public static java.lang.Object doAs(javax.security.auth.Subject, java.security.PrivilegedAction);
+ public static java.lang.Object doAs(javax.security.auth.Subject, java.security.PrivilegedExceptionAction);
+ public static java.lang.Object doAsPrivileged(javax.security.auth.Subject, java.security.PrivilegedAction, java.security.AccessControlContext);
+ public static java.lang.Object doAsPrivileged(javax.security.auth.Subject, java.security.PrivilegedExceptionAction, java.security.AccessControlContext);
+ public boolean equals(java.lang.Object);
+ public java.util.Set getPrincipals();
+ public java.util.Set getPrincipals(java.lang.Class);
+ public java.util.Set getPrivateCredentials();
+ public java.util.Set getPrivateCredentials(java.lang.Class);
+ public java.util.Set getPublicCredentials();
+ public java.util.Set getPublicCredentials(java.lang.Class);
+ public static javax.security.auth.Subject getSubject(java.security.AccessControlContext);
+ public int hashCode();
+ public boolean isReadOnly();
+ public void setReadOnly();
+ public java.lang.String toString();
+
+
+}
+
+-keep class libcore.util.NativeAllocationRegistry {
+ <init>(java.lang.ClassLoader, long, long);
+
+ public static void applyFreeFunction(long, long);
+ public java.lang.Runnable registerNativeAllocation(java.lang.Object, long);
+ public java.lang.Runnable registerNativeAllocation(java.lang.Object, libcore.util.NativeAllocationRegistry$Allocator);
+
+
+}
+
+-keep class libcore.util.NativeAllocationRegistry$Allocator {
+
+ public abstract long allocate();
}
@@ -9932,3 +31372,10 @@
}
+-keep class sun.nio.ch.Interruptible {
+
+ public abstract void interrupt(java.lang.Thread);
+
+
+}
+
diff --git a/car-support-lib/src/android/support/car/Car.java b/car-support-lib/src/android/support/car/Car.java
index a374d87..c12b13c 100644
--- a/car-support-lib/src/android/support/car/Car.java
+++ b/car-support-lib/src/android/support/car/Car.java
@@ -19,14 +19,16 @@
import android.content.Context;
import android.os.Handler;
import android.os.Looper;
-import android.support.annotation.IntDef;
-import android.support.annotation.NonNull;
-import android.support.annotation.Nullable;
import android.support.car.content.pm.CarPackageManager;
import android.support.car.hardware.CarSensorManager;
import android.support.car.media.CarAudioManager;
import android.support.car.navigation.CarNavigationStatusManager;
import android.util.Log;
+
+import androidx.annotation.IntDef;
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.reflect.Constructor;
@@ -168,10 +170,10 @@
*/
public static final String PERMISSION_MILEAGE = "android.car.permission.CAR_MILEAGE";
/**
- * Permission necessary to access car fuel level.
+ * Permission necessary to access car's energy information.
* @hide
*/
- public static final String PERMISSION_FUEL = "android.car.permission.CAR_FUEL";
+ public static final String PERMISSION_ENERGY = "android.car.permission.CAR_ENERGY";
/**
* Permission necessary to access car speed.
* @hide
@@ -237,6 +239,7 @@
if (mConnectionState == STATE_DISCONNECTED) {
return;
}
+ tearDownCarManagers();
mConnectionState = STATE_DISCONNECTED;
}
mCarConnectionCallback.onDisconnected(Car.this);
diff --git a/car-support-lib/src/android/support/car/CarAppFocusManager.java b/car-support-lib/src/android/support/car/CarAppFocusManager.java
index c33265c..395ff61 100644
--- a/car-support-lib/src/android/support/car/CarAppFocusManager.java
+++ b/car-support-lib/src/android/support/car/CarAppFocusManager.java
@@ -16,7 +16,7 @@
package android.support.car;
-import android.support.annotation.IntDef;
+import androidx.annotation.IntDef;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
diff --git a/car-support-lib/src/android/support/car/CarInfoManager.java b/car-support-lib/src/android/support/car/CarInfoManager.java
index 8b05436..7a29339 100644
--- a/car-support-lib/src/android/support/car/CarInfoManager.java
+++ b/car-support-lib/src/android/support/car/CarInfoManager.java
@@ -16,8 +16,9 @@
package android.support.car;
-import android.support.annotation.IntDef;
-import android.support.annotation.Nullable;
+import androidx.annotation.IntDef;
+import androidx.annotation.Nullable;
+
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
@@ -101,4 +102,30 @@
* @return {@link #DRIVER_SIDE_UNKNOWN} if information is not available.
*/
public abstract @DriverSide int getDriverPosition() throws CarNotConnectedException;
+
+ /**
+ * Return fuel capacity of the car in milliliters.
+ * @return 0 if car doesn't run on fuel.
+ */
+ public abstract float getFuelCapacity() throws CarNotConnectedException;
+
+ /**
+ * Return array of fuel types available in the car, defined in
+ * android.hardware.automotive.vehicle.V2_0.FuelType
+ * @return empty array if no fuel types available.
+ */
+ public abstract int[] getFuelTypes() throws CarNotConnectedException;
+
+ /**
+ * Return battery capacity of the car in WH.
+ * @return 0 if car doesn't run on battery.
+ */
+ public abstract float getEvBatteryCapacity() throws CarNotConnectedException;
+
+ /**
+ * Return array of EV connector types available in the car, defined in
+ * android.hardware.automotive.vehicle.V2_0.EvConnectorType
+ * @return empty array if no connector types available.
+ */
+ public abstract int[] getEvConnectorTypes() throws CarNotConnectedException;
}
diff --git a/car-support-lib/src/android/support/car/CarInfoManagerEmbedded.java b/car-support-lib/src/android/support/car/CarInfoManagerEmbedded.java
index ddb893d..0d41053 100644
--- a/car-support-lib/src/android/support/car/CarInfoManagerEmbedded.java
+++ b/car-support-lib/src/android/support/car/CarInfoManagerEmbedded.java
@@ -88,6 +88,42 @@
return CarInfoManager.DRIVER_SIDE_UNKNOWN; // N/A
}
+ @Override
+ public float getFuelCapacity() throws CarNotConnectedException {
+ try {
+ return mManager.getFuelCapacity();
+ } catch (android.car.CarNotConnectedException e) {
+ throw new CarNotConnectedException(e);
+ }
+ }
+
+ @Override
+ public int[] getFuelTypes() throws CarNotConnectedException {
+ try {
+ return mManager.getFuelTypes();
+ } catch (android.car.CarNotConnectedException e) {
+ throw new CarNotConnectedException(e);
+ }
+ }
+
+ @Override
+ public float getEvBatteryCapacity() throws CarNotConnectedException {
+ try {
+ return mManager.getEvBatteryCapacity();
+ } catch (android.car.CarNotConnectedException e) {
+ throw new CarNotConnectedException(e);
+ }
+ }
+
+ @Override
+ public int[] getEvConnectorTypes() throws CarNotConnectedException {
+ try {
+ return mManager.getEvConnectorTypes();
+ } catch (android.car.CarNotConnectedException e) {
+ throw new CarNotConnectedException(e);
+ }
+ }
+
/** @hide */
@Override
public void onCarDisconnected() {
diff --git a/car-support-lib/src/android/support/car/CarServiceLoaderEmbedded.java b/car-support-lib/src/android/support/car/CarServiceLoaderEmbedded.java
index 3a21b1e..cfd598a 100644
--- a/car-support-lib/src/android/support/car/CarServiceLoaderEmbedded.java
+++ b/car-support-lib/src/android/support/car/CarServiceLoaderEmbedded.java
@@ -22,7 +22,6 @@
import android.os.Handler;
import android.os.IBinder;
import android.support.car.content.pm.CarPackageManagerEmbedded;
-import android.support.car.hardware.CarSensorManagerEmbedded;
import android.support.car.media.CarAudioManagerEmbedded;
import android.support.car.navigation.CarNavigationStatusManagerEmbedded;
@@ -92,8 +91,6 @@
switch (serviceName) {
case Car.AUDIO_SERVICE:
return new CarAudioManagerEmbedded(manager);
- case Car.SENSOR_SERVICE:
- return new CarSensorManagerEmbedded(manager, getContext());
case Car.INFO_SERVICE:
return new CarInfoManagerEmbedded(manager);
case Car.APP_FOCUS_SERVICE:
diff --git a/car-support-lib/src/android/support/car/content/pm/CarPackageManagerEmbedded.java b/car-support-lib/src/android/support/car/content/pm/CarPackageManagerEmbedded.java
index 6bce420..e6f1b67 100644
--- a/car-support-lib/src/android/support/car/content/pm/CarPackageManagerEmbedded.java
+++ b/car-support-lib/src/android/support/car/content/pm/CarPackageManagerEmbedded.java
@@ -38,7 +38,7 @@
public boolean isActivityAllowedWhileDriving(String packageName, String className)
throws CarNotConnectedException {
try {
- return mManager.isActivityAllowedWhileDriving(packageName, className);
+ return mManager.isActivityDistractionOptimized(packageName, className);
} catch (android.car.CarNotConnectedException e) {
throw new CarNotConnectedException(e);
}
@@ -48,7 +48,7 @@
public boolean isServiceAllowedWhileDriving(String packageName, String className)
throws CarNotConnectedException {
try {
- return mManager.isServiceAllowedWhileDriving(packageName, className);
+ return mManager.isServiceDistractionOptimized(packageName, className);
} catch (android.car.CarNotConnectedException e) {
throw new CarNotConnectedException(e);
}
diff --git a/car-support-lib/src/android/support/car/hardware/CarSensorConfig.java b/car-support-lib/src/android/support/car/hardware/CarSensorConfig.java
index 3c71e04..b39d205 100644
--- a/car-support-lib/src/android/support/car/hardware/CarSensorConfig.java
+++ b/car-support-lib/src/android/support/car/hardware/CarSensorConfig.java
@@ -16,11 +16,11 @@
package android.support.car.hardware;
-import android.os.Bundle;
-import android.support.annotation.RestrictTo;
-import java.util.ArrayList;
+import static androidx.annotation.RestrictTo.Scope.GROUP_ID;
-import static android.support.annotation.RestrictTo.Scope.GROUP_ID;
+import android.os.Bundle;
+
+import androidx.annotation.RestrictTo;
/**
* A CarSensorConfig object corresponds to a single sensor type coming from the car.
@@ -30,7 +30,7 @@
/** List of property specific mapped elements in bundle for WHEEL_TICK_DISTANCE sensor*/
/** @hide */
public final static String WHEEL_TICK_DISTANCE_SUPPORTED_WHEELS =
- "android.car.wheelTickDistanceSupportedWhheels";
+ "android.car.wheelTickDistanceSupportedWheels";
/** @hide */
public final static String WHEEL_TICK_DISTANCE_FRONT_LEFT_UM_PER_TICK =
"android.car.wheelTickDistanceFrontLeftUmPerTick";
diff --git a/car-support-lib/src/android/support/car/hardware/CarSensorEvent.java b/car-support-lib/src/android/support/car/hardware/CarSensorEvent.java
index f7b4dba..7b1bf1a 100644
--- a/car-support-lib/src/android/support/car/hardware/CarSensorEvent.java
+++ b/car-support-lib/src/android/support/car/hardware/CarSensorEvent.java
@@ -16,12 +16,14 @@
package android.support.car.hardware;
+import static androidx.annotation.RestrictTo.Scope.GROUP_ID;
+
+import android.car.VehicleOilLevel;
import android.location.GpsSatellite;
import android.location.Location;
import android.os.SystemClock;
-import android.support.annotation.RestrictTo;
-import static android.support.annotation.RestrictTo.Scope.GROUP_ID;
+import androidx.annotation.RestrictTo;
/**
* A CarSensorEvent object corresponds to a single sensor event coming from the car. Sensor
@@ -374,25 +376,6 @@
/**
- * Index in {@link #floatValues} for {@link CarSensorManager#SENSOR_TYPE_FUEL_LEVEL} type of
- * sensor. This value is fuel level in percentile.
- * @hide
- */
- public static final int INDEX_FUEL_LEVEL_IN_PERCENTILE = 0;
- /**
- * Index in {@link #floatValues} for {@link CarSensorManager#SENSOR_TYPE_FUEL_LEVEL} type of
- * sensor. This value is fuel level in coverable distance. The unit is Km.
- * @hide
- */
- public static final int INDEX_FUEL_LEVEL_IN_DISTANCE = 1;
- /**
- * Index in {@link #intValues} for {@link CarSensorManager#SENSOR_TYPE_FUEL_LEVEL} type of
- * sensor. This value is set to 1 if fuel low level warning is on.
- * @hide
- */
- public static final int INDEX_FUEL_LOW_WARNING = 0;
-
- /**
* GEAR_* represents meaning of intValues[0] for {@link CarSensorManager#SENSOR_TYPE_GEAR}
* sensor type.
* GEAR_NEUTRAL means transmission gear is in neutral state, and the car may be moving.
@@ -450,7 +433,7 @@
* Both byte values and float values are used.
* Two first bytes encode number of satellites in-use/in-view (or 0xFF if unavailable).
* Then optionally with INDEX_GPS_SATELLITE_ARRAY_BYTE_OFFSET offset and interval
- * INDEX_GPS_SATELLITE_ARRAY_BYTE_INTERVAL between elements are encoded boolean flags of
+ * INDEX_GPS_SATELLITE_ARRAY_BYTE_INTERVAL between elements are encoded boolean flags of
* whether particular satellite from in-view participate in in-use subset.
* Float values with INDEX_GPS_SATELLITE_ARRAY_FLOAT_OFFSET offset and interval
* INDEX_GPS_SATELLITE_ARRAY_FLOAT_INTERVAL between elements can optionally contain
@@ -590,20 +573,14 @@
public static class FuelLevelData {
/** The time in nanoseconds since system boot. */
public final long timestamp;
- /** Fuel level in %. If unsupported by the car, this value is -1. */
- public final int level;
- /** Fuel as possible range in Km. If unsupported by the car, this value is -1. */
- public final float range;
- /** If unsupported by the car, this value is false. */
- public final boolean lowFuelWarning;
+ /** Fuel level in milliliters. If unsupported by the car, this value is -1. */
+ public final float level;
/** @hide */
@RestrictTo(GROUP_ID)
- public FuelLevelData(long timestamp, int level, float range, boolean lowFuelWarning) {
+ public FuelLevelData(long timestamp, float level) {
this.timestamp = timestamp;
this.level = level;
- this.range = range;
- this.lowFuelWarning = lowFuelWarning;
}
}
@@ -616,19 +593,13 @@
*/
public FuelLevelData getFuelLevelData() {
checkType(CarSensorManager.SENSOR_TYPE_FUEL_LEVEL);
- int level = -1;
- float range = -1;
+ float level = -1.0f;
if (floatValues != null) {
- if (floatValues[INDEX_FUEL_LEVEL_IN_PERCENTILE] >= 0) {
- level = (int) floatValues[INDEX_FUEL_LEVEL_IN_PERCENTILE];
- }
-
- if (floatValues[INDEX_FUEL_LEVEL_IN_DISTANCE] >= 0) {
- range = floatValues[INDEX_FUEL_LEVEL_IN_DISTANCE];
+ if (floatValues[0] >= 0) {
+ level = floatValues[0];
}
}
- boolean lowFuelWarning = (intValues[0] == 1);
- return new FuelLevelData(timestamp, level, range, lowFuelWarning);
+ return new FuelLevelData(timestamp, level);
}
/** @hide */
@@ -894,7 +865,7 @@
/**
* Convenience method for obtaining a {@link GpsSatelliteData} object from a CarSensorEvent
- * object with type {@link CarSensorManager#SENSOR_TYPE_GPS_SATELLITE} with optional
+ * object with type {@link CarSensorManager#SENSOR_TYPE_GPS_SATELLITE} with optional
* per-satellite info.
*
* @param withPerSatellite whether to include per-satellite data.
@@ -997,8 +968,6 @@
* Convenience method for obtaining a {@link CarAbsActiveData} object from a CarSensorEvent
* object with type {@link CarSensorManager#SENSOR_TYPE_ABS_ACTIVE}.
*
- * @param data an optional output parameter which, if non-null, will be used by this method
- * instead of a newly created object.
* @return a CarAbsActiveData object corresponding to data contained in the CarSensorEvent.
* @hide
*/
@@ -1025,8 +994,6 @@
* Convenience method for obtaining a {@link CarTractionControlActiveData} object from a
* CarSensorEvent object with type {@link CarSensorManager#SENSOR_TYPE_TRACTION_CONTROL_ACTIVE}.
*
- * @param data an optional output parameter which, if non-null, will be used by this method
- * instead of a newly created object.
* @return a CarTractionControlActiveData object corresponding to data contained in the
* CarSensorEvent.
* @hide
@@ -1038,6 +1005,179 @@
}
/** @hide */
+ public static class CarFuelDoorOpenData {
+ public final long timestamp;
+ public final boolean fuelDoorIsOpen;
+
+ /** @hide */
+ @RestrictTo(GROUP_ID)
+ public CarFuelDoorOpenData(long timestamp, boolean fuelDoorIsOpen) {
+ this.timestamp = timestamp;
+ this.fuelDoorIsOpen = fuelDoorIsOpen;
+ };
+ }
+
+ /**
+ * Convenience method for obtaining a {@link CarFuelDoorOpenData} object from a
+ * CarSensorEvent object with type {@link CarSensorManager#SENSOR_TYPE_FUEL_DOOR_OPEN}.
+ *
+ * @return a CarFuelDoorOpenData object corresponding to data contained in the
+ * CarSensorEvent.
+ * @hide
+ */
+ public CarFuelDoorOpenData getCarFuelDoorOpenData() {
+ checkType(CarSensorManager.SENSOR_TYPE_FUEL_DOOR_OPEN);
+ boolean fuelDoorIsOpen = intValues[0] == 1;
+ return new CarFuelDoorOpenData(timestamp, fuelDoorIsOpen);
+ }
+
+ /** @hide */
+ public static class CarEvBatteryLevelData {
+ public final long timestamp;
+ public final float evBatteryLevel;
+
+ /** @hide */
+ @RestrictTo(GROUP_ID)
+ public CarEvBatteryLevelData(long timestamp, float evBatteryLevel) {
+ this.timestamp = timestamp;
+ this.evBatteryLevel = evBatteryLevel;
+ };
+ }
+
+ /**
+ * Convenience method for obtaining a {@link CarEvBatteryLevelData} object from a
+ * CarSensorEvent object with type {@link CarSensorManager#SENSOR_TYPE_EV_BATTERY_LEVEL}.
+ *
+ * @return a CarEvBatteryLevelData object corresponding to data contained in the
+ * CarSensorEvent.
+ * @hide
+ */
+ public CarEvBatteryLevelData getCarEvBatteryLevelData() {
+ checkType(CarSensorManager.SENSOR_TYPE_EV_BATTERY_LEVEL);
+ float evBatteryLevel = -1.0f;
+ if (floatValues != null) {
+ if (floatValues[0] >= 0) {
+ evBatteryLevel = floatValues[0];
+ }
+ }
+ return new CarEvBatteryLevelData(timestamp, evBatteryLevel);
+ }
+
+ /** @hide */
+ public static class CarEvChargePortOpenData {
+ public final long timestamp;
+ public final boolean evChargePortIsOpen;
+
+ /** @hide */
+ @RestrictTo(GROUP_ID)
+ public CarEvChargePortOpenData(long timestamp, boolean evChargePortIsOpen) {
+ this.timestamp = timestamp;
+ this.evChargePortIsOpen = evChargePortIsOpen;
+ };
+ }
+
+ /**
+ * Convenience method for obtaining a {@link CarEvChargePortOpenData} object from a
+ * CarSensorEvent object with type {@link CarSensorManager#SENSOR_TYPE_EV_CHARGE_PORT_OPEN}.
+ *
+ * @return a CarEvChargePortOpenData object corresponding to data contained in the
+ * CarSensorEvent.
+ * @hide
+ */
+ public CarEvChargePortOpenData getCarEvChargePortOpenData() {
+ checkType(CarSensorManager.SENSOR_TYPE_EV_CHARGE_PORT_OPEN);
+ boolean evChargePortIsOpen = intValues[0] == 1;
+ return new CarEvChargePortOpenData(timestamp, evChargePortIsOpen);
+ }
+
+ /** @hide */
+ public static class CarEvChargePortConnectedData {
+ public final long timestamp;
+ public final boolean evChargePortIsConnected;
+
+ /** @hide */
+ @RestrictTo(GROUP_ID)
+ public CarEvChargePortConnectedData(long timestamp, boolean evChargePortIsConnected) {
+ this.timestamp = timestamp;
+ this.evChargePortIsConnected = evChargePortIsConnected;
+ };
+ }
+
+ /**
+ * Convenience method for obtaining a {@link CarEvChargePortConnectedData} object from a
+ * CarSensorEvent object with type {@link CarSensorManager#SENSOR_TYPE_EV_CHARGE_PORT_CONNECTED}.
+ *
+ * @return a CarEvChargePortConnectedData object corresponding to data contained in the
+ * CarSensorEvent.
+ * @hide
+ */
+ public CarEvChargePortConnectedData getCarEvChargePortConnectedData() {
+ checkType(CarSensorManager.SENSOR_TYPE_EV_CHARGE_PORT_CONNECTED);
+ boolean evChargePortIsConnected = intValues[0] == 1;
+ return new CarEvChargePortConnectedData(timestamp, evChargePortIsConnected);
+ }
+
+ /** @hide */
+ public static class CarEvBatteryChargeRateData {
+ public final long timestamp;
+ public final float evChargeRate;
+
+ /** @hide */
+ @RestrictTo(GROUP_ID)
+ public CarEvBatteryChargeRateData(long timestamp, float evChargeRate) {
+ this.timestamp = timestamp;
+ this.evChargeRate = evChargeRate;
+ };
+ }
+
+ /**
+ * Convenience method for obtaining a {@link CarEvBatteryChargeRateData} object from a
+ * CarSensorEvent object with type {@link CarSensorManager#SENSOR_TYPE_EV_BATTERY_CHARGE_RATE}.
+ *
+ * @return a CarEvBatteryChargeRateData object corresponding to data contained in the
+ * CarSensorEvent.
+ * @hide
+ */
+ public CarEvBatteryChargeRateData getCarEvBatteryChargeRateData() {
+ checkType(CarSensorManager.SENSOR_TYPE_EV_BATTERY_CHARGE_RATE);
+ float evChargeRate = 0;
+ if (floatValues != null) {
+ evChargeRate = floatValues[0];
+ }
+ return new CarEvBatteryChargeRateData(timestamp, evChargeRate);
+ }
+
+ /** @hide */
+ public static class CarEngineOilLevelData {
+ public final long timestamp;
+ public final int engineOilLevel;
+
+ /** @hide */
+ @RestrictTo(GROUP_ID)
+ public CarEngineOilLevelData(long timestamp, int engineOilLevel) {
+ this.timestamp = timestamp;
+ this.engineOilLevel = engineOilLevel;
+ };
+ }
+
+ /**
+ * Convenience method for obtaining a {@link CarEngineOilLevelData} object from a
+ * CarSensorEvent object with type {@link CarSensorManager#SENSOR_TYPE_ENGINE_OIL_LEVEL}.
+ *
+ * @return a CarEngineOilLevelData object corresponding to data contained in the
+ * CarSensorEvent.
+ * @hide
+ */
+ public CarEngineOilLevelData getCarEngineOilLevelData() {
+ checkType(CarSensorManager.SENSOR_TYPE_ENGINE_OIL_LEVEL);
+ int engineOilLevel = VehicleOilLevel.ERROR;
+ if (intValues != null) {
+ engineOilLevel = intValues[0];
+ }
+ return new CarEngineOilLevelData(timestamp, engineOilLevel);
+ }
+
+ /** @hide */
@Override
public String toString() {
StringBuilder sb = new StringBuilder();
diff --git a/car-support-lib/src/android/support/car/hardware/CarSensorManager.java b/car-support-lib/src/android/support/car/hardware/CarSensorManager.java
index 8bddce1..29d6f40 100644
--- a/car-support-lib/src/android/support/car/hardware/CarSensorManager.java
+++ b/car-support-lib/src/android/support/car/hardware/CarSensorManager.java
@@ -17,12 +17,13 @@
package android.support.car.hardware;
import android.Manifest;
-import android.support.annotation.IntDef;
-import android.support.annotation.RequiresPermission;
import android.support.car.Car;
import android.support.car.CarManagerBase;
import android.support.car.CarNotConnectedException;
+import androidx.annotation.IntDef;
+import androidx.annotation.RequiresPermission;
+
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
@@ -57,12 +58,8 @@
*/
public static final int SENSOR_TYPE_ODOMETER = 4;
/**
- * Represent the fuel level of the car. In {@link CarSensorEvent}, floatValues[{@link
- * CarSensorEvent#INDEX_FUEL_LEVEL_IN_PERCENTILE}] represents fuel level in percentile (0 to
- * 100) while floatValues[{@link CarSensorEvent#INDEX_FUEL_LEVEL_IN_DISTANCE}] represents
- * estimated range in kilometers with the remaining fuel. The gas mileage used for the
- * estimation may not represent the current driving condition. Requires {@link
- * Car#PERMISSION_FUEL} permission.
+ * Represent the fuel level of the car. In {@link CarSensorEvent}, represents fuel level in
+ * milliliters. Requires {@link Car#PERMISSION_ENERGY} permission.
* @hide
*/
public static final int SENSOR_TYPE_FUEL_LEVEL = 5;
@@ -141,6 +138,37 @@
* Requires {@link Car#PERMISSION_VEHICLE_DYNAMICS_STATE} permission.
*/
public static final int SENSOR_TYPE_TRACTION_CONTROL_ACTIVE = 25;
+ /** @hide */
+ public static final int SENSOR_TYPE_RESERVED26 = 26;
+ /**
+ * Set to true if the fuel door is open.
+ */
+ public static final int SENSOR_TYPE_FUEL_DOOR_OPEN = 27;
+
+ /**
+ * Indicates battery level of the car.
+ * In {@link CarSensorEvent}, represents battery level in WH.
+ * This requires {@link Car#PERMISSION_ENERGY} permission.
+ */
+ public static final int SENSOR_TYPE_EV_BATTERY_LEVEL = 28;
+ /**
+ * Set to true if EV charging port is open.
+ */
+ public static final int SENSOR_TYPE_EV_CHARGE_PORT_OPEN = 29;
+ /**
+ * Set to true if EV charging port is connected.
+ */
+ public static final int SENSOR_TYPE_EV_CHARGE_PORT_CONNECTED = 30;
+ /**
+ * Indicates the instantaneous battery charging rate in mW.
+ * This requires {@link Car#PERMISSION_ENERGY} permission.
+ */
+ public static final int SENSOR_TYPE_EV_BATTERY_CHARGE_RATE = 31;
+ /**
+ * Oil level sensor.
+ * @hide
+ */
+ public static final int SENSOR_TYPE_ENGINE_OIL_LEVEL = 32;
/**
* Sensors defined in this range [{@link #SENSOR_TYPE_VENDOR_EXTENSION_START},
@@ -175,19 +203,25 @@
SENSOR_TYPE_GYROSCOPE,
SENSOR_TYPE_WHEEL_TICK_DISTANCE,
SENSOR_TYPE_ABS_ACTIVE,
- SENSOR_TYPE_TRACTION_CONTROL_ACTIVE
+ SENSOR_TYPE_TRACTION_CONTROL_ACTIVE,
+ SENSOR_TYPE_FUEL_DOOR_OPEN,
+ SENSOR_TYPE_EV_BATTERY_LEVEL,
+ SENSOR_TYPE_EV_CHARGE_PORT_OPEN,
+ SENSOR_TYPE_EV_CHARGE_PORT_CONNECTED,
+ SENSOR_TYPE_EV_BATTERY_CHARGE_RATE,
+ SENSOR_TYPE_ENGINE_OIL_LEVEL,
})
@Retention(RetentionPolicy.SOURCE)
public @interface SensorType {}
/** Read sensor at the default normal rate set for each sensors. This is default rate. */
- public static final int SENSOR_RATE_NORMAL = 3;
+ public static final int SENSOR_RATE_NORMAL = 1;
/**@hide*/
- public static final int SENSOR_RATE_UI = 2;
+ public static final int SENSOR_RATE_UI = 5;
/**@hide*/
- public static final int SENSOR_RATE_FAST = 1;
+ public static final int SENSOR_RATE_FAST = 10;
/** Read sensor at the maximum rate. Actual rate will be different depending on the sensor. */
- public static final int SENSOR_RATE_FASTEST = 0;
+ public static final int SENSOR_RATE_FASTEST = 100;
/** @hide */
@IntDef({
@@ -250,7 +284,7 @@
* @throws SecurityException if missing the appropriate permission.
*/
@RequiresPermission(anyOf={Manifest.permission.ACCESS_FINE_LOCATION, Car.PERMISSION_SPEED,
- Car.PERMISSION_MILEAGE, Car.PERMISSION_FUEL, Car.PERMISSION_VEHICLE_DYNAMICS_STATE},
+ Car.PERMISSION_MILEAGE, Car.PERMISSION_ENERGY, Car.PERMISSION_VEHICLE_DYNAMICS_STATE},
conditional=true)
public abstract boolean addListener(OnSensorChangedListener listener,
@SensorType int sensorType, @SensorRate int rate)
diff --git a/car-support-lib/src/android/support/car/hardware/CarSensorManagerEmbedded.java b/car-support-lib/src/android/support/car/hardware/CarSensorManagerEmbedded.java
index 0fde10f..a8d8d28 100644
--- a/car-support-lib/src/android/support/car/hardware/CarSensorManagerEmbedded.java
+++ b/car-support-lib/src/android/support/car/hardware/CarSensorManagerEmbedded.java
@@ -16,16 +16,18 @@
package android.support.car.hardware;
+import static androidx.annotation.RestrictTo.Scope.GROUP_ID;
+
import android.content.Context;
-import android.support.annotation.RestrictTo;
import android.support.car.CarNotConnectedException;
+
+import androidx.annotation.RestrictTo;
+
import java.util.Collection;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.Set;
-import static android.support.annotation.RestrictTo.Scope.GROUP_ID;
-
/**
* @hide
*/
diff --git a/car-support-lib/src/android/support/car/hardware/CarSensorsProxy.java b/car-support-lib/src/android/support/car/hardware/CarSensorsProxy.java
index e110d07..69feb84 100644
--- a/car-support-lib/src/android/support/car/hardware/CarSensorsProxy.java
+++ b/car-support-lib/src/android/support/car/hardware/CarSensorsProxy.java
@@ -379,7 +379,7 @@
}
int present = 0;
present |= (0x1 << CarSensorEvent.INDEX_LOCATION_LONGITUDE);
- event.intValues[CarSensorEvent.INDEX_LOCATION_LATITUDE_INTS] =
+ event.intValues[CarSensorEvent.INDEX_LOCATION_LONGITUDE_INTS] =
(int) (location.getLongitude() * 1E7);
present |= (0x1 << CarSensorEvent.INDEX_LOCATION_LATITUDE);
diff --git a/car-support-lib/src/android/support/car/media/CarAudioManager.java b/car-support-lib/src/android/support/car/media/CarAudioManager.java
index 822ddbf..e3b783a 100644
--- a/car-support-lib/src/android/support/car/media/CarAudioManager.java
+++ b/car-support-lib/src/android/support/car/media/CarAudioManager.java
@@ -16,17 +16,12 @@
package android.support.car.media;
import android.Manifest;
-import android.media.AudioAttributes;
import android.media.AudioFormat;
import android.media.AudioManager;
-import android.media.AudioManager.OnAudioFocusChangeListener;
-import android.support.annotation.IntDef;
-import android.support.annotation.RequiresPermission;
import android.support.car.CarManagerBase;
import android.support.car.CarNotConnectedException;
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
+import androidx.annotation.RequiresPermission;
/**
* APIs for handling car-specific audio use cases. Provides a set of CAR_AUDIO_USAGE_* constants
@@ -37,105 +32,6 @@
public abstract class CarAudioManager implements CarManagerBase {
/**
- * Audio usage for unspecified type.
- */
- public static final int CAR_AUDIO_USAGE_DEFAULT = 0;
- /**
- * Audio usage for playing music.
- */
- public static final int CAR_AUDIO_USAGE_MUSIC = 1;
- /**
- * Audio usage for hardware radio.
- * @hide
- */
- public static final int CAR_AUDIO_USAGE_RADIO = 2;
- /**
- * Audio usage for playing navigation guidance.
- */
- public static final int CAR_AUDIO_USAGE_NAVIGATION_GUIDANCE = 3;
- /**
- * Audio usage for voice call.
- */
- public static final int CAR_AUDIO_USAGE_VOICE_CALL = 4;
- /**
- * Audio usage for voice search or voice command.
- */
- public static final int CAR_AUDIO_USAGE_VOICE_COMMAND = 5;
- /**
- * Audio usage for playing alarm.
- */
- public static final int CAR_AUDIO_USAGE_ALARM = 6;
- /**
- * Audio usage for notification sound.
- */
- public static final int CAR_AUDIO_USAGE_NOTIFICATION = 7;
- /**
- * Audio usage for system sound (such as UI feedback).
- */
- public static final int CAR_AUDIO_USAGE_SYSTEM_SOUND = 8;
- /**
- * Audio usage for playing safety alerts.
- */
- public static final int CAR_AUDIO_USAGE_SYSTEM_SAFETY_ALERT = 9;
-
- /** @hide */
- public static final int CAR_AUDIO_USAGE_MAX = CAR_AUDIO_USAGE_SYSTEM_SAFETY_ALERT;
-
- /** @hide */
- @IntDef({CAR_AUDIO_USAGE_DEFAULT, CAR_AUDIO_USAGE_MUSIC, CAR_AUDIO_USAGE_RADIO,
- CAR_AUDIO_USAGE_NAVIGATION_GUIDANCE, CAR_AUDIO_USAGE_VOICE_CALL,
- CAR_AUDIO_USAGE_VOICE_COMMAND, CAR_AUDIO_USAGE_ALARM, CAR_AUDIO_USAGE_NOTIFICATION,
- CAR_AUDIO_USAGE_SYSTEM_SOUND, CAR_AUDIO_USAGE_SYSTEM_SAFETY_ALERT})
- @Retention(RetentionPolicy.SOURCE)
- public @interface CarAudioUsage {}
-
- /**
- * Return {@link AudioAttributes} relevant for the given usage in car.
- */
- public abstract AudioAttributes getAudioAttributesForCarUsage(@CarAudioUsage int carUsage)
- throws CarNotConnectedException;
-
- /**
- * Request audio focus. Send a request to obtain audio focus.
- *
- * @param listener The listener to be notified of audio focus changes.
- * @param requestAttributes Obtained from {@link #getAudioAttributesForCarUsage(int)}.
- * @param durationHint Use {@link AudioManager#AUDIOFOCUS_GAIN_TRANSIENT} to indicate this
- * focus request is temporary and focus will be abandoned shortly. Examples of transient
- * requests include playback of driving directions and notification sounds.
- * </p>
- * Use {@link AudioManager#AUDIOFOCUS_GAIN_TRANSIENT_MAY_DUCK} to indicate it's OK for the
- * previous focus owner to keep playing if it ducks its audio output.
- * </p>
- * Use {@link AudioManager#AUDIOFOCUS_GAIN_TRANSIENT_EXCLUSIVE} for a temporary request that
- * benefits from the system not playing disruptive sounds such as notifications, for use cases
- * such as voice memo recording, or speech recognition.
- * </p>
- * Use {@link AudioManager#AUDIOFOCUS_GAIN} for a focus request of unknown duration, such as
- * the playback of a song or a video.
- * @return {@link AudioManager#AUDIOFOCUS_REQUEST_FAILED}, or
- * {@link AudioManager#AUDIOFOCUS_REQUEST_GRANTED}.
- * @throws IllegalArgumentException
- */
- public abstract int requestAudioFocus(OnAudioFocusChangeListener listener,
- AudioAttributes requestAttributes,
- int durationHint) throws CarNotConnectedException, IllegalArgumentException;
-
- /**
- * @hide
- */
- public abstract int requestAudioFocus(OnAudioFocusChangeListener listener,
- AudioAttributes requestAttributes,
- int durationHint,
- int flags) throws CarNotConnectedException, IllegalArgumentException;
- /**
- * Abandon audio focus. Causes the previous focus owner (if any) to receive focus.
- * @param listener The listener with which focus was requested.
- * @param aa
- */
- public abstract void abandonAudioFocus(OnAudioFocusChangeListener listener, AudioAttributes aa);
-
- /**
* Get {@link AudioFormat} for audio record.
* @return {@link AudioFormat} for audio record.
*/
@@ -175,26 +71,4 @@
@RequiresPermission(Manifest.permission.RECORD_AUDIO)
public abstract CarAudioRecord createCarAudioRecord(int bufferSize)
throws SecurityException, CarNotConnectedException;
-
- /**
- * Check if media audio is muted or not (includes music and radio). Any application
- * taking audio focus for media stream will move it out of a mute state.
- *
- * @return Returns {@code true} if media is muted.
- */
- public abstract boolean isMediaMuted() throws CarNotConnectedException;
-
- /**
- * Mute or unmute media stream including radio. Can involve audio focus change to stop
- * the the app currently holding audio focus. If requester is currently holding audio focus,
- * it gets LOSS_TRANSIENT focus loss. Requires
- * {@link android.support.car.Car#PERMISSION_CAR_CONTROL_AUDIO_VOLUME}
- * permission.
- *
- * @param mute Returns {@code true} if media stream should be muted.
- * @return Mute state of system after the request. A mute request can fail if a higher priority
- * audio stream (such as a voice call) is already being played.
- * @hide
- */
- public abstract boolean setMediaMute(boolean mute) throws CarNotConnectedException;
}
diff --git a/car-support-lib/src/android/support/car/media/CarAudioManagerEmbedded.java b/car-support-lib/src/android/support/car/media/CarAudioManagerEmbedded.java
index 2d172cd..518058a 100644
--- a/car-support-lib/src/android/support/car/media/CarAudioManagerEmbedded.java
+++ b/car-support-lib/src/android/support/car/media/CarAudioManagerEmbedded.java
@@ -15,14 +15,13 @@
*/
package android.support.car.media;
-import android.media.AudioAttributes;
+import static androidx.annotation.RestrictTo.Scope.GROUP_ID;
+
import android.media.AudioFormat;
-import android.media.AudioManager.OnAudioFocusChangeListener;
import android.media.AudioRecord;
-import android.support.annotation.RestrictTo;
import android.support.car.CarNotConnectedException;
-import static android.support.annotation.RestrictTo.Scope.GROUP_ID;
+import androidx.annotation.RestrictTo;
/**
* @hide
@@ -45,45 +44,6 @@
}
@Override
- public AudioAttributes getAudioAttributesForCarUsage(@CarAudioUsage int carUsage)
- throws CarNotConnectedException {
- try {
- return mManager.getAudioAttributesForCarUsage(carUsage);
- } catch (android.car.CarNotConnectedException e) {
- throw new CarNotConnectedException(e);
- }
- }
-
- @Override
- public int requestAudioFocus(OnAudioFocusChangeListener listener,
- AudioAttributes requestAttributes,
- int durationHint,
- int flags) throws CarNotConnectedException, IllegalArgumentException {
- try {
- return mManager.requestAudioFocus(listener, requestAttributes, durationHint, flags);
- } catch (android.car.CarNotConnectedException e) {
- throw new CarNotConnectedException(e);
- }
- }
-
- @Override
- public int requestAudioFocus(OnAudioFocusChangeListener listener,
- AudioAttributes requestAttributes,
- int durationHint) throws CarNotConnectedException, IllegalArgumentException {
- try {
- return mManager.requestAudioFocus(listener, requestAttributes, durationHint,
- 0 /*flags*/);
- } catch (android.car.CarNotConnectedException e) {
- throw new CarNotConnectedException(e);
- }
- }
-
- @Override
- public void abandonAudioFocus(OnAudioFocusChangeListener listener, AudioAttributes aa) {
- mManager.abandonAudioFocus(listener, aa);
- }
-
- @Override
public boolean isAudioRecordSupported() throws CarNotConnectedException {
//always true in embedded
return true;
@@ -116,24 +76,6 @@
}
@Override
- public boolean isMediaMuted() throws CarNotConnectedException {
- try {
- return mManager.isMediaMuted();
- } catch (android.car.CarNotConnectedException e) {
- throw new CarNotConnectedException(e);
- }
- }
-
- @Override
- public boolean setMediaMute(boolean mute) throws CarNotConnectedException {
- try {
- return mManager.setMediaMute(mute);
- } catch (android.car.CarNotConnectedException e) {
- throw new CarNotConnectedException(e);
- }
- }
-
- @Override
public void onCarDisconnected() {
//nothing to do
}
diff --git a/car-support-lib/src/android/support/car/media/CarAudioRecordEmbedded.java b/car-support-lib/src/android/support/car/media/CarAudioRecordEmbedded.java
index a85bb8f..7a614cc 100644
--- a/car-support-lib/src/android/support/car/media/CarAudioRecordEmbedded.java
+++ b/car-support-lib/src/android/support/car/media/CarAudioRecordEmbedded.java
@@ -15,12 +15,13 @@
*/
package android.support.car.media;
+import static androidx.annotation.RestrictTo.Scope.GROUP_ID;
+
import android.media.AudioFormat;
import android.media.AudioRecord;
-import android.support.annotation.RestrictTo;
import android.support.car.CarNotConnectedException;
-import static android.support.annotation.RestrictTo.Scope.GROUP_ID;
+import androidx.annotation.RestrictTo;
/**
* CarAudioRecordEmbedded allows apps to use microphone.
diff --git a/car-support-lib/src/android/support/car/navigation/CarNavigationInstrumentCluster.java b/car-support-lib/src/android/support/car/navigation/CarNavigationInstrumentCluster.java
index 9d2175c..9f70ef0 100644
--- a/car-support-lib/src/android/support/car/navigation/CarNavigationInstrumentCluster.java
+++ b/car-support-lib/src/android/support/car/navigation/CarNavigationInstrumentCluster.java
@@ -15,12 +15,14 @@
*/
package android.support.car.navigation;
-import static android.support.annotation.RestrictTo.Scope.GROUP_ID;
+import static androidx.annotation.RestrictTo.Scope.GROUP_ID;
import android.os.Bundle;
-import android.support.annotation.IntDef;
-import android.support.annotation.Nullable;
-import android.support.annotation.RestrictTo;
+
+import androidx.annotation.IntDef;
+import androidx.annotation.Nullable;
+import androidx.annotation.RestrictTo;
+
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
diff --git a/car-support-lib/src/android/support/car/navigation/CarNavigationStatusManager.java b/car-support-lib/src/android/support/car/navigation/CarNavigationStatusManager.java
index adf9208..3583827 100644
--- a/car-support-lib/src/android/support/car/navigation/CarNavigationStatusManager.java
+++ b/car-support-lib/src/android/support/car/navigation/CarNavigationStatusManager.java
@@ -15,11 +15,12 @@
*/
package android.support.car.navigation;
+import android.annotation.IntDef;
import android.graphics.Bitmap;
import android.os.Bundle;
-import android.support.annotation.IntDef;
import android.support.car.CarManagerBase;
import android.support.car.CarNotConnectedException;
+
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
@@ -70,121 +71,117 @@
}
/* Navigation statuses */
+ /** @hide */
public static final int STATUS_UNAVAILABLE = 0;
+ /** @hide */
public static final int STATUS_ACTIVE = 1;
+ /** @hide */
public static final int STATUS_INACTIVE = 2;
/** @hide */
@IntDef({
- STATUS_UNAVAILABLE,
- STATUS_ACTIVE,
- STATUS_INACTIVE
+ STATUS_UNAVAILABLE,
+ STATUS_ACTIVE,
+ STATUS_INACTIVE
})
@Retention(RetentionPolicy.SOURCE)
public @interface Status {}
/* Turn Types */
- /** Turn is of an unknown type.*/
+ /** @hide */
public static final int TURN_UNKNOWN = 0;
- /** Starting point of the navigation. */
+ /** @hide */
public static final int TURN_DEPART = 1;
- /** No turn, but the street name changes. */
+ /** @hide */
public static final int TURN_NAME_CHANGE = 2;
- /** Slight turn. */
+ /** @hide */
public static final int TURN_SLIGHT_TURN = 3;
- /** Regular turn. */
+ /** @hide */
public static final int TURN_TURN = 4;
- /** Sharp turn. */
+ /** @hide */
public static final int TURN_SHARP_TURN = 5;
- /** U-turn. */
+ /** @hide */
public static final int TURN_U_TURN = 6;
- /** On ramp. */
+ /** @hide */
public static final int TURN_ON_RAMP = 7;
- /** Off ramp. */
+ /** @hide */
public static final int TURN_OFF_RAMP = 8;
- /** Road forks (diverges). */
+ /** @hide */
public static final int TURN_FORK = 9;
- /** Road merges. */
+ /** @hide */
public static final int TURN_MERGE = 10;
- /** Roundabout entrance on which the route ends. Instruction says "Enter roundabout". */
+ /** @hide */
public static final int TURN_ROUNDABOUT_ENTER = 11;
- /** Roundabout exit. */
+ /** @hide */
public static final int TURN_ROUNDABOUT_EXIT = 12;
- /**
- * Roundabout entrance and exit. For example, "At the roundabout, take Nth exit." Be sure to
- * specify the "turnNumber" parameter when using this type.
- */
+ /** @hide */
public static final int TURN_ROUNDABOUT_ENTER_AND_EXIT = 13;
- /** Potentially confusing intersection where the user should steer straight. */
+ /** @hide */
public static final int TURN_STRAIGHT = 14;
- /** You're on a boat! */
+ /** @hide */
public static final int TURN_FERRY_BOAT = 16;
- /** Train ferries for vehicles. */
+ /** @hide */
public static final int TURN_FERRY_TRAIN = 17;
- /** You have arrived. */
+ /** @hide */
public static final int TURN_DESTINATION = 19;
/** @hide */
@IntDef({
- TURN_UNKNOWN,
- TURN_DEPART,
- TURN_NAME_CHANGE,
- TURN_SLIGHT_TURN,
- TURN_TURN,
- TURN_SHARP_TURN,
- TURN_U_TURN,
- TURN_ON_RAMP,
- TURN_OFF_RAMP,
- TURN_FORK,
- TURN_MERGE,
- TURN_ROUNDABOUT_ENTER,
- TURN_ROUNDABOUT_EXIT,
- TURN_ROUNDABOUT_ENTER_AND_EXIT,
- TURN_STRAIGHT,
- TURN_FERRY_BOAT,
- TURN_FERRY_TRAIN,
- TURN_DESTINATION
+ TURN_UNKNOWN,
+ TURN_DEPART,
+ TURN_NAME_CHANGE,
+ TURN_SLIGHT_TURN,
+ TURN_TURN,
+ TURN_SHARP_TURN,
+ TURN_U_TURN,
+ TURN_ON_RAMP,
+ TURN_OFF_RAMP,
+ TURN_FORK,
+ TURN_MERGE,
+ TURN_ROUNDABOUT_ENTER,
+ TURN_ROUNDABOUT_EXIT,
+ TURN_ROUNDABOUT_ENTER_AND_EXIT,
+ TURN_STRAIGHT,
+ TURN_FERRY_BOAT,
+ TURN_FERRY_TRAIN,
+ TURN_DESTINATION
})
@Retention(RetentionPolicy.SOURCE)
public @interface TurnEvent {}
- /* Turn Side */
- /** Turn is on the left side of the vehicle. */
+ /** @hide */
public static final int TURN_SIDE_LEFT = 1;
- /** Turn is on the right side of the vehicle. */
+ /** @hide */
public static final int TURN_SIDE_RIGHT = 2;
- /** Turn side is unspecified. */
+ /** @hide */
public static final int TURN_SIDE_UNSPECIFIED = 3;
/** @hide */
@IntDef({
- TURN_SIDE_LEFT,
- TURN_SIDE_RIGHT,
- TURN_SIDE_UNSPECIFIED
+ TURN_SIDE_LEFT,
+ TURN_SIDE_RIGHT,
+ TURN_SIDE_UNSPECIFIED
})
public @interface TurnSide {}
- /*
- * Distance units for use in {@link #sendNavigationTurnDistanceEvent(int, int, int, int)}.
- */
- /** Distance is specified in meters. */
+ /** @hide */
public static final int DISTANCE_METERS = 1;
- /** Distance is specified in kilometers. */
+ /** @hide */
public static final int DISTANCE_KILOMETERS = 2;
- /** Distance is specified in miles. */
+ /** @hide */
public static final int DISTANCE_MILES = 3;
- /** Distance is specified in feet. */
+ /** @hide */
public static final int DISTANCE_FEET = 4;
- /** Distance is specified in yards. */
+ /** @hide */
public static final int DISTANCE_YARDS = 5;
/** @hide */
@IntDef({
- DISTANCE_METERS,
- DISTANCE_KILOMETERS,
- DISTANCE_MILES,
- DISTANCE_FEET,
- DISTANCE_YARDS
+ DISTANCE_METERS,
+ DISTANCE_KILOMETERS,
+ DISTANCE_MILES,
+ DISTANCE_FEET,
+ DISTANCE_YARDS
})
public @interface DistanceUnit {}
@@ -211,7 +208,9 @@
* @throws CarNotConnectedException if the connection to the car service has been lost.
*
* @deprecated Use {@link #sendEvent(int, Bundle)} instead.
+ * @hide
*/
+ @Deprecated
public abstract void sendNavigationStatus(@Status int status) throws CarNotConnectedException;
/**
@@ -237,7 +236,9 @@
* @throws CarNotConnectedException if the connection to the car service has been lost.
*
* @deprecated Use {@link #sendEvent(int, Bundle)} instead.
+ * @hide
*/
+ @Deprecated
public abstract void sendNavigationTurnEvent(@TurnEvent int turnEvent, CharSequence eventName,
int turnAngle, int turnNumber, @TurnSide int turnSide) throws CarNotConnectedException;
@@ -254,9 +255,10 @@
* @hide only first party applications may send a custom image to the cluster.
* @deprecated Use {@link #sendEvent(int, Bundle)} instead.
*/
+ @Deprecated
public abstract void sendNavigationTurnEvent(@TurnEvent int turnEvent, CharSequence eventName,
int turnAngle, int turnNumber, Bitmap image, @TurnSide int turnSide)
- throws CarNotConnectedException;
+ throws CarNotConnectedException;
/**
* Send a Navigation Next Step Distance event to the car.
@@ -267,11 +269,13 @@
* the calling app, in milli-units. For example, 1.25 should be supplied as 1250.
* @param displayDistanceUnit Unit type to use on of the DISTANCE_* types defined in this
* file.
- * @return Returns {@code true} if successful.
+ * @returns {@code true} if successful.
* @throws CarNotConnectedException if the connection to the car service has been lost.
*
* @deprecated Use {@link #sendEvent(int, Bundle)} instead.
+ * @hide
*/
+ @Deprecated
public abstract void sendNavigationTurnDistanceEvent(int distanceMeters, int timeSeconds,
int displayDistanceMillis, int displayDistanceUnit) throws CarNotConnectedException;
@@ -279,16 +283,11 @@
* Sends events from navigation app to instrument cluster.
*
* @param eventType event type, the value could be either
- * {@link #EVENT_TYPE_NEXT_MANEUVER_INFO}, {@link EVENT_TYPE_NEXT_MANEUVER_COUNTDOWN}, or
+ * {@link #EVENT_TYPE_NEXT_MANEUVER_INFO}, {@link #EVENT_TYPE_NEXT_MANEUVER_COUNTDOWN}, or
* vendor-specific code.
*
* @param bundle object that holds data about the event
- * @throws android.car.CarNotConnectedException if the connection to the car service has been lost.
- *
- * @see #EVENT_TYPE_NEXT_MANEUVER_INFO
- * @see #EVENT_TYPE_NEXT_MANEUVER_COUNTDOWN
- *
- * @hide
+ * @throws CarNotConnectedException if the connection to the car service has been lost.
*/
public abstract void sendEvent(int eventType, Bundle bundle)
throws CarNotConnectedException;
diff --git a/car-support-lib/src/android/support/car/navigation/CarNavigationStatusManagerEmbedded.java b/car-support-lib/src/android/support/car/navigation/CarNavigationStatusManagerEmbedded.java
index a72e20e..4ab5ec6 100644
--- a/car-support-lib/src/android/support/car/navigation/CarNavigationStatusManagerEmbedded.java
+++ b/car-support-lib/src/android/support/car/navigation/CarNavigationStatusManagerEmbedded.java
@@ -36,39 +36,25 @@
*/
@Override
public void sendNavigationStatus(int status) throws CarNotConnectedException {
- try {
- mManager.sendNavigationStatus(status);
- } catch (android.car.CarNotConnectedException e) {
- throw new CarNotConnectedException(e);
- }
+ // Not implemented in embedded.
}
@Override
public void sendNavigationTurnEvent(int event, CharSequence eventName, int turnAngle,
int turnNumber, int turnSide) throws CarNotConnectedException {
- sendNavigationTurnEvent(event, eventName, turnAngle, turnNumber, null, turnSide);
+ // Not implemented in embedded.
}
@Override
public void sendNavigationTurnEvent(int event, CharSequence eventName, int turnAngle,
int turnNumber, Bitmap image, int turnSide) throws CarNotConnectedException {
- try {
- mManager.sendNavigationTurnEvent(event, eventName, turnAngle, turnNumber, image,
- turnSide);
- } catch (android.car.CarNotConnectedException e) {
- throw new CarNotConnectedException(e);
- }
+ // Not implemented in embedded.
}
@Override
public void sendNavigationTurnDistanceEvent(int distanceMeters, int timeSeconds,
int displayDistanceMillis, int displayDistanceUnit) throws CarNotConnectedException {
- try {
- mManager.sendNavigationTurnDistanceEvent(distanceMeters, timeSeconds,
- displayDistanceMillis, displayDistanceUnit);
- } catch (android.car.CarNotConnectedException e) {
- throw new CarNotConnectedException(e);
- }
+ // Not implemented in embedded.
}
@Override
diff --git a/car_product/build/car.mk b/car_product/build/car.mk
index 9984726..669e828 100644
--- a/car_product/build/car.mk
+++ b/car_product/build/car.mk
@@ -16,6 +16,9 @@
# Common make file for all car builds
+BOARD_PLAT_PUBLIC_SEPOLICY_DIR += packages/services/Car/car_product/sepolicy/public
+BOARD_PLAT_PRIVATE_SEPOLICY_DIR += packages/services/Car/car_product/sepolicy/private
+
PRODUCT_PACKAGES += \
Bluetooth \
OneTimeInitializer \
@@ -30,19 +33,27 @@
screenrecord
# This is for testing
+ifneq (,$(filter userdebug eng, $(TARGET_BUILD_VARIANT)))
PRODUCT_PACKAGES += \
+ DefaultStorageMonitoringCompanionApp \
EmbeddedKitchenSinkApp \
VmsPublisherClientSample \
VmsSubscriberClientSample \
android.car.cluster.loggingrenderer \
DirectRenderingClusterSample \
+ com.android.car.powertestservice \
+
+# SEPolicy for test apps / services
+BOARD_SEPOLICY_DIRS += packages/services/Car/car_product/sepolicy/test
+endif
PRODUCT_COPY_FILES := \
frameworks/av/media/libeffects/data/audio_effects.conf:system/etc/audio_effects.conf \
packages/services/Car/car_product/preloaded-classes-car:system/etc/preloaded-classes \
PRODUCT_PROPERTY_OVERRIDES += \
- ro.carrier=unknown
+ ro.carrier=unknown \
+ persist.bluetooth.enablenewavrcp=false
# Overlay for Google network and fused location providers
$(call inherit-product, device/sample/products/location_overlay.mk)
@@ -74,12 +85,12 @@
# Automotive specific packages
PRODUCT_PACKAGES += \
- vehicle_monitor_service \
CarService \
CarTrustAgentService \
CarDialerApp \
CarRadioApp \
OverviewApp \
+ CarLauncher \
CarLensPickerApp \
LocalMediaPlayer \
CarMediaApp \
@@ -87,9 +98,15 @@
CarHvacApp \
CarMapsPlaceholder \
CarLatinIME \
+ CarSettings \
CarUsbHandler \
android.car \
- libvehiclemonitor-native \
+ car-frameworks-service \
+ com.android.car.procfsinspector \
+ libcar-framework-service-jni \
+
+# System Server components
+PRODUCT_SYSTEM_SERVER_JARS += car-frameworks-service
# Boot animation
PRODUCT_COPY_FILES += \
diff --git a/car_product/build/car_base.mk b/car_product/build/car_base.mk
index 2971774..6788a49 100644
--- a/car_product/build/car_base.mk
+++ b/car_product/build/car_base.mk
@@ -56,11 +56,10 @@
# EVS resources
PRODUCT_PACKAGES += android.automotive.evs.manager@1.0
-PRODUCT_PACKAGES += evs_app
# The following packages, or their vendor specific equivalents should be include in the device.mk
+#PRODUCT_PACKAGES += evs_app
#PRODUCT_PACKAGES += evs_app_default_resources
#PRODUCT_PACKAGES += android.hardware.automotive.evs@1.0-service
-#PRODUCT_PACKAGES += android.hardware.automotive.evs@1.0-sample
# Device running Android is a car
PRODUCT_COPY_FILES += \
diff --git a/car_product/init/init.car.rc b/car_product/init/init.car.rc
index 8cec36e..1ca29ce 100644
--- a/car_product/init/init.car.rc
+++ b/car_product/init/init.car.rc
@@ -1,8 +1 @@
-service vms /system/bin/vehicle_monitor_service
- class core
- user root
- group root
- critical
-
-on boot
- start vms
+# Insert car-specific startup services here
diff --git a/car_product/overlay/frameworks/base/core/res/res/drawable/dialog_button_background.xml b/car_product/overlay/frameworks/base/core/res/res/drawable/dialog_button_background.xml
new file mode 100644
index 0000000..c7b4e06
--- /dev/null
+++ b/car_product/overlay/frameworks/base/core/res/res/drawable/dialog_button_background.xml
@@ -0,0 +1,22 @@
+<?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.
+ -->
+<ripple xmlns:android="http://schemas.android.com/apk/res/android"
+ android:color="@color/car_card_ripple_background">
+ <item android:id="@android:id/mask">
+ <color android:color="@color/car_white_1000" />
+ </item>
+</ripple>
\ No newline at end of file
diff --git a/car_product/overlay/frameworks/base/core/res/res/drawable/round_corner.xml b/car_product/overlay/frameworks/base/core/res/res/drawable/round_corner.xml
new file mode 100644
index 0000000..82909be
--- /dev/null
+++ b/car_product/overlay/frameworks/base/core/res/res/drawable/round_corner.xml
@@ -0,0 +1,29 @@
+<!--
+ ~ 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="rectangle">
+
+ <solid android:color="#fffafafa" />
+ <padding
+ android:bottom="16dp"
+ android:left="16dp"
+ android:right="16dp"
+ android:top="16dp" />
+ <corners android:topLeftRadius="16dp"
+ android:topRightRadius="16dp"/>
+
+</shape>
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
new file mode 100644
index 0000000..7203849
--- /dev/null
+++ b/car_product/overlay/frameworks/base/core/res/res/layout/alert_dialog_button_bar_material.xml
@@ -0,0 +1,64 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (C) 2014 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.
+-->
+
+<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
+ android:id="@+id/buttonPanel"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:scrollbarAlwaysDrawVerticalTrack="true"
+ android:scrollIndicators="top|bottom"
+ android:fillViewport="true"
+ style="?attr/buttonBarStyle">
+ <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:layoutDirection="locale"
+ android:orientation="horizontal"
+ android:gravity="center_vertical">
+
+ <Button
+ android:id="@+id/button3"
+ style="@style/CarAction1"
+ android:background="@drawable/dialog_button_background"
+ android:layout_width="wrap_content"
+ android:layout_height="@dimen/car_card_action_bar_height" />
+
+ <Button
+ android:id="@+id/button2"
+ style="@style/CarAction1"
+ android:background="@drawable/dialog_button_background"
+ android:layout_marginEnd="@dimen/car_padding_4"
+ android:layout_width="wrap_content"
+ android:layout_height="@dimen/car_card_action_bar_height" />
+
+ <Button
+ android:id="@+id/button1"
+ style="@style/CarAction1"
+ android:background="@drawable/dialog_button_background"
+ android:layout_marginStart="@dimen/car_padding_4"
+ android:layout_width="wrap_content"
+ android:layout_height="@dimen/car_card_action_bar_height" />
+ <Space
+ android:id="@+id/spacer"
+ android:layout_width="0dp"
+ android:layout_height="0dp"
+ android:visibility="invisible" />
+ </com.android.internal.widget.ButtonBarLayout>
+</ScrollView>
diff --git a/car_product/overlay/frameworks/base/core/res/res/layout/alert_dialog_material.xml b/car_product/overlay/frameworks/base/core/res/res/layout/alert_dialog_material.xml
new file mode 100644
index 0000000..a302a5d
--- /dev/null
+++ b/car_product/overlay/frameworks/base/core/res/res/layout/alert_dialog_material.xml
@@ -0,0 +1,86 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (C) 2014 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.internal.widget.AlertDialogLayout
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:id="@+id/parentPanel"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:gravity="start|top"
+ android:orientation="vertical">
+
+ <include layout="@layout/alert_dialog_title_material" />
+
+ <FrameLayout
+ android:id="@+id/contentPanel"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:minHeight="48dp">
+
+ <ScrollView
+ android:id="@+id/scrollView"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:clipToPadding="false">
+
+ <LinearLayout
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:orientation="vertical">
+
+ <!-- we don't need this spacer, but the id needs to be here for compatibility -->
+ <Space
+ android:id="@+id/textSpacerNoTitle"
+ android:visibility="gone"
+ android:layout_width="match_parent"
+ android:layout_height="0dp" />
+
+ <TextView
+ android:id="@+id/message"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_marginStart="@dimen/car_keyline_1"
+ android:layout_marginEnd="@dimen/car_keyline_1"
+ style="@style/CarBody2"/>
+
+ <!-- we don't need this spacer, but the id needs to be here for compatibility -->
+ <Space
+ android:id="@+id/textSpacerNoButtons"
+ android:visibility="gone"
+ android:layout_width="match_parent"
+ android:layout_height="0dp" />
+ </LinearLayout>
+ </ScrollView>
+ </FrameLayout>
+
+ <FrameLayout
+ android:id="@+id/customPanel"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:minHeight="48dp">
+
+ <FrameLayout
+ android:id="@+id/custom"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content" />
+ </FrameLayout>
+
+ <include
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ layout="@layout/alert_dialog_button_bar_material" />
+</com.android.internal.widget.AlertDialogLayout>
diff --git a/car_product/overlay/frameworks/base/core/res/res/layout/alert_dialog_title_material.xml b/car_product/overlay/frameworks/base/core/res/res/layout/alert_dialog_title_material.xml
new file mode 100644
index 0000000..0071d5c
--- /dev/null
+++ b/car_product/overlay/frameworks/base/core/res/res/layout/alert_dialog_title_material.xml
@@ -0,0 +1,62 @@
+<?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:id="@+id/topPanel"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:gravity="center_vertical"
+ android:orientation="vertical">
+
+ <!-- If the client uses a customTitle, it will be added here. -->
+
+ <RelativeLayout
+ android:id="@+id/title_template"
+ android:layout_width="match_parent"
+ android:layout_height="@dimen/car_card_header_height"
+ android:orientation="horizontal">
+
+ <ImageView
+ android:id="@+id/icon"
+ android:layout_width="@dimen/car_icon_size"
+ android:layout_height="@dimen/car_icon_size"
+ android:layout_marginStart="@dimen/car_keyline_1"
+ android:layout_alignParentStart="true"
+ android:layout_centerVertical="true"
+ android:scaleType="fitCenter"
+ android:src="@null" />
+
+ <com.android.internal.widget.DialogTitle
+ android:id="@+id/alertTitle"
+ android:maxLines="1"
+ android:ellipsize="none"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_toEndOf="@+id/icon"
+ android:textAlignment="viewStart"
+ android:layout_centerVertical="true"
+ android:layout_marginStart="@dimen/car_keyline_1"
+ android:layout_marginEnd="@dimen/car_keyline_1"
+ style="@style/CarTitle"/>
+ </RelativeLayout>
+
+ <Space
+ android:id="@+id/titleDividerNoCustom"
+ android:visibility="gone"
+ android:layout_width="match_parent"
+ android:layout_height="0dp" />
+</LinearLayout>
diff --git a/car_product/overlay/frameworks/base/core/res/res/values-h1752dp/dimens.xml b/car_product/overlay/frameworks/base/core/res/res/values-h1752dp/dimens.xml
new file mode 100644
index 0000000..f975711
--- /dev/null
+++ b/car_product/overlay/frameworks/base/core/res/res/values-h1752dp/dimens.xml
@@ -0,0 +1,35 @@
+<?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>
+ <!-- Text size for car -->
+ <dimen name="car_title2_size">32sp</dimen>
+ <dimen name="car_body1_size">32sp</dimen>
+ <dimen name="car_body2_size">26sp</dimen>
+ <dimen name="car_action1_size">26sp</dimen>
+
+ <!-- Common icon size for car app -->
+ <dimen name="car_icon_size">44dp</dimen>
+
+ <dimen name="car_card_header_height">76dp</dimen>
+ <dimen name="car_card_action_bar_height">76dp</dimen>
+
+ <!-- Keylines for content. -->
+ <dimen name="car_keyline_1">48dp</dimen>
+ <dimen name="car_keyline_2">108dp</dimen>
+ <dimen name="car_keyline_3">152dp</dimen>
+ <dimen name="car_keyline_4">182dp</dimen>
+</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
new file mode 100644
index 0000000..d1af884
--- /dev/null
+++ b/car_product/overlay/frameworks/base/core/res/res/values-sw900dp/dimens.xml
@@ -0,0 +1,27 @@
+<?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-w1280dp/dimens.xml b/car_product/overlay/frameworks/base/core/res/res/values-w1280dp/dimens.xml
new file mode 100644
index 0000000..2e2f851
--- /dev/null
+++ b/car_product/overlay/frameworks/base/core/res/res/values-w1280dp/dimens.xml
@@ -0,0 +1,22 @@
+<?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>
+ <dimen name="car_keyline_1">32dp</dimen>
+ <dimen name="car_keyline_2">108dp</dimen>
+ <dimen name="car_keyline_3">128dp</dimen>
+ <dimen name="car_keyline_4">168dp</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
new file mode 100644
index 0000000..dcb92dc
--- /dev/null
+++ b/car_product/overlay/frameworks/base/core/res/res/values-w1920dp/dimens.xml
@@ -0,0 +1,20 @@
+<?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>
+ <dimen name="status_bar_height">56dp</dimen>
+ <dimen name="car_keyline_4">184dp</dimen>
+</resources>
diff --git a/car_product/overlay/frameworks/base/packages/SystemUI/res/drawable/remote_input_bg.xml b/car_product/overlay/frameworks/base/core/res/res/values-w690dp/dimens.xml
similarity index 67%
copy from car_product/overlay/frameworks/base/packages/SystemUI/res/drawable/remote_input_bg.xml
copy to car_product/overlay/frameworks/base/core/res/res/values-w690dp/dimens.xml
index 3120679..ce66163 100644
--- a/car_product/overlay/frameworks/base/packages/SystemUI/res/drawable/remote_input_bg.xml
+++ b/car_product/overlay/frameworks/base/core/res/res/values-w690dp/dimens.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2016 The Android Open Source Project
+<!-- 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.
@@ -13,9 +13,9 @@
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="#ff6c6c6c" />
- <corners
- android:bottomRightRadius="16dp"
- android:bottomLeftRadius="16dp"/>
-</shape>
+<resources>
+ <dimen name="car_keyline_1">24dp</dimen>
+ <dimen name="car_keyline_2">96dp</dimen>
+ <dimen name="car_keyline_3">112dp</dimen>
+ <dimen name="car_keyline_4">148dp</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 1efd0eb..37dc0bf 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
@@ -38,4 +38,150 @@
<!-- The default color for text in a notification. This color is also the default color for
icons. -->
<color name="notification_default_color">@color/notification_primary_text_color_light</color>
+
+ <!-- Keep in sync with //frameworks/support/car/res/values/colors.xml -->
+ <color name="car_grey_50">#fffafafa</color>
+ <color name="car_grey_100">#fff5f5f5</color>
+ <color name="car_grey_200">#ffeeeeee</color>
+ <color name="car_grey_300">#ffe0e0e0</color>
+ <color name="car_grey_400">#ffbdbdbd</color>
+ <color name="car_grey_500">#ff9e9e9e</color>
+ <color name="car_grey_600">#ff757575</color>
+ <color name="car_grey_650">#ff6B6B6B</color>
+ <color name="car_grey_700">#ff616161</color>
+ <color name="car_grey_800">#ff424242</color>
+ <color name="car_grey_900">#ff212121</color>
+ <color name="car_grey_1000">#cc000000</color>
+ <color name="car_white_1000">#1effffff</color>
+ <color name="car_blue_grey_800">#ff37474F</color>
+ <color name="car_blue_grey_900">#ff263238</color>
+ <color name="car_dark_blue_grey_600">#ff1d272d</color>
+ <color name="car_dark_blue_grey_700">#ff172026</color>
+ <color name="car_dark_blue_grey_800">#ff11181d</color>
+ <color name="car_dark_blue_grey_900">#ff0c1013</color>
+ <color name="car_dark_blue_grey_1000">#ff090c0f</color>
+ <color name="car_light_blue_300">#ff4fc3f7</color>
+ <color name="car_light_blue_500">#ff03A9F4</color>
+ <color name="car_light_blue_600">#ff039be5</color>
+ <color name="car_light_blue_700">#ff0288d1</color>
+ <color name="car_light_blue_800">#ff0277bd</color>
+ <color name="car_light_blue_900">#ff01579b</color>
+ <color name="car_blue_300">#ff91a7ff</color>
+ <color name="car_blue_500">#ff5677fc</color>
+ <color name="car_green_500">#ff0f9d58</color>
+ <color name="car_green_700">#ff0b8043</color>
+ <color name="car_yellow_500">#fff4b400</color>
+ <color name="car_yellow_800">#ffee8100</color>
+ <color name="car_red_400">#ffe06055</color>
+ <color name="car_red_500">#ffdb4437</color>
+ <color name="car_red_500a">#ffd50000</color>
+ <color name="car_red_700">#ffc53929</color>
+ <color name="car_teal_200">#ff80cbc4</color>
+ <color name="car_teal_700">#ff00796b</color>
+ <color name="car_indigo_800">#ff283593</color>
+
+ <!-- Various colors for text sizes. "Light" and "dark" here refer to the lighter or darker
+ shades. -->
+ <color name="car_title_light">@color/car_grey_100</color>
+ <color name="car_title_dark">@color/car_grey_900</color>
+ <color name="car_title">@color/car_title_dark</color>
+
+ <color name="car_title2_light">@color/car_grey_100</color>
+ <color name="car_title2_dark">@color/car_grey_900</color>
+ <color name="car_title2">@color/car_title2_dark</color>
+
+ <color name="car_headline1_light">@color/car_grey_100</color>
+ <color name="car_headline1_dark">@color/car_grey_800</color>
+ <color name="car_headline1">@color/car_headline1_dark</color>
+
+ <color name="car_headline2_light">@color/car_grey_100</color>
+ <color name="car_headline2_dark">@color/car_grey_900</color>
+ <color name="car_headline2">@color/car_headline2_dark</color>
+
+ <color name="car_headline3_light">@android:color/white</color>
+ <color name="car_headline3_dark">@color/car_grey_900</color>
+ <color name="car_headline3">@color/car_headline3_dark</color>
+
+ <color name="car_headline4_light">@android:color/white</color>
+ <color name="car_headline4_dark">@android:color/black</color>
+ <color name="car_headline4">@color/car_headline4_dark</color>
+
+ <color name="car_body1_light">@color/car_grey_100</color>
+ <color name="car_body1_dark">@color/car_grey_900</color>
+ <color name="car_body1">@color/car_body1_dark</color>
+
+ <color name="car_body2_light">@color/car_grey_300</color>
+ <color name="car_body2_dark">@color/car_grey_650</color>
+ <color name="car_body2">@color/car_body2_dark</color>
+
+ <color name="car_body3_light">@android:color/white</color>
+ <color name="car_body3_dark">@android:color/black</color>
+ <color name="car_body3">@color/car_body3_dark</color>
+
+ <color name="car_body4_light">@android:color/white</color>
+ <color name="car_body4_dark">@android:color/black</color>
+ <color name="car_body4">@color/car_body4_dark</color>
+
+ <color name="car_action1_light">@color/car_grey_900</color>
+ <color name="car_action1_dark">@color/car_grey_50</color>
+ <color name="car_action1">@color/car_action1_dark</color>
+
+ <!-- The tinting colors to create a light- and dark-colored icon respectively. -->
+ <color name="car_tint_light">@color/car_grey_50</color>
+ <color name="car_tint_dark">@color/car_grey_900</color>
+
+ <!-- The tinting color for an icon. This icon is assumed to be on a light background. -->
+ <color name="car_tint">@color/car_tint_dark</color>
+
+ <!-- An inverted tinting from car_tint. -->
+ <color name="car_tint_inverse">@color/car_tint_light</color>
+
+ <!-- The color of the divider. The color here is a lighter shade. -->
+ <color name="car_list_divider_light">#1fffffff</color>
+
+ <!-- The color of the divider. The color here is a darker shade. -->
+ <color name="car_list_divider_dark">#1f000000</color>
+
+ <!-- The color of the dividers in the list. This color is assumed to be on a light colored
+ view. -->
+ <color name="car_list_divider">@color/car_list_divider_dark</color>
+
+ <!-- A light and dark colored card. -->
+ <color name="car_card_light">@color/car_grey_50</color>
+ <color name="car_card_dark">@color/car_dark_blue_grey_700</color>
+
+ <!-- The default color of a card in car UI. -->
+ <color name="car_card">@color/car_card_light</color>
+
+ <!-- The ripple colors. The "dark" and "light" designation here refers to the color of the
+ ripple itself. -->
+ <color name="car_card_ripple_background_dark">#8F000000</color>
+ <color name="car_card_ripple_background_light">#27ffffff</color>
+
+ <!-- The ripple color for a light colored card. -->
+ <color name="car_card_ripple_background">@color/car_card_ripple_background_dark</color>
+
+ <!-- The ripple color for a dark-colored card. This color is the opposite of
+ car_card_ripple_background. -->
+ <color name="car_card_ripple_background_inverse">@color/car_card_ripple_background_light</color>
+
+ <!-- The top margin before the start of content in an application. -->
+ <dimen name="app_header_height">96dp</dimen>
+
+ <!-- The lighter and darker color for the scrollbar thumb. -->
+ <color name="car_scrollbar_thumb_light">#99ffffff</color>
+ <color name="car_scrollbar_thumb_dark">#7f0b0f12</color>
+
+ <!-- The color of the scroll bar indicator in the PagedListView. This color is assumed to be on
+ a light-colored background. -->
+ <color name="car_scrollbar_thumb">@color/car_scrollbar_thumb_dark</color>
+
+ <!-- The inverted color of the scroll bar indicator. This color is always the opposite of
+ car_scrollbar_thumb. -->
+ <color name="car_scrollbar_thumb_inverse">@color/car_scrollbar_thumb_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>
</resources>
diff --git a/car_product/overlay/frameworks/base/core/res/res/values/config.xml b/car_product/overlay/frameworks/base/core/res/res/values/config.xml
index ca8a8d8..8e55f8c 100644
--- a/car_product/overlay/frameworks/base/core/res/res/values/config.xml
+++ b/car_product/overlay/frameworks/base/core/res/res/values/config.xml
@@ -47,8 +47,6 @@
<integer name="config_jobSchedulerInactivityIdleThreshold">0</integer>
<integer name="config_jobSchedulerIdleWindowSlop">0</integer>
- <bool name="config_supportsMultiWindow">false</bool>
-
<!-- Automotive Bluetooth pairing option -->
<bool name="enable_pbap_pce_profile">true</bool>
@@ -69,4 +67,12 @@
<!-- Home screen(Launcher) app presence -->
<bool name="config_noHomeScreen">true</bool>
+
+ <!-- Flag indicating that this device does not rotate and will always remain in its default
+ orientation. Activities that desire to run in a non-compatible orientation will find that
+ they are not able to. -->
+ <bool name="config_forceDefaultOrientation">true</bool>
+
+ <!-- Corner radius of system dialogs -->
+ <dimen name="config_dialogCornerRadius">16dp</dimen>
</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 314d757..2adc535 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,7 +17,8 @@
*/
-->
<resources>
- <dimen name="status_bar_height">56dp</dimen>
+ <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>
@@ -106,4 +107,38 @@
<!-- The top margin before the notification progress bar. -->
<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>
+
+ <!-- Common icon size for car app -->
+ <dimen name="car_icon_size">56dp</dimen>
+
+ <dimen name="car_card_header_height">96dp</dimen>
+ <dimen name="car_card_action_bar_height">96dp</dimen>
+
+ <!-- Paddings -->
+ <dimen name="car_padding_1">4dp</dimen>
+ <dimen name="car_padding_2">10dp</dimen>
+ <dimen name="car_padding_3">16dp</dimen>
+ <dimen name="car_padding_4">28dp</dimen>
+ <dimen name="car_padding_5">32dp</dimen>
+
+ <!-- Radius -->
+ <dimen name="car_radius_1">4dp</dimen>
+ <dimen name="car_radius_2">8dp</dimen>
+ <dimen name="car_radius_3">16dp</dimen>
+ <dimen name="car_radius_5">100dp</dimen>
+
+ <!-- Keylines for content. -->
+ <dimen name="car_keyline_1">48dp</dimen>
+ <dimen name="car_keyline_2">108dp</dimen>
+ <dimen name="car_keyline_3">152dp</dimen>
+ <dimen name="car_keyline_4">182dp</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 7bcedb9..f654f3d 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
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2016 The Android Open Source Project
+<!-- 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.
@@ -75,4 +75,48 @@
<item name="paddingBottom">@dimen/media_notification_actions_padding_bottom</item>
<item name="gravity">center</item>
</style>
+
+ <!-- Car text -->
+ <style name="CarBody2">
+ <item name="android:textStyle">normal</item>
+ <item name="android:textSize">@dimen/car_body2_size</item>
+ <item name="android:textColor">@color/car_body2</item>
+ </style>
+
+ <style name="CarBody2.Dark">
+ <item name="android:textColor">@color/car_body2_dark</item>
+ </style>
+ <style name="CarBody2.Light">
+ <item name="android:textColor">@color/car_body2_light</item>
+ </style>
+
+ <style name="CarAction1">
+ <item name="android:textStyle">bold</item>
+ <item name="android:textSize">@dimen/car_action1_size</item>
+ <item name="android:textColor">@color/car_highlight</item>
+ </style>
+
+ <style name="CarAction1.Dark">
+ <item name="android:textColor">@color/car_highlight_dark</item>
+ </style>
+ <style name="CarAction1.Light">
+ <item name="android:textColor">@color/car_highlight_light</item>
+ </style>
+
+ <!-- The styling for title text. The color of this text changes based on day/night mode. -->
+ <style name="CarTitle" >
+ <item name="android:textStyle">bold</item>
+ <item name="android:textSize">@dimen/car_title2_size</item>
+ <item name="android:textColor">@color/car_title</item>
+ </style>
+
+ <!-- Title text that is permanently a dark color. -->
+ <style name="CarTitle.Dark" >
+ <item name="android:textColor">@color/car_title_dark</item>
+ </style>
+
+ <!-- Title text that is permanently a light color. -->
+ <style name="CarTitle.Light" >
+ <item name="android:textColor">@color/car_title_light</item>
+ </style>
</resources>
diff --git a/car_product/overlay/frameworks/base/core/res/res/xml/config_webview_packages.xml b/car_product/overlay/frameworks/base/core/res/res/xml/config_webview_packages.xml
deleted file mode 100644
index c5b11a7..0000000
--- a/car_product/overlay/frameworks/base/core/res/res/xml/config_webview_packages.xml
+++ /dev/null
@@ -1,39 +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.
--->
-
-<!-- WebView providers in order of preference -->
-<!-- Signature checks are ignored if the package is preinstalled or if this is a userdebug or eng
- build. If no signature is provided, the package can provide a WebView implementation only on userdebug/eng builds or if it's preinstalled -->
-<webviewproviders>
- <webviewprovider description="Chrome Stable" packageName="com.android.chrome" availableByDefault="true">
- <!-- Ignore this package on user/release builds unless preinstalled. -->
- </webviewprovider>
- <webviewprovider description="Google WebView" packageName="com.google.android.webview" availableByDefault="true" isFallback="true">
- <!-- Ignore this package on user/release builds unless preinstalled. -->
- </webviewprovider>
- <webviewprovider description="Chrome Beta" packageName="com.chrome.beta">
- <signature>MIIDwzCCAqugAwIBAgIJAOoj9MXoVhH6MA0GCSqGSIb3DQEBBQUAMHgxCzAJBgNVBAYTAlVTMRMwEQYDVQQIDApDYWxpZm9ybmlhMRYwFAYDVQQHDA1Nb3VudGFpbiBWaWV3MRQwEgYDVQQKDAtHb29nbGUgSW5jLjEQMA4GA1UECwwHQW5kcm9pZDEUMBIGA1UEAwwLY2hyb21lX2JldGEwHhcNMTYwMjI5MTUxNTIzWhcNNDMwNzE3MTUxNTIzWjB4MQswCQYDVQQGEwJVUzETMBEGA1UECAwKQ2FsaWZvcm5pYTEWMBQGA1UEBwwNTW91bnRhaW4gVmlldzEUMBIGA1UECgwLR29vZ2xlIEluYy4xEDAOBgNVBAsMB0FuZHJvaWQxFDASBgNVBAMMC2Nocm9tZV9iZXRhMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAo/wW27nRxVqGbFOyXr8jtv2pc2Ke8XMr6Sfs+3JK2licVaAljGFpLtWH4wUdb50w/QQSPALNLSSyuK/94rtp5Jjs4RSJI+whuewV/R6El+mFXBO3Ek5/op4UrOsR91IM4emvS67Ji2u8gp5EmttVgJtllFZCbtZLPmKuTaOkOB+EdWIxrYiHVEEaAcQpEHa9UgWUZ0bMfPj8j3F0w+Ak2ttmTjoFGLaZjuBAYwfdctN1b0sdLT9Lif45kMCb8QwPp0F9/ozs0rrTc+I6vnTS8kfFQfk7GIE4Hgm+cYQEHkIA6gLJxUVWvPZGdulAZw7wPt/neOkazHNZPcV4pYuNLQIDAQABo1AwTjAdBgNVHQ4EFgQU5t7dhcZfOSixRsiJ1E46JhzPlwowHwYDVR0jBBgwFoAU5t7dhcZfOSixRsiJ1E46JhzPlwowDAYDVR0TBAUwAwEB/zANBgkqhkiG9w0BAQUFAAOCAQEAZO2jB8P1d8ki3KZILvp27a2VM3DInlp8I8UgG3gh7nBQfTrnZr5M1PL8eFHqX7MEvAiGCMTcrPklEhjtcHK/c7BcdeCWq6oL56UK3JTl33RxJcjmjrz3e3VI6ehRSm1feNAkMD0Nr2RWr2LCYheAEmwTPtluLOJS+i7WhnXJzBtg5UpUFEbdFYenqUbDzya+cUVp0197k7hUTs8/Hxs0wf79o/TZXzTBq9eYQkiITonRN8+5QCBl1XmZKV0IHkzGFES1RP+fTiZpIjZT+W4tasHgs9QTTks4CCpyHBAy+uy7tApe1AxCzihgecCfUN1hWIltKwGZS6EE0bu0OXPzaQ==</signature>
- </webviewprovider>
- <webviewprovider description="Chrome Dev" packageName="com.chrome.dev">
- <signature>MIIDwTCCAqmgAwIBAgIJAOSN+O0cdii5MA0GCSqGSIb3DQEBBQUAMHcxCzAJBgNVBAYTAlVTMRMwEQYDVQQIDApDYWxpZm9ybmlhMRYwFAYDVQQHDA1Nb3VudGFpbiBWaWV3MRQwEgYDVQQKDAtHb29nbGUgSW5jLjEQMA4GA1UECwwHQW5kcm9pZDETMBEGA1UEAwwKY2hyb21lX2RldjAeFw0xNjAyMjkxNzUwMDdaFw00MzA3MTcxNzUwMDdaMHcxCzAJBgNVBAYTAlVTMRMwEQYDVQQIDApDYWxpZm9ybmlhMRYwFAYDVQQHDA1Nb3VudGFpbiBWaWV3MRQwEgYDVQQKDAtHb29nbGUgSW5jLjEQMA4GA1UECwwHQW5kcm9pZDETMBEGA1UEAwwKY2hyb21lX2RldjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBANOYPj6Y9rVt8xizSHDYjDEkDfFZAgSiZ9T6tevkQXsFyfaq3Gk3h2qssi29G6cTPJ2VXFKlVB71wSXv5p9/LEcDQPWQiO3Q2cLmgUXxyhJWXI3g96tPAhZQX2q6SC37ZQdiBR/raMO70DAkvCyBGtNplsvutzSE3oZ7LYfzB8vTbe7zCh3fDYSS/7xb3ZVvFqydHS40uVq1qqg1S80Pge7tW3pDGsPMZN7yA4yfmsvA1rbHm9N8t3Rc9hqzh6OxNAAgRB535YcsWL7iF+mpdFILXk3jLYT0nMvMnB83rsdgnRREjlGQYHl2mh8+6CqujsW/eICDq/LR6BYDyqHhk0ECAwEAAaNQME4wHQYDVR0OBBYEFKzsl07JglgpbeYDYGqsgqRDo+01MB8GA1UdIwQYMBaAFKzsl07JglgpbeYDYGqsgqRDo+01MAwGA1UdEwQFMAMBAf8wDQYJKoZIhvcNAQEFBQADggEBACka6SFF6xAcj8L8O6R36++E09DTiGZEjvKT8eIycgcQQ+p1WUmPb6M2EJpN6zvvSE62ussmXdzf8rIyc0JXA8jbViZt62Y39epNENFxPTLN9QzXlT+w8AW73Ka3cnbOuL5EgoDl8fM79WVlARY3X+wB/jGNrkiGIdRm2IZIeAodWgC2mtXMiferyYBKz2/F2bhnU6DwgCbegS8trFjEWviijWdJ+lBdobn7LRc3orZCtHl8UyvRDi7cye3sK9y3BM39k0g20F21wTNHAonnvL6zbuNgpd+UEsVxDpOeWrEdBFN7Md0CI2wnu8eA8ljJD45v0WWMEoxsIi131g5piNM=</signature>
- </webviewprovider>
- <webviewprovider description="Chrome Canary" packageName="com.chrome.canary">
- <signature>MIIDxzCCAq+gAwIBAgIJAML7APITsgV7MA0GCSqGSIb3DQEBBQUAMHoxCzAJBgNVBAYTAlVTMRMwEQYDVQQIDApDYWxpZm9ybmlhMRYwFAYDVQQHDA1Nb3VudGFpbiBWaWV3MRQwEgYDVQQKDAtHb29nbGUgSW5jLjEQMA4GA1UECwwHQW5kcm9pZDEWMBQGA1UEAwwNY2hyb21lX2NhbmFyeTAeFw0xNjAyMjkxOTA5MDdaFw00MzA3MTcxOTA5MDdaMHoxCzAJBgNVBAYTAlVTMRMwEQYDVQQIDApDYWxpZm9ybmlhMRYwFAYDVQQHDA1Nb3VudGFpbiBWaWV3MRQwEgYDVQQKDAtHb29nbGUgSW5jLjEQMA4GA1UECwwHQW5kcm9pZDEWMBQGA1UEAwwNY2hyb21lX2NhbmFyeTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBANXfeAoZlr0ya1HBzIfAz/nLLjpPJeAPvuX5dueaxmiQgv2hNG22acriFuiiJI6TU0t8AIVJD5Ifbc4OOuA0zeFhdzWWGnmTRH6x27WI7bzOKnAqOvv21ZBmE9i8Vo++K13xWdTs3qVn1bn9oUONxFu0wKDzXYZhoj1Jom0RZGjXm16xuPlEuOzMcjiNBDoYuxPAXkMcK/G1gP4P4nAV8Rd/GGIjKRS/SUtcShhoAMOQhs4WIEkUrvEVRwhBDIbpM87oFbCVdBH38r0XS6F6CdhPJsKFhoEfq4c01HZqNmDpCPA8AAcCuSWqmXoTIqs7OqkWgduE2bInbWU7WMaTl+kCAwEAAaNQME4wHQYDVR0OBBYEFB/AsC4iPAqaLoNytNSx29qByI7+MB8GA1UdIwQYMBaAFB/AsC4iPAqaLoNytNSx29qByI7+MAwGA1UdEwQFMAMBAf8wDQYJKoZIhvcNAQEFBQADggEBAMb2Td3ro/+MGVnCPAbwBSOZMVLUKGqt6zr8CShW9mtFHnmy29EaWSYYAj1M4+6Vpkq85NsgBEck7rnUjV8A3Q0NKdTys1KRKJqVvQRBN6SwqQenSf/abxQCa8Z+69rh+3BkIU1HLtu5lrMDZwon5H91L5mpORn6vItd20uW132lwSDeUEW2CHslTrodoFuTUcSUlRiq/URfUH3baO1QHXkxpQwrBPKL5deJfcZnxh5MAtAGSQL7gHvayEFlDppETXdDO7vgGTH2dEK2TjKWALbGiKkxSqjRyTNt4/FOj10TqNRdUamj+ydVJgzGQ8bki4Vc6NnKm/r4asusxapkVR4=</signature>
- </webviewprovider>
- <webviewprovider description="Chrome Debug" packageName="com.google.android.apps.chrome">
- <!-- Ignore this package on user/release builds unless preinstalled. -->
- </webviewprovider>
-</webviewproviders>
diff --git a/car_product/overlay/frameworks/base/packages/SystemUI/res-keyguard/drawable/ic_backspace.xml b/car_product/overlay/frameworks/base/packages/SystemUI/res-keyguard/drawable/ic_backspace.xml
new file mode 100644
index 0000000..f3a2f0f
--- /dev/null
+++ b/car_product/overlay/frameworks/base/packages/SystemUI/res-keyguard/drawable/ic_backspace.xml
@@ -0,0 +1,26 @@
+<?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.
+-->
+
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="36dp"
+ android:height="36dp"
+ android:viewportWidth="24.0"
+ android:viewportHeight="24.0">
+ <path
+ android:fillColor="#FF000000"
+ android:pathData="M9,15.59L12.59,12L9,8.41L10.41,7L14,10.59L17.59,7L19,8.41L15.41,12L19,15.59L17.59,17L14,13.41L10.41,17L9,15.59zM21,6H8l-4.5,6L8,18h13V6M21,4c1.1,0 2,0.9 2,2v12c0,1.1 -0.9,2 -2,2H8c-0.63,0 -1.22,-0.3 -1.6,-0.8L1,12l5.4,-7.2C6.78,4.3 7.37,4 8,4H21L21,4z"/>
+</vector>
diff --git a/car_product/overlay/frameworks/base/packages/SystemUI/res-keyguard/drawable/ic_done_wht.xml b/car_product/overlay/frameworks/base/packages/SystemUI/res-keyguard/drawable/ic_done.xml
similarity index 61%
rename from car_product/overlay/frameworks/base/packages/SystemUI/res-keyguard/drawable/ic_done_wht.xml
rename to car_product/overlay/frameworks/base/packages/SystemUI/res-keyguard/drawable/ic_done.xml
index 9e265d4..ef0aac2 100644
--- a/car_product/overlay/frameworks/base/packages/SystemUI/res-keyguard/drawable/ic_done_wht.xml
+++ b/car_product/overlay/frameworks/base/packages/SystemUI/res-keyguard/drawable/ic_done.xml
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
- Copyright 2017, The Android Open Source Project
+ 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.
@@ -14,15 +14,13 @@
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="64dp"
- android:height="64dp"
- android:viewportWidth="48"
- android:viewportHeight="48">
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="36dp"
+ android:height="36dp"
+ android:viewportWidth="24.0"
+ android:viewportHeight="24.0">
<path
- android:pathData="M0 0h48v48H0z" />
- <path
- android:fillColor="#ffffff"
- android:pathData="M18 32.34L9.66 24l-2.83 2.83L18 38l24-24-2.83-2.83z" />
+ android:fillColor="#FF000000"
+ android:pathData="M9,16.2l-3.5,-3.5a0.984,0.984 0,0 0,-1.4 0,0.984 0.984,0 0,0 0,1.4l4.19,4.19c0.39,0.39 1.02,0.39 1.41,0L20.3,7.7a0.984,0.984 0,0 0,0 -1.4,0.984 0.984,0 0,0 -1.4,0L9,16.2z"/>
</vector>
diff --git a/car_product/overlay/frameworks/base/packages/SystemUI/res-keyguard/drawable/keyguard_button_background.xml b/car_product/overlay/frameworks/base/packages/SystemUI/res-keyguard/drawable/keyguard_button_background.xml
new file mode 100644
index 0000000..b428931
--- /dev/null
+++ b/car_product/overlay/frameworks/base/packages/SystemUI/res-keyguard/drawable/keyguard_button_background.xml
@@ -0,0 +1,31 @@
+<?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.
+-->
+
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+ <item android:state_pressed="true">
+ <shape android:shape="rectangle">
+ <corners android:radius="@dimen/car_button_radius"/>
+ <solid android:color="#131315"/>
+ </shape>
+ </item>
+ <item>
+ <shape android:shape="rectangle">
+ <corners android:radius="@dimen/car_button_radius"/>
+ <solid android:color="@color/button_background"/>
+ </shape>
+ </item>
+</selector>
diff --git a/car_product/overlay/frameworks/base/packages/SystemUI/res-keyguard/layout-land/keyguard_pin_view.xml b/car_product/overlay/frameworks/base/packages/SystemUI/res-keyguard/layout-land/keyguard_pin_view.xml
new file mode 100644
index 0000000..0bca46b
--- /dev/null
+++ b/car_product/overlay/frameworks/base/packages/SystemUI/res-keyguard/layout-land/keyguard_pin_view.xml
@@ -0,0 +1,189 @@
+<?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.
+-->
+
+<!-- Car customizations
+ - Added title "Enter your PIN" under the entry field
+ - Put backspace and enter buttons in row 4
+ - PIN pad is on start side while entry field and title are on the end side
+ - Hid the emergency call at the bottom
+-->
+
+<com.android.keyguard.KeyguardPINView
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:app="http://schemas.android.com/apk/res-auto"
+ android:id="@+id/keyguard_pin_view"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent">
+
+ <FrameLayout
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:layout_marginLeft="@dimen/num_pad_margin_left"
+ android:layout_marginRight="@dimen/num_pad_margin_right">
+
+ <GridLayout
+ android:id="@+id/container"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_gravity="center_vertical|start"
+ android:columnCount="3">
+
+ <!-- Row 1 -->
+ <com.android.keyguard.NumPadKey
+ android:id="@+id/key1"
+ style="@style/NumPadKeyButton"
+ app:digit="@string/one" />
+ <com.android.keyguard.NumPadKey
+ android:id="@+id/key2"
+ style="@style/NumPadKeyButton"
+ app:digit="@string/two" />
+ <com.android.keyguard.NumPadKey
+ android:id="@+id/key3"
+ style="@style/NumPadKeyButton"
+ app:digit="@string/three" />
+
+ <!-- Row 2 -->
+ <com.android.keyguard.NumPadKey
+ android:id="@+id/key4"
+ style="@style/NumPadKeyButton"
+ app:digit="@string/four" />
+ <com.android.keyguard.NumPadKey
+ android:id="@+id/key5"
+ style="@style/NumPadKeyButton"
+ app:digit="@string/five" />
+ <com.android.keyguard.NumPadKey
+ android:id="@+id/key6"
+ style="@style/NumPadKeyButton"
+ app:digit="@string/six" />
+
+ <!-- Row 3 -->
+ <com.android.keyguard.NumPadKey
+ android:id="@+id/key7"
+ style="@style/NumPadKeyButton"
+ app:digit="@string/seven" />
+ <com.android.keyguard.NumPadKey
+ android:id="@+id/key8"
+ style="@style/NumPadKeyButton"
+ app:digit="@string/eight" />
+ <com.android.keyguard.NumPadKey
+ android:id="@+id/key9"
+ style="@style/NumPadKeyButton"
+ app:digit="@string/nine" />
+
+ <!-- Row 4 -->
+ <ImageButton
+ android:id="@+id/delete_button"
+ style="@style/NumPadKeyButton"
+ android:gravity="center_vertical"
+ android:src="@drawable/ic_backspace"
+ android:clickable="true"
+ android:tint="@android:color/white"
+ android:background="@drawable/ripple_drawable"
+ android:contentDescription="@string/keyboardview_keycode_delete" />
+ <com.android.keyguard.NumPadKey
+ android:id="@+id/key0"
+ style="@style/NumPadKeyButton"
+ app:digit="@string/zero" />
+ <ImageButton
+ android:id="@+id/key_enter"
+ style="@style/NumPadKeyButton"
+ android:src="@drawable/ic_done"
+ android:tint="@android:color/white"
+ android:background="@drawable/ripple_drawable"
+ android:contentDescription="@string/keyboardview_keycode_enter" />
+ </GridLayout>
+
+ <LinearLayout
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_gravity="center_vertical|end"
+ android:gravity="center"
+ android:orientation="vertical">
+
+ <com.android.keyguard.PasswordTextView
+ android:id="@+id/pinEntry"
+ android:layout_width="@dimen/keyguard_security_width"
+ android:layout_height="@dimen/pin_entry_height"
+ android:gravity="center"
+ app:scaledTextSize="@integer/password_text_view_scale"
+ android:contentDescription="@string/keyguard_accessibility_pin_area" />
+
+ <View
+ android:id="@+id/divider"
+ android:layout_width="@dimen/keyguard_security_width"
+ android:layout_height="@dimen/divider_height"
+ android:background="@android:color/white" />
+
+ <TextView
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_margin="@dimen/car_padding_2"
+ android:gravity="center"
+ android:textColor="@android:color/white"
+ android:textSize="@dimen/car_body1_size"
+ android:text="@string/keyguard_enter_your_pin" />
+
+ <include layout="@layout/keyguard_message_area"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_marginBottom="@dimen/car_padding_4"/>
+
+ <Button
+ android:id="@+id/cancel_button"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_gravity="center"
+ style="@style/KeyguardButton"
+ android:text="@string/cancel"/>
+ </LinearLayout>
+ </FrameLayout>
+
+ <!-- KeyguardPinView references these resources ids in code so removing them will cause the
+ keyguard to crash. Instead put them down here where they are out of the way and set their
+ visibility to gone. -->
+ <com.android.keyguard.AlphaOptimizedRelativeLayout
+ android:id="@+id/row0"
+ android:layout_width="0dp"
+ android:layout_height="0dp"
+ android:visibility="gone" />
+ <LinearLayout
+ android:id="@+id/row1"
+ android:layout_width="0dp"
+ android:layout_height="0dp"
+ android:visibility="gone" />
+ <LinearLayout
+ android:id="@+id/row2"
+ android:layout_width="0dp"
+ android:layout_height="0dp"
+ android:visibility="gone" />
+ <LinearLayout
+ android:id="@+id/row3"
+ android:layout_width="0dp"
+ android:layout_height="0dp"
+ android:visibility="gone" />
+ <LinearLayout
+ android:id="@+id/row4"
+ android:layout_width="0dp"
+ android:layout_height="0dp"
+ android:visibility="gone" />
+
+ <include layout="@layout/keyguard_eca"
+ android:id="@+id/keyguard_selector_fade_container"
+ android:layout_width="0dp"
+ android:layout_height="0dp"
+ android:visibility="gone" />
+</com.android.keyguard.KeyguardPINView>
diff --git a/car_product/overlay/frameworks/base/packages/SystemUI/res-keyguard/layout/keyguard_bouncer.xml b/car_product/overlay/frameworks/base/packages/SystemUI/res-keyguard/layout/keyguard_bouncer.xml
new file mode 100644
index 0000000..062f7bd
--- /dev/null
+++ b/car_product/overlay/frameworks/base/packages/SystemUI/res-keyguard/layout/keyguard_bouncer.xml
@@ -0,0 +1,32 @@
+<?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
+ -->
+
+<!-- Car customizations
+ Car has solid black background instead of a transparent one
+-->
+<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:background="@android:color/black"
+ android:fitsSystemWindows="true">
+
+ <include
+ style="@style/BouncerSecurityContainer"
+ layout="@layout/keyguard_host_view"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content" />
+</FrameLayout>
+
diff --git a/car_product/overlay/frameworks/base/packages/SystemUI/res-keyguard/layout/keyguard_num_pad_key.xml b/car_product/overlay/frameworks/base/packages/SystemUI/res-keyguard/layout/keyguard_num_pad_key.xml
new file mode 100644
index 0000000..c7eda38
--- /dev/null
+++ b/car_product/overlay/frameworks/base/packages/SystemUI/res-keyguard/layout/keyguard_num_pad_key.xml
@@ -0,0 +1,37 @@
+<?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
+ -->
+
+<!-- Car customizations
+ The mnemonics is not shown for car but KeyguardPinView references the resource id in code.
+ Removing it will cause the keyguard to crash. Hide them instead
+-->
+<merge xmlns:android="http://schemas.android.com/apk/res/android">
+ <TextView
+ android:id="@+id/digit_text"
+ style="@style/Widget.TextView.NumPadKey"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ />
+ <!-- The mnemonics is not shown for car but KeyguardPinView references the resource id in code.
+ Removing it will cause the keyguard to crash. Hide them instead -->
+ <TextView
+ android:id="@+id/klondike_text"
+ android:layout_width="0dp"
+ android:layout_height="0dp"
+ android:visibility="gone"
+ />
+</merge>
+
diff --git a/car_product/overlay/frameworks/base/packages/SystemUI/res-keyguard/layout/keyguard_password_view.xml b/car_product/overlay/frameworks/base/packages/SystemUI/res-keyguard/layout/keyguard_password_view.xml
new file mode 100644
index 0000000..cab52e8
--- /dev/null
+++ b/car_product/overlay/frameworks/base/packages/SystemUI/res-keyguard/layout/keyguard_password_view.xml
@@ -0,0 +1,109 @@
+<?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.
+*/
+-->
+
+<!-- Car customizations
+ - Added title "Enter your Password" below the password field
+ - Hid the emergency call at the bottom
+-->
+
+<com.android.keyguard.KeyguardPasswordView
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:androidprv="http://schemas.android.com/apk/res-auto"
+ android:id="@+id/keyguard_password_view"
+ android:orientation="vertical"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ androidprv:layout_maxWidth="@dimen/keyguard_security_width"
+ androidprv:layout_maxHeight="@dimen/keyguard_security_height"
+ android:gravity="center"
+ >
+
+ <include
+ layout="@layout/keyguard_message_area"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_marginBottom="@dimen/car_padding_2"/>
+
+ <!-- Password entry field -->
+ <LinearLayout
+ android:layout_height="wrap_content"
+ android:layout_width="wrap_content"
+ android:layout_gravity="center_horizontal"
+ android:orientation="vertical"
+ android:theme="?attr/passwordStyle">
+
+ <EditText
+ android:id="@+id/passwordEntry"
+ android:layout_width="@dimen/password_field_width"
+ android:layout_height="wrap_content"
+ android:gravity="center_horizontal"
+ android:singleLine="true"
+ android:textStyle="normal"
+ android:inputType="textPassword"
+ android:textSize="@dimen/car_body1_size"
+ android:textColor="?attr/wallpaperTextColor"
+ android:textAppearance="?android:attr/textAppearanceMedium"
+ android:imeOptions="flagForceAscii|actionDone"
+ android:maxLength="@integer/password_text_view_scale"
+ />
+
+ <TextView
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_margin="@dimen/car_padding_2"
+ android:gravity="center"
+ android:textColor="@android:color/white"
+ android:textSize="@dimen/car_body1_size"
+ android:text="@string/keyguard_enter_your_password" />
+
+ <Button
+ android:id="@+id/cancel_button"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_gravity="center"
+ style="@style/KeyguardButton"
+ android:text="@string/cancel"/>
+
+ <ImageView android:id="@+id/switch_ime_button"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_marginBottom="12dp"
+ android:src="@drawable/ic_lockscreen_ime"
+ android:contentDescription="@string/accessibility_ime_switch_button"
+ android:clickable="true"
+ android:padding="8dp"
+ android:tint="@color/background_protected"
+ android:layout_gravity="end|center_vertical"
+ android:background="?android:attr/selectableItemBackground"
+ android:visibility="gone"
+ />
+ </LinearLayout>
+
+ <include layout="@layout/keyguard_eca"
+ android:id="@+id/keyguard_selector_fade_container"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_marginBottom="12dp"
+ android:orientation="vertical"
+ android:layout_gravity="bottom|center_horizontal"
+ android:gravity="center_horizontal"
+ android:visibility="gone"
+ />
+
+</com.android.keyguard.KeyguardPasswordView>
diff --git a/car_product/overlay/frameworks/base/packages/SystemUI/res-keyguard/layout/keyguard_pattern_view.xml b/car_product/overlay/frameworks/base/packages/SystemUI/res-keyguard/layout/keyguard_pattern_view.xml
new file mode 100644
index 0000000..de879e0
--- /dev/null
+++ b/car_product/overlay/frameworks/base/packages/SystemUI/res-keyguard/layout/keyguard_pattern_view.xml
@@ -0,0 +1,86 @@
+<?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.
+*/
+-->
+
+<!-- Car customizations
+ - Added title "Enter your Pattern" at the top
+ - Hid the emergency call at the bottom
+-->
+
+<com.android.keyguard.KeyguardPatternView
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:androidprv="http://schemas.android.com/apk/res-auto"
+ android:id="@+id/keyguard_pattern_view"
+ android:orientation="vertical"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ androidprv:layout_maxWidth="@dimen/keyguard_security_width"
+ android:gravity="center_horizontal">
+
+ <FrameLayout
+ android:layout_width="match_parent"
+ android:layout_height="match_parent">
+
+ <LinearLayout
+ android:id="@+id/container"
+ android:layout_height="wrap_content"
+ android:layout_width="wrap_content"
+ android:orientation="vertical"
+ android:layout_gravity="center">
+
+ <TextView
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_margin="@dimen/car_padding_2"
+ android:gravity="center"
+ android:textColor="@android:color/white"
+ android:textSize="@dimen/car_body1_size"
+ android:text="@string/keyguard_enter_your_pattern" />
+
+ <include layout="@layout/keyguard_message_area"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content" />
+
+ <com.android.internal.widget.LockPatternView
+ android:id="@+id/lockPatternView"
+ android:layout_width="@dimen/keyguard_pattern_dimension"
+ android:layout_height="@dimen/keyguard_pattern_dimension"
+ android:layout_marginVertical="@dimen/pin_pattern_pad_margin_vertical"
+ android:layout_gravity="center_horizontal"
+ android:gravity="center" />
+
+ <Button
+ android:id="@+id/cancel_button"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_gravity="center"
+ style="@style/KeyguardButton"
+ android:text="@string/cancel"/>
+
+ <include layout="@layout/keyguard_eca"
+ android:id="@+id/keyguard_selector_fade_container"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:orientation="vertical"
+ android:layout_gravity="bottom|center_horizontal"
+ android:gravity="center_horizontal"
+ android:visibility="gone" />
+ </LinearLayout>
+ </FrameLayout>
+
+</com.android.keyguard.KeyguardPatternView>
diff --git a/car_product/overlay/frameworks/base/packages/SystemUI/res-keyguard/layout/keyguard_pin_view.xml b/car_product/overlay/frameworks/base/packages/SystemUI/res-keyguard/layout/keyguard_pin_view.xml
index 08fe6d0..657595b 100644
--- a/car_product/overlay/frameworks/base/packages/SystemUI/res-keyguard/layout/keyguard_pin_view.xml
+++ b/car_product/overlay/frameworks/base/packages/SystemUI/res-keyguard/layout/keyguard_pin_view.xml
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
- Copyright 2017, The Android Open Source Project
+ 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.
@@ -14,6 +14,13 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
+
+<!-- Car customizations
+ - Added title "Enter your PIN" under the entry field
+ - Put backspace and enter buttons in row 4
+ - Hid the emergency call at the bottom
+-->
+
<com.android.keyguard.KeyguardPINView
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
@@ -21,18 +28,54 @@
android:layout_width="match_parent"
android:layout_height="match_parent">
- <FrameLayout
+ <LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginLeft="@dimen/num_pad_margin_left"
- android:layout_marginRight="@dimen/num_pad_margin_right">
+ android:layout_marginRight="@dimen/num_pad_margin_right"
+ android:orientation="vertical"
+ android:gravity="center">
+ <LinearLayout
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:gravity="center"
+ android:orientation="vertical">
+
+ <com.android.keyguard.PasswordTextView
+ android:id="@+id/pinEntry"
+ android:layout_width="@dimen/keyguard_security_width"
+ android:layout_height="@dimen/pin_entry_height"
+ android:gravity="center"
+ app:scaledTextSize="@integer/password_text_view_scale"
+ android:contentDescription="@string/keyguard_accessibility_pin_area" />
+
+ <View
+ android:id="@+id/divider"
+ android:layout_width="@dimen/keyguard_security_width"
+ android:layout_height="@dimen/divider_height"
+ android:background="@android:color/white" />
+
+ <TextView
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_margin="@dimen/car_padding_2"
+ android:gravity="center"
+ android:textColor="@android:color/white"
+ android:textSize="@dimen/car_body1_size"
+ android:text="@string/keyguard_enter_your_pin" />
+
+ <include
+ layout="@layout/keyguard_message_area"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"/>
+ </LinearLayout>
<GridLayout
android:id="@+id/container"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
- android:layout_gravity="center_vertical|left"
+ android:layout_marginVertical="@dimen/pin_pattern_pad_margin_vertical"
android:columnCount="3">
<!-- Row 1 -->
@@ -78,95 +121,71 @@
app:digit="@string/nine" />
<!-- Row 4 -->
- <Space
- android:layout_width="wrap_content"
- android:layout_height="wrap_content" />
+ <ImageButton
+ android:id="@+id/delete_button"
+ style="@style/NumPadKeyButton"
+ android:gravity="center_vertical"
+ android:src="@drawable/ic_backspace"
+ android:clickable="true"
+ android:tint="@android:color/white"
+ android:background="@drawable/ripple_drawable"
+ android:contentDescription="@string/keyboardview_keycode_delete" />
<com.android.keyguard.NumPadKey
android:id="@+id/key0"
style="@style/NumPadKeyButton"
app:digit="@string/zero" />
<ImageButton
- android:id="@+id/delete_button"
+ android:id="@+id/key_enter"
style="@style/NumPadKeyButton"
- android:gravity="center_vertical"
- android:src="@drawable/ic_backspace_black_24dp"
- android:clickable="true"
+ android:src="@drawable/ic_done"
+ android:tint="@android:color/white"
android:background="@drawable/ripple_drawable"
- android:contentDescription="@string/keyboardview_keycode_delete"
- android:layout_alignParentRight="true" />
+ android:contentDescription="@string/keyboardview_keycode_enter" />
</GridLayout>
- <LinearLayout
+ <Button
+ android:id="@+id/cancel_button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
- android:layout_gravity="center_vertical|right"
- android:gravity="center"
- android:orientation="vertical">
+ android:layout_gravity="center"
+ style="@style/KeyguardButton"
+ android:text="@string/cancel"/>
- <com.android.keyguard.PasswordTextView
- android:id="@+id/pinEntry"
- android:layout_width="@dimen/keyguard_security_width"
- android:layout_height="@dimen/pin_entry_height"
- android:gravity="center"
- app:scaledTextSize="@integer/password_text_view_scale"
- android:contentDescription="@string/keyguard_accessibility_pin_area" />
-
- <View
- android:id="@+id/divider"
- android:layout_width="@dimen/keyguard_security_width"
- android:layout_height="@dimen/divider_height"
- android:background="@android:color/white" />
-
- <com.android.keyguard.AlphaOptimizedImageButton
- android:id="@+id/key_enter"
- android:layout_width="@dimen/num_pad_key_width"
- android:layout_height="@dimen/num_pad_key_height"
- android:src="@drawable/ic_done_wht"
- android:background="@drawable/ripple_drawable"
- android:layout_marginTop="@dimen/key_enter_margin_top"
- android:contentDescription="@string/keyboardview_keycode_enter" />
-
- <include layout="@layout/keyguard_message_area"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"/>
- </LinearLayout>
- </FrameLayout>
+ </LinearLayout>
<!-- KeyguardPinView references these resources ids in code so removing them will cause the
keyguard to crash. Instead put them down here where they are out of the way and set their
visibility to gone. -->
<com.android.keyguard.AlphaOptimizedRelativeLayout
android:id="@+id/row0"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
+ android:layout_width="0dp"
+ android:layout_height="0dp"
android:visibility="gone" />
<LinearLayout
android:id="@+id/row1"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
+ android:layout_width="0dp"
+ android:layout_height="0dp"
android:visibility="gone" />
<LinearLayout
android:id="@+id/row2"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
+ android:layout_width="0dp"
+ android:layout_height="0dp"
android:visibility="gone" />
<LinearLayout
android:id="@+id/row3"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
+ android:layout_width="0dp"
+ android:layout_height="0dp"
android:visibility="gone" />
<LinearLayout
android:id="@+id/row4"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
+ android:layout_width="0dp"
+ android:layout_height="0dp"
android:visibility="gone" />
- <include layout="@layout/keyguard_eca"
- android:id="@+id/keyguard_selector_fade_container"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:orientation="vertical"
- android:layout_gravity="bottom|center_horizontal"
- android:gravity="center_horizontal"
- android:visibility="gone" />
+ <include
+ layout="@layout/keyguard_eca"
+ android:id="@+id/keyguard_selector_fade_container"
+ android:layout_width="0dp"
+ android:layout_height="0dp"
+ android:visibility="gone" />
</com.android.keyguard.KeyguardPINView>
diff --git a/car_product/overlay/frameworks/base/packages/SystemUI/res-keyguard/values-h1000dp/dimens.xml b/car_product/overlay/frameworks/base/packages/SystemUI/res-keyguard/values-h1000dp/dimens.xml
new file mode 100644
index 0000000..24f1ee3
--- /dev/null
+++ b/car_product/overlay/frameworks/base/packages/SystemUI/res-keyguard/values-h1000dp/dimens.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright 2018s, 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>
+ <dimen name="pin_pattern_pad_margin_vertical">178dp</dimen>
+</resources>
diff --git a/car_product/overlay/frameworks/base/packages/SystemUI/res-keyguard/values/colors.xml b/car_product/overlay/frameworks/base/packages/SystemUI/res-keyguard/values/colors.xml
new file mode 100644
index 0000000..a75dd88
--- /dev/null
+++ b/car_product/overlay/frameworks/base/packages/SystemUI/res-keyguard/values/colors.xml
@@ -0,0 +1,21 @@
+<?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.
+-->
+
+<resources>
+ <color name="button_background">@color/car_dark_blue_grey_600</color>
+ <color name="button_text">@color/car_action1_dark</color>
+</resources>
\ No newline at end of file
diff --git a/car_product/overlay/frameworks/base/packages/SystemUI/res-keyguard/values/dimens.xml b/car_product/overlay/frameworks/base/packages/SystemUI/res-keyguard/values/dimens.xml
index f1dbe75..ea9f5bd 100644
--- a/car_product/overlay/frameworks/base/packages/SystemUI/res-keyguard/values/dimens.xml
+++ b/car_product/overlay/frameworks/base/packages/SystemUI/res-keyguard/values/dimens.xml
@@ -17,12 +17,13 @@
<resources>
<dimen name="num_pad_margin_left">112dp</dimen>
<dimen name="num_pad_margin_right">144dp</dimen>
- <dimen name="num_pad_key_width">160dp</dimen>
- <dimen name="num_pad_key_height">128dp</dimen>
- <dimen name="num_pad_key_margin">32dp</dimen>
- <dimen name="num_pad_key_digit_size">48sp</dimen>
- <dimen name="num_pad_key_text_size">24sp</dimen>
+ <dimen name="num_pad_key_width">120dp</dimen>
+ <dimen name="num_pad_key_height">80dp</dimen>
+ <dimen name="num_pad_key_margin">12dp</dimen>
<dimen name="pin_entry_height">@dimen/num_pad_key_height</dimen>
<dimen name="divider_height">1dp</dimen>
<dimen name="key_enter_margin_top">128dp</dimen>
+ <dimen name="keyguard_pattern_dimension">350dp</dimen>
+ <dimen name="password_field_width">350dp</dimen>
+ <dimen name="pin_pattern_pad_margin_vertical">0dp</dimen>
</resources>
diff --git a/car_product/overlay/frameworks/base/packages/SystemUI/res-keyguard/values/integers.xml b/car_product/overlay/frameworks/base/packages/SystemUI/res-keyguard/values/integers.xml
index 0408ca4..bad1346 100644
--- a/car_product/overlay/frameworks/base/packages/SystemUI/res-keyguard/values/integers.xml
+++ b/car_product/overlay/frameworks/base/packages/SystemUI/res-keyguard/values/integers.xml
@@ -15,5 +15,6 @@
limitations under the License.
-->
<resources>
- <integer name="password_text_view_scale">72</integer>
+ <integer name="password_text_view_scale">40</integer>
+ <integer name="password_max_length">500</integer>
</resources>
diff --git a/car_product/overlay/frameworks/base/packages/SystemUI/res-keyguard/values/styles.xml b/car_product/overlay/frameworks/base/packages/SystemUI/res-keyguard/values/styles.xml
index c1e9622..e26c515 100644
--- a/car_product/overlay/frameworks/base/packages/SystemUI/res-keyguard/values/styles.xml
+++ b/car_product/overlay/frameworks/base/packages/SystemUI/res-keyguard/values/styles.xml
@@ -26,13 +26,14 @@
<item name="textView">@id/pinEntry</item>
</style>
- <style name="Widget.TextView.NumPadKey" parent="@android:style/Widget.TextView">
- <!-- Only replaces the text size. -->
- <item name="android:textSize">@dimen/num_pad_key_digit_size</item>
+ <style name="KeyguardButton" parent="Widget.Car.Button">
+ <item name="android:background">@drawable/keyguard_button_background</item>
+ <item name="android:textColor">@color/button_text</item>
+ <item name="android:textAllCaps">false</item>
</style>
- <style name="Widget.TextView.NumPadKey.Klondike" parent="Widget.TextView.NumPadKey">
+ <style name="Widget.TextView.NumPadKey" parent="@android:style/Widget.TextView">
<!-- Only replaces the text size. -->
- <item name="android:textSize">@dimen/num_pad_key_text_size</item>
+ <item name="android:textSize">@dimen/car_body1_size</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
new file mode 100644
index 0000000..f5fbe6d
--- /dev/null
+++ b/car_product/overlay/frameworks/base/packages/SystemUI/res/drawable/car_ic_apps.xml
@@ -0,0 +1,28 @@
+<!--
+ 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_hvac.xml b/car_product/overlay/frameworks/base/packages/SystemUI/res/drawable/car_ic_hvac.xml
new file mode 100644
index 0000000..bdc44b3
--- /dev/null
+++ b/car_product/overlay/frameworks/base/packages/SystemUI/res/drawable/car_ic_hvac.xml
@@ -0,0 +1,51 @@
+<!--
+ 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_notification.xml b/car_product/overlay/frameworks/base/packages/SystemUI/res/drawable/car_ic_notification.xml
new file mode 100644
index 0000000..61d937b
--- /dev/null
+++ b/car_product/overlay/frameworks/base/packages/SystemUI/res/drawable/car_ic_notification.xml
@@ -0,0 +1,28 @@
+<!--
+ 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/layout/car_navigation_bar.xml b/car_product/overlay/frameworks/base/packages/SystemUI/res/layout/car_navigation_bar.xml
index 07fb02c..a4902cd 100644
--- 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
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
**
-** Copyright 2016, The Android Open Source Project
+** 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.
@@ -19,41 +19,147 @@
<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">
- <!-- phone.NavigationBarView has rot0 and rot90 but we expect the car head unit to have a fixed
- rotation so skip this level of the heirarchy.
- -->
<LinearLayout
- android:layout_height="wrap_content"
- android:layout_width="match_parent"
+ 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:clipChildren="false"
- android:clipToPadding="false"
android:id="@+id/nav_buttons"
- android:layout_gravity="center"
- android:paddingTop="@dimen/navigation_bar_padding_top"
- android:paddingLeft="@dimen/navigation_bar_padding_side"
- android:paddingRight="@dimen/navigation_bar_padding_side"
+ android:gravity="center"
+ android:layout_weight="1"
android:animateLayoutChanges="true">
- <!-- Buttons get populated here from a car_arrays.xml. -->
+ <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>
- <!-- lights out layout to match exactly -->
<LinearLayout
- android:layout_height="wrap_content"
- android:layout_width="match_parent"
- android:orientation="horizontal"
- android:id="@+id/lights_out"
- android:layout_gravity="center"
- android:paddingTop="@dimen/navigation_bar_padding_top"
- android:paddingLeft="@dimen/navigation_bar_padding_side"
- android:paddingRight="@dimen/navigation_bar_padding_side"
+ 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">
- <!-- Must match nav_buttons. -->
+
+ <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/car_navigation_button.xml b/car_product/overlay/frameworks/base/packages/SystemUI/res/layout/car_navigation_button.xml
deleted file mode 100644
index 5d17c4e..0000000
--- a/car_product/overlay/frameworks/base/packages/SystemUI/res/layout/car_navigation_button.xml
+++ /dev/null
@@ -1,44 +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.
-*/
--->
-
-<com.android.systemui.statusbar.car.CarNavigationButton
- xmlns:android="http://schemas.android.com/apk/res/android"
- android:layout_height="wrap_content"
- android:layout_width="@dimen/car_navigation_button_holder_width"
- android:orientation="horizontal"
- android:background="?android:attr/selectableItemBackgroundBorderless">
- <com.android.keyguard.AlphaOptimizedImageButton
- android:id="@+id/car_nav_button_icon"
- android:layout_height="wrap_content"
- android:layout_width="@dimen/car_navigation_button_width"
- android:layout_centerInParent="true"
- android:animateLayoutChanges="true"
- android:scaleType="fitCenter">
- </com.android.keyguard.AlphaOptimizedImageButton>
-
- <com.android.keyguard.AlphaOptimizedImageButton
- android:id="@+id/car_nav_button_more_icon"
- android:layout_height="wrap_content"
- android:layout_width="wrap_content"
- android:layout_centerVertical="true"
- android:layout_toRightOf="@+id/car_nav_button_icon"
- android:animateLayoutChanges="true"
- android:scaleType="fitCenter">
- </com.android.keyguard.AlphaOptimizedImageButton>
-</com.android.systemui.statusbar.car.CarNavigationButton>
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
index c9434e1..b99bfe8 100644
--- 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
@@ -48,6 +48,8 @@
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
diff --git a/car_product/overlay/frameworks/base/packages/SystemUI/res/layout/volume_dialog_row.xml b/car_product/overlay/frameworks/base/packages/SystemUI/res/layout/volume_dialog_row.xml
deleted file mode 100644
index 069936c..0000000
--- a/car_product/overlay/frameworks/base/packages/SystemUI/res/layout/volume_dialog_row.xml
+++ /dev/null
@@ -1,66 +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:layout_width="match_parent"
- android:layout_height="@dimen/volume_row_height"
- android:clipChildren="false"
- android:clipToPadding="false"
- android:orientation="vertical"
- android:paddingBottom="@dimen/volume_row_padding_bottom" >
-
- <!-- don't need this view in car, the visibility is overriden by system UI, so set the
- layout_height to 0dp.
- TODO: figure out a better way to switch UI based on FEATURE_AUTOMOTIVE -->
- <TextView
- android:id="@+id/volume_row_header"
- android:layout_width="wrap_content"
- android:layout_height="0dp"
- android:ellipsize="end"
- android:visibility="gone"
- android:maxLines="1"
- android:textSize="40sp"
- android:textColor="?android:attr/textColorSecondary"
- android:paddingStart="@dimen/volume_row_header_padding_start" />
-
- <FrameLayout
- android:layout_width="match_parent"
- android:layout_height="@dimen/line_item_height">
- <com.android.keyguard.AlphaOptimizedImageButton
- android:id="@+id/volume_row_icon"
- style="@style/VolumeButtons"
- android:tint="@color/car_grey_900"
- android:gravity="center_vertical"
- android:layout_gravity="center_vertical"
- android:layout_width="@dimen/volume_icon_size"
- android:layout_height="@dimen/volume_icon_size"
- android:layout_marginStart="@dimen/car_keyline_1"
- android:soundEffectsEnabled="false" />
-
- <SeekBar
- android:id="@+id/volume_row_slider"
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:gravity="center_vertical"
- android:layout_gravity="center_vertical"
- android:layout_marginStart="@dimen/car_keyline_3"
- android:progressDrawable="@drawable/car_ic_seekbar_track"
- android:thumb="@drawable/car_ic_seekbar_thumb"
- android:focusable="true"
- android:focusableInTouchMode="true"/>
- </FrameLayout>
-</LinearLayout>
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
index 94a6d45..1fa0b3b 100644
--- 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
@@ -33,7 +33,7 @@
<!-- 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.LAUNCHER;launchFlags=0x14000000;package=com.android.support.car.lenspicker;S.system_command=toggle_notifications;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>
@@ -57,6 +57,6 @@
<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</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
index 54d926f..30c0c58 100644
--- a/car_product/overlay/frameworks/base/packages/SystemUI/res/values/colors.xml
+++ b/car_product/overlay/frameworks/base/packages/SystemUI/res/values/colors.xml
@@ -38,4 +38,6 @@
<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/dimens.xml b/car_product/overlay/frameworks/base/packages/SystemUI/res/values/dimens.xml
index 047a6b7..37a6238 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
@@ -25,10 +25,10 @@
<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">42sp</dimen>
+ <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">24dp</dimen>
+ <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>
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
index 1fc3503..68fc641 100644
--- a/car_product/overlay/frameworks/base/packages/SystemUI/res/values/styles.xml
+++ b/car_product/overlay/frameworks/base/packages/SystemUI/res/values/styles.xml
@@ -27,4 +27,11 @@
<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/background_round_corners.xml b/car_product/overlay/packages/apps/PackageInstaller/res/drawable/background_round_corners.xml
new file mode 100644
index 0000000..03d7418
--- /dev/null
+++ b/car_product/overlay/packages/apps/PackageInstaller/res/drawable/background_round_corners.xml
@@ -0,0 +1,20 @@
+<?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" >
+ <solid android:color="@color/car_card" />
+ <corners android:radius="@dimen/car_radius_3" />
+</shape>
diff --git a/car_product/overlay/packages/apps/PackageInstaller/res/drawable/dialog_button_background.xml b/car_product/overlay/packages/apps/PackageInstaller/res/drawable/dialog_button_background.xml
new file mode 100644
index 0000000..17df216
--- /dev/null
+++ b/car_product/overlay/packages/apps/PackageInstaller/res/drawable/dialog_button_background.xml
@@ -0,0 +1,22 @@
+<?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.
+ -->
+<ripple xmlns:android="http://schemas.android.com/apk/res/android"
+ android:color="@color/car_card_ripple_background">
+ <item android:id="@android:id/mask">
+ <color android:color="@color/car_white_1000" />
+ </item>
+</ripple>
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 3da218e..08e5fd8 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
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2016 The Android Open Source Project
+<!-- 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.
@@ -18,25 +18,26 @@
two is text sizes and spacing. -->
<com.android.packageinstaller.permission.ui.ManualLayoutFrame
xmlns:android="http://schemas.android.com/apk/res/android"
- android:layout_width="match_parent"
- android:layout_height="match_parent"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
android:clipChildren="false">
<LinearLayout
android:id="@+id/dialog_container"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
- android:padding="96dp"
+ android:background="@drawable/background_round_corners"
android:orientation="vertical">
<FrameLayout
android:id="@+id/desc_container"
android:layout_width="match_parent"
android:layout_height="wrap_content"
- android:paddingTop="24dp"
- android:paddingStart="22dp"
- android:paddingEnd="16dp"
- android:background="?android:attr/colorBackgroundFloating">
+ android:layout_marginTop="@dimen/car_padding_4"
+ android:layout_marginStart="@dimen/car_keyline_1"
+ android:layout_marginBottom="@dimen/car_padding_2"
+ android:layout_marginEnd="@dimen/car_keyline_1">
+
<include
layout="@layout/permission_description" />
</FrameLayout>
@@ -44,22 +45,20 @@
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
- android:orientation="vertical"
- android:paddingBottom="8dp"
- android:paddingStart="22dp"
- android:paddingEnd="16dp"
- android:background="?android:attr/colorBackgroundFloating">
+ android:orientation="vertical">
<CheckBox
android:id="@+id/do_not_ask_checkbox"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:layout_marginTop="@dimen/auto_permission_checkbox_margin_top"
- android:layout_marginBottom="@dimen/auto_permission_checkbox_margin_bottom"
- android:layout_marginStart="@dimen/auto_permission_text_keyline"
+ android:layout_width="wrap_content"
+ android:layout_height="@dimen/car_single_line_list_item_height"
+ android:layout_marginStart="@dimen/car_keyline_1"
+ android:layout_marginEnd="@dimen/car_keyline_1"
+ android:gravity="center_vertical"
+ android:paddingLeft="@dimen/car_keyline_1_keyline_3_diff"
+ android:button="@drawable/ic_check_box"
android:text="@string/never_ask_again"
android:textColor="?android:attr/textColorSecondary"
- android:textSize="@dimen/auto_permission_button_bar_text_size"
+ android:textSize="@dimen/car_action1_size"
android:visibility="gone">
</CheckBox>
@@ -67,53 +66,54 @@
android:id="@+id/button_group"
android:layout_width="match_parent"
android:layout_height="wrap_content"
- android:layout_marginTop="16dp"
- android:orientation="horizontal"
- android:paddingStart="2dp"
- android:paddingTop="16dp">
+ android:layout_marginTop="@dimen/car_padding_2"
+ android:layoutDirection="locale"
+ android:gravity="center_vertical"
+ android:orientation="horizontal">
- <TextView
- android:id="@+id/current_page_text"
+ <Button
+ android:id="@+id/permission_deny_button"
android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:paddingTop="4dp"
- android:paddingStart="@dimen/auto_permission_text_keyline"
- android:paddingBottom="4dp"
- android:paddingEnd="12dp"
- android:singleLine="true"
- android:textSize="@dimen/auto_permission_button_bar_text_size"
- android:textColor="?android:attr/textColorSecondary"
- android:visibility="invisible">
- </TextView>
+ android:layout_height="@dimen/car_dialog_action_bar_height"
+ android:background="@drawable/dialog_button_background"
+ android:paddingStart="@dimen/car_keyline_1"
+ 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:textStyle="bold">
+ </Button>
+
+ <Button
+ android:id="@+id/permission_allow_button"
+ android:layout_width="wrap_content"
+ android:layout_height="@dimen/car_dialog_action_bar_height"
+ android:background="@drawable/dialog_button_background"
+ android:paddingStart="@dimen/car_padding_4"
+ 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:textStyle="bold">
+ </Button>
<Space
android:id="@*android:id/spacer"
android:layout_width="0dp"
android:layout_height="0dp"
android:layout_weight="1"
- android:visibility="invisible" >
+ android:visibility="invisible">
</Space>
- <Button
- android:id="@+id/permission_deny_button"
+ <TextView
+ android:id="@+id/current_page_text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
- style="?android:attr/buttonBarButtonStyle"
- android:padding="@dimen/auto_permission_button_padding"
- android:textSize="@dimen/auto_permission_button_bar_text_size"
- android:text="@string/grant_dialog_button_deny" >
- </Button>
-
- <Button
- android:id="@+id/permission_allow_button"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- style="?android:attr/buttonBarButtonStyle"
- android:layout_marginStart="8dp"
- android:padding="@dimen/auto_permission_button_padding"
- android:textSize="@dimen/auto_permission_button_bar_text_size"
- android:text="@string/grant_dialog_button_allow" >
- </Button>
+ android:paddingEnd="@dimen/car_keyline_1"
+ android:maxLines="1"
+ android:textAppearance="@style/TextAppearance.Car.Body2"
+ android:visibility="invisible">
+ </TextView>
</com.android.packageinstaller.permission.ui.ButtonBarLayout>
diff --git a/car_product/overlay/packages/apps/PackageInstaller/res/layout/permission_description.xml b/car_product/overlay/packages/apps/PackageInstaller/res/layout/permission_description.xml
index d3ea515..cdbaf56 100644
--- a/car_product/overlay/packages/apps/PackageInstaller/res/layout/permission_description.xml
+++ b/car_product/overlay/packages/apps/PackageInstaller/res/layout/permission_description.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2016 The Android Open Source Project
+<!-- 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.
@@ -20,7 +20,7 @@
android:id="@+id/perm_desc_root"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
- android:orientation="horizontal">
+ android:gravity="left|center_vertical">
<!-- No icon for Android Auto Embedded, so this visibility is GONE. The view remains so that
no code change needs to occur in the GrantPermissionsViewHandlerImpl. -->
@@ -35,10 +35,7 @@
android:id="@+id/permission_message"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
- android:layout_marginTop="3dp"
- android:paddingStart="@dimen/auto_permission_text_keyline"
- android:paddingEnd="8dp"
- android:textSize="@dimen/auto_permission_text_size" >
- </TextView>
+ android:textSize="@dimen/car_body2_size"
+ android:textColor="@color/car_body2"/>
</LinearLayout>
diff --git a/car_product/overlay/packages/apps/PackageInstaller/res/values/dimens.xml b/car_product/overlay/packages/apps/PackageInstaller/res/values/dimens.xml
deleted file mode 100644
index 366a10f..0000000
--- a/car_product/overlay/packages/apps/PackageInstaller/res/values/dimens.xml
+++ /dev/null
@@ -1,40 +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.
--->
-
-<resources>
- <!-- The text size for the main text explaining what permission to allow or deny. -->
- <dimen name="auto_permission_text_size">36sp</dimen>
-
- <!-- The text size for the text along the button bar. This includes the "Allow"/"Deny" buttons.
- This text size is slightly smaller than auto_permission_text_size because they are in
- all-caps. The smaller text size makes the text sizes look the same. -->
- <dimen name="auto_permission_button_bar_text_size">28sp</dimen>
-
- <!-- The padding around the Allow/Deny buttons. This is larger to make the buttons easier to
- click. -->
- <dimen name="auto_permission_button_padding">16dp</dimen>
-
- <!-- The starting keyline for all text in the permission dialog. -->
- <dimen name="auto_permission_text_keyline">16dp</dimen>
-
- <!-- The top margin before the "Don't ask again" checkbox. -->
- <dimen name="auto_permission_checkbox_margin_top">16dp</dimen>
-
- <!-- The bottom margin after the "Don't ask again" checkbox. This value is negative to move
- the buttons below the checkbox up. Normally the buttons would have padding to separate
- it from the text above them, but the checkbox takes care of this now. -->
- <dimen name="auto_permission_checkbox_margin_bottom">-24dp</dimen>
-</resources>
diff --git a/car_product/overlay/packages/services/Car/service/res/values/Config.xml b/car_product/overlay/packages/services/Car/service/res/values/Config.xml
deleted file mode 100644
index 0680f15..0000000
--- a/car_product/overlay/packages/services/Car/service/res/values/Config.xml
+++ /dev/null
@@ -1,4 +0,0 @@
-<resources>
- <!-- default activity whitelist which are allowed while driving -->
- <string name="defauiltActivityWhitelist">com.android.systemui,com.android.car.dialer,com.android.car.hvac,com.android.car.media,com.android.car.radio,com.android.support.car.lenspicker,com.google.android.setupwizard</string>
-</resources>
diff --git a/car_product/overlay/vendor/google/apps/SetupWizard/res/xml/wizard_script_setup_as_new_flow.xml b/car_product/overlay/vendor/google/apps/SetupWizard/res/xml/wizard_script_setup_as_new_flow.xml
deleted file mode 100644
index 3732918..0000000
--- a/car_product/overlay/vendor/google/apps/SetupWizard/res/xml/wizard_script_setup_as_new_flow.xml
+++ /dev/null
@@ -1,191 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
- Copyright (c) 2017 Google Inc.
-
- 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.
--->
-
-<!--
- The wizard:uris recorded here have the inconvenience of being generated by hand, but they allow
- for the full spread of launch flags (we need FLAG_ACTIVITY_NEW_TASK [0x10000000]), where the
- <intent> tag processed by Intent.parseIntent() does not.
-
- adb shell am to-intent-uri -a com.android.setupwizard.WELCOME -f 0x10000000 \-\-ez firstRun true
--->
-<WizardScript xmlns:wizard="http://schemas.android.com/apk/res/com.google.android.setupwizard"
- wizard:firstAction="device_owner_warning">
-
- <!-- Security warning [RECOMMENDED] -->
- <WizardAction id="device_owner_warning"
- wizard:uri="intent:#Intent;action=com.google.android.setupwizard.DEVICE_OWNER_WARNING;end">
- <result wizard:name="skip"
- wizard:resultCode="1"
- wizard:action="check_frp" />
- <result wizard:action="factory_reset" />
- </WizardAction>
-
- <WizardAction id="factory_reset"
- wizard:uri="intent:#Intent;action=com.google.android.setupwizard.FACTORY_RESET;end">
- <!-- Factory reset should cause a reboot, but if it returns unexpectedly,
- continue on to check_frp -->
- <result wizard:action="check_frp" />
- </WizardAction>
-
-
- <!-- Wait to check factory reset protection status [RECOMMENDED] -->
- <WizardAction id="check_frp"
- wizard:uri="intent:#Intent;action=com.google.android.setupwizard.CHECK_FRP;end">
- <result wizard:action="bluetooth_settings" />
- </WizardAction>
-
- <!-- Bluetooth selection [REQUIRED, CUSTOMIZABLE] -->
- <WizardAction id="bluetooth_settings"
- wizard:uri="intent:#Intent;action=com.android.car.setupwizard.BLUETOOTH_SETTINGS;end">
- <result wizard:action="network_settings" />
- </WizardAction>
-
-
- <!-- Users must be given the opportunity to set up an internet connection, using the given
- screens or a custom flow. -->
- <!-- Network selection [REQUIRED, CUSTOMIZABLE] -->
- <WizardAction id="network_settings"
- wizard:uri="intent:#Intent;action=com.android.setupwizard.NETWORK_SETTINGS;end">
- <result wizard:name="see_all_wifi"
- wizard:resultCode="101"
- wizard:action="wifi_settings" />
- <result wizard:name="use_cellular"
- wizard:resultCode="102"
- wizard:action="activate_mobile_data" />
- <result wizard:name="skip"
- wizard:resultCode="1"
- wizard:action="no_network_flow" />
- <result wizard:action="captive_portal" />
- </WizardAction>
-
- <!-- Mobile data activation -->
- <WizardAction id="activate_mobile_data"
- wizard:uri="intent:#Intent;action=com.android.setupwizard.ACTIVATE_MOBILE_DATA;end">
- <result wizard:action="captive_portal" />
- </WizardAction>
-
- <!-- Wi-Fi setup -->
- <WizardAction id="wifi_settings"
- wizard:uri="intent:#Intent;action=com.android.setupwizard.WIFI_SETTINGS;end">
- <result wizard:action="captive_portal" />
- </WizardAction>
-
-
- <!-- Resolve captive portal access, and wait for check-in [REQUIRED] -->
- <WizardAction id="captive_portal"
- wizard:uri="intent:#Intent;action=com.android.setupwizard.CAPTIVE_PORTAL;end">
- <result wizard:action="gms_checkin" />
- </WizardAction>
- <WizardAction id="gms_checkin"
- wizard:uri="intent:#Intent;action=com.google.android.setupwizard.GMS_CHECKIN;end">
- <result wizard:action="ota_update" />
- </WizardAction>
-
-
- <!-- Update system packages [REQUIRED] -->
- <WizardAction id="ota_update"
- wizard:uri="intent:#Intent;action=com.google.android.setupwizard.OTA_UPDATE;end">
- <result wizard:name="skip"
- wizard:resultCode="1"
- wizard:action="early_update" />
- <result wizard:action="system_update" />
- </WizardAction>
-
- <WizardAction id="system_update"
- wizard:uri="intent:#Intent;action=android.settings.SYSTEM_UPDATE_SETTINGS;end">
- <!-- System update should cause a reboot, but if it returns unexpectedly, continue on to
- early update -->
- <result wizard:action="early_update" />
- </WizardAction>
-
-
- <!-- Update other important packages [REQUIRED] -->
- <WizardAction id="early_update"
- wizard:uri="intent:#Intent;action=com.google.android.setupwizard.EARLY_UPDATE;end">
- <result wizard:action="zero_touch" />
- </WizardAction>
-
-
- <!-- Zero touch provisioning (for enterprise) [RECOMMENDED] -->
- <WizardAction id="zero_touch"
- wizard:script="android.resource://com.google.android.setupwizard/xml/wizard_script_zero_touch_flow" >
- <result wizard:name="dpm_user_complete"
- wizard:resultCode="111" />
- <result wizard:action="load_account_intent" />
- </WizardAction>
-
-
- <!-- Add an account [REQUIRED] -->
- <WizardAction id="load_account_intent"
- wizard:uri="intent:#Intent;action=com.google.android.setupwizard.LOAD_ADD_ACCOUNT_INTENT;B.showTapAndGo=false;end">
- <result wizard:action="account_setup" />
- </WizardAction>
-
- <WizardAction id="account_setup"
- wizard:uri="intent:#Intent;action=com.google.android.setupwizard.ACCOUNT_SETUP;end">
- <result wizard:name="skip"
- wizard:resultCode="1"
- wizard:action="no_account_flow" />
- <!-- Alternate flow if managed provisioning already set the user up (for enterprise) [RECOMMENDED] -->
- <result wizard:name="dpm_user_complete"
- wizard:resultCode="111" />
- <result wizard:action="gms_account_checkin" />
- </WizardAction>
-
-
- <!-- Checkin with Gservices using account. If it fails, VPA will not be available. [REQUIRED] -->
- <WizardAction id="gms_account_checkin"
- wizard:uri="intent:#Intent;action=com.google.android.setupwizard.GMS_ACCOUNT_CHECKIN;end">
- <result wizard:name="skip"
- wizard:resultCode="1"
- wizard:action="mfm_check" />
- <result wizard:action="start_vpa" />
- </WizardAction>
-
-
- <!-- Initiate VPA (required for Play Auto-Installs) [RECOMMENDED] -->
- <WizardAction id="start_vpa"
- wizard:uri="intent:#Intent;action=com.google.android.setupwizard.START_VPA;end">
- <result wizard:action="mfm_check" />
- </WizardAction>
-
-
- <!-- Branch to script for setting up with or without an account [REQUIRED] -->
- <WizardAction id="mfm_check"
- wizard:uri="intent:#Intent;action=com.google.android.setupwizard.ACCOUNT_CHECK;end">
- <result wizard:name="skip"
- wizard:resultCode="1"
- wizard:action="no_account_flow" />
- <result wizard:action="account_flow" />
- </WizardAction>
-
-
- <!-- Set up with an account [REQUIRED] -->
- <WizardAction id="account_flow"
- wizard:script="android.resource://com.google.android.setupwizard/xml/wizard_script_new_device_account_flow" />
-
-
- <!-- Set up without an account [REQUIRED] -->
- <WizardAction id="no_account_flow"
- wizard:script="android.resource://com.google.android.setupwizard/xml/wizard_script_no_account_flow" />
-
-
- <!-- Set up without a network connection [RECOMMENDED] -->
- <WizardAction id="no_network_flow"
- wizard:script="android.resource://com.google.android.setupwizard/xml/wizard_script_no_network_flow" />
-
-</WizardScript>
diff --git a/car_product/overlay/vendor/google/apps/SetupWizard/res/xml/wizard_script_user.xml b/car_product/overlay/vendor/google/apps/SetupWizard/res/xml/wizard_script_user.xml
deleted file mode 100644
index 795c573..0000000
--- a/car_product/overlay/vendor/google/apps/SetupWizard/res/xml/wizard_script_user.xml
+++ /dev/null
@@ -1,163 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
- Copyright (c) 2017 Google Inc.
-
- 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.
--->
-
-<!--
- The wizard:uris recorded here have the inconvenience of being generated by hand, but they allow
- for the full spread of launch flags (we need FLAG_ACTIVITY_NEW_TASK [0x10000000]), where the
- <intent> tag processed by Intent.parseIntent() does not.
-
- adb shell am to-intent-uri -a com.android.setupwizard.WELCOME -f 0x10000000 \-\-ez firstRun true
--->
-<WizardScript xmlns:wizard="http://schemas.android.com/apk/res/com.google.android.setupwizard"
- wizard:firstAction="oem_pre_setup">
-
- <!-- Preliminary setup for OEMs [CUSTOMIZABLE] -->
- <WizardAction id="oem_pre_setup"
- wizard:uri="intent:#Intent;action=com.android.setupwizard.OEM_PRE_SETUP;end">
- <result wizard:action="secondary_user_warning" />
- </WizardAction>
-
-
- <!-- Secondary user warning [RECOMMENDED, CUSTOMIZABLE] -->
- <WizardAction id="secondary_user_warning"
- wizard:uri="intent:#Intent;action=com.android.setupwizard.USER_WARNING;end">
- <result wizard:name="dpm_user_complete"
- wizard:resultCode="111"
- wizard:action="check_user_unlock_dpm_user_complete" />
- <result wizard:action="check_user_unlock" />
- </WizardAction>
-
- <WizardAction id="check_user_unlock_dpm_user_complete"
- wizard:uri="intent:#Intent;action=com.android.setupwizard.CHECK_USER_UNLOCK;end">
- <result wizard:action="oem_post_setup" />
- </WizardAction>
-
- <WizardAction id="check_user_unlock"
- wizard:uri="intent:#Intent;action=com.android.setupwizard.CHECK_USER_UNLOCK;end">
- <result wizard:action="bluetooth_settings" />
- </WizardAction>
-
- <!-- Bluetooth selection [REQUIRED, CUSTOMIZABLE] -->
- <WizardAction id="bluetooth_settings"
- wizard:uri="intent:#Intent;action=com.android.car.setupwizard.BLUETOOTH_SETTINGS;end">
- <result wizard:action="network_settings" />
- </WizardAction>
-
- <!-- Network selection [REQUIRED, CUSTOMIZABLE] -->
- <WizardAction id="network_settings"
- wizard:uri="intent:#Intent;action=com.android.setupwizard.NETWORK_SETTINGS;end">
- <result wizard:name="see_all_wifi"
- wizard:resultCode="101"
- wizard:action="wifi_settings" />
- <result wizard:name="skip"
- wizard:resultCode="1"
- wizard:action="no_account_flow" />
- <result wizard:action="captive_portal" />
- </WizardAction>
-
-
- <!-- Wi-Fi setup [REQUIRED, CUSTOMIZABLE] -->
- <WizardAction id="wifi_settings"
- wizard:uri="intent:#Intent;action=com.android.setupwizard.WIFI_SETTINGS;end">
- <result wizard:action="captive_portal" />
- </WizardAction>
-
-
- <!-- Resolve captive portal access, and wait for check-in [REQUIRED] -->
- <WizardAction id="captive_portal"
- wizard:uri="intent:#Intent;action=com.android.setupwizard.CAPTIVE_PORTAL;end">
- <result wizard:action="gms_checkin" />
- </WizardAction>
-
- <WizardAction id="gms_checkin"
- wizard:uri="intent:#Intent;action=com.google.android.setupwizard.GMS_CHECKIN;end">
- <result wizard:action="load_account_intent" />
- </WizardAction>
-
-
- <!-- Add an account [REQUIRED] -->
- <WizardAction id="load_account_intent"
- wizard:uri="intent:#Intent;action=com.google.android.setupwizard.LOAD_ADD_ACCOUNT_INTENT;end">
- <result wizard:action="account_setup" />
- </WizardAction>
-
- <WizardAction id="account_setup"
- wizard:uri="intent:#Intent;action=com.google.android.setupwizard.ACCOUNT_SETUP;end">
- <result wizard:name="skip"
- wizard:resultCode="1"
- wizard:action="no_account_flow" />
- <!-- Alternate flow if managed provisioning already set the user up (for enterprise) [RECOMMENDED] -->
- <result wizard:name="dpm_user_complete"
- wizard:resultCode="111"
- wizard:action="oem_post_setup" />
- <result wizard:action="gms_account_checkin" />
- </WizardAction>
-
-
- <!-- Checkin with Gservices using account. If it fails, VPA will not be available. [REQUIRED] -->
- <WizardAction id="gms_account_checkin"
- wizard:uri="intent:#Intent;action=com.google.android.setupwizard.GMS_ACCOUNT_CHECKIN;end">
- <result wizard:name="skip"
- wizard:resultCode="1"
- wizard:action="mfm_check" />
- <result wizard:action="start_vpa" />
- </WizardAction>
-
-
- <!-- Initiate VPA (required for Play Auto-Installs) [RECOMMENDED] -->
- <WizardAction id="start_vpa"
- wizard:uri="intent:#Intent;action=com.google.android.setupwizard.START_VPA;end">
- <result wizard:action="mfm_check" />
- </WizardAction>
-
-
- <!-- Branch to script for setting up with or without an account [REQUIRED] -->
- <WizardAction id="mfm_check"
- wizard:uri="intent:#Intent;action=com.google.android.setupwizard.ACCOUNT_CHECK;end">
- <result wizard:name="skip"
- wizard:resultCode="1"
- wizard:action="no_account_flow" />
- <result wizard:action="account_flow" />
- </WizardAction>
-
-
- <!-- Set up with an account [REQUIRED] -->
- <WizardAction id="account_flow"
- wizard:script="android.resource://com.google.android.setupwizard/xml/wizard_script_user_account_flow">
- <result wizard:action="oem_post_setup" />
- </WizardAction>
-
-
- <!-- Set up without an account [REQUIRED] -->
- <WizardAction id="no_account_flow"
- wizard:script="android.resource://com.google.android.setupwizard/xml/wizard_script_user_no_account_flow">
- <result wizard:action="oem_post_setup" />
- </WizardAction>
-
-
- <!-- OEM completion [CUSTOMIZABLE] -->
- <WizardAction id="oem_post_setup"
- wizard:uri="intent:#Intent;action=com.android.setupwizard.OEM_POST_SETUP;end">
- <result wizard:action="exit" />
- </WizardAction>
-
-
- <!-- Leave Setup Wizard [REQUIRED] -->
- <WizardAction id="exit"
- wizard:uri="intent:#Intent;action=com.android.setupwizard.EXIT;end" />
-
-</WizardScript>
diff --git a/car_product/sepolicy/attributes b/car_product/sepolicy/attributes
deleted file mode 100644
index e47042c..0000000
--- a/car_product/sepolicy/attributes
+++ /dev/null
@@ -1,4 +0,0 @@
-# HALs
-attribute hal_vehicle;
-attribute hal_vehicle_client;
-attribute hal_vehicle_server;
diff --git a/car_product/sepolicy/domain.te b/car_product/sepolicy/domain.te
deleted file mode 100644
index bb451f3..0000000
--- a/car_product/sepolicy/domain.te
+++ /dev/null
@@ -1,3 +0,0 @@
-# Ignore personality-8 denials.
-dontaudit domain kernel:system module_request;
-
diff --git a/car_product/sepolicy/file_contexts b/car_product/sepolicy/file_contexts
deleted file mode 100644
index 3705765..0000000
--- a/car_product/sepolicy/file_contexts
+++ /dev/null
@@ -1,10 +0,0 @@
-
-###################################
-# System files
-#
-/system/bin/vehicle_monitor_service u:object_r:vms_exec:s0
-
-/(vendor|system/vendor)/bin/hw/android\.hardware\.automotive\.vehicle@2\.0-service u:object_r:hal_vehicle_default_exec:s0
-/(vendor|system/vendor)/bin/hw/android\.hardware\.automotive\.vehicle@2\.1-service u:object_r:hal_vehicle_default_exec:s0
-
-###################################
diff --git a/car_product/sepolicy/hal_vehicle.te b/car_product/sepolicy/hal_vehicle.te
deleted file mode 100644
index 6db6c82..0000000
--- a/car_product/sepolicy/hal_vehicle.te
+++ /dev/null
@@ -1,3 +0,0 @@
-# HwBinder IPC from client to server, and callbacks
-binder_call(hal_vehicle_client, hal_vehicle_server)
-binder_call(hal_vehicle_server, hal_vehicle_client)
diff --git a/car_product/sepolicy/hal_vehicle_default.te b/car_product/sepolicy/hal_vehicle_default.te
deleted file mode 100644
index dcae7a6..0000000
--- a/car_product/sepolicy/hal_vehicle_default.te
+++ /dev/null
@@ -1,9 +0,0 @@
-# vehicle subsystem
-type hal_vehicle_default, domain;
-hal_server_domain(hal_vehicle_default, hal_vehicle)
-
-# may be started by init
-type hal_vehicle_default_exec, exec_type, file_type;
-init_daemon_domain(hal_vehicle_default)
-
-allow hal_vehicle_default car_service:service_manager { add };
diff --git a/car_product/sepolicy/init.te b/car_product/sepolicy/init.te
deleted file mode 100644
index a80ab0e..0000000
--- a/car_product/sepolicy/init.te
+++ /dev/null
@@ -1,2 +0,0 @@
-# Allow legacy sdcard for creating directory symlinks
-allow init tmpfs:lnk_file create_file_perms;
diff --git a/car_product/sepolicy/netd.te b/car_product/sepolicy/netd.te
deleted file mode 100644
index 2b002ec..0000000
--- a/car_product/sepolicy/netd.te
+++ /dev/null
@@ -1 +0,0 @@
-dontaudit netd self:capability sys_module;
diff --git a/car_product/sepolicy/priv_app.te b/car_product/sepolicy/priv_app.te
deleted file mode 100644
index e6b5292..0000000
--- a/car_product/sepolicy/priv_app.te
+++ /dev/null
@@ -1 +0,0 @@
-hal_client_domain(priv_app, hal_vehicle)
diff --git a/car_product/sepolicy/private/carservice_app.te b/car_product/sepolicy/private/carservice_app.te
new file mode 100644
index 0000000..d02c377
--- /dev/null
+++ b/car_product/sepolicy/private/carservice_app.te
@@ -0,0 +1,49 @@
+# Domain to run Car Service (com.android.car)
+app_domain(carservice_app);
+
+# Allow Car Service to be the client of Vehicle and Audio Control HALs
+hal_client_domain(carservice_app, hal_audiocontrol)
+hal_client_domain(carservice_app, hal_vehicle)
+
+# Allow to set boot.car_service_created property
+set_prop(carservice_app, system_prop)
+
+# Allow Car Service to register itself with ServiceManager
+allow carservice_app carservice_service:service_manager add;
+
+# Allow Car Service to access certain system services.
+# Keep alphabetically sorted.
+allow carservice_app {
+ accessibility_service
+ activity_service
+ audio_service
+ audioserver_service
+ autofill_service
+ bluetooth_manager_service
+ connectivity_service
+ content_service
+ deviceidle_service
+ display_service
+ graphicsstats_service
+ input_method_service
+ input_service
+ location_service
+ network_management_service
+ power_service
+ procfsinspector_service
+ sensorservice_service
+ surfaceflinger_service
+ uimode_service
+}:service_manager find;
+
+# Read and write /data/data subdirectory.
+allow carservice_app system_app_data_file:dir create_dir_perms;
+allow carservice_app system_app_data_file:{ file lnk_file } create_file_perms;
+
+# For I/O stats tracker
+allow carservice_app proc_uid_io_stats:file { read open getattr };
+
+allow carservice_app procfsinspector:binder call;
+
+# To access /sys/fs/<type>/<partition>/lifetime_write_kbytes
+allow carservice_app sysfs_fs_lifetime_write:file { getattr open read };
diff --git a/car_product/sepolicy/private/file_contexts b/car_product/sepolicy/private/file_contexts
new file mode 100644
index 0000000..5283993
--- /dev/null
+++ b/car_product/sepolicy/private/file_contexts
@@ -0,0 +1 @@
+/system/bin/com\.android\.car\.procfsinspector u:object_r:procfsinspector_exec:s0
diff --git a/car_product/sepolicy/private/procfsinspector.te b/car_product/sepolicy/private/procfsinspector.te
new file mode 100644
index 0000000..9bee707
--- /dev/null
+++ b/car_product/sepolicy/private/procfsinspector.te
@@ -0,0 +1,12 @@
+type procfsinspector, domain, coredomain;
+type procfsinspector_exec, exec_type, file_type;
+
+init_daemon_domain(procfsinspector)
+
+add_service(procfsinspector, procfsinspector_service)
+binder_use(procfsinspector)
+
+allow carservice_app procfsinspector:binder call;
+
+dontaudit procfsinspector domain:dir getattr;
+
diff --git a/car_product/sepolicy/private/property_contexts b/car_product/sepolicy/private/property_contexts
new file mode 100644
index 0000000..dc6b0c5
--- /dev/null
+++ b/car_product/sepolicy/private/property_contexts
@@ -0,0 +1 @@
+boot.car_service_created u:object_r:system_prop:s0
diff --git a/car_product/sepolicy/private/seapp_contexts b/car_product/sepolicy/private/seapp_contexts
new file mode 100644
index 0000000..97217bf
--- /dev/null
+++ b/car_product/sepolicy/private/seapp_contexts
@@ -0,0 +1 @@
+user=system seinfo=platform name=com.android.car domain=carservice_app type=system_app_data_file
diff --git a/car_product/sepolicy/private/service_contexts b/car_product/sepolicy/private/service_contexts
new file mode 100644
index 0000000..7ac544c
--- /dev/null
+++ b/car_product/sepolicy/private/service_contexts
@@ -0,0 +1,2 @@
+car_service u:object_r:carservice_service:s0
+com.android.car.procfsinspector u:object_r:procfsinspector_service:s0
diff --git a/car_product/sepolicy/property.te b/car_product/sepolicy/property.te
deleted file mode 100644
index 64340e7..0000000
--- a/car_product/sepolicy/property.te
+++ /dev/null
@@ -1,3 +0,0 @@
-type hw_cabl_prop, property_type;
-type wlan_driver_prop, property_type;
-type car_prop, property_type;
diff --git a/car_product/sepolicy/property_contexts b/car_product/sepolicy/property_contexts
deleted file mode 100644
index 3b680cb..0000000
--- a/car_product/sepolicy/property_contexts
+++ /dev/null
@@ -1,4 +0,0 @@
-hw.cabl. u:object_r:hw_cabl_prop:s0
-wlan.driver. u:object_r:wlan_driver_prop:s0
-
-boot.car_service_created u:object_r:car_prop:s0
diff --git a/car_product/sepolicy/public/carservice_app.te b/car_product/sepolicy/public/carservice_app.te
new file mode 100644
index 0000000..fd276b6
--- /dev/null
+++ b/car_product/sepolicy/public/carservice_app.te
@@ -0,0 +1,2 @@
+# Domain to run Car Service (com.android.car)
+type carservice_app, domain, coredomain;
diff --git a/car_product/sepolicy/public/file.te b/car_product/sepolicy/public/file.te
new file mode 100644
index 0000000..ea79a24
--- /dev/null
+++ b/car_product/sepolicy/public/file.te
@@ -0,0 +1,5 @@
+# This type for lifetime_write_kbytes files which resides in
+# /sys/fs/<filesystem>/<partition>/lifetime_writes_kbytes
+# Vendors are supposed to extend genfs_contexts with the
+# partition names for their devices.
+type sysfs_fs_lifetime_write, sysfs_type, fs_type;
diff --git a/car_product/sepolicy/public/service.te b/car_product/sepolicy/public/service.te
new file mode 100644
index 0000000..6c514f3
--- /dev/null
+++ b/car_product/sepolicy/public/service.te
@@ -0,0 +1,2 @@
+type carservice_service, service_manager_type;
+type procfsinspector_service, service_manager_type;
diff --git a/car_product/sepolicy/service.te b/car_product/sepolicy/service.te
deleted file mode 100644
index b92ed0a..0000000
--- a/car_product/sepolicy/service.te
+++ /dev/null
@@ -1 +0,0 @@
-type car_service, service_manager_type;
diff --git a/car_product/sepolicy/service_contexts b/car_product/sepolicy/service_contexts
deleted file mode 100644
index 63aff46..0000000
--- a/car_product/sepolicy/service_contexts
+++ /dev/null
@@ -1 +0,0 @@
-com.android.car.vehiclenetwork.IVehicleNetwork u:object_r:car_service:s0
diff --git a/car_product/sepolicy/system_app.te b/car_product/sepolicy/system_app.te
deleted file mode 100644
index 903febf..0000000
--- a/car_product/sepolicy/system_app.te
+++ /dev/null
@@ -1,3 +0,0 @@
-hal_client_domain(system_app, hal_vehicle)
-
-set_prop(system_app, car_prop)
diff --git a/car_product/sepolicy/system_server.te b/car_product/sepolicy/system_server.te
deleted file mode 100644
index b6785c1..0000000
--- a/car_product/sepolicy/system_server.te
+++ /dev/null
@@ -1,4 +0,0 @@
-# Set wlan.driver.* properties.
-set_prop(system_server, wlan_driver_prop)
-
-dontaudit system_server self:capability sys_module;
diff --git a/car_product/sepolicy/test/file_contexts b/car_product/sepolicy/test/file_contexts
new file mode 100644
index 0000000..7be7605
--- /dev/null
+++ b/car_product/sepolicy/test/file_contexts
@@ -0,0 +1 @@
+/system/bin/com\.android\.car\.powertestservice u:object_r:powertestservice_exec:s0
diff --git a/car_product/sepolicy/test/kitchensink_app.te b/car_product/sepolicy/test/kitchensink_app.te
new file mode 100644
index 0000000..8bd5a68
--- /dev/null
+++ b/car_product/sepolicy/test/kitchensink_app.te
@@ -0,0 +1,30 @@
+# Domain to run EmbeddedKitchenSink app (for test-purpose)
+type kitchensink_app, domain;
+app_domain(kitchensink_app);
+
+# Allow Car Service to be the client of Vehicle HAL
+hal_client_domain(kitchensink_app, hal_vehicle)
+
+# Keep alphabetically sorted.
+allow kitchensink_app {
+ accessibility_service
+ activity_service
+ autofill_service
+ connectivity_service
+ content_service
+ deviceidle_service
+ display_service
+ graphicsstats_service
+ input_method_service
+ input_service
+ location_service
+ network_management_service
+ power_service
+ sensorservice_service
+ surfaceflinger_service
+ uimode_service
+}:service_manager find;
+
+# Read and write /data/data subdirectory.
+allow kitchensink_app system_app_data_file:dir { create_dir_perms getattr };
+allow kitchensink_app system_app_data_file:{ file lnk_file } create_file_perms;
diff --git a/car_product/sepolicy/test/powertestservice.te b/car_product/sepolicy/test/powertestservice.te
new file mode 100644
index 0000000..2e2ace7
--- /dev/null
+++ b/car_product/sepolicy/test/powertestservice.te
@@ -0,0 +1,9 @@
+type powertestservice, domain, coredomain;
+type powertestservice_exec, exec_type, file_type;
+
+init_daemon_domain(powertestservice)
+
+binder_use(powertestservice)
+binder_call(powertestservice, carservice_app)
+
+allow powertestservice carservice_service:service_manager find;
diff --git a/car_product/sepolicy/test/seapp_contexts b/car_product/sepolicy/test/seapp_contexts
new file mode 100644
index 0000000..530e60e
--- /dev/null
+++ b/car_product/sepolicy/test/seapp_contexts
@@ -0,0 +1 @@
+user=system seinfo=platform name=com.google.android.car.kitchensink domain=kitchensink_app type=system_app_data_file
diff --git a/car_product/sepolicy/vehicle_monitor_service.te b/car_product/sepolicy/vehicle_monitor_service.te
deleted file mode 100644
index 16c6f81..0000000
--- a/car_product/sepolicy/vehicle_monitor_service.te
+++ /dev/null
@@ -1,4 +0,0 @@
-type vehicle_monitor_service_exec, exec_type, file_type;
-type vehicle_monitor_service, domain;
-
-init_daemon_domain(vehicle_monitor_service)
diff --git a/car_product/sepolicy/vehicle_network_service.te b/car_product/sepolicy/vehicle_network_service.te
deleted file mode 100644
index cef863a..0000000
--- a/car_product/sepolicy/vehicle_network_service.te
+++ /dev/null
@@ -1,4 +0,0 @@
-type vehicle_network_service_exec, exec_type, file_type;
-type vehicle_network_service, domain;
-
-init_daemon_domain(vehicle_network_service)
diff --git a/car_product/sepolicy/vms.te b/car_product/sepolicy/vms.te
deleted file mode 100644
index fc77b53..0000000
--- a/car_product/sepolicy/vms.te
+++ /dev/null
@@ -1,11 +0,0 @@
-# Vehicle monitor service
-type vms, domain;
-type vms_exec, exec_type, file_type;
-
-allow vms system_app:binder { call };
-allow vms car_service:service_manager { add };
-allow vms priv_app:binder { call };
-
-init_daemon_domain(vms)
-
-binder_use(vms);
\ No newline at end of file
diff --git a/evs/app/RenderTopView.cpp b/evs/app/RenderTopView.cpp
index e8f7399..5bc943c 100644
--- a/evs/app/RenderTopView.cpp
+++ b/evs/app/RenderTopView.cpp
@@ -133,7 +133,7 @@
// Load the checkerboard text image
mTexAssets.checkerBoard.reset(createTextureFromPng(
"/system/etc/automotive/evs/LabeledChecker.png"));
- if (!mTexAssets.checkerBoard->glId()) {
+ if (!mTexAssets.checkerBoard) {
ALOGE("Failed to load checkerboard texture");
return false;
}
@@ -141,7 +141,7 @@
// Load the car image
mTexAssets.carTopView.reset(createTextureFromPng(
"/system/etc/automotive/evs/CarFromTop.png"));
- if (!mTexAssets.carTopView->glId()) {
+ if (!mTexAssets.carTopView) {
ALOGE("Failed to load carTopView texture");
return false;
}
diff --git a/evs/app/WindowSurface.cpp b/evs/app/WindowSurface.cpp
index a3f56bc..04e7ac4 100644
--- a/evs/app/WindowSurface.cpp
+++ b/evs/app/WindowSurface.cpp
@@ -62,19 +62,10 @@
return;
}
- SurfaceComposerClient::openGlobalTransaction();
- err = sc->setLayer(0x7FFFFFFF); // always on top
- if (err != NO_ERROR) {
- fprintf(stderr, "SurfaceComposer::setLayer error: %#x\n", err);
- return;
- }
-
- err = sc->show();
- if (err != NO_ERROR) {
- fprintf(stderr, "SurfaceComposer::show error: %#x\n", err);
- return;
- }
- SurfaceComposerClient::closeGlobalTransaction();
+ SurfaceComposerClient::Transaction{}
+ .setLayer(sc, 0x7FFFFFFF) // always on top
+ .show(sc)
+ .apply();
mSurfaceControl = sc;
}
diff --git a/evs/app/evs_app.cpp b/evs/app/evs_app.cpp
index 618e8cc..31e5ab6 100644
--- a/evs/app/evs_app.cpp
+++ b/evs/app/evs_app.cpp
@@ -50,7 +50,7 @@
SubscribeOptions optionsData[] = {
{
.propId = static_cast<int32_t>(propertyId),
- .flags = SubscribeFlags::DEFAULT
+ .flags = SubscribeFlags::EVENTS_FROM_CAR
},
};
hidl_vec <SubscribeOptions> options;
@@ -97,7 +97,10 @@
// Load our configuration information
ConfigManager config;
- config.initialize("/system/etc/automotive/evs/config.json");
+ if (!config.initialize("/system/etc/automotive/evs/config.json")) {
+ ALOGE("Missing or improper configuration for the EVS application. Exiting.");
+ return 1;
+ }
// Set thread pool size to one to avoid concurrent events from the HAL.
// This pool will handle the EvsCameraStream callbacks.
diff --git a/evs/app/evs_app.rc b/evs/app/evs_app.rc
index a61edfe..69832f9 100644
--- a/evs/app/evs_app.rc
+++ b/evs/app/evs_app.rc
@@ -1,5 +1,5 @@
-service evs_app /system/bin/evs_app
- class hal
- priority -20
- user automotive_evs
- group automotive_evs
+#service evs_app /system/bin/evs_app
+# class hal
+# priority -20
+# user automotive_evs
+# group automotive_evs
diff --git a/evs/manager/android.automotive.evs.manager@1.0.rc b/evs/manager/android.automotive.evs.manager@1.0.rc
index 8a53ba7..b1b2c97 100644
--- a/evs/manager/android.automotive.evs.manager@1.0.rc
+++ b/evs/manager/android.automotive.evs.manager@1.0.rc
@@ -1,6 +1,6 @@
-service evs_manager /system/bin/android.automotive.evs.manager@1.0
- class hal
- priority -20
- user automotive_evs
- group automotive_evs
- onrestart restart evs_app
+#service evs_manager /system/bin/android.automotive.evs.manager@1.0
+# class hal
+# priority -20
+# user automotive_evs
+# group automotive_evs
+# onrestart restart evs_app
diff --git a/evs/manager/service.cpp b/evs/manager/service.cpp
index f9e45eb..20504a0 100644
--- a/evs/manager/service.cpp
+++ b/evs/manager/service.cpp
@@ -38,6 +38,28 @@
using namespace android;
+static void startService(const char *hardwareServiceName, const char * managerServiceName) {
+ ALOGI("EVS managed service connecting to hardware service at %s", hardwareServiceName);
+ android::sp<Enumerator> service = new Enumerator();
+ if (!service->init(hardwareServiceName)) {
+ ALOGE("Failed to connect to hardware service - quitting from registrationThread");
+ exit(1);
+ }
+
+ // Register our service -- if somebody is already registered by our name,
+ // they will be killed (their thread pool will throw an exception).
+ ALOGI("EVS managed service is starting as %s", managerServiceName);
+ status_t status = service->registerAsService(managerServiceName);
+ if (status != OK) {
+ ALOGE("Could not register service %s (%d) - quitting from registrationThread",
+ managerServiceName, status);
+ exit(2);
+ }
+
+ ALOGD("Registration complete");
+}
+
+
int main(int argc, char** argv) {
ALOGI("EVS manager starting\n");
@@ -72,26 +94,14 @@
// threads beyond the main thread which will "join" the pool below.
configureRpcThreadpool(1, true /* callerWillJoin */);
- ALOGI("EVS managed service connecting to hardware service at %s", evsHardwareServiceName);
- android::sp<Enumerator> service = new Enumerator();
- if (!service->init(evsHardwareServiceName)) {
- ALOGE("Failed to initialize");
- return 1;
- }
+ // The connection to the underlying hardware service must happen on a dedicated thread to ensure
+ // that the hwbinder response can be processed by the thread pool without blocking.
+ std::thread registrationThread(startService, evsHardwareServiceName, kManagedEnumeratorName);
- // Register our service -- if somebody is already registered by our name,
- // they will be killed (their thread pool will throw an exception).
- ALOGI("EVS managed service is starting as %s", kManagedEnumeratorName);
- status_t status = service->registerAsService(kManagedEnumeratorName);
- if (status == OK) {
- ALOGD("Registration complete");
-
- // Send this main thread to become a permanent part of the thread pool.
- // This is not expected to return.
- joinRpcThreadpool();
- } else {
- ALOGE("Could not register service %s (%d).", kManagedEnumeratorName, status);
- }
+ // Send this main thread to become a permanent part of the thread pool.
+ // This is not expected to return.
+ ALOGD("Main thread entering thread pool");
+ joinRpcThreadpool();
// In normal operation, we don't expect the thread pool to exit
ALOGE("EVS Hardware Enumerator is shutting down");
diff --git a/evs/sampleDriver/GlWrapper.cpp b/evs/sampleDriver/GlWrapper.cpp
index eb45bc9..3055ba0 100644
--- a/evs/sampleDriver/GlWrapper.cpp
+++ b/evs/sampleDriver/GlWrapper.cpp
@@ -339,19 +339,19 @@
void GlWrapper::showWindow() {
if (mFlingerSurfaceControl != nullptr) {
- SurfaceComposerClient::openGlobalTransaction();
- mFlingerSurfaceControl->setLayer(0x7FFFFFFF); // always on top
- mFlingerSurfaceControl->show();
- SurfaceComposerClient::closeGlobalTransaction();
+ SurfaceComposerClient::Transaction{}
+ .setLayer(mFlingerSurfaceControl, 0x7FFFFFFF) // always on top
+ .show(mFlingerSurfaceControl)
+ .apply();
}
}
void GlWrapper::hideWindow() {
if (mFlingerSurfaceControl != nullptr) {
- SurfaceComposerClient::openGlobalTransaction();
- mFlingerSurfaceControl->hide();
- SurfaceComposerClient::closeGlobalTransaction();
+ SurfaceComposerClient::Transaction{}
+ .hide(mFlingerSurfaceControl)
+ .apply();
}
}
diff --git a/evs/sepolicy/attributes b/evs/sepolicy/attributes
deleted file mode 100644
index d31005b..0000000
--- a/evs/sepolicy/attributes
+++ /dev/null
@@ -1,4 +0,0 @@
-# EVS specific attributes
-attribute hal_evs;
-attribute hal_evs_client;
-attribute hal_evs_server;
diff --git a/evs/sepolicy/evs_app.te b/evs/sepolicy/evs_app.te
index 28e71a9..ef78f0b 100644
--- a/evs/sepolicy/evs_app.te
+++ b/evs/sepolicy/evs_app.te
@@ -1,5 +1,5 @@
# evs app
-type evs_app, domain;
+type evs_app, domain, coredomain;
hal_client_domain(evs_app, hal_evs)
hal_client_domain(evs_app, hal_vehicle)
@@ -19,4 +19,4 @@
# Permit communication with the vehicle HAL
# (Communcations with the rest of the EVS stack is allowed via hal_evs)
-binder_call(evs_app, hal_vehicle);
\ No newline at end of file
+binder_call(evs_app, hal_vehicle);
diff --git a/evs/sepolicy/evs_default.te b/evs/sepolicy/evs_default.te
deleted file mode 100644
index c90e34b..0000000
--- a/evs/sepolicy/evs_default.te
+++ /dev/null
@@ -1,7 +0,0 @@
-# evs_mock mock hardware driver service
-type hal_evs_default, domain;
-hal_server_domain(hal_evs_default, hal_evs)
-
-# allow init to launch processes in this context
-type hal_evs_default_exec, exec_type, file_type;
-init_daemon_domain(hal_evs_default)
diff --git a/evs/sepolicy/evs_driver.te b/evs/sepolicy/evs_driver.te
index 2226dd6..5d316a4 100644
--- a/evs/sepolicy/evs_driver.te
+++ b/evs/sepolicy/evs_driver.te
@@ -1,5 +1,5 @@
# evs_mock mock hardware driver service
-type hal_evs_driver, domain;
+type hal_evs_driver, domain, coredomain;
hal_server_domain(hal_evs_driver, hal_evs)
# allow init to launch processes in this context
diff --git a/evs/sepolicy/evs_manager.te b/evs/sepolicy/evs_manager.te
index 70a2cda..1f99d96 100644
--- a/evs/sepolicy/evs_manager.te
+++ b/evs/sepolicy/evs_manager.te
@@ -1,5 +1,5 @@
# evs manager
-type evs_manager, domain;
+type evs_manager, domain, coredomain;
hal_server_domain(evs_manager, hal_evs)
hal_client_domain(evs_manager, hal_evs)
diff --git a/evs/sepolicy/file_contexts b/evs/sepolicy/file_contexts
index 097a588..0358e16 100644
--- a/evs/sepolicy/file_contexts
+++ b/evs/sepolicy/file_contexts
@@ -3,7 +3,6 @@
# Binaries associated with the default EVS stack, plus
# the directory which contains the configuration for the evs_app
#
-/(vendor|system/vendor)/bin/hw/android\.hardware\.automotive\.evs@1\.0-service u:object_r:hal_evs_default_exec:s0
/system/bin/android\.hardware\.automotive\.evs@1\.0-sample u:object_r:hal_evs_driver_exec:s0
/system/bin/android\.automotive\.evs\.manager@1\.0 u:object_r:evs_manager_exec:s0
/system/bin/evs_app u:object_r:evs_app_exec:s0
diff --git a/evs/sepolicy/hal_evs.te b/evs/sepolicy/hal_evs.te
deleted file mode 100644
index 525f2be..0000000
--- a/evs/sepolicy/hal_evs.te
+++ /dev/null
@@ -1,6 +0,0 @@
-hwbinder_use(hal_evs_client)
-hwbinder_use(hal_evs_server)
-binder_call(hal_evs_client, hal_evs_server)
-binder_call(hal_evs_server, hal_evs_client)
-
-allow hal_evs_server hal_graphics_allocator_default:fd use;
\ No newline at end of file
diff --git a/libvehiclemonitor/include/HandlerThread.h b/libvehiclemonitor/include/HandlerThread.h
deleted file mode 100644
index 03f523e..0000000
--- a/libvehiclemonitor/include/HandlerThread.h
+++ /dev/null
@@ -1,49 +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.
- */
-
-#ifndef LIBVEHICLEMONITOR_HANDLER_THREAD_H_
-#define LIBVEHICLEMONITOR_HANDLER_THREAD_H_
-
-#include <utils/Looper.h>
-#include <utils/threads.h>
-
-namespace android {
-
-/**
- * Native HandlerThread implementation looking similar to Java version.
- */
-class HandlerThread : public Thread {
-public:
- HandlerThread();
- virtual ~HandlerThread();
-
- sp<Looper> getLooper();
- status_t start(const char* name = 0, int32_t priority = PRIORITY_DEFAULT, size_t stack = 0);
- void quit();
-
-private:
- bool threadLoop();
-
-private:
- sp<Looper> mLooper;
- mutable Mutex mLock;
- bool mShouldQuit;
- Condition mLooperWait;
-};
-
-};
-
-#endif /* LIBVEHICLEMONITOR_HANDLER_THREAD_H_ */
diff --git a/libvehiclemonitor/include/IVehicleMonitor.h b/libvehiclemonitor/include/IVehicleMonitor.h
deleted file mode 100644
index 4aa2e14..0000000
--- a/libvehiclemonitor/include/IVehicleMonitor.h
+++ /dev/null
@@ -1,60 +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.
- */
-
-#ifndef ANDROID_IVEHICLE_MONITOR_H
-#define ANDROID_IVEHICLE_MONITOR_H
-
-#include <binder/Parcel.h>
-
-#include <IVehicleMonitorListener.h>
-
-namespace android {
-
-// ----------------------------------------------------------------------------
-
-/**
- * Application priorities used in vehicle monitoring.
- */
-enum vehicle_app_priority {
- VEHICLE_APP_PRIORITY_NONE = 0,
- VEHICLE_APP_PRIORITY_FOREGROUND = 1,
-};
-
-// ----------------------------------------------------------------------------
-
-class IVehicleMonitor : public IInterface {
-public:
- static const char SERVICE_NAME[];
- DECLARE_META_INTERFACE(VehicleMonitor);
-
- virtual status_t setAppPriority(
- uint32_t pid, uint32_t uid, vehicle_app_priority priority) = 0;
- virtual status_t setMonitorListener(
- const sp<IVehicleMonitorListener> &listener) = 0;
-};
-// ----------------------------------------------------------------------------
-
-class BnVehicleMonitor : public BnInterface<IVehicleMonitor> {
- virtual status_t onTransact(uint32_t code,
- const Parcel& data,
- Parcel* reply,
- uint32_t flags = 0);
-};
-
-// ----------------------------------------------------------------------------
-}; // namespace android
-
-#endif /* ANDROID_IVEHICLE_MONITOR_H */
diff --git a/libvehiclemonitor/include/IVehicleMonitorListener.h b/libvehiclemonitor/include/IVehicleMonitorListener.h
deleted file mode 100644
index 9c9e1f5..0000000
--- a/libvehiclemonitor/include/IVehicleMonitorListener.h
+++ /dev/null
@@ -1,53 +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.
- */
-
-#ifndef ANDROID_IVEHICLE_MONITOR_LISTENER_H
-#define ANDROID_IVEHICLE_MONITOR_LISTENER_H
-
-#include <binder/Parcel.h>
-
-namespace android {
-
-// ----------------------------------------------------------------------------
-
-class IVehicleMonitorListener : public IInterface
-{
-public:
- DECLARE_META_INTERFACE(VehicleMonitorListener);
-
- /**
- * Notifies when app misbehaved. Client (Bn implementor) should
- * hold sp to keep the data received outside this call.
- */
- virtual void onAppViolation(
- int32_t pid, int32_t uid, int32_t action, int32_t violation) = 0;
-};
-
-// ----------------------------------------------------------------------------
-
-class BnVehicleMonitorListener : public BnInterface<IVehicleMonitorListener>
-{
- virtual status_t onTransact(uint32_t code,
- const Parcel& data,
- Parcel* reply,
- uint32_t flags = 0);
-};
-
-// ----------------------------------------------------------------------------
-
-}; // namespace android
-
-#endif /* ANDROID_IVEHICLE_MONITOR_LISTENER_H */
diff --git a/libvehiclemonitor/include/VehicleMonitor.h b/libvehiclemonitor/include/VehicleMonitor.h
deleted file mode 100644
index 12510ec..0000000
--- a/libvehiclemonitor/include/VehicleMonitor.h
+++ /dev/null
@@ -1,66 +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.
- */
-
-#ifndef ANDROID_VEHICLE_MONITOR_H
-#define ANDROID_VEHICLE_MONITOR_H
-
-#include <binder/IInterface.h>
-
-#include <utils/Mutex.h>
-
-#include "IVehicleMonitor.h"
-
-namespace android {
-
-// ----------------------------------------------------------------------------
-
-/**
- * Vehicle monitor API for low level components like HALs to access
- * monitoring service.
- * This is reference counted. So use with sp<>.
- */
-class VehicleMonitor : public IBinder::DeathRecipient {
-public:
- /**
- * Factory method for VehicleMonitor. Client should use this method
- * to create a new instance.
- */
- static sp<VehicleMonitor> createVehicleMonitor();
-
- virtual ~VehicleMonitor();
-
- status_t setAppPriority(
- uint32_t pid, uint32_t uid, vehicle_app_priority priority);
-
- //IBinder::DeathRecipient, not for client
- void binderDied(const wp<IBinder>& who);
-
-private:
- VehicleMonitor(sp<IVehicleMonitor>& vehicleMonitor);
- // RefBase
- virtual void onFirstRef();
- sp<IVehicleMonitor> getService();
-
-private:
- sp<IVehicleMonitor> mService;
- Mutex mLock;
-};
-
-// ----------------------------------------------------------------------------
-
-}; // namespace android
-
-#endif /* ANDROID_VEHICLE_MONITOR_H */
diff --git a/libvehiclemonitor/java/src/com/android/car/vehiclemonitor/IVehicleMonitor.aidl b/libvehiclemonitor/java/src/com/android/car/vehiclemonitor/IVehicleMonitor.aidl
deleted file mode 100644
index 0c495ec..0000000
--- a/libvehiclemonitor/java/src/com/android/car/vehiclemonitor/IVehicleMonitor.aidl
+++ /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.
- */
-
-package com.android.car.vehiclemonitor;
-
-import com.android.car.vehiclemonitor.IVehicleMonitorListener;
-
-/**
- * Binder API to access vehicle monitor service.
- * @hide
- */
-oneway interface IVehicleMonitor {
- void setAppPriority(int pid, int uid, int priority) = 0;
- void setMonitorListener(IVehicleMonitorListener listener) = 1;
-}
diff --git a/libvehiclemonitor/java/src/com/android/car/vehiclemonitor/VehicleMonitor.java b/libvehiclemonitor/java/src/com/android/car/vehiclemonitor/VehicleMonitor.java
deleted file mode 100644
index f5a9363..0000000
--- a/libvehiclemonitor/java/src/com/android/car/vehiclemonitor/VehicleMonitor.java
+++ /dev/null
@@ -1,182 +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.vehiclemonitor;
-
-import android.annotation.IntDef;
-import android.os.Handler;
-import android.os.Looper;
-import android.os.Message;
-import android.os.RemoteException;
-import android.os.ServiceManager;
-import android.os.ServiceSpecificException;
-
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-import java.lang.ref.WeakReference;
-
-/**
- * System API to access Vehicle monitor. This is only for system services and applications should
- * not use this. All APIs will fail with security error if normal app tries this.
- */
-public class VehicleMonitor {
- private static final String TAG = VehicleMonitor.class.getSimpleName();
-
- private final IVehicleMonitor mService;
- private final VehicleMonitorListener mListener;
- private final IVehicleMonitorListenerImpl mVehicleMonitorListener;
- private final EventHandler mEventHandler;
-
- private static final int VMS_CONNECT_MAX_RETRY = 10;
- private static final long VMS_RETRY_WAIT_TIME_MS = 1000;
-
- /**
- * Application priorities used in vehicle monitoring.
- */
- @Retention(RetentionPolicy.SOURCE)
- @IntDef({
- ApplicationPriority.NONE,
- ApplicationPriority.FOREGROUND
- })
- public @interface ApplicationPriority {
- int NONE = 0;
- int FOREGROUND = 1;
- }
-
- /**
- * Listener for VMS events.
- */
- public interface VehicleMonitorListener {
- void onAppViolation(int pid, int uid, int action, int violation);
- }
-
- /**
- * Factory method to create VehicleMonitor
- */
- public static VehicleMonitor createVehicleMonitor(
- VehicleMonitorListener listener, Looper looper) {
- int retryCount = 0;
- IVehicleMonitor service = null;
- while (true) {
- service = IVehicleMonitor.Stub.asInterface(
- ServiceManager.getService(IVehicleMonitor.class.getCanonicalName()));
- if (service != null) {
- break;
- }
- retryCount++;
- if (retryCount > VMS_CONNECT_MAX_RETRY) {
- break;
- }
- try {
- Thread.sleep(VMS_RETRY_WAIT_TIME_MS);
- } catch (InterruptedException e) {
- //ignore
- }
- }
- if (service == null) {
- throw new RuntimeException("Vehicle monitor service not available:"
- + IVehicleMonitor.class.getCanonicalName());
- }
- return new VehicleMonitor(service, listener, looper);
- }
-
- private VehicleMonitor(
- IVehicleMonitor service, VehicleMonitorListener listener, Looper looper) {
- mService = service;
- mListener = listener;
- mEventHandler = new EventHandler(looper);
- mVehicleMonitorListener = new IVehicleMonitorListenerImpl(this);
- try {
- mService.setMonitorListener(mVehicleMonitorListener);
- } catch (RemoteException e) {
- throw new RuntimeException("Vehicle monitor service not working ", e);
- }
- }
-
- /**
- * Set application priority.
- * <p>
- * This will lead into writing application priority into vehicle monitor.
- */
- public void setAppPriority(int pid, int uid, @ApplicationPriority int priority)
- throws ServiceSpecificException {
- try {
- mService.setAppPriority(pid, uid, priority);
- } catch (RemoteException e) {
- throw new RuntimeException("Vehicle monitor service not working ", e);
- }
- }
-
- private void handleVehicleMonitorAppViolation(AppViolation appViolation) {
- mListener.onAppViolation(appViolation.mPid, appViolation.mUid, appViolation.mAction,
- appViolation.mViolation);
- }
-
- private class EventHandler extends Handler {
-
- private static final int MSG_APP_VIOLATION = 0;
-
- private EventHandler(Looper looper) {
- super(looper);
- }
-
- private void notifyAppViolation(int pid, int uid, int action, int violation) {
- AppViolation appViolation = new AppViolation(pid, uid, action, violation);
- Message msg = obtainMessage(MSG_APP_VIOLATION, appViolation);
- sendMessage(msg);
- }
-
- @Override
- public void handleMessage(Message msg) {
- switch (msg.what) {
- case MSG_APP_VIOLATION:
- AppViolation appViolation = (AppViolation) msg.obj;
- handleVehicleMonitorAppViolation(appViolation);
- break;
- }
- }
- }
-
- private static class IVehicleMonitorListenerImpl extends IVehicleMonitorListener.Stub {
-
- private final WeakReference<VehicleMonitor> mVehicleMonitor;
-
- private IVehicleMonitorListenerImpl(VehicleMonitor vehicleNewotk) {
- mVehicleMonitor = new WeakReference<>(vehicleNewotk);
- }
-
- @Override
- public void onAppViolation(int pid, int uid, int action, int violation) {
- VehicleMonitor vehicleMonitor = mVehicleMonitor.get();
- if (vehicleMonitor != null) {
- vehicleMonitor.mEventHandler.notifyAppViolation(pid, uid, action, violation);
- }
- }
- }
-
- private static class AppViolation {
- public final int mPid;
- public final int mUid;
- public final int mAction;
- public final int mViolation;
-
- AppViolation(int pid, int uid, int action, int violation) {
- mPid = pid;
- mUid = uid;
- mAction = action;
- mViolation = violation;
- }
- }
-}
diff --git a/libvehiclemonitor/native/HandlerThread.cpp b/libvehiclemonitor/native/HandlerThread.cpp
deleted file mode 100644
index 5ee2715..0000000
--- a/libvehiclemonitor/native/HandlerThread.cpp
+++ /dev/null
@@ -1,72 +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.
- */
-
-#include "HandlerThread.h"
-
-namespace android {
-
-HandlerThread::HandlerThread()
- : mShouldQuit(false) {
-
-}
-
-HandlerThread::~HandlerThread() {
- quit();
-}
-
-sp<Looper> HandlerThread::getLooper() {
- Mutex::Autolock autoLock(mLock);
- if (mLooper.get() == 0) {
- mLooperWait.wait(mLock);
- }
- return mLooper;
-}
-
-status_t HandlerThread::start(const char* name, int32_t priority, size_t stack) {
- return run(name, priority, stack);
-}
-
-void HandlerThread::quit() {
- if (!isRunning()) {
- return;
- }
- sp<Looper> looper = getLooper();
- mLock.lock();
- mShouldQuit = true;
- mLock.unlock();
- looper->wake();
- requestExitAndWait();
-}
-
-bool HandlerThread::threadLoop() {
- mLock.lock();
- mLooper = Looper::prepare(0);
- mLooperWait.broadcast();
- mLock.unlock();
- while (true) {
- do {
- Mutex::Autolock autoLock(mLock);
- if (mShouldQuit) {
- return false;
- }
- } while (false);
- mLooper->pollOnce(-1);
- }
- return false;
-}
-
-
-};
diff --git a/libvehiclemonitor/native/IVehicleMonitor.cpp b/libvehiclemonitor/native/IVehicleMonitor.cpp
deleted file mode 100644
index b29f665..0000000
--- a/libvehiclemonitor/native/IVehicleMonitor.cpp
+++ /dev/null
@@ -1,128 +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.
- */
-
-#define LOG_TAG "VehicleMonitor"
-
-#include <binder/IPCThreadState.h>
-#include <binder/Status.h>
-#include <private/android_filesystem_config.h>
-
-#include <utils/Log.h>
-
-#include <IVehicleMonitor.h>
-
-namespace android {
-enum {
- SET_APP_PRIORITY = IBinder::FIRST_CALL_TRANSACTION,
- SET_MONITOR_LISTENER,
-};
-
-const char IVehicleMonitor::SERVICE_NAME[] = "com.android.car.vehiclemonitor.IVehicleMonitor";
-
-// ----------------------------------------------------------------------------
-
-class BpVehicleMonitor : public BpInterface<IVehicleMonitor> {
-public:
- explicit BpVehicleMonitor(const sp<IBinder> & impl)
- : BpInterface<IVehicleMonitor>(impl) {
- }
-
- virtual status_t setAppPriority(
- uint32_t pid, uint32_t uid, vehicle_app_priority priority) {
- Parcel data, reply;
- data.writeInterfaceToken(IVehicleMonitor::getInterfaceDescriptor());
- data.writeInt32(1);
- data.writeInt32(pid);
- data.writeInt32(uid);
- data.writeInt32(priority);
- status_t status = remote()->transact(SET_APP_PRIORITY, data, &reply);
- if (status == NO_ERROR) {
- int32_t exceptionCode = reply.readExceptionCode();
- if (exceptionCode != NO_ERROR) {
- if (exceptionCode == binder::Status::EX_SERVICE_SPECIFIC) {
- return -EAGAIN;
- } else if (exceptionCode == binder::Status::EX_ILLEGAL_STATE) {
- return -ESHUTDOWN;
- }
- return exceptionCode;
- }
- }
- return status;
- }
-
- virtual status_t setMonitorListener(
- const sp<IVehicleMonitorListener> &listener) {
- Parcel data, reply;
- data.writeInterfaceToken(IVehicleMonitor::getInterfaceDescriptor());
- data.writeStrongBinder(IInterface::asBinder(listener));
- status_t status = remote()->transact(SET_MONITOR_LISTENER, data, &reply);
- return status;
- }
-};
-
-IMPLEMENT_META_INTERFACE(VehicleMonitor, IVehicleMonitor::SERVICE_NAME);
-
-// ----------------------------------------------------------------------
-
-static bool isSystemUser() {
- uid_t uid = IPCThreadState::self()->getCallingUid();
- switch (uid) {
- // This list will be expanded. Only these UIDs are allowed to access vehicle monitor.
- case AID_ROOT:
- case AID_SYSTEM: {
- return true;
- } break;
- default: {
- ALOGE("non-system user tried access, uid %d", uid);
- } break;
- }
- return false;
-}
-
-status_t BnVehicleMonitor::onTransact(uint32_t code, const Parcel& data, Parcel* reply,
- uint32_t flags) {
- if (!isSystemUser()) {
- return PERMISSION_DENIED;
- }
- status_t r;
- switch (code) {
- case SET_APP_PRIORITY: {
- CHECK_INTERFACE(IVehicleMonitor, data, reply);
- if (data.readInt32() == 0) { // no data
- ALOGE("null data");
- return BAD_VALUE;
- }
- int32_t pid = data.readInt32();
- int32_t uid = data.readInt32();
- int32_t priority = data.readInt32();
- r = setAppPriority(pid, uid, (vehicle_app_priority) priority);
- reply->writeNoException();
- return r;
- } break;
- case SET_MONITOR_LISTENER: {
- CHECK_INTERFACE(IVehicleMonitor, data, reply);
- sp<IVehicleMonitorListener> listener =
- interface_cast<IVehicleMonitorListener>(data.readStrongBinder());
- r = setMonitorListener(listener);
- reply->writeNoException();
- return r;
- } break;
- default:
- return BBinder::onTransact(code, data, reply, flags);
- }
-}
-
-}; // namespace android
diff --git a/libvehiclemonitor/native/IVehicleMonitorListener.cpp b/libvehiclemonitor/native/IVehicleMonitorListener.cpp
deleted file mode 100644
index 985a228..0000000
--- a/libvehiclemonitor/native/IVehicleMonitorListener.cpp
+++ /dev/null
@@ -1,79 +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.
- */
-
-
-
-#define LOG_TAG "VehicleMonitorListener"
-
-#include <memory>
-
-#include <utils/Errors.h>
-#include <utils/Log.h>
-
-#include <IVehicleMonitorListener.h>
-
-namespace android {
-
-enum {
- ON_APP_VIOLATION = IBinder::FIRST_CALL_TRANSACTION,
-};
-
-class BpVehicleMonitorListener : public BpInterface<IVehicleMonitorListener>
-{
- public:
- explicit BpVehicleMonitorListener(const sp<IBinder> & impl)
- : BpInterface<IVehicleMonitorListener>(impl) {
- }
-
- virtual void onAppViolation(
- int32_t pid, int32_t uid, int32_t action, int32_t violation) {
- Parcel data, reply;
- data.writeInterfaceToken(IVehicleMonitorListener::getInterfaceDescriptor());
- data.writeInt32(1);
- data.writeInt32(pid);
- data.writeInt32(uid);
- data.writeInt32(action);
- data.writeInt32(violation);
- remote()->transact(ON_APP_VIOLATION, data, &reply, IBinder::FLAG_ONEWAY);
- }
-};
-
-IMPLEMENT_META_INTERFACE(VehicleMonitorListener, "com.android.car.vehiclemonitor.IVehicleMonitorListener");
-
-// ----------------------------------------------------------------------
-
-status_t BnVehicleMonitorListener::onTransact(uint32_t code, const Parcel& data, Parcel* reply,
- uint32_t flags) {
- status_t r;
- switch (code) {
- case ON_APP_VIOLATION: {
- CHECK_INTERFACE(IVehicleMonitorListener, data, reply);
- if (data.readInt32() == 0) { // java side allows passing null with this.
- return BAD_VALUE;
- }
- int32_t pid = data.readInt32();
- int32_t uid = data.readInt32();
- int32_t action = data.readInt32();
- int32_t violation = data.readInt32();
- onAppViolation(pid, uid, action, violation);
- return NO_ERROR;
- } break;
- default:
- return BBinder::onTransact(code, data, reply, flags);
- }
-}
-
-}; // namespace android
diff --git a/libvehiclemonitor/native/VehicleMonitor.cpp b/libvehiclemonitor/native/VehicleMonitor.cpp
deleted file mode 100644
index 33235cc..0000000
--- a/libvehiclemonitor/native/VehicleMonitor.cpp
+++ /dev/null
@@ -1,90 +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.
- */
-#define LOG_TAG "VehicleMonitor.Lib"
-
-#include <assert.h>
-#include <binder/IServiceManager.h>
-#include <binder/ProcessState.h>
-
-#include <VehicleMonitor.h>
-
-namespace android {
-// ----------------------------------------------------------------------------
-
-static const int MAX_SERVICE_RETRY = 4;
-
-sp<VehicleMonitor> VehicleMonitor::createVehicleMonitor() {
- sp<IBinder> binder;
- int retry = 0;
- while (true) {
- binder = defaultServiceManager()->getService(String16(IVehicleMonitor::SERVICE_NAME));
- if (binder.get() != NULL) {
- break;
- }
- retry++;
- if (retry > MAX_SERVICE_RETRY) {
- ALOGE("cannot get VMS, will crash");
- break;
- }
- }
- assert(binder.get() != NULL);
- sp<IVehicleMonitor> ivm(interface_cast<IVehicleMonitor>(binder));
- sp<VehicleMonitor> vm;
- vm = new VehicleMonitor(ivm);
- assert(vm.get() != NULL);
- // in case thread pool is not started, start it.
- ProcessState::self()->startThreadPool();
- return vm;
-}
-
-VehicleMonitor::VehicleMonitor(sp<IVehicleMonitor>& vehicleMonitor) :
- mService(vehicleMonitor) {
-}
-
-VehicleMonitor::~VehicleMonitor() {
- sp<IVehicleMonitor> service = getService();
- IInterface::asBinder(service)->unlinkToDeath(this);
-}
-
-void VehicleMonitor::onFirstRef() {
- sp<IVehicleMonitor> service = getService();
- IInterface::asBinder(service)->linkToDeath(this);
-}
-
-status_t VehicleMonitor::setAppPriority(
- uint32_t pid, uint32_t uid, vehicle_app_priority priority) {
- return getService()->setAppPriority(pid, uid, priority);
-}
-
-void VehicleMonitor::binderDied(const wp<IBinder>& who) {
- ALOGE("service died");
- {
- Mutex::Autolock autoLock(mLock);
- sp<IBinder> ibinder = who.promote();
- ibinder->unlinkToDeath(this);
- sp<IBinder> binder = defaultServiceManager()->getService(
- String16(IVehicleMonitor::SERVICE_NAME));
- mService = interface_cast<IVehicleMonitor>(binder);
- IInterface::asBinder(mService)->linkToDeath(this);
- };
-}
-
-sp<IVehicleMonitor> VehicleMonitor::getService() {
- Mutex::Autolock autoLock(mLock);
- return mService;
-}
-
-}; // namespace android
diff --git a/libvehiclenetwork/libvehiclenetwork-audio-helper/Android.mk b/libvehiclenetwork/libvehiclenetwork-audio-helper/Android.mk
deleted file mode 100644
index 889eec8..0000000
--- a/libvehiclenetwork/libvehiclenetwork-audio-helper/Android.mk
+++ /dev/null
@@ -1,41 +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.
-#
-#
-LOCAL_PATH:= $(call my-dir)
-
-ifeq ($(VN_AUDIO_HELPER_BLAH), true)
-
-include $(CLEAR_VARS)
-
-LOCAL_SRC_FILES := $(patsubst ./%,%, $(shell cd $(LOCAL_PATH); \
- find . -name "*.cpp" -and -not -name ".*"))
-
-LOCAL_C_INCLUDES += \
- packages/services/Car/libvehiclenetwork/include \
- $(LOCAL_PATH)/include
-
-LOCAL_SHARED_LIBRARIES := \
- libutils \
- libvehiclenetwork-native \
- liblog
-
-LOCAL_STRIP_MODULE := keep_symbols
-
-LOCAL_MODULE := libvehiclenetwork-audio-helper
-LOCAL_MODULE_TAGS := optional
-
-include $(BUILD_STATIC_LIBRARY)
-
-endif #ifeq ($(VN_AUDIO_HELPER_BLAH), true)
diff --git a/libvehiclenetwork/libvehiclenetwork-audio-helper/include/VehicleNetworkAudioHelper.h b/libvehiclenetwork/libvehiclenetwork-audio-helper/include/VehicleNetworkAudioHelper.h
deleted file mode 100644
index 220524b..0000000
--- a/libvehiclenetwork/libvehiclenetwork-audio-helper/include/VehicleNetworkAudioHelper.h
+++ /dev/null
@@ -1,93 +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.
- */
-
-#ifndef ANDROID_VEHICLE_NETWORK_AUDIO_HELPER_H
-#define ANDROID_VEHICLE_NETWORK_AUDIO_HELPER_H
-
-#include <stdint.h>
-#include <sys/types.h>
-
-#include <utils/threads.h>
-#include <utils/RefBase.h>
-
-// for enums
-#include "vehicle-network-audio-helper-for-c.h"
-
-namespace android {
-
-class VehicleNetworkAudioFocusListener : public virtual RefBase {
-public:
- virtual void onFocusChange(int32_t activeStreams) = 0;
-};
-
-// ----------------------------------------------------------------------------
-
-class VehicleNetwork;
-class VehicleNetworkListener;
-class LocalListener;
-
-class VehicleNetworkAudioHelper : public VehicleNetworkListener {
-public:
-
- VehicleNetworkAudioHelper(int64_t timeoutNs = FOCUS_WAIT_DEFAULT_TIMEOUT_NS);
- VehicleNetworkAudioHelper(int64_t timeoutNs, sp<VehicleNetworkAudioFocusListener> listener);
- virtual ~VehicleNetworkAudioHelper();
-
- status_t init();
-
- void release();
-
- void notifyStreamStarted(int32_t stream);
- void notifyStreamStopped(int32_t stream);
-
- vehicle_network_audio_helper_focus_state getStreamFocusState(int32_t stream);
-
- bool waitForStreamFocus(int32_t stream, nsecs_t waitTimeNs);
-
- // from VehicleNetworkListener
- void onEvents(sp<VehiclePropValueListHolder>& events) override;
- void onHalError(int32_t errorCode, int32_t property, int32_t operation) override;
- void onHalRestart(bool inMocking) override;
- void onPropertySet(const vehicle_prop_value_t& value) override;
-private:
- void updatePropertiesLocked();
-
- class StreamState {
- public:
- int64_t timeoutStartNs;
- bool started;
- StreamState()
- : timeoutStartNs(0),
- started(false) { };
- };
-
- StreamState& getStreamStateLocked(int32_t streamNumber);
-
-private:
- const int64_t mTimeoutNs;
- sp<VehicleNetworkAudioFocusListener> mListener;
- Mutex mLock;
- Condition mFocusWait;
- sp<VehicleNetwork> mService;
- bool mHasFocusProperty;
- int32_t mAllowedStreams;
- vehicle_prop_value_t mScratchValueFocus;
- vehicle_prop_value_t mScratchValueStreamState;
- Vector<StreamState> mStreamStates;
-};
-
-}; // namespace android
-#endif /*ANDROID_VEHICLE_NETWORK_AUDIO_HELPER_H*/
diff --git a/libvehiclenetwork/libvehiclenetwork-audio-helper/include/vehicle-network-audio-helper-for-c.h b/libvehiclenetwork/libvehiclenetwork-audio-helper/include/vehicle-network-audio-helper-for-c.h
deleted file mode 100644
index 5e97ef6..0000000
--- a/libvehiclenetwork/libvehiclenetwork-audio-helper/include/vehicle-network-audio-helper-for-c.h
+++ /dev/null
@@ -1,100 +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.
- */
-
-#ifndef ANDROID_VEHICLE_NETWORK_AUDIO_HELPER_FOR_C_H
-#define ANDROID_VEHICLE_NETWORK_AUDIO_HELPER_FOR_C_H
-
-#include <stdint.h>
-#include <sys/cdefs.h>
-#include <sys/types.h>
-#include <errno.h>
-
-#include <hardware/hardware.h>
-#include <utils/Timers.h>
-
-__BEGIN_DECLS
-
-/**
- * Container to hold all objects / bookkeeping stuffs.
- * Audio HAL is not supposed to touch the contents.
- */
-typedef struct vehicle_network_audio_helper
-{
- void* obj;
-} vehicle_network_audio_helper_t;
-
-enum vehicle_network_audio_helper_stream {
- VEHICLE_NETWORK_AUDIO_HELPER_STREAM_0 = 0x1,
- VEHICLE_NETWORK_AUDIO_HELPER_STREAM_1 = 0x2,
- VEHICLE_NETWORK_AUDIO_HELPER_STREAM_2 = 0x4,
- VEHICLE_NETWORK_AUDIO_HELPER_STREAM_3 = 0x8,
-};
-
-#define FOCUS_WAIT_DEFAULT_TIMEOUT_NS 1000000000
-
-/**
- * Create helper instance with default timeout. Timer is reset when
- * vehicle_network_audio_helper_notify_stream_started is called, and subsequent call to
- * vehicle_network_audio_helper_get_stream_focus_state can return timeout if focus is not
- * granted within given time.
- * Timeout timer will also reset if focus is taken away while having focus and stream is started.
- */
-vehicle_network_audio_helper_t* vehicle_network_audio_helper_create(int64_t timeout);
-
-vehicle_network_audio_helper_t* vehicle_network_audio_helper_create_with_default_timeout();
-
-void vehicle_network_audio_helper_destroy(vehicle_network_audio_helper_t* helper);
-
-/**
- * Notify stream start and reset focus timeout timer if it is not reset already.
- */
-void vehicle_network_audio_helper_notify_stream_started(vehicle_network_audio_helper_t* helper,
- int32_t stream);
-
-/**
- * Notify stream stop.
- */
-void vehicle_network_audio_helper_notify_stream_stopped(vehicle_network_audio_helper_t* helper,
- int32_t stream);
-
-enum vehicle_network_audio_helper_focus_state {
- VEHICLE_NETWORK_AUDIO_HELPER_FOCUS_STATE_TIMEOUT = -1,
- VEHICLE_NETWORK_AUDIO_HELPER_FOCUS_STATE_NO_FOCUS = 0,
- VEHICLE_NETWORK_AUDIO_HELPER_FOCUS_STATE_FOCUS = 1,
-};
-
-/**
- * Check if target stream has focus or not. This function also checks if default timeout has passed
- * since stream was started or since focus was lost last time.
- * @return VEHICLE_NETWORK_AUDIO_HELPER_FOCUS_STATE_FOCUS if there is focus.
- * VEHICLE_NETWORK_AUDIO_HELPER_FOCUS_STATE_NO_FOCUS no focus, no timeout
- * VEHICLE_NETWORK_AUDIO_HELPER_FOCUS_STATE_FOCUS no focus, timed out
- */
-int vehicle_network_audio_helper_get_stream_focus_state(
- vehicle_network_audio_helper_t* helper, int32_t stream);
-
-/**
- * Wait for focus until given timeout. It will return immediately if given stream has focus.
- * Otherwise, it will be waiting for focus for given waitTimeNs.
- * @return 1 if focus is available
- * 0 if focus is not available and timeout has happened.
- */
-int vehicle_network_audio_helper_wait_for_stream_focus(vehicle_network_audio_helper_t* helper,
- int32_t stream, nsecs_t waitTimeNs);
-
-__END_DECLS
-
-#endif /* ANDROID_VEHICLE_NETWORK_AUDIO_HELPER_FOR_C_H */
diff --git a/libvehiclenetwork/libvehiclenetwork-audio-helper/src/VehicleNetworkAudioHelper.cpp b/libvehiclenetwork/libvehiclenetwork-audio-helper/src/VehicleNetworkAudioHelper.cpp
deleted file mode 100644
index e2b899d..0000000
--- a/libvehiclenetwork/libvehiclenetwork-audio-helper/src/VehicleNetworkAudioHelper.cpp
+++ /dev/null
@@ -1,248 +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.
- */
-#define LOG_TAG "VehicleNetworkAudioHelper"
-
-#include <VehicleNetwork.h>
-#include <vehicle-internal.h>
-#include <utils/SystemClock.h>
-#include "VehicleNetworkAudioHelper.h"
-
-//#define DBG
-#ifdef DBG
-#define LOGD(x...) ALOGD(x)
-#else
-#define LOGD(x...)
-#endif
-namespace android {
-
-// ----------------------------------------------------------------------------
-
-VehicleNetworkAudioHelper::VehicleNetworkAudioHelper(int64_t timeoutNs)
- : mTimeoutNs(timeoutNs),
- mListener(NULL),
- mHasFocusProperty(false) {
-}
-
-VehicleNetworkAudioHelper::VehicleNetworkAudioHelper(int64_t timeoutNs,
- sp<VehicleNetworkAudioFocusListener> listener)
- : mTimeoutNs(timeoutNs),
- mListener(listener),
- mHasFocusProperty(false) {
-}
-
-VehicleNetworkAudioHelper::~VehicleNetworkAudioHelper() {
- // nothing to do
-}
-
-status_t VehicleNetworkAudioHelper::init() {
- Mutex::Autolock autoLock(mLock);
- sp<VehicleNetworkListener> listener(this);
- mService = VehicleNetwork::createVehicleNetwork(listener);
- mScratchValueStreamState.prop = VEHICLE_PROPERTY_INTERNAL_AUDIO_STREAM_STATE;
- mScratchValueStreamState.value_type = VEHICLE_VALUE_TYPE_INT32_VEC2;
- mScratchValueStreamState.timestamp = 0;
- mScratchValueFocus.prop = VEHICLE_PROPERTY_AUDIO_FOCUS;
- mScratchValueFocus.value_type = VEHICLE_VALUE_TYPE_INT32_VEC4;
- mScratchValueFocus.timestamp = 0;
- updatePropertiesLocked();
- return NO_ERROR;
-}
-
-void VehicleNetworkAudioHelper::updatePropertiesLocked() {
- sp<VehiclePropertiesHolder> holder = mService->listProperties(VEHICLE_PROPERTY_AUDIO_FOCUS);
- if (holder.get() != NULL && holder->getList().size() == 1) {
- mHasFocusProperty = true;
- mService->subscribe(VEHICLE_PROPERTY_AUDIO_FOCUS, 0);
- mService->getProperty(&mScratchValueFocus);
- mAllowedStreams = mScratchValueFocus.value.int32_array[VEHICLE_AUDIO_FOCUS_INDEX_STREAMS];
- ALOGI("initial focus state 0x%x", mAllowedStreams);
- } else {
- ALOGW("No focus property, assume focus always granted");
- mHasFocusProperty = false;
- mAllowedStreams = 0xffffffff;
- }
- for (size_t i = 0; i < mStreamStates.size(); i++) {
- mStreamStates.editItemAt(i).timeoutStartNs = 0;
- }
-}
-
-void VehicleNetworkAudioHelper::release() {
- Mutex::Autolock autoLock(mLock);
- if (mService.get() == NULL) {
- return;
- }
- mService = NULL;
-}
-
-static int32_t streamFlagToStreamNumber(int32_t streamFlag) {
- int32_t flag = 0x1;
- for (int32_t i = 0; i < 32; i++) {
- if ((flag & streamFlag) != 0) {
- return i;
- }
- flag = flag << 1;
- }
- return -1;
-}
-
-void VehicleNetworkAudioHelper::notifyStreamStarted(int32_t stream) {
- Mutex::Autolock autoLock(mLock);
- if (!mHasFocusProperty) {
- return;
- }
- int32_t streamNumber = streamFlagToStreamNumber(stream);
- if (streamNumber < 0) {
- ALOGE("notifyStreamStarted, wrong stream:0x%x", stream);
- return;
- }
- StreamState& state = getStreamStateLocked(streamNumber);
- if (state.started) {
- return;
- }
- state.started = true;
- state.timeoutStartNs = elapsedRealtimeNano();
- mScratchValueStreamState.value.int32_array[VEHICLE_AUDIO_STREAM_STATE_INDEX_STATE] =
- VEHICLE_AUDIO_STREAM_STATE_STARTED;
- mScratchValueStreamState.value.int32_array[VEHICLE_AUDIO_STREAM_STATE_INDEX_STREAM] =
- streamNumber;
- mScratchValueStreamState.timestamp = android::elapsedRealtimeNano();
- mService->setProperty(mScratchValueStreamState);
-}
-
-void VehicleNetworkAudioHelper::notifyStreamStopped(int32_t stream) {
- Mutex::Autolock autoLock(mLock);
- if (!mHasFocusProperty) {
- return;
- }
- int32_t streamNumber = streamFlagToStreamNumber(stream);
- if (streamNumber < 0) {
- ALOGE("notifyStreamStopped, wrong stream:0x%x", stream);
- return;
- }
- StreamState& state = getStreamStateLocked(streamNumber);
- if (!state.started) {
- return;
- }
- state.started = false;
- state.timeoutStartNs = 0;
- mScratchValueStreamState.value.int32_array[VEHICLE_AUDIO_STREAM_STATE_INDEX_STATE] =
- VEHICLE_AUDIO_STREAM_STATE_STOPPED;
- mScratchValueStreamState.value.int32_array[VEHICLE_AUDIO_STREAM_STATE_INDEX_STREAM] =
- streamNumber;
- mScratchValueStreamState.timestamp = android::elapsedRealtimeNano();
- mService->setProperty(mScratchValueStreamState);
-}
-
-VehicleNetworkAudioHelper::StreamState& VehicleNetworkAudioHelper::getStreamStateLocked(
- int32_t streamNumber) {
- if (streamNumber >= (int32_t) mStreamStates.size()) {
- mStreamStates.insertAt(mStreamStates.size(), streamNumber - mStreamStates.size() + 1);
- }
- return mStreamStates.editItemAt(streamNumber);
-}
-
-vehicle_network_audio_helper_focus_state VehicleNetworkAudioHelper::getStreamFocusState(
- int32_t stream) {
- Mutex::Autolock autoLock(mLock);
- if ((mAllowedStreams & stream) == stream) {
- return VEHICLE_NETWORK_AUDIO_HELPER_FOCUS_STATE_FOCUS;
- }
- int32_t streamNumber = streamFlagToStreamNumber(stream);
- if (streamNumber < 0) {
- ALOGE("getStreamFocusState, wrong stream:0x%x", stream);
- return VEHICLE_NETWORK_AUDIO_HELPER_FOCUS_STATE_TIMEOUT;
- }
- StreamState& state = getStreamStateLocked(streamNumber);
- if (state.timeoutStartNs == 0) {
- if (state.started) {
- state.timeoutStartNs = elapsedRealtimeNano();
- }
- } else {
- int64_t now = elapsedRealtimeNano();
- if ((state.timeoutStartNs + mTimeoutNs) < now) {
- return VEHICLE_NETWORK_AUDIO_HELPER_FOCUS_STATE_TIMEOUT;
- }
- }
- return VEHICLE_NETWORK_AUDIO_HELPER_FOCUS_STATE_NO_FOCUS;
-}
-
-bool VehicleNetworkAudioHelper::waitForStreamFocus(int32_t stream, nsecs_t waitTimeNs) {
- LOGD("waitForStreamFocus");
- Mutex::Autolock autoLock(mLock);
- int64_t currentTime = android::elapsedRealtimeNano();
- int64_t finishTime = currentTime + waitTimeNs;
- while (true) {
- if ((stream & mAllowedStreams) == stream) {
- LOGD("waitForStreamFocus, has focus");
- return true;
- }
- currentTime = android::elapsedRealtimeNano();
- if (currentTime >= finishTime) {
- break;
- }
- nsecs_t waitTime = finishTime - currentTime;
- mFocusWait.waitRelative(mLock, waitTime);
- }
- LOGD("waitForStreamFocus, no focus");
- return false;
-}
-
-void VehicleNetworkAudioHelper::onEvents(sp<VehiclePropValueListHolder>& events) {
- sp<VehicleNetworkAudioFocusListener> listener;
- int32_t allowedStreams;
- bool changed = false;
- do {
- Mutex::Autolock autoLock(mLock);
- if (mService.get() == NULL) { // already released
- return;
- }
- for (vehicle_prop_value_t* value : events->getList()) {
- if (value->prop == VEHICLE_PROPERTY_AUDIO_FOCUS) {
- mAllowedStreams = value->value.int32_array[VEHICLE_AUDIO_FOCUS_INDEX_STREAMS];
- ALOGI("audio focus change 0x%x", mAllowedStreams);
- changed = true;
- }
- }
- listener = mListener;
- allowedStreams = mAllowedStreams;
- if (changed) {
- mFocusWait.signal();
- }
- } while (false);
- if (listener.get() != NULL && changed) {
- listener->onFocusChange(allowedStreams);
- }
-}
-
-void VehicleNetworkAudioHelper::onHalError(int32_t /*errorCode*/, int32_t /*property*/,
- int32_t /*operation*/) {
- // not used
-}
-
-void VehicleNetworkAudioHelper::onHalRestart(bool /*inMocking*/) {
- LOGD("onHalRestart");
- Mutex::Autolock autoLock(mLock);
- if (mService.get() == NULL) { // already released
- return;
- }
- updatePropertiesLocked();
- mFocusWait.signal();
-}
-
-void VehicleNetworkAudioHelper::onPropertySet(const vehicle_prop_value_t &value __attribute__((unused))) {
-}
-
-}; // namespace android
diff --git a/libvehiclenetwork/libvehiclenetwork-audio-helper/src/vehicle-network-audio-helper-for-c.cpp b/libvehiclenetwork/libvehiclenetwork-audio-helper/src/vehicle-network-audio-helper-for-c.cpp
deleted file mode 100644
index 81888fa..0000000
--- a/libvehiclenetwork/libvehiclenetwork-audio-helper/src/vehicle-network-audio-helper-for-c.cpp
+++ /dev/null
@@ -1,93 +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.
- */
-
-#define LOG_TAG "VehicleNetworkAudioHelper-C"
-
-#include <VehicleNetwork.h>
-#include <vehicle-internal.h>
-#include <utils/SystemClock.h>
-#include "VehicleNetworkAudioHelper.h"
-#include "vehicle-network-audio-helper-for-c.h"
-
-extern "C" {
-
-vehicle_network_audio_helper_t* vehicle_network_audio_helper_create(nsecs_t timeout) {
- android::status_t r;
- android::VehicleNetworkAudioHelper* helperObj = new android::VehicleNetworkAudioHelper(timeout);
- if (helperObj == NULL) {
- return NULL;
- }
- vehicle_network_audio_helper_t *helper = new vehicle_network_audio_helper_t();
- if (helper == NULL) {
- goto error;
- }
- r = helperObj->init();
- if (r != android::NO_ERROR) {
- goto error;
- }
- helper->obj = helperObj;
- return helper;
-
-error:
- delete helperObj;
- delete helper;
- return NULL;
-}
-
-vehicle_network_audio_helper_t* vehicle_network_audio_helper_create_with_default_timeout() {
- return vehicle_network_audio_helper_create(FOCUS_WAIT_DEFAULT_TIMEOUT_NS);
-}
-
-void vehicle_network_audio_helper_destroy(vehicle_network_audio_helper_t* helper) {
- android::VehicleNetworkAudioHelper* helperObj =
- (android::VehicleNetworkAudioHelper*) helper->obj;
- helperObj->release();
- delete helperObj;
- delete helper;
-}
-
-void vehicle_network_audio_helper_notify_stream_started(vehicle_network_audio_helper_t* helper,
- int32_t stream) {
- android::VehicleNetworkAudioHelper* helperObj =
- (android::VehicleNetworkAudioHelper*) helper->obj;
- helperObj->notifyStreamStarted(stream);
-}
-
-void vehicle_network_audio_helper_notify_stream_stopped(vehicle_network_audio_helper_t* helper,
- int32_t stream) {
- android::VehicleNetworkAudioHelper* helperObj =
- (android::VehicleNetworkAudioHelper*) helper->obj;
- helperObj->notifyStreamStopped(stream);
-}
-
-int vehicle_network_audio_helper_get_stream_focus_state(
- vehicle_network_audio_helper_t* helper, int32_t stream) {
- android::VehicleNetworkAudioHelper* helperObj =
- (android::VehicleNetworkAudioHelper*) helper->obj;
- return helperObj->getStreamFocusState(stream);
-}
-
-int vehicle_network_audio_helper_wait_for_stream_focus(vehicle_network_audio_helper_t* helper,
- int32_t stream, nsecs_t waitTimeNs) {
- android::VehicleNetworkAudioHelper* helperObj =
- (android::VehicleNetworkAudioHelper*) helper->obj;
- if (helperObj->waitForStreamFocus(stream, waitTimeNs)) {
- return 1;
- }
- return 0;
-}
-
-}
diff --git a/tools/bootanalyze/Android.mk b/procfs-inspector/Android.mk
similarity index 96%
rename from tools/bootanalyze/Android.mk
rename to procfs-inspector/Android.mk
index 5df0dd8..89bdf30 100644
--- a/tools/bootanalyze/Android.mk
+++ b/procfs-inspector/Android.mk
@@ -15,6 +15,6 @@
#
LOCAL_PATH := $(call my-dir)
-
+include $(CLEAR_VARS)
# Include the sub-makefiles
include $(call all-makefiles-under,$(LOCAL_PATH))
diff --git a/libvehiclemonitor/java/Android.mk b/procfs-inspector/client/Android.mk
similarity index 87%
rename from libvehiclemonitor/java/Android.mk
rename to procfs-inspector/client/Android.mk
index 1ced365..d9713de 100644
--- a/libvehiclemonitor/java/Android.mk
+++ b/procfs-inspector/client/Android.mk
@@ -1,4 +1,4 @@
-# Copyright (C) 2016 The Android Open Source Project
+# 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.
@@ -18,7 +18,7 @@
include $(CLEAR_VARS)
-LOCAL_MODULE := libvehiclemonitor-java
+LOCAL_MODULE := com.android.car.procfsinspector-client
LOCAL_MODULE_TAGS := optional
LOCAL_SRC_FILES := $(call all-java-files-under, src) $(call all-Iaidl-files-under, src)
diff --git a/car-lib/src/android/car/media/ICarAudioCallback.aidl b/procfs-inspector/client/src/com/android/car/procfsinspector/IProcfsInspector.aidl
similarity index 78%
copy from car-lib/src/android/car/media/ICarAudioCallback.aidl
copy to procfs-inspector/client/src/com/android/car/procfsinspector/IProcfsInspector.aidl
index 7e01c71..7022ff4 100644
--- a/car-lib/src/android/car/media/ICarAudioCallback.aidl
+++ b/procfs-inspector/client/src/com/android/car/procfsinspector/IProcfsInspector.aidl
@@ -14,9 +14,10 @@
* limitations under the License.
*/
-package android.car.media;
+package com.android.car.procfsinspector;
-/** @hide */
-oneway interface ICarAudioCallback {
- void onParameterChange(in String params) = 0;
+import com.android.car.procfsinspector.ProcessInfo;
+
+interface IProcfsInspector {
+ List<ProcessInfo> readProcessTable();
}
diff --git a/car-lib/src/android/car/media/ICarAudioCallback.aidl b/procfs-inspector/client/src/com/android/car/procfsinspector/ProcessInfo.aidl
similarity index 82%
rename from car-lib/src/android/car/media/ICarAudioCallback.aidl
rename to procfs-inspector/client/src/com/android/car/procfsinspector/ProcessInfo.aidl
index 7e01c71..ca8d4be 100644
--- a/car-lib/src/android/car/media/ICarAudioCallback.aidl
+++ b/procfs-inspector/client/src/com/android/car/procfsinspector/ProcessInfo.aidl
@@ -14,9 +14,6 @@
* limitations under the License.
*/
-package android.car.media;
+package com.android.car.procfsinspector;
-/** @hide */
-oneway interface ICarAudioCallback {
- void onParameterChange(in String params) = 0;
-}
+parcelable ProcessInfo;
diff --git a/procfs-inspector/client/src/com/android/car/procfsinspector/ProcessInfo.java b/procfs-inspector/client/src/com/android/car/procfsinspector/ProcessInfo.java
new file mode 100644
index 0000000..310e1ba
--- /dev/null
+++ b/procfs-inspector/client/src/com/android/car/procfsinspector/ProcessInfo.java
@@ -0,0 +1,77 @@
+/*
+ * 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.android.car.procfsinspector;
+
+import android.os.Parcel;
+import android.os.Parcelable;
+import java.util.Objects;
+
+public class ProcessInfo implements Parcelable {
+ public static final Parcelable.Creator<ProcessInfo> CREATOR =
+ new Parcelable.Creator<ProcessInfo>() {
+ public ProcessInfo createFromParcel(Parcel in) {
+ return new ProcessInfo(in);
+ }
+
+ public ProcessInfo[] newArray(int size) {
+ return new ProcessInfo[size];
+ }
+ };
+
+ public final int pid;
+ public final int uid;
+
+ public ProcessInfo(int pid, int uid) {
+ this.pid = pid;
+ this.uid = uid;
+ }
+
+ public ProcessInfo(Parcel in) {
+ this.pid = in.readInt();
+ this.uid = in.readInt();
+ }
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ @Override
+ public void writeToParcel(Parcel dest, int flags) {
+ dest.writeInt(pid);
+ dest.writeInt(uid);
+ }
+
+ @Override
+ public boolean equals(Object other) {
+ if (other instanceof ProcessInfo) {
+ ProcessInfo processInfo = (ProcessInfo)other;
+ return processInfo.pid == pid && processInfo.uid == uid;
+ }
+
+ return false;
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(pid, uid);
+ }
+
+ @Override
+ public String toString() {
+ return String.format("pid = %d, uid = %d", pid, uid);
+ }
+}
diff --git a/procfs-inspector/client/src/com/android/car/procfsinspector/ProcfsInspector.java b/procfs-inspector/client/src/com/android/car/procfsinspector/ProcfsInspector.java
new file mode 100644
index 0000000..ff00bbf
--- /dev/null
+++ b/procfs-inspector/client/src/com/android/car/procfsinspector/ProcfsInspector.java
@@ -0,0 +1,54 @@
+/*
+ * 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.android.car.procfsinspector;
+
+import android.annotation.Nullable;
+import android.os.RemoteException;
+import android.os.ServiceManager;
+import android.util.Log;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+import java.util.Objects;
+
+public final class ProcfsInspector {
+ private static final String TAG = "car.procfsinspector";
+ private static final String SERVICE_NAME = "com.android.car.procfsinspector";
+ private final IProcfsInspector mService;
+
+ private ProcfsInspector(IProcfsInspector service) {
+ mService = service;
+ }
+
+ @Nullable
+ private static IProcfsInspector tryGet() {
+ return IProcfsInspector.Stub.asInterface(
+ ServiceManager.getService(SERVICE_NAME));
+ }
+
+ public static List<ProcessInfo> readProcessTable() {
+ IProcfsInspector procfsInspector = tryGet();
+ if (procfsInspector != null) {
+ try {
+ return procfsInspector.readProcessTable();
+ } catch (RemoteException e) {
+ Log.w(TAG, "caught RemoteException", e);
+ }
+ }
+
+ return Collections.emptyList();
+ }
+}
diff --git a/libvehiclemonitor/native/Android.mk b/procfs-inspector/server/Android.mk
similarity index 62%
rename from libvehiclemonitor/native/Android.mk
rename to procfs-inspector/server/Android.mk
index 880fcae..fab1cf8 100644
--- a/libvehiclemonitor/native/Android.mk
+++ b/procfs-inspector/server/Android.mk
@@ -1,4 +1,4 @@
-# Copyright (C) 2016 The Android Open Source Project
+# 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.
@@ -13,30 +13,33 @@
# limitations under the License.
#
#
+
LOCAL_PATH:= $(call my-dir)
include $(CLEAR_VARS)
-LOCAL_SRC_FILES := $(patsubst ./%,%, $(shell cd $(LOCAL_PATH); \
- find . -name "*.cpp" -and -not -name ".*"))
+LOCAL_SRC_FILES := \
+ main.cpp \
+ server.cpp \
+ impl.cpp \
+ process.cpp \
+ directory.cpp
LOCAL_C_INCLUDES += \
- frameworks/base/include \
- packages/services/Car/libvehiclemonitor/include
+ frameworks/base/include
LOCAL_SHARED_LIBRARIES := \
+ libbinder \
liblog \
- libutils \
- libhardware \
- libbinder
-
-LOCAL_EXPORT_SHARED_LIBRARY_HEADERS := libbinder
+ libutils
LOCAL_STRIP_MODULE := keep_symbols
-LOCAL_MODULE := libvehiclemonitor-native
+LOCAL_INIT_RC := com.android.car.procfsinspector.rc
+
+LOCAL_MODULE := com.android.car.procfsinspector
LOCAL_MODULE_TAGS := optional
-LOCAL_CFLAGS += -Werror
+LOCAL_CFLAGS += -Wall -Werror
-include $(BUILD_SHARED_LIBRARY)
+include $(BUILD_EXECUTABLE)
diff --git a/procfs-inspector/server/com.android.car.procfsinspector.rc b/procfs-inspector/server/com.android.car.procfsinspector.rc
new file mode 100644
index 0000000..7faaf69
--- /dev/null
+++ b/procfs-inspector/server/com.android.car.procfsinspector.rc
@@ -0,0 +1,7 @@
+service com.android.car.procfsinspector /system/bin/com.android.car.procfsinspector
+ class core
+ user nobody
+ group readproc
+
+on boot && property:boot.car_service_created=1
+ start com.android.car.procfsinspector
diff --git a/procfs-inspector/server/directory.cpp b/procfs-inspector/server/directory.cpp
new file mode 100644
index 0000000..45dbc0a
--- /dev/null
+++ b/procfs-inspector/server/directory.cpp
@@ -0,0 +1,72 @@
+/*
+ * 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.
+ */
+
+#include "directory.h"
+
+#include <android-base/stringprintf.h>
+
+procfsinspector::Directory::Directory(const char* path) {
+ if (path && path[0]) {
+ mPath.assign(path);
+ mDirectory.reset(opendir(path));
+ }
+}
+
+bool procfsinspector::Directory::Entry::isEmpty() const {
+ return mParent.empty() && mChild.empty();
+}
+
+procfsinspector::Directory::Entry::Entry(std::string parent, std::string child) :
+ mParent(parent), mChild(child) {
+ if (!isEmpty()) {
+ if (mParent.back() != '/') {
+ mParent += '/';
+ }
+ }
+}
+
+std::string procfsinspector::Directory::Entry::str() {
+ return mParent + mChild;
+}
+
+uid_t procfsinspector::Directory::Entry::getOwnerUserId() {
+ if (isEmpty()) {
+ return -1;
+ }
+ struct stat buf;
+ // fill in stat info for this entry, or return invalid UID on failure
+ if (stat(str().c_str(), &buf)) {
+ return -1;
+ }
+ return buf.st_uid;
+}
+
+procfsinspector::Directory::Entry procfsinspector::Directory::next(unsigned char type) {
+ if (auto dir = mDirectory.get()) {
+ dirent *entry = readdir(dir);
+ if (entry) {
+ // only return entries of the right type (regular file, directory, ...)
+ // but always return UNKNOWN entries as it is an allowed wildcard entry
+ if (entry->d_type == DT_UNKNOWN ||
+ type == DT_UNKNOWN ||
+ entry->d_type == type) {
+ return Entry(mPath, entry->d_name);
+ }
+ }
+ }
+
+ return Entry();
+}
diff --git a/procfs-inspector/server/directory.h b/procfs-inspector/server/directory.h
new file mode 100644
index 0000000..19528fe
--- /dev/null
+++ b/procfs-inspector/server/directory.h
@@ -0,0 +1,69 @@
+/*
+ * 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.
+ */
+
+#ifndef CAR_PROCFS_DIRECTORY
+#define CAR_PROCFS_DIRECTORY
+
+#include <dirent.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <unistd.h>
+
+#include <memory>
+#include <string>
+
+namespace procfsinspector {
+
+class Directory {
+public:
+ class Entry {
+ public:
+ Entry(std::string parent = "", std::string child = "");
+
+ const std::string& getChild() { return mChild; }
+ std::string str();
+
+ bool isEmpty() const;
+
+ operator bool() const {
+ return !isEmpty();
+ }
+
+ uid_t getOwnerUserId();
+
+ private:
+ std::string mParent;
+ std::string mChild;
+ };
+
+ Directory(const char* path);
+
+ Entry next(unsigned char type = DT_UNKNOWN);
+
+private:
+ class Deleter {
+ public:
+ void operator()(DIR* dir) {
+ if (dir) closedir(dir);
+ }
+ };
+ std::string mPath;
+ std::unique_ptr<DIR, Deleter> mDirectory;
+};
+
+}
+
+#endif // CAR_PROCFS_DIRECTORY
\ No newline at end of file
diff --git a/procfs-inspector/server/impl.cpp b/procfs-inspector/server/impl.cpp
new file mode 100644
index 0000000..888f77d
--- /dev/null
+++ b/procfs-inspector/server/impl.cpp
@@ -0,0 +1,48 @@
+/*
+ * 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.
+ */
+
+#include "directory.h"
+#include "server.h"
+
+template<typename IntTy>
+static bool asNumber(const std::string& s, IntTy *value) {
+ IntTy v = 0;
+ for (auto&& c : s) {
+ if (c < '0' || c > '9') {
+ return false;
+ } else {
+ v = v * 10 + (c - '0');
+ }
+ }
+
+ if (value) *value = v;
+
+ return true;
+}
+
+std::vector<procfsinspector::ProcessInfo> procfsinspector::Impl::readProcessTable() {
+ std::vector<procfsinspector::ProcessInfo> processes;
+
+ Directory dir("/proc");
+ while (auto entry = dir.next()) {
+ pid_t pid;
+ if (asNumber(entry.getChild(), &pid)) {
+ processes.push_back(ProcessInfo{pid, entry.getOwnerUserId()});
+ }
+ }
+
+ return processes;
+}
diff --git a/procfs-inspector/server/main.cpp b/procfs-inspector/server/main.cpp
new file mode 100644
index 0000000..1555aa3
--- /dev/null
+++ b/procfs-inspector/server/main.cpp
@@ -0,0 +1,46 @@
+/*
+ * 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.
+ */
+
+#include "server.h"
+
+#include <signal.h>
+
+#include <binder/IServiceManager.h>
+
+#include <utils/Log.h>
+
+using namespace android;
+
+int main(int, char**)
+{
+ ALOGI("starting " LOG_TAG);
+ signal(SIGPIPE, SIG_IGN);
+
+ sp<ProcessState> processSelf(ProcessState::self());
+ sp<IServiceManager> serviceManager = defaultServiceManager();
+ std::unique_ptr<procfsinspector::Impl> server(new procfsinspector::Impl());
+
+ serviceManager->addService(String16(SERVICE_NAME), server.get());
+
+ processSelf->startThreadPool();
+
+ ALOGI(LOG_TAG " started");
+
+ IPCThreadState::self()->joinThreadPool();
+
+ ALOGW(LOG_TAG " joined and going down");
+ return 0;
+}
diff --git a/procfs-inspector/server/process.cpp b/procfs-inspector/server/process.cpp
new file mode 100644
index 0000000..3c25ce2
--- /dev/null
+++ b/procfs-inspector/server/process.cpp
@@ -0,0 +1,15 @@
+#include "process.h"
+
+#include <binder/Parcel.h>
+
+status_t procfsinspector::ProcessInfo::writeToParcel(Parcel* parcel) const {
+ parcel->writeUint32(mPid);
+ parcel->writeUint32(mUid);
+ return android::OK;
+}
+
+status_t procfsinspector::ProcessInfo::readFromParcel(const Parcel* parcel) {
+ mPid = parcel->readUint32();
+ mUid = parcel->readUint32();
+ return android::OK;
+}
diff --git a/procfs-inspector/server/process.h b/procfs-inspector/server/process.h
new file mode 100644
index 0000000..75b76c7
--- /dev/null
+++ b/procfs-inspector/server/process.h
@@ -0,0 +1,44 @@
+/*
+ * 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.
+ */
+
+#ifndef CAR_PROCFS_PROCESS
+#define CAR_PROCFS_PROCESS
+
+#include <sys/types.h>
+
+#include <binder/Parcelable.h>
+
+using namespace android;
+
+namespace procfsinspector {
+ class ProcessInfo : public Parcelable {
+ public:
+ pid_t getPid() { return mPid; }
+ uid_t getUid() { return mUid; }
+
+ // default initialize to invalid values
+ ProcessInfo(pid_t pid = -1, uid_t uid = -1) : mPid(pid), mUid(uid) {}
+
+ virtual status_t writeToParcel(Parcel* parcel) const override;
+ virtual status_t readFromParcel(const Parcel* parcel) override;
+
+ private:
+ pid_t mPid;
+ uid_t mUid;
+ };
+}
+
+#endif // CAR_PROCFS_PROCESS
diff --git a/procfs-inspector/server/server.cpp b/procfs-inspector/server/server.cpp
new file mode 100644
index 0000000..82e196f
--- /dev/null
+++ b/procfs-inspector/server/server.cpp
@@ -0,0 +1,72 @@
+/*
+ * 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.
+ */
+
+#include "server.h"
+
+#include <binder/IPCThreadState.h>
+
+#include <private/android_filesystem_config.h>
+
+static bool isSystemUser() {
+ uid_t uid = IPCThreadState::self()->getCallingUid();
+ switch (uid) {
+ case AID_ROOT:
+ case AID_SYSTEM: {
+ return true;
+ } break;
+ default: {
+ ALOGE("uid %u is not root nor system - access denied", uid);
+ } break;
+ }
+ return false;
+}
+
+namespace procfsinspector {
+class BpProcfsInspector: public BpInterface<IProcfsInspector> {
+ public:
+ BpProcfsInspector(sp<IBinder> binder) : BpInterface<IProcfsInspector>(binder) {}
+
+ virtual std::vector<ProcessInfo> readProcessTable() override {
+ Parcel data, reply;
+ remote()->transact((uint32_t)IProcfsInspector::Call::READ_PROCESS_TABLE, data, &reply);
+
+ std::vector<procfsinspector::ProcessInfo> result;
+ reply.readParcelableVector(&result);
+ return result;
+ }
+
+};
+
+IMPLEMENT_META_INTERFACE(ProcfsInspector, "com.android.car.procfsinspector.IProcfsInspector");
+
+status_t Impl::onTransact(uint32_t code,
+ const Parcel& data, Parcel* reply, uint32_t flags) {
+
+ if (code == (uint32_t)IProcfsInspector::Call::READ_PROCESS_TABLE) {
+ CHECK_INTERFACE(IProcfsInspector, data, reply);
+ if (isSystemUser()) {
+ reply->writeNoException();
+ reply->writeParcelableVector(readProcessTable());
+ return NO_ERROR;
+ } else {
+ return PERMISSION_DENIED;
+ }
+ }
+
+ return BBinder::onTransact(code, data, reply, flags);
+}
+
+}
diff --git a/procfs-inspector/server/server.h b/procfs-inspector/server/server.h
new file mode 100644
index 0000000..ae529ff
--- /dev/null
+++ b/procfs-inspector/server/server.h
@@ -0,0 +1,62 @@
+/*
+ * 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.
+ */
+
+#ifndef CAR_PROCFS_SERVER
+#define CAR_PROCFS_SERVER
+
+#define LOG_TAG "com.android.car.procfsinspector"
+#define SERVICE_NAME "com.android.car.procfsinspector"
+
+#include <vector>
+
+#include <binder/Parcel.h>
+#include <binder/IPCThreadState.h>
+#include <binder/ProcessState.h>
+#include <binder/IServiceManager.h>
+#include <binder/IBinder.h>
+#include <binder/IInterface.h>
+
+#include <utils/Log.h>
+#include <utils/String16.h>
+
+#include "process.h"
+
+using namespace android;
+
+namespace procfsinspector {
+ class IProcfsInspector : public IInterface {
+ public:
+ DECLARE_META_INTERFACE(ProcfsInspector);
+
+ enum class Call : uint32_t {
+ READ_PROCESS_TABLE = IBinder::FIRST_CALL_TRANSACTION,
+ };
+
+ // API declarations start here
+ virtual std::vector<ProcessInfo> readProcessTable() = 0;
+ };
+
+ class Impl : public BnInterface<IProcfsInspector> {
+ public:
+ virtual status_t onTransact(uint32_t code,
+ const Parcel& data,
+ Parcel *reply,
+ uint32_t flags) override;
+ virtual std::vector<ProcessInfo> readProcessTable() override;
+ };
+}
+
+#endif // CAR_PROCFS_SERVER
diff --git a/service/Android.mk b/service/Android.mk
index e4c3f80..2ec4c4a 100644
--- a/service/Android.mk
+++ b/service/Android.mk
@@ -40,9 +40,12 @@
LOCAL_JAVA_LIBRARIES += android.car
LOCAL_STATIC_JAVA_LIBRARIES += \
android.hidl.base-V1.0-java \
+ android.hardware.automotive.audiocontrol-V1.0-java \
android.hardware.automotive.vehicle-V2.0-java \
vehicle-hal-support-lib \
+ car-frameworks-service \
car-systemtest \
+ com.android.car.procfsinspector-client \
include $(BUILD_PACKAGE)
@@ -59,12 +62,15 @@
LOCAL_MODULE := car-service-lib-for-test
-LOCAL_JAVA_LIBRARIES += android.car
+LOCAL_JAVA_LIBRARIES += android.car \
+ car-frameworks-service
LOCAL_STATIC_JAVA_LIBRARIES += \
android.hidl.base-V1.0-java \
+ android.hardware.automotive.audiocontrol-V1.0-java \
android.hardware.automotive.vehicle-V2.0-java \
vehicle-hal-support-lib \
car-systemtest \
+ com.android.car.procfsinspector-client \
LOCAL_MIN_SDK_VERSION := 25
diff --git a/service/AndroidManifest.xml b/service/AndroidManifest.xml
index 7e2121f..7cef341 100644
--- a/service/AndroidManifest.xml
+++ b/service/AndroidManifest.xml
@@ -21,49 +21,81 @@
android:sharedUserId="android.uid.system">
<original-package android:name="com.android.car" />
-
- <permission-group
- android:name="android.car.permission.CAR_INFORMATION"
+ <permission-group
+ android:name="android.car.permission-group.CAR_MONITORING"
android:icon="@drawable/car_ic_mode"
android:description="@string/car_permission_desc"
android:label="@string/car_permission_label" />
<permission
- android:name="android.car.permission.CAR_CABIN"
+ android:name="android.car.permission.ADJUST_CAR_CABIN"
android:protectionLevel="system|signature"
android:label="@string/car_permission_label_cabin"
android:description="@string/car_permission_desc_cabin" />
<permission
- android:name="android.car.permission.CAR_CAMERA"
- android:protectionLevel="system|signature"
- android:label="@string/car_permission_label_camera"
- android:description="@string/car_permission_desc_camera" />
- <permission
- android:name="android.car.permission.CAR_FUEL"
- android:permissionGroup="android.car.permission.CAR_INFORMATION"
+ android:name="android.car.permission.CAR_ENERGY"
+ android:permissionGroup="android.car.permission-group.CAR_MONITORING"
android:protectionLevel="dangerous"
- android:label="@string/car_permission_label_fuel"
- android:description="@string/car_permission_desc_fuel" />
+ android:label="@string/car_permission_label_energy"
+ android:description="@string/car_permission_desc_energy" />
<permission
- android:name="android.car.permission.CAR_HVAC"
+ android:name="android.car.permission.CAR_IDENTIFICATION"
+ android:protectionLevel="system|signature"
+ android:label="@string/car_permission_label_car_identification"
+ android:description="@string/car_permission_desc_car_identification" />
+ <permission
+ android:name="android.car.permission.CONTROL_CAR_CLIMATE"
android:protectionLevel="system|signature"
android:label="@string/car_permission_label_hvac"
android:description="@string/car_permission_desc_hvac" />
<permission
+ android:name="android.car.permission.CONTROL_CAR_DOORS"
+ android:protectionLevel="system|signature"
+ android:label="@string/car_permission_label_control_car_doors"
+ android:description="@string/car_permission_desc_control_car_doors" />
+ <permission
+ android:name="android.car.permission.CONTROL_CAR_WINDOWS"
+ android:protectionLevel="system|signature"
+ android:label="@string/car_permission_label_control_car_windows"
+ android:description="@string/car_permission_desc_control_car_windows" />
+ <permission
+ android:name="android.car.permission.CONTROL_CAR_MIRRORS"
+ android:protectionLevel="system|signature"
+ android:label="@string/car_permission_label_control_car_mirrors"
+ android:description="@string/car_permission_desc_control_car_mirrors" />
+ <permission
+ android:name="android.car.permission.CONTROL_CAR_SEATS"
+ android:protectionLevel="system|signature"
+ android:label="@string/car_permission_label_control_car_seats"
+ android:description="@string/car_permission_desc_control_car_seats" />
+ <permission
android:name="android.car.permission.CAR_MILEAGE"
- android:permissionGroup="android.car.permission.CAR_INFORMATION"
- android:protectionLevel="dangerous"
+ android:protectionLevel="system|signature"
android:label="@string/car_permission_label_mileage"
android:description="@string/car_permission_desc_mileage" />
<permission
+ android:name="android.car.permission.CAR_TIRES"
+ android:protectionLevel="system|signature"
+ android:label="@string/car_permission_label_car_tires"
+ android:description="@string/car_permission_desc_car_tires" />
+ <permission
android:name="android.car.permission.CAR_SPEED"
android:permissionGroup="android.permission-group.LOCATION"
android:protectionLevel="dangerous"
android:label="@string/car_permission_label_speed"
android:description="@string/car_permission_desc_speed" />
<permission
- android:name="android.car.permission.VEHICLE_DYNAMICS_STATE"
- android:permissionGroup="android.permission-group.CAR_INFORMATION"
- android:protectionLevel="dangerous"
+ android:name="android.car.permission.CAR_ENERGY_PORTS"
+ android:protectionLevel="normal"
+ android:label="@string/car_permission_label_car_energy_ports"
+ android:description="@string/car_permission_desc_car_energy_ports" />
+ <permission
+ android:name="android.car.permission.CAR_ENGINE_DETAILED"
+ android:protectionLevel="system|signature"
+ android:label="@string/car_permission_label_car_engine_detailed"
+ android:description="@string/car_permission_desc_car_engine_detailed" />
+ <permission
+ android:name="android.car.permission.CAR_DYNAMICS_STATE"
+ android:protectionLevel="system|signature"
android:label="@string/car_permission_label_vehicle_dynamics_state"
android:description="@string/car_permission_desc_vehicle_dynamics_state" />
<permission
@@ -72,11 +104,6 @@
android:label="@string/car_permission_label_vendor_extension"
android:description="@string/car_permission_desc_vendor_extension" />
<permission
- android:name="android.car.permission.CAR_RADIO"
- android:protectionLevel="system|signature"
- android:label="@string/car_permission_label_radio"
- android:description="@string/car_permission_desc_radio" />
- <permission
android:name="android.car.permission.CAR_PROJECTION"
android:protectionLevel="system|signature"
android:label="@string/car_permission_label_projection"
@@ -87,17 +114,42 @@
android:label="@string/car_permission_label_mock_vehicle_hal"
android:description="@string/car_permission_desc_mock_vehicle_hal" />
<permission
+ android:name="android.car.permission.CAR_INFO"
+ android:protectionLevel="normal"
+ android:label="@string/car_permission_label_car_info"
+ android:description="@string/car_permission_desc_car_info" />
+ <permission
+ android:name="android.car.permission.CAR_EXTERIOR_ENVIRONMENT"
+ android:protectionLevel="normal"
+ android:label="@string/car_permission_label_car_exterior_environment"
+ android:description="@string/car_permission_desc_car_exterior_environment" />
+ <permission
+ android:name="android.car.permission.CAR_EXTERIOR_LIGHTS"
+ android:protectionLevel="system|signature"
+ android:label="@string/car_permission_label_car_exterior_lights"
+ android:description="@string/car_permission_desc_car_exterior_lights" />
+ <permission
+ android:name="android.car.permission.CONTROL_CAR_EXTERIOR_LIGHTS"
+ android:protectionLevel="system|signature"
+ 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_POWERTRAIN"
+ android:protectionLevel="normal"
+ android:label="@string/car_permission_label_car_powertrain"
+ android:description="@string/car_permission_desc_car_powertrain" />
+ <permission
android:name="android.car.permission.CAR_NAVIGATION_MANAGER"
android:protectionLevel="system|signature"
android:label="@string/car_permission_car_navigation_manager"
android:description="@string/car_permission_desc_car_navigation_manager" />
<permission
- android:name="android.car.permission.DIAGNOSTIC_READ_ALL"
- android:protectionLevel="system|signature"
- android:label="@string/car_permission_label_diag_read"
- android:description="@string/car_permission_desc_diag_read" />
+ android:name="android.car.permission.CAR_DIAGNOSTICS"
+ android:protectionLevel="system|signature"
+ android:label="@string/car_permission_label_diag_read"
+ android:description="@string/car_permission_desc_diag_read" />
<permission
- android:name="android.car.permission.DIAGNOSTIC_CLEAR"
+ android:name="android.car.permission.CLEAR_CAR_DIAGNOSTICS"
android:protectionLevel="system|signature"
android:label="@string/car_permission_label_diag_clear"
android:description="@string/car_permission_desc_diag_clear" />
@@ -111,7 +163,11 @@
android:protectionLevel="system|signature"
android:label="@string/car_permission_label_vms_subscriber"
android:description="@string/car_permission_desc_vms_subscriber" />
-
+ <permission
+ android:name="android.car.permission.CAR_DRIVING_STATE"
+ android:protectionLevel="system|signature"
+ android:label="@string/car_permission_label_driving_state"
+ android:description="@string/car_permission_desc_driving_state" />
<!-- may replace this with system permission if proper one is defined. -->
<permission
android:name="android.car.permission.CONTROL_APP_BLOCKING"
@@ -154,6 +210,11 @@
android:label="@string/car_permission_car_cluster_control"
android:description="@string/car_permission_desc_car_cluster_control" />
+ <permission android:name="android.car.permission.STORAGE_MONITORING"
+ android:protectionLevel="system|signature"
+ android:label="@string/car_permission_label_storage_monitoring"
+ android:description="@string/car_permission_desc_storage_monitoring" />
+
<uses-permission android:name="android.permission.CALL_PHONE" />
<uses-permission android:name="android.permission.DEVICE_POWER" />
<uses-permission android:name="android.permission.GRANT_RUNTIME_PERMISSIONS" />
@@ -172,12 +233,15 @@
<uses-permission android:name="android.permission.WRITE_SECURE_SETTINGS" />
<uses-permission android:name="android.permission.BLUETOOTH" />
<uses-permission android:name="android.permission.MANAGE_USERS" />
+ <uses-permission android:name="android.permission.LOCATION_HARDWARE" />
+ <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<application android:label="@string/app_title"
android:directBootAware="true"
android:allowBackup="false"
android:persistent="true">
+ <uses-library android:name="android.test.runner" />
<service android:name=".CarService"
android:singleUser="true">
<intent-filter>
@@ -187,7 +251,9 @@
<service android:name=".PerUserCarService" android:exported="false" />
<activity android:name="com.android.car.pm.ActivityBlockingActivity"
android:excludeFromRecents="true"
- android:exported="false">
+ android:theme="@android:style/Theme.Translucent.NoTitleBar"
+ android:exported="false"
+ android:launchMode="singleTask">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
</intent-filter>
diff --git a/car_product/overlay/frameworks/base/packages/SystemUI/res/drawable/remote_input_bg.xml b/service/res/drawable/exit_button_background.xml
similarity index 76%
rename from car_product/overlay/frameworks/base/packages/SystemUI/res/drawable/remote_input_bg.xml
rename to service/res/drawable/exit_button_background.xml
index 3120679..92d32fd 100644
--- a/car_product/overlay/frameworks/base/packages/SystemUI/res/drawable/remote_input_bg.xml
+++ b/service/res/drawable/exit_button_background.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2016 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,8 +14,6 @@
limitations under the License.
-->
<shape xmlns:android="http://schemas.android.com/apk/res/android">
- <solid android:color="#ff6c6c6c" />
- <corners
- android:bottomRightRadius="16dp"
- android:bottomLeftRadius="16dp"/>
+ <solid android:color="@color/exit_button_background"/>
+ <corners android:radius="@dimen/exit_button_radius"/>
</shape>
diff --git a/car_product/overlay/frameworks/base/packages/SystemUI/res/drawable/remote_input_bg.xml b/service/res/drawable/exit_button_ripple_background.xml
similarity index 67%
copy from car_product/overlay/frameworks/base/packages/SystemUI/res/drawable/remote_input_bg.xml
copy to service/res/drawable/exit_button_ripple_background.xml
index 3120679..54fd00f 100644
--- a/car_product/overlay/frameworks/base/packages/SystemUI/res/drawable/remote_input_bg.xml
+++ b/service/res/drawable/exit_button_ripple_background.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2016 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,9 +13,8 @@
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="#ff6c6c6c" />
- <corners
- android:bottomRightRadius="16dp"
- android:bottomLeftRadius="16dp"/>
-</shape>
+<ripple
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:color="@color/ripple_background">
+ <item android:drawable="@drawable/exit_button_background" />
+</ripple>
diff --git a/service/res/layout/activity_blocking.xml b/service/res/layout/activity_blocking.xml
index 14dcce3..687afbe 100644
--- a/service/res/layout/activity_blocking.xml
+++ b/service/res/layout/activity_blocking.xml
@@ -13,18 +13,25 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
-<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+<LinearLayout
+ xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
- android:orientation="vertical" >
+ android:orientation="vertical"
+ android:background="@color/activity_blocking_activity_background"
+ android:padding="@dimen/blocking_activity_padding"
+ android:gravity="center">
<TextView
android:id="@+id/activity_blocked_title"
- android:layout_width="wrap_content"
android:layout_height="wrap_content"
- android:text="@string/activity_blocked_string" />
+ android:layout_width="wrap_content"
+ android:textColor="@color/blocking_text"
+ android:textAppearance="@style/ActivityBlockingActivityText" />
<Button
- android:id="@+id/botton_exit_now"
- android:layout_width="wrap_content"
+ android:id="@+id/exit"
android:layout_height="wrap_content"
- android:text="@string/exit_now" />
+ android:layout_width="wrap_content"
+ android:layout_marginTop="@dimen/exit_button_top_margin"
+ android:text="@string/exit_button"
+ style="@style/ExitButtonStyle"/>
</LinearLayout>
diff --git a/service/res/raw/car_config.json b/service/res/raw/car_config.json
new file mode 100644
index 0000000..85d9712
--- /dev/null
+++ b/service/res/raw/car_config.json
@@ -0,0 +1,7 @@
+{
+ "SpeedBump": {
+ "acquiredPermitsPerSecond": 0.5,
+ "maxPermitPool": 5,
+ "permitFillDelay": 600
+ }
+}
diff --git a/service/res/values-h1920dp/dimens.xml b/service/res/values-h1920dp/dimens.xml
new file mode 100644
index 0000000..938fb17
--- /dev/null
+++ b/service/res/values-h1920dp/dimens.xml
@@ -0,0 +1,26 @@
+<?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.
+*/
+-->
+<resources>
+ <!-- Text size in ActivityBlockingActivity. -->
+ <dimen name="blocking_text_size">40sp</dimen>
+ <!-- Padding of exit button in ActivityBlockingActivity. -->
+ <dimen name="exit_button_padding">28dp</dimen>
+ <!-- Top margin of exit button in ActivityBlockingActivity. -->
+ <dimen name="exit_button_top_margin">20dp</dimen>
+</resources>
diff --git a/service/res/values-h800dp/dimens.xml b/service/res/values-h800dp/dimens.xml
new file mode 100644
index 0000000..9594554
--- /dev/null
+++ b/service/res/values-h800dp/dimens.xml
@@ -0,0 +1,22 @@
+<?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.
+*/
+-->
+<resources>
+ <!-- Padding of exit button in ActivityBlockingActivity. -->
+ <dimen name="exit_button_padding">28dp</dimen>
+</resources>
diff --git a/service/res/values-night/colors.xml b/service/res/values-night/colors.xml
new file mode 100644
index 0000000..65f8fb1
--- /dev/null
+++ b/service/res/values-night/colors.xml
@@ -0,0 +1,35 @@
+<?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.
+*/
+-->
+<resources>
+ <!-- Semi-transparent background color of blocking activity. -->
+ <!-- In Call background scrim: black @ 80% -->
+ <color name="activity_blocking_activity_background">#cc000000</color>
+
+ <!-- Color of text in blocking activity. -->
+ <color name="blocking_text">#fff5f5f5</color>
+
+ <!-- Background color of exit button. -->
+ <color name="exit_button_background">#ff80cbc4</color>
+
+ <!-- Color of exit button text. -->
+ <color name="exit_button_text">#ff212121</color>
+
+ <!-- Ripple color. -->
+ <color name="ripple_background">#3dffffff</color>
+</resources>
diff --git a/service/res/values-w1280dp/dimens.xml b/service/res/values-w1280dp/dimens.xml
new file mode 100644
index 0000000..f5469f2
--- /dev/null
+++ b/service/res/values-w1280dp/dimens.xml
@@ -0,0 +1,22 @@
+<?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.
+*/
+-->
+<resources>
+ <!-- Padding of ActivityBlockingActivity. -->
+ <dimen name="blocking_activity_padding">148dp</dimen>
+</resources>
diff --git a/service/res/values-w1920dp/dimens.xml b/service/res/values-w1920dp/dimens.xml
new file mode 100644
index 0000000..75d2deb
--- /dev/null
+++ b/service/res/values-w1920dp/dimens.xml
@@ -0,0 +1,22 @@
+<?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.
+*/
+-->
+<resources>
+ <!-- Padding of ActivityBlockingActivity. -->
+ <dimen name="blocking_activity_padding">192dp</dimen>
+</resources>
diff --git a/service/res/values-w690dp/dimens.xml b/service/res/values-w690dp/dimens.xml
new file mode 100644
index 0000000..0b06ada
--- /dev/null
+++ b/service/res/values-w690dp/dimens.xml
@@ -0,0 +1,22 @@
+<?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.
+*/
+-->
+<resources>
+ <!-- Padding of ActivityBlockingActivity. -->
+ <dimen name="blocking_activity_padding">112dp</dimen>
+</resources>
diff --git a/service/res/values/attrs.xml b/service/res/values/attrs.xml
new file mode 100644
index 0000000..89c4258
--- /dev/null
+++ b/service/res/values/attrs.xml
@@ -0,0 +1,103 @@
+<?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.
+*/
+-->
+
+<resources>
+ <!-- Defines the attributes and values used in res/xml/car_volume_group.xml -->
+ <declare-styleable name="volumeGroups" />
+
+ <declare-styleable name="volumeGroups_group"/>
+
+ <declare-styleable name="volumeGroups_context">
+ <!-- Align with hardware/interfaces/automotive/audiocontrol/1.0/types.hal:ContextNumber -->
+ <attr name="context">
+ <enum name="music" value="1"/>
+ <enum name="navigation" value="2"/>
+ <enum name="voice_command" value="3"/>
+ <enum name="call_ring" value="4"/>
+ <enum name="call" value="5"/>
+ <enum name="alarm" value="6"/>
+ <enum name="notification" value="7"/>
+ <enum name="system_sound" value="8"/>
+ </attr>
+ </declare-styleable>
+
+ <!-- Defines the UX restrictions to be imposed for different driving states of a vehicle -->
+ <declare-styleable name="UxRestrictions"/>
+ <!-- 1. UX restriction Mapping from a driving state of the vehicle-->
+ <declare-styleable name="UxRestrictions_RestrictionMapping"/>
+
+ <!-- 1.a. Driving states supported -->
+ <declare-styleable name="UxRestrictions_DrivingState">
+ <!-- Align with the driving states (@CarDrivingState) defined in
+ packages/services/Car/car-lib/src/android/car/drivingstate/CarDrivingStateEvent.java-->
+ <attr name="state">
+ <enum name="parked" value="0"/>
+ <enum name="idling" value="1"/>
+ <enum name="moving" value="2"/>
+ </attr>
+ <!-- Minimum and Maximum speed attributes useful to provide different restrictions
+ for different speed ranges -->
+ <attr name="minSpeed" format="float"/>
+ <attr name="maxSpeed" format="float"/>
+ </declare-styleable>
+
+ <!-- 1.b. UX restriction types-->
+ <declare-styleable name="UxRestrictions_Restrictions">
+ <!-- This corresponds to what CarUxRestrictions#mRequiresDistractionOptimization needs to
+ be set to. This means that apps will have to follow the general baseline
+ distraction optimization rules defined in the Driver Distraction Guidelines. -->
+ <attr name="requiresDistractionOptimization" format="boolean"/>
+ <!-- These are the additional UX restrictions that OEMs can configure in addition to
+ the baseline restrictions defined in the above requiresDistractionOptimization.
+ The values here have to align with the UX Restrictions defined in
+ packages/services/Car/car-lib/src/android/car/drivingstate/CarUxRestrictions.java-->
+ <attr name="uxr">
+ <flag name="baseline" value="0"/>
+ <flag name="no_dialpad" value="1"/>
+ <flag name="no_filtering" value="2"/>
+ <flag name="limit_string_length" value="4"/>
+ <flag name="no_keyboard" value="8"/>
+ <flag name="no_video" value="16"/>
+ <flag name="limit_content" value="32"/>
+ <flag name="no_setup" value="64"/>
+ <flag name="no_text_message" value="128"/>
+ <flag name="no_voice_transcription" value="256"/>
+ <flag name="fully_restricted" value="511"/>
+ </attr>
+ </declare-styleable>
+
+ <!-- 2. Some of UX restrictions can be parametrized. -->
+ <declare-styleable name="UxRestrictions_RestrictionParameters"/>
+
+ <!-- 2.a Parameters to express displayed String related restrictions -->
+ <declare-styleable name="UxRestrictions_StringRestrictions">
+ <!-- Max allowed length of general purpose strings when limit_string_length is imposed-->
+ <attr name="maxLength" format="integer"/>
+ </declare-styleable>
+
+ <!-- 2.b. Parameters to express content related restrictions -->
+ <declare-styleable name="UxRestrictions_ContentRestrictions">
+ <!-- Max number of cumulative content items allowed to be displayed when
+ limit_content is imposed. -->
+ <attr name="maxCumulativeItems" format="integer"/>
+ <!-- Maximum levels deep that the user can navigate to when limit_content is imposed. -->
+ <attr name="maxDepth" format="integer"/>
+ </declare-styleable>
+
+</resources>
diff --git a/service/res/values/colors.xml b/service/res/values/colors.xml
new file mode 100644
index 0000000..ed86a3b
--- /dev/null
+++ b/service/res/values/colors.xml
@@ -0,0 +1,35 @@
+<?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.
+*/
+-->
+<resources>
+ <!-- Semi-transparent background color of blocking activity. -->
+ <!-- In Call background scrim: grey 200 @ 90% -->
+ <color name="activity_blocking_activity_background">#e6eeeeee</color>
+
+ <!-- Color of text in blocking activity. -->
+ <color name="blocking_text">#ff212121</color>
+
+ <!-- Background color of exit button. -->
+ <color name="exit_button_background">#ff00796b</color>
+
+ <!-- Color of exit button text. -->
+ <color name="exit_button_text">#fffafafa</color>
+
+ <!-- Ripple color of exit button background. -->
+ <color name="ripple_background">#3d000000</color>
+</resources>
diff --git a/service/res/values/config.xml b/service/res/values/config.xml
index 61cef59..45e6e0b 100644
--- a/service/res/values/config.xml
+++ b/service/res/values/config.xml
@@ -20,37 +20,10 @@
<!-- Resources to configure car service based on each OEM's preference. -->
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <!-- Audio routing policy for all H/W variants. Each item represents policy for one variant.
-
- Each item is defined in this format:
- physicalStreamNumber:(streamType,)*StreamType#physicalStreamNumber:...
-
- Stream type is logical stream type to route to the physical stream. Currently defined
- types are: call, media, nav_guidance, voice_command, alarm, notification, system, safety,
- and unknown
- unknown is for stream not tagged with specific contents.
- physicalStreamNumber should be [0, maxNumberOfPhysicalStream - 1].
- There is no "radio" as radio routing is outside android (for external module) or same as
- music (for android internal module)
- OEM can put multiple policies as item and VEHICLE_PROPERTY_AUDIO_HW_VARIANT in vehicle HAL
- can decide which policy to use for the given H/W. This allows OEMs to support multiple
- audio policy from single android S/W by detecting system's audio capability in
- vehicle HAL.-->
- <string-array translatable="false" name="audioRoutingPolicy">
- <!-- alll logical streams into single physical stream 0. -->
- <item>"0:call,media,radio,nav_guidance,voice_command,alarm,notification,system,safety,unknown"</item>
- <!-- call and media to physical stream 0 while all others go to physical stream 1 -->
- <item>"0:call,media,radio,unknown#1:nav_guidance,voice_command,alarm,notification,system,safety"</item>
- </string-array>
- <!-- Timeout value in Ms for audio focus wait. Audio focus request not responsed within
- this value will be treated as timeout and audio focus will be reset to LOSS state. -->
- <integer name="audioFocusWaitTimeoutMs">1000</integer>
<!-- Configuration to enable usage of dynamic audio routing. If this is set to false,
dynamic audio routing is disabled and audio works in legacy mode. It may be useful
during initial development where audio hal does not support bus based addressing yet. -->
- <bool name="audioUseDynamicRouting">true</bool>
- <!-- Number of audio focus timeouts that indicate vehicle CAN bus failure. -->
- <integer name="consecutiveHalFailures">3</integer>
+ <bool name="audioUseDynamicRouting">false</bool>
<!-- Whether to block other audio while media audio is muted with display off. When set to true,
other sounds cannot be played either while display is off. If false, only media is muted
and other sounds can be still played. -->
@@ -60,20 +33,26 @@
<string name="instrumentClusterRendererService">android.car.cluster.sample/.SampleClusterServiceImpl</string>
- <!-- Whether to enable Avtivity blocking for safety. When Activity blocking is enabled,
+ <!-- Whether to enable Activity blocking for safety. When Activity blocking is enabled,
only whitelisted safe Activities will be allowed while car is not parked. -->
<bool name="enableActivityBlockingForSafety">true</bool>
<!-- Activity to be presented when un-safe activity is launched. Take a look at the javadoc of the
default implementation. -->
<string name="activityBlockingActivity">com.android.car/com.android.car.pm.ActivityBlockingActivity</string>
- <!-- Comma separated list of activities that will be allowed by default. This only applies to
- system apps which is included into system image and non-system app in the list will be
- ignored. Format of each entry is either to specify package name to whitelist the whole
- package or use format of "packagename/activity_classname" for tagging each activities.
- Besides this, system apps with car app meta data will be auto whitelisted. -->
- <string name="defauiltActivityWhitelist">android,com.android.systemui</string>
+ <!-- Comma separated list of activities that need to be exempted from getting
+ blocked in a UX restricted state.
+ Format of each entry is either to specify package name to whitelist the whole package or
+ use format of "packagename/activity_classname" for tagging each activities.
+ The current implementations expects the following system packages/activities to be
+ whitelisted. For general guidelines to design distraction optimized apps, please refer
+ to Android Auto Driver Distraction Guidelines. -->
+ <string name="activityWhitelist">com.android.systemui,com.google.android.packageinstaller/com.android.packageinstaller.permission.ui.GrantPermissionsActivity</string>
+ <!-- Comma separated list of activities that will be blocked during restricted state.
+ Format of each entry is either to specify package name to whitelist the whole package
+ or use format of "packagename/activity_classname" for tagging each activities.-->
+ <string name="activityBlacklist"></string>
<!-- Default home activity -->
- <string name="defaultHomeActivity">com.android.car.overview/com.android.car.overview.StreamOverviewActivity</string>
+ <string name="defaultHomeActivity"><!--com.your.package/com.your.package.Activity--></string>
<!-- The com.android.car.VmsPublisherService will bind to this list of clients -->
<string-array translatable="false" name="vmsPublisherClients">
</string-array>
@@ -81,4 +60,73 @@
<string-array translatable="false" name="vmsSafePermissions">
<item>"android.permission.ACCESS_FINE_LOCATION"</item>
</string-array>
+
+ <!-- Number of milliseconds to wait before trying re-bind to a crashed publisher. -->
+ <integer name="millisecondsBeforeRebindToVmsPublisher">10000</integer>
+
+ <!-- Hours of uptime (excluding sleep) after which a 1% increase in the wear of the flash
+ storage in the head-unit is considered as acceptable level of wear. -->
+ <integer name="acceptableHoursPerOnePercentFlashWear">70</integer>
+
+ <!-- How often (in hours of uptime excluding sleep) CarService will flush to disk information
+ about the total running time of the head-unit. A shutdown or reboot of the head-unit
+ will always cause a flush of the uptime information, regardless of this setting. -->
+ <integer name="uptimeHoursIntervalBetweenUptimeDataWrite">5</integer>
+
+ <!-- The name of an activity to be launched by CarService whenever it detects a change in the
+ level of wear of the flash storage. Value must either be an empty string, which means that
+ no activity shall be launched, or must be in the format of a flattened ComponentName and
+ reference a valid activity. It is strongly recommended that the chosen activity be
+ protected with the android.car.permission.STORAGE_MONITORING permission. -->
+ <string name="activityHandlerForFlashWearChanges">com.google.android.car.defaultstoragemonitoringcompanionapp/.MainActivity</string>
+
+ <!-- How often (in seconds) CarService will update I/O metrics from the kernel. -->
+ <integer name="ioStatsRefreshRateSeconds">60</integer>
+
+ <!-- The number of I/O metrics samples to keep in memory at one time.
+ The system will keep a sliding window of samples of this size, and allow
+ retrieval of activity this many sample windows back in time. Setting this to
+ 0 means no samples will be collected, effectively disabling I/O metric collection. -->
+ <integer name="ioStatsNumSamplesToStore">15</integer>
+
+ <!-- The maximum number of KB (1024 bytes) that can be written to storage in one sample
+ before CarService deems I/O activity excessive. A simple way to set this value
+ is - given the total writable amount (storage size * P/E cycles) - to make
+ reasonable assumptions about the expected lifetime of the vehicle and the average
+ daily driving time, and use that to allocate a per-sample budget. -->
+ <integer name="acceptableWrittenKBytesPerSample">115000</integer>
+ <!-- The maximum number of fsync() system calls that can be made in one sample before
+ CarService deems I/O activity excessive. -->
+ <integer name="acceptableFsyncCallsPerSample">150</integer>
+
+ <!-- The maximum number of samples (within an I/O stats sample window) that CarService
+ should consider exhibiting excessive I/O activity before broadcasting an intent
+ to signal the potential for flash wear. -->
+ <integer name="maxExcessiveIoSamplesInWindow">11</integer>
+
+ <!-- The name of an intent to be notified by CarService whenever it detects too many
+ samples with excessive I/O activity. Value must either be an empty string, which
+ means that no notification will take place, or be in the format of a flattened
+ ComponentName and reference a valid BroadcastReceiver. This broadcast receiver
+ must be registered in its containing app's AndroidManifest.xml and it is
+ strongly recommended that it be protected with the
+ android.car.permission.STORAGE_MONITORING permission. -->
+ <string name="intentReceiverForUnacceptableIoMetrics">com.google.android.car.defaultstoragemonitoringcompanionapp/.ExcessiveIoIntentReceiver</string>
+
+ <!-- The Model ID to advertise Bluetooth Fast Pair connections with. Must be overlayed with
+ device specific model id. -->
+ <integer name="fastPairModelId">0x000000</integer>
+
+ <!-- The garage mode configuration, specifying the time after shutdown to reboot into garage
+ mode and the number of attempts at that time to try before moving to the next wake up
+ time. This is intended to be a back-off pattern. -->
+ <string-array translatable="false" name="config_garageModeCadence">
+ <!-- <wake up after X min/hour/days>,<how many times> -->
+ <item>15m,1</item>
+ <item>6h,8</item>
+ <item>1d,5</item>
+ <item>3d,2</item>
+ <item>7d,3</item>
+ </string-array>
+
</resources>
diff --git a/service/res/values/dimens.xml b/service/res/values/dimens.xml
new file mode 100644
index 0000000..f75a358
--- /dev/null
+++ b/service/res/values/dimens.xml
@@ -0,0 +1,36 @@
+<?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.
+*/
+-->
+<resources>
+ <!-- Text size in ActivityBlockingActivity. -->
+ <dimen name="blocking_text_size">32sp</dimen>
+ <!-- Padding of ActivityBlockingActivity. -->
+ <dimen name="blocking_activity_padding">20dp</dimen>
+
+ <!-- Minimum height of exit button in ActivityBlockingActivity. -->
+ <dimen name="exit_button_min_height">56dp</dimen>
+ <!-- Minimum width of exit button in ActivityBlockingActivity. -->
+ <dimen name="exit_button_min_width">156dp</dimen>
+ <!-- Padding of exit button in ActivityBlockingActivity. -->
+ <dimen name="exit_button_padding">16dp</dimen>
+ <!-- Radius of exit button in ActivityBlockingActivity. -->
+ <dimen name="exit_button_radius">4dp</dimen>
+ <!-- Top margin of exit button. It should be half the height of
+ button (exit_button_min_height). -->
+ <dimen name="exit_button_top_margin">28dp</dimen>
+</resources>
diff --git a/service/res/values/strings.xml b/service/res/values/strings.xml
index b159dd2..1947e43 100644
--- a/service/res/values/strings.xml
+++ b/service/res/values/strings.xml
@@ -13,7 +13,7 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
-<resources>
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_title">Car service</string>
<!-- For permissions -->
@@ -30,10 +30,10 @@
<string name="car_permission_label_camera">Car Camera</string>
<!-- Permission text: apps can control car camera [CHAR LIMIT=NONE] -->
<string name="car_permission_desc_camera">Access your car\'s camera(s).</string>
- <!-- Permission text: can access your car's fuel level [CHAR LIMIT=NONE] -->
- <string name="car_permission_label_fuel">Car fuel level</string>
- <!-- Permission text: can access your car's fuel level [CHAR LIMIT=NONE] -->
- <string name="car_permission_desc_fuel">Access your car\'s fuel level information.</string>
+ <!-- Permission text: can access your car's energy information [CHAR LIMIT=NONE] -->
+ <string name="car_permission_label_energy">Car energy</string>
+ <!-- Permission text: can access your car's energy information [CHAR LIMIT=NONE] -->
+ <string name="car_permission_desc_energy">Access your car\'s energy information.</string>
<!-- Permission text: apps can control car hvac [CHAR LIMIT=NONE] -->
<string name="car_permission_label_hvac">Car Hvac</string>
<!-- Permission text: apps can control car hvac [CHAR LIMIT=NONE] -->
@@ -103,10 +103,10 @@
<string name="car_can_bus_failure_desc">CAN bus does not respond. Unplug and plug back headunit
box and restart the car</string>
- <!-- Blocking activity: Message to show to user when an application is not allowed. [CHAR LIMIT=NONE] -->
- <string name="activity_blocked_string">The application is not allowed while driving.</string>
- <!-- Blocking activity: Message on exit button. [CHAR LIMIT=NONE] -->
- <string name="exit_now">Exit</string>
+ <!-- Blocking activity: Message to show to user when a feature of current application is not allowed. [CHAR LIMIT=60] -->
+ <string name="activity_blocked_string">This <xliff:g id="app_name" example="Google Maps">%1$s</xliff:g> feature can\'t be used while driving.</string>
+ <!-- Blocking activity: Button text that restarts the current blocked application. [CHAR LIMIT=10] -->
+ <string name="exit_button">OK</string>
<!-- Permission text: apps can control diagnostic data [CHAR LIMIT=NONE] -->
<string name="car_permission_label_diag_read">Diagnostic Data</string>
@@ -127,4 +127,79 @@
<string name="car_permission_label_vms_subscriber">VMS subscriber</string>
<!-- Permission text: apps can receive VMS messages from the car [CHAR LIMIT=NONE] -->
<string name="car_permission_desc_vms_subscriber">Subscribe to vms messages</string>
+
+ <!-- Permission text: apps can monitor flash storage usage [CHAR LIMIT=NONE] -->
+ <string name="car_permission_label_storage_monitoring">Flash storage monitoring</string>
+ <!-- Permission text: apps can monitor flash storage usage [CHAR LIMIT=NONE] -->
+ <string name="car_permission_desc_storage_monitoring">Monitor flash storage usage</string>
+
+ <!-- Permission text: apps can listen to driving state changes [CHAR LIMIT=NONE] -->
+ <string name="car_permission_label_driving_state">Driving State</string>
+ <!-- Permission text: apps can listen to driving state changes [CHAR LIMIT=NONE] -->
+ <string name="car_permission_desc_driving_state">Listen to Driving state changes </string>
+
+ <!-- Permission text: apps read Engine Detailed [CHAR LIMIT=NONE] -->
+ <string name="car_permission_label_car_engine_detailed">Engine Detailed</string>
+ <!-- Permission text: apps can listen to Engine Detailed [CHAR LIMIT=NONE] -->
+ <string name="car_permission_desc_car_engine_detailed">Access your car\'s detailed engine information</string>
+
+ <!-- Permission text: apps can access car's fuel door and ev charge port [CHAR LIMIT=NONE] -->
+ <string name="car_permission_label_car_energy_ports">Energy Ports</string>
+ <!-- Permission text: apps can access car's fuel door and ev charge port [CHAR LIMIT=NONE] -->
+ <string name="car_permission_desc_car_energy_ports">Access energy ports</string>
+
+ <!-- Permission text: apps can access car's VIN information [CHAR LIMIT=NONE] -->
+ <string name="car_permission_label_car_identification">Car identification</string>
+ <!-- Permission text: apps can access car's VIN information [CHAR LIMIT=NONE] -->
+ <string name="car_permission_desc_car_identification">Access car\'s identification</string>
+
+ <!-- Permission text: apps can control car doors [CHAR LIMIT=NONE] -->
+ <string name="car_permission_label_control_car_doors">Car Doors</string>
+ <!-- Permission text: apps can control car doors [CHAR LIMIT=NONE] -->
+ <string name="car_permission_desc_control_car_doors">Control car\'s doors</string>
+
+ <!-- Permission text: apps can control car windows [CHAR LIMIT=NONE] -->
+ <string name="car_permission_label_control_car_windows">Car Windows</string>
+ <!-- Permission text: apps can control car windows [CHAR LIMIT=NONE] -->
+ <string name="car_permission_desc_control_car_windows">Control car\'s windows</string>
+
+ <!-- Permission text: apps can control car mirrors [CHAR LIMIT=NONE] -->
+ <string name="car_permission_label_control_car_mirrors">Car Mirrors</string>
+ <!-- Permission text: apps can control car mirrors [CHAR LIMIT=NONE] -->
+ <string name="car_permission_desc_control_car_mirrors">Control car\'s mirrors</string>
+
+ <!-- Permission text: apps can control car seats [CHAR LIMIT=NONE] -->
+ <string name="car_permission_label_control_car_seats">Car Seats</string>
+ <!-- Permission text: apps can control car seats [CHAR LIMIT=NONE] -->
+ <string name="car_permission_desc_control_car_seats">Control car\'s seats</string>
+
+ <!-- Permission text: apps read car's basic information [CHAR LIMIT=NONE] -->
+ <string name="car_permission_label_car_info">Car basic information</string>
+ <!-- Permission text: apps read car's basic information [CHAR LIMIT=NONE] -->
+ <string name="car_permission_desc_car_info">Access car basic information</string>
+
+ <!-- Permission text: apps access car's exterior lights state [CHAR LIMIT=NONE] -->
+ <string name="car_permission_label_car_exterior_lights">Car exterior lights</string>
+ <!-- Permission text: apps access car's exterior lights state [CHAR LIMIT=NONE] -->
+ <string name="car_permission_desc_car_exterior_lights">Access car exterior lights state</string>
+
+ <!-- Permission text: apps control car's exterior lights [CHAR LIMIT=NONE] -->
+ <string name="car_permission_label_control_car_exterior_lights">Car exterior lights</string>
+ <!-- Permission text: apps control car's exterior lights [CHAR LIMIT=NONE] -->
+ <string name="car_permission_desc_control_car_exterior_lights">Control car exterior lights </string>
+
+ <!-- Permission text: apps control car's exterior temperature [CHAR LIMIT=NONE] -->
+ <string name="car_permission_label_car_exterior_environment">Car exterior temperature</string>
+ <!-- Permission text: apps control car's exterior lights [CHAR LIMIT=NONE] -->
+ <string name="car_permission_desc_car_exterior_environment">Access car exterior temperature </string>
+
+ <!-- Permission text: apps access car's tire information [CHAR LIMIT=NONE] -->
+ <string name="car_permission_label_car_tires">Car tires</string>
+ <!-- Permission text: apps access car's tire information [CHAR LIMIT=NONE] -->
+ <string name="car_permission_desc_car_tires">Access car tire information</string>
+
+ <!-- Permission text: apps read information of car's powertrain [CHAR LIMIT=NONE] -->
+ <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>
</resources>
diff --git a/service/res/values/styles.xml b/service/res/values/styles.xml
new file mode 100644
index 0000000..4098e96
--- /dev/null
+++ b/service/res/values/styles.xml
@@ -0,0 +1,37 @@
+<?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>
+ <!-- TextAppearances for ActivityBlockingActivity. -->
+ <style name="ActivityBlockingActivityText">
+ <item name="android:fontFamily">sans-serif-medium</item>
+ <item name="android:textStyle">normal</item>
+ <item name="android:textSize">@dimen/blocking_text_size</item>
+ </style>
+
+ <!-- Style of exit button. -->
+ <style name="ExitButtonStyle">
+ <item name="android:background">@drawable/exit_button_ripple_background</item>
+ <item name="android:fontFamily">sans-serif-medium</item>
+ <item name="android:minHeight">@dimen/exit_button_min_height</item>
+ <item name="android:minWidth">@dimen/exit_button_min_width</item>
+ <item name="android:paddingHorizontal">@dimen/exit_button_padding</item>
+ <item name="android:textAllCaps">true</item>
+ <item name="android:textAlignment">center</item>
+ <item name="android:textAppearance">@style/ActivityBlockingActivityText</item>
+ <item name="android:textColor">@color/exit_button_text</item>
+ </style>
+</resources>
+
diff --git a/service/res/xml/car_ux_restrictions_map.xml b/service/res/xml/car_ux_restrictions_map.xml
new file mode 100644
index 0000000..385869a
--- /dev/null
+++ b/service/res/xml/car_ux_restrictions_map.xml
@@ -0,0 +1,69 @@
+<?xml version="1.0" encoding="utf-8"?>
+
+<!--
+This XML allows OEMs to configure a driving state to UX restrictions. There are 2 major classes
+of configuration:
+1. Restriction Mapping as defined by the <restrictionMapping> tag.
+2. Restriction Parameters for restrictions that can be parametrized as defined by
+ <restrictionParameters> tag.
+
+Note:
+ 1. The tags and attributes are declared in packages/services/Car/service/res/attrs.xml.
+ 2. The driving states defined there should align with driving states (@CarDrivingState) defined in
+ packages/services/Car/car-lib/src/android/car/drivingstate/CarDrivingStateEvent.java
+ 3. Similarly the UX restrictions should align with
+ packages/services/Car/car-lib/src/android/car/drivingstate/CarUxRestrictions.java
+-->
+
+<UxRestrictions xmlns:car="http://schemas.android.com/apk/res-auto">
+ <!-- Map the driving states to UX restrictions here -->
+ <!-- Note - The platform takes a fully restricted approach when there is no information or if
+ the information is malformed. As a result,
+ 1. Default values for requiresDistractionOptimization is true, and uxr is fully_restricted.
+ 2. If uxr != baseline, then requiresDistractionOptimization is automatically promoted to true,
+ even if it is declared as false. Because it doesn't make sense to have an non baseline UX
+ restriction without requiresDistractionOptimization set to true.
+ So if we don't want any restrictions, requiresDistractionOptimization should be explicitly
+ marked as false and uxr should be explicitly set to baseline. -->
+ <RestrictionMapping>
+ <DrivingState car:state="parked">
+ <Restrictions car:requiresDistractionOptimization="false" car:uxr="baseline"/>
+ </DrivingState>
+
+ <DrivingState car:state="idling">
+ <Restrictions car:requiresDistractionOptimization="false" car:uxr="baseline"/>
+ </DrivingState>
+
+ <!-- This is to illustrate how to add multiple speed ranges. The restrictions here
+ are the same for both the speed ranges, but could be configured to be different.
+ NOTE:
+ 1. The speed units is in meters per second to be in accordance with the
+ PERF_VEHICLE SPEED definition in hardware/interfaces/automotive/vehicle/2.0/types.hal
+ 2. The speed ranges should be non overlapping, i.e one speed value cannot be in more
+ than one range. It is denoted in a left closed, right open interval [minSpeed, maxSpeed).
+ For ex: [0,5) indicates speed >= 0 && speed < 5.0m/s.
+ 3. For a speed range with no high limit, maxSpeed is not filled. For ex., if the speed
+ range is anything >=5m/s, only the minSpeed is filled with a value of 5m/s. There cannot be
+ a range higher than this, which will violate the 2nd condition above.
+ 4. If the above conditions are not met, mapping behavior is undefined. -->
+ <!-- This is restrictions for moving and speed [0,5m/s) -->
+ <DrivingState car:state="moving" car:minSpeed="0" car:maxSpeed="5.0">
+ <Restrictions car:requiresDistractionOptimization="true" car:uxr="fully_restricted"/>
+ </DrivingState>
+
+ <!-- Restrictions for speed >=5 -->
+ <DrivingState car:state="moving" car:minSpeed="5.0">
+ <Restrictions car:requiresDistractionOptimization="true" car:uxr="fully_restricted"/>
+ </DrivingState>
+
+ </RestrictionMapping>
+
+ <!-- Configure restriction parameters here-->
+ <RestrictionParameters>
+ <!-- Parameters to express displayed String related restrictions -->
+ <StringRestrictions car:maxLength="120"/>
+ <!-- Parameters to express content related restrictions -->
+ <ContentRestrictions car:maxCumulativeItems="21" car:maxDepth="3"/>
+ </RestrictionParameters>
+
+</UxRestrictions>
\ No newline at end of file
diff --git a/service/res/xml/car_volume_groups.xml b/service/res/xml/car_volume_groups.xml
new file mode 100644
index 0000000..9bfc305
--- /dev/null
+++ b/service/res/xml/car_volume_groups.xml
@@ -0,0 +1,53 @@
+<?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.
+-->
+
+<!--
+ Defines the all available volume groups for volume control in a car.
+ One can overlay this configuration to customize the groups.
+
+ This configuration will be populated by CarAudioService and
+ surfaced to Car Settings App and/or other volume control interfaces.
+
+ Certain constraints applied to this configuration
+ - One context should not appear in two groups
+ - All contexts are assigned
+ - One bus should not appear in two groups
+ - All gain controllers (set on each bus) in one group have same step value
+
+ It is fine that there are buses that do not appear in any group, those buses
+ may be reserved for other usages.
+
+ Important note: when overlaying this configuration,
+ make sure the resources are in the same package as CarAudioService.
+-->
+<volumeGroups xmlns:car="http://schemas.android.com/apk/res-auto">
+ <group>
+ <context car:context="music"/>
+ <context car:context="call_ring"/>
+ <context car:context="notification"/>
+ <context car:context="system_sound"/>
+ </group>
+ <group>
+ <context car:context="navigation"/>
+ <context car:context="voice_command"/>
+ </group>
+ <group>
+ <context car:context="call"/>
+ </group>
+ <group>
+ <context car:context="alarm"/>
+ </group>
+</volumeGroups>
diff --git a/service/src/com/android/car/AppFocusService.java b/service/src/com/android/car/AppFocusService.java
index 3db21d2..9d46dad 100644
--- a/service/src/com/android/car/AppFocusService.java
+++ b/service/src/com/android/car/AppFocusService.java
@@ -305,11 +305,11 @@
}
private void updateFocusOwner(int appType, OwnershipClientInfo owner) {
- synchronized (this) {
- mFocusOwners.put(appType, owner);
- }
-
CarServiceUtils.runOnMain(() -> {
+ synchronized (this) {
+ mFocusOwners.put(appType, owner);
+ }
+
for (FocusOwnershipCallback callback : mFocusOwnershipCallbacks) {
callback.onFocusAcquired(appType, owner.getUid(), owner.getPid());
}
diff --git a/service/src/com/android/car/AudioRoutingPolicy.java b/service/src/com/android/car/AudioRoutingPolicy.java
deleted file mode 100644
index 9d341e2..0000000
--- a/service/src/com/android/car/AudioRoutingPolicy.java
+++ /dev/null
@@ -1,146 +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;
-
-import android.car.media.CarAudioManager;
-import android.content.Context;
-import android.content.res.Resources;
-import android.media.AudioAttributes;
-import android.util.Log;
-
-import java.io.PrintWriter;
-import java.util.Arrays;
-
-/**
- * Holds audio routing policy from config.xml. R.array.audioRoutingPolicy can contain
- * multiple policies and VEHICLE_PROPERTY_AUDIO_HW_VARIANT decide which one to use.
- */
-public class AudioRoutingPolicy {
-
- private final int USAGE_TYPE_INVALID = -1;
-
- private static final String ROUTING_POLICY_FOR_MOCKED_TEST =
- "0:call,media,radio,unknown#1:nav_guidance,voice_command,alarm,notification,system,safety";
-
- /** Physical stream to logical streams mapping */
- private final int[][] mLogicalStreams;
- /** Logical stream to physical stream mapping */
- private final int[] mPhysicalStreamForLogicalStream;
-
- public static AudioRoutingPolicy create(Context context, int policyNumber) {
- final Resources res = context.getResources();
- String[] policies = res.getStringArray(R.array.audioRoutingPolicy);
- String policy;
- if (policyNumber > (policies.length - 1)) {
- Log.e(CarLog.TAG_AUDIO, "AudioRoutingPolicy.create got wrong policy number:" +
- policyNumber + ", num of avaiable policies:" + policies.length);
- policy = policies[0];
- } else if (policyNumber < 0) { // this is special case for mocked testing.
- policy = ROUTING_POLICY_FOR_MOCKED_TEST;
- } else {
- policy = policies[policyNumber];
- }
- return new AudioRoutingPolicy(policy);
- }
-
- private static int getStreamType(String str) {
- switch (str) {
- case "call":
- return CarAudioManager.CAR_AUDIO_USAGE_VOICE_CALL;
- case "media":
- return CarAudioManager.CAR_AUDIO_USAGE_MUSIC;
- case "radio":
- return CarAudioManager.CAR_AUDIO_USAGE_RADIO;
- case "nav_guidance":
- return CarAudioManager.CAR_AUDIO_USAGE_NAVIGATION_GUIDANCE;
- case "voice_command":
- return CarAudioManager.CAR_AUDIO_USAGE_VOICE_COMMAND;
- case "alarm":
- return CarAudioManager.CAR_AUDIO_USAGE_ALARM;
- case "notification":
- return CarAudioManager.CAR_AUDIO_USAGE_NOTIFICATION;
- case "system":
- return CarAudioManager.CAR_AUDIO_USAGE_SYSTEM_SOUND;
- case "safety":
- return CarAudioManager.CAR_AUDIO_USAGE_SYSTEM_SAFETY_ALERT;
- case "unknown":
- return CarAudioManager.CAR_AUDIO_USAGE_DEFAULT;
- }
- throw new IllegalArgumentException("Wrong audioRoutingPolicy config, unknown stream type:" +
- str);
- }
-
- private AudioRoutingPolicy(String policy) {
- String[] streamPolicies = policy.split("#");
- final int nPhysicalStreams = streamPolicies.length;
- mLogicalStreams = new int[nPhysicalStreams][];
- mPhysicalStreamForLogicalStream = new int[CarAudioManager.CAR_AUDIO_USAGE_MAX + 1];
- for (int i = 0; i < mPhysicalStreamForLogicalStream.length; i++) {
- mPhysicalStreamForLogicalStream[i] = USAGE_TYPE_INVALID;
- }
- int defaultStreamType = USAGE_TYPE_INVALID;
- for (String streamPolicy : streamPolicies) {
- String[] numberVsStreams = streamPolicy.split(":");
- int physicalStream = Integer.parseInt(numberVsStreams[0]);
- String[] logicalStreams = numberVsStreams[1].split(",");
- int[] logicalStreamsInt = new int[logicalStreams.length];
- for (int i = 0; i < logicalStreams.length; i++) {
- int logicalStreamNumber = getStreamType(logicalStreams[i]);
- if (logicalStreamNumber == CarAudioManager.CAR_AUDIO_USAGE_DEFAULT) {
- defaultStreamType = physicalStream;
- }
- logicalStreamsInt[i] = logicalStreamNumber;
- mPhysicalStreamForLogicalStream[logicalStreamNumber] = physicalStream;
- }
- Arrays.sort(logicalStreamsInt);
- mLogicalStreams[physicalStream] = logicalStreamsInt;
- }
- if (defaultStreamType == USAGE_TYPE_INVALID) {
- Log.e(CarLog.TAG_AUDIO, "Audio routing policy did not include unknown");
- defaultStreamType = 0;
- }
- for (int i = 0; i < mPhysicalStreamForLogicalStream.length; i++) {
- if (mPhysicalStreamForLogicalStream[i] == USAGE_TYPE_INVALID) {
- Log.w(CarLog.TAG_AUDIO, "Audio routing policy did not cover logical stream " + i);
- mPhysicalStreamForLogicalStream[i] = defaultStreamType;
- }
- }
- }
-
- public int getPhysicalStreamsCount() {
- return mLogicalStreams.length;
- }
-
- public int[] getLogicalStreamsForPhysicalStream(int physicalStreamNumber) {
- return mLogicalStreams[physicalStreamNumber];
- }
-
- public int getPhysicalStreamForLogicalStream(int logicalStream) {
- return mPhysicalStreamForLogicalStream[logicalStream];
- }
-
- public void dump(PrintWriter writer) {
- writer.println("*AudioRoutingPolicy*");
- writer.println("**Logical Streams**");
- for (int i = 0; i < mLogicalStreams.length; i++) {
- writer.print("physical stream " + i + ":");
- for (int logicalStream : mLogicalStreams[i]) {
- writer.print(Integer.toString(logicalStream) + ",");
- }
- writer.println("");
- }
- }
-}
diff --git a/service/src/com/android/car/BluetoothAutoConnectStateMachine.java b/service/src/com/android/car/BluetoothAutoConnectStateMachine.java
index 01caee2..981db5b 100644
--- a/service/src/com/android/car/BluetoothAutoConnectStateMachine.java
+++ b/service/src/com/android/car/BluetoothAutoConnectStateMachine.java
@@ -15,6 +15,8 @@
*/
package com.android.car;
+import android.bluetooth.BluetoothDevice;
+import android.bluetooth.BluetoothProfile;
import android.os.Message;
import android.util.Log;
@@ -36,7 +38,7 @@
*/
public class BluetoothAutoConnectStateMachine extends StateMachine {
private static final String TAG = "BTAutoConnStateMachine";
- private static final boolean DBG = false;
+ private static final boolean DBG = Utils.DBG;
private final BluetoothDeviceConnectionPolicy mPolicy;
private final Idle mIdle;
private final Processing mProcessing;
@@ -46,7 +48,12 @@
public static final int CONNECT_TIMEOUT = 103;
public static final int DEVICE_CONNECTED = 104;
public static final int DEVICE_DISCONNECTED = 105;
+ // The following is used when PBAP and MAP should be connected to,
+ // after device connects on HFP.
+ public static final int CHECK_CLIENT_PROFILES = 1006;
+
public static final int CONNECTION_TIMEOUT_MS = 8000;
+ static final int CONNECT_MORE_PROFILES_TIMEOUT_MS = 2000;
BluetoothAutoConnectStateMachine(BluetoothDeviceConnectionPolicy policy) {
@@ -111,6 +118,21 @@
break;
}
+ case CHECK_CLIENT_PROFILES: {
+ removeMessages(CHECK_CLIENT_PROFILES);
+ BluetoothDeviceConnectionPolicy.ConnectionParams params =
+ (BluetoothDeviceConnectionPolicy.ConnectionParams) msg.obj;
+ BluetoothDevice device = params.getBluetoothDevice();
+ // After pairing/disconnect, always try to connect to both PBAP and MAP
+ if (DBG) {
+ Log.d(TAG, "try to connect to PBAP/MAP after pairing or disconnect: "
+ + Utils.getDeviceDebugInfo(device));
+ }
+ mPolicy.connectToDeviceOnProfile(BluetoothProfile.PBAP_CLIENT, device);
+ mPolicy.connectToDeviceOnProfile(BluetoothProfile.MAP_CLIENT, device);
+ break;
+ }
+
default: {
if (DBG) {
Log.d(TAG, "Idle->Unhandled Msg; " + msg.what);
diff --git a/service/src/com/android/car/BluetoothDeviceConnectionPolicy.java b/service/src/com/android/car/BluetoothDeviceConnectionPolicy.java
index 94cbdb1..f9c8a1e 100644
--- a/service/src/com/android/car/BluetoothDeviceConnectionPolicy.java
+++ b/service/src/com/android/car/BluetoothDeviceConnectionPolicy.java
@@ -16,6 +16,11 @@
package com.android.car;
+import static android.car.settings.CarSettings.Secure.KEY_BLUETOOTH_AUTOCONNECT_MESSAGING_DEVICES;
+import static android.car.settings.CarSettings.Secure.KEY_BLUETOOTH_AUTOCONNECT_MUSIC_DEVICES;
+import static android.car.settings.CarSettings.Secure.KEY_BLUETOOTH_AUTOCONNECT_NETWORK_DEVICES;
+import static android.car.settings.CarSettings.Secure.KEY_BLUETOOTH_AUTOCONNECT_PHONE_DEVICES;
+
import android.annotation.Nullable;
import android.app.ActivityManager;
import android.bluetooth.BluetoothA2dpSink;
@@ -23,43 +28,38 @@
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothHeadsetClient;
import android.bluetooth.BluetoothMapClient;
+import android.bluetooth.BluetoothPan;
import android.bluetooth.BluetoothPbapClient;
import android.bluetooth.BluetoothProfile;
import android.bluetooth.BluetoothUuid;
-import android.car.hardware.CarPropertyValue;
-import android.car.hardware.CarSensorEvent;
-import android.car.hardware.CarSensorManager;
-import android.car.hardware.ICarSensorEventListener;
-import android.car.hardware.cabin.CarCabinManager;
-import android.car.hardware.property.CarPropertyEvent;
-import android.car.hardware.property.ICarPropertyEventListener;
+import android.car.CarBluetoothManager;
import android.car.ICarBluetoothUserService;
import android.car.ICarUserService;
-
-import static android.car.settings.CarSettings.Secure.KEY_BLUETOOTH_AUTOCONNECT_MUSIC_DEVICES;
-import static android.car.settings.CarSettings.Secure.KEY_BLUETOOTH_AUTOCONNECT_PHONE_DEVICES;
-import static android.car.settings.CarSettings.Secure.KEY_BLUETOOTH_AUTOCONNECT_MESSAGING_DEVICES;
-
-import android.car.CarBluetoothManager;
-import android.os.ParcelUuid;
-import android.os.Parcelable;
-import android.os.UserHandle;
-import android.provider.Settings;
-
+import android.car.drivingstate.CarUxRestrictions;
+import android.car.drivingstate.ICarUxRestrictionsChangeListener;
+import android.car.hardware.CarPropertyValue;
+import android.car.hardware.property.CarPropertyEvent;
+import android.car.hardware.property.ICarPropertyEventListener;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
+import android.hardware.automotive.vehicle.V2_0.VehicleIgnitionState;
+import android.hardware.automotive.vehicle.V2_0.VehicleProperty;
+import android.os.ParcelUuid;
+import android.os.Parcelable;
import android.os.RemoteException;
+import android.os.UserHandle;
+import android.provider.Settings;
import android.util.Log;
import com.android.internal.annotations.VisibleForTesting;
-import java.lang.StringBuilder;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
+import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
@@ -90,7 +90,7 @@
public class BluetoothDeviceConnectionPolicy {
private static final String TAG = "BTDevConnectionPolicy";
private static final String SETTINGS_DELIMITER = ",";
- private static final boolean DBG = false;
+ private static final boolean DBG = Utils.DBG;
private final Context mContext;
private boolean mInitialized = false;
private boolean mUserSpecificInfoInitialized = false;
@@ -99,12 +99,11 @@
// The main data structure that holds on to the {profile:list of known and connectible devices}
private HashMap<Integer, BluetoothDevicesInfo> mProfileToConnectableDevicesMap;
- // The foll. number of connections are what the Bluetooth services and stack supports
- // and has been tested with. MAP and A2DP are limited to one connection only. HFP and PBAP,
- // though having the capability to support more than 2, has been tested with 2 connections.
- private static final int NUM_SUPPORTED_PHONE_CONNECTIONS = 2; // num of HFP and PBAP connections
- private static final int NUM_SUPPORTED_MSG_CONNECTIONS = 1; // num of MAP connections
+ /// TODO(vnori): fix this. b/70029056
+ private static final int NUM_SUPPORTED_PHONE_CONNECTIONS = 4; // num of HFP and PBAP connections
+ private static final int NUM_SUPPORTED_MSG_CONNECTIONS = 4; // num of MAP connections
private static final int NUM_SUPPORTED_MUSIC_CONNECTIONS = 1; // num of A2DP connections
+ private static final int NUM_SUPPORTED_NETWORK_CONNECTIONS = 1; // num of PAN connections
private Map<Integer, Integer> mNumSupportedActiveConnections;
private BluetoothAutoConnectStateMachine mBluetoothAutoConnectStateMachine;
@@ -117,12 +116,9 @@
private ReentrantLock mCarUserServiceAccessLock;
// Events that are listened to for triggering an auto-connect:
- // Cabin events like Door unlock coming from the Cabin Service.
- private final CarCabinService mCarCabinService;
- private final CarPropertyListener mCabinEventListener;
- // Sensor events like Ignition switch ON from the Car Sensor Service
- private final CarSensorService mCarSensorService;
- private final CarSensorEventListener mCarSensorEventListener;
+ // Door unlock and ignition switch ON come from Car Property Service
+ private final CarPropertyService mCarPropertyService;
+ private final CarPropertyListener mPropertyEventListener;
// PerUserCarService related listeners
private final UserServiceConnectionCallback mServiceCallback;
@@ -130,6 +126,12 @@
// Car Bluetooth Priority Settings Manager
private final CarBluetoothService mCarBluetoothService;
+ // Car UX Restrictions Manager Service to know when user restrictions are in place
+ private final CarUxRestrictionsManagerService mUxRService;
+ private final CarUxRServiceListener mUxRListener;
+ // Fast Pair Provider to allow discovery of new phones
+ private final FastPairProvider mFastPairProvider;
+
// The Bluetooth profiles that the CarService will try to auto-connect on.
private final List<Integer> mProfilesToConnect;
private final List<Integer> mPrioritiesSupported;
@@ -140,26 +142,28 @@
private ConnectionParams mConnectionInFlight;
// Allow write to Settings.Secure
private boolean mAllowReadWriteToSettings = true;
+ // Maintain a list of Paired devices which haven't connected on any profiles yet.
+ private Set<BluetoothDevice> mPairedButUnconnectedDevices = new HashSet<>();
public static BluetoothDeviceConnectionPolicy create(Context context,
- CarCabinService carCabinService, CarSensorService carSensorService,
- PerUserCarServiceHelper userServiceHelper, CarBluetoothService bluetoothService) {
- return new BluetoothDeviceConnectionPolicy(context, carCabinService, carSensorService,
- userServiceHelper, bluetoothService);
+ CarPropertyService carPropertyService, PerUserCarServiceHelper userServiceHelper,
+ CarUxRestrictionsManagerService uxrService, CarBluetoothService bluetoothService) {
+ return new BluetoothDeviceConnectionPolicy(context, carPropertyService, userServiceHelper,
+ uxrService, bluetoothService);
}
- private BluetoothDeviceConnectionPolicy(Context context, CarCabinService carCabinService,
- CarSensorService carSensorService, PerUserCarServiceHelper userServiceHelper,
+ private BluetoothDeviceConnectionPolicy(Context context, CarPropertyService carPropertyService,
+ PerUserCarServiceHelper userServiceHelper, CarUxRestrictionsManagerService uxrService,
CarBluetoothService bluetoothService) {
mContext = context;
- mCarCabinService = carCabinService;
- mCarSensorService = carSensorService;
+ mCarPropertyService = carPropertyService;
mUserServiceHelper = userServiceHelper;
+ mUxRService = uxrService;
mCarBluetoothService = bluetoothService;
mCarUserServiceAccessLock = new ReentrantLock();
mProfilesToConnect = Arrays.asList(
BluetoothProfile.HEADSET_CLIENT, BluetoothProfile.A2DP_SINK,
- BluetoothProfile.PBAP_CLIENT, BluetoothProfile.MAP_CLIENT);
+ BluetoothProfile.PBAP_CLIENT, BluetoothProfile.MAP_CLIENT, BluetoothProfile.PAN);
mPrioritiesSupported = Arrays.asList(
CarBluetoothManager.BLUETOOTH_DEVICE_CONNECTION_PRIORITY_0,
CarBluetoothManager.BLUETOOTH_DEVICE_CONNECTION_PRIORITY_1
@@ -185,18 +189,24 @@
mNumSupportedActiveConnections.put(BluetoothProfile.MAP_CLIENT,
NUM_SUPPORTED_MSG_CONNECTIONS);
break;
+ case BluetoothProfile.PAN:
+ mNumSupportedActiveConnections.put(BluetoothProfile.PAN,
+ NUM_SUPPORTED_NETWORK_CONNECTIONS);
+ break;
}
}
- // Listen to Cabin events for triggering auto connect
- mCabinEventListener = new CarPropertyListener();
- mCarSensorEventListener = new CarSensorEventListener();
+ // Listen to events for triggering auto connect
+ mPropertyEventListener = new CarPropertyListener();
+ // Listen to UX Restrictions to know when to enable fast-pairing
+ mUxRListener = new CarUxRServiceListener();
// Listen to User switching to connect to per User device.
mServiceCallback = new UserServiceConnectionCallback();
mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
if (mBluetoothAdapter == null) {
Log.w(TAG, "No Bluetooth Adapter Available");
}
+ mFastPairProvider = new FastPairProvider(mContext);
}
/**
@@ -278,6 +288,12 @@
BluetoothProfile.STATE_DISCONNECTED);
notifyConnectionStatus(connectParams, currState);
+ } else if (BluetoothPan.ACTION_CONNECTION_STATE_CHANGED.equals(action)) {
+ connectParams = new ConnectionParams(BluetoothProfile.PAN, device);
+ int currState = intent.getIntExtra(BluetoothProfile.EXTRA_STATE,
+ BluetoothProfile.STATE_DISCONNECTED);
+ notifyConnectionStatus(connectParams, currState);
+
} else if (BluetoothPbapClient.ACTION_CONNECTION_STATE_CHANGED.equals(action)) {
connectParams = new ConnectionParams(BluetoothProfile.PBAP_CLIENT, device);
int currState = intent.getIntExtra(BluetoothProfile.EXTRA_STATE,
@@ -379,6 +395,9 @@
case BluetoothProfile.MAP_CLIENT:
uuidsToCheck.add(BluetoothUuid.MAS);
break;
+ case BluetoothProfile.PAN:
+ uuidsToCheck.add(BluetoothUuid.PANU);
+ break;
}
for (ParcelUuid uuid : uuidsToCheck) {
@@ -542,6 +561,7 @@
profileFilter.addAction(BluetoothDevice.ACTION_BOND_STATE_CHANGED);
profileFilter.addAction(BluetoothA2dpSink.ACTION_CONNECTION_STATE_CHANGED);
profileFilter.addAction(BluetoothHeadsetClient.ACTION_CONNECTION_STATE_CHANGED);
+ profileFilter.addAction(BluetoothPan.ACTION_CONNECTION_STATE_CHANGED);
profileFilter.addAction(BluetoothPbapClient.ACTION_CONNECTION_STATE_CHANGED);
profileFilter.addAction(BluetoothMapClient.ACTION_CONNECTION_STATE_CHANGED);
profileFilter.addAction(BluetoothAdapter.ACTION_STATE_CHANGED);
@@ -577,70 +597,82 @@
* Bluetooth connection attempts.
*/
private void setupEventListenersLocked() {
- // Setting up a listener for events from CarCabinService
- // For now, we listen to door unlock signal coming from {@link CarCabinService},
- // and Ignition state START from {@link CarSensorService}
- mCarCabinService.registerListener(mCabinEventListener);
- mCarSensorService.registerOrUpdateSensorListener(
- CarSensorManager.SENSOR_TYPE_IGNITION_STATE, 0, mCarSensorEventListener);
+ // Setting up a listener for events from CarPropertyService
+ // For now, we listen to door unlock signal and Ignition state START coming from
+ // {@link CarPropertyService}
+ mCarPropertyService.registerListener(VehicleProperty.DOOR_LOCK, 0, mPropertyEventListener);
+ mCarPropertyService.registerListener(VehicleProperty.IGNITION_STATE, 0,
+ mPropertyEventListener);
+ // Get Current restrictions and handle them
+ handleUxRestrictionsChanged(mUxRService.getCurrentUxRestrictions());
+ // Register for future changes to the UxRestrictions
+ mUxRService.registerUxRestrictionsChangeListener(mUxRListener);
mUserServiceHelper.registerServiceCallback(mServiceCallback);
}
/**
- * Handles events coming in from the {@link CarCabinService}
- * The events that can trigger Bluetooth Scanning from CarCabinService is Door Unlock.
- * Upon receiving the event that is of interest, initiate a connection attempt by calling
+ * Handles events coming in from the {@link CarPropertyService}
+ * The events that can trigger Bluetooth Scanning from CarPropertyService are Door Unlock and
+ * Igntion START. Upon an event of interest, initiate a connection attempt by calling
* the policy {@link BluetoothDeviceConnectionPolicy}
*/
@VisibleForTesting
class CarPropertyListener extends ICarPropertyEventListener.Stub {
@Override
- public void onEvent(CarPropertyEvent event) throws RemoteException {
- if (DBG) {
- Log.d(TAG, "Cabin change Event : " + event.getEventType());
- }
- Boolean locked;
- CarPropertyValue value = event.getCarPropertyValue();
- Object o = value.getValue();
+ public void onEvent(List<CarPropertyEvent> events) throws RemoteException {
+ for (CarPropertyEvent event : events) {
+ if (DBG) {
+ Log.d(TAG, "Cabin change Event : " + event.getEventType());
+ }
+ CarPropertyValue value = event.getCarPropertyValue();
+ Object o = value.getValue();
- if (value.getPropertyId() == CarCabinManager.ID_DOOR_LOCK) {
- if (o instanceof Boolean) {
- locked = (Boolean) o;
- if (DBG) {
- Log.d(TAG, "Door Lock: " + locked);
- }
- // Attempting a connection only on a door unlock
- if (!locked) {
- initiateConnection();
- }
+ switch (value.getPropertyId()) {
+ case VehicleProperty.DOOR_LOCK:
+ if (o instanceof Boolean) {
+ Boolean locked = (Boolean) o;
+ if (DBG) {
+ Log.d(TAG, "Door Lock: " + locked);
+ }
+ // Attempting a connection only on a door unlock
+ if (!locked) {
+ initiateConnection();
+ }
+ }
+ break;
+ case VehicleProperty.IGNITION_STATE:
+ if (o instanceof Integer) {
+ Integer state = (Integer) o;
+ if (DBG) {
+ Log.d(TAG, "Sensor value : " + state);
+ }
+ // Attempting a connection only on IgntionState START
+ if (state == VehicleIgnitionState.START) {
+ initiateConnection();
+ }
+ }
+ break;
}
}
}
}
- /**
- * Handles events coming in from the {@link CarSensorService}
- * The events that can trigger Bluetooth Scanning from CarSensorService is Ignition START.
- * Upon receiving the event that is of interest, initiate a connection attempt by calling
- * the policy {@link BluetoothDeviceConnectionPolicy}
- */
- private class CarSensorEventListener extends ICarSensorEventListener.Stub {
+ private class CarUxRServiceListener extends ICarUxRestrictionsChangeListener.Stub {
@Override
- public void onSensorChanged(List<CarSensorEvent> events) throws RemoteException {
- if (events != null & !events.isEmpty()) {
- CarSensorEvent event = events.get(0);
- if (DBG) {
- Log.d(TAG, "Sensor event Type : " + event.sensorType);
- }
- if (event.sensorType == CarSensorManager.SENSOR_TYPE_IGNITION_STATE) {
- if (DBG) {
- Log.d(TAG, "Sensor value : " + event.intValues[0]);
- }
- if (event.intValues[0] == CarSensorEvent.IGNITION_STATE_START) {
- initiateConnection();
- }
- }
- }
+ public void onUxRestrictionsChanged(CarUxRestrictions restrictions) {
+ handleUxRestrictionsChanged(restrictions);
+ }
+ }
+
+ private void handleUxRestrictionsChanged(CarUxRestrictions restrictions) {
+ if (restrictions == null) {
+ return;
+ }
+ if ((restrictions.getActiveRestrictions() & CarUxRestrictions.UX_RESTRICTIONS_NO_SETUP)
+ == CarUxRestrictions.UX_RESTRICTIONS_NO_SETUP) {
+ mFastPairProvider.stopAdvertising();
+ } else {
+ mFastPairProvider.startAdvertising();
}
}
@@ -694,9 +726,9 @@
if (DBG) {
Log.d(TAG, "closeEventListeners()");
}
- mCarCabinService.unregisterListener(mCabinEventListener);
- mCarSensorService.unregisterSensorListener(CarSensorManager.SENSOR_TYPE_IGNITION_STATE,
- mCarSensorEventListener);
+ mCarPropertyService.unregisterListener(VehicleProperty.DOOR_LOCK, mPropertyEventListener);
+ mCarPropertyService.unregisterListener(VehicleProperty.IGNITION_STATE,
+ mPropertyEventListener);
mUserServiceHelper.unregisterServiceCallback(mServiceCallback);
}
@@ -729,7 +761,7 @@
@VisibleForTesting
CarPropertyListener getCarPropertyListener() {
- return mCabinEventListener;
+ return mPropertyEventListener;
}
@VisibleForTesting
@@ -742,6 +774,17 @@
return mProfileToConnectableDevicesMap.get(profile);
}
+ @VisibleForTesting
+ String toDebugString() {
+ StringBuilder buf = new StringBuilder();
+ for (Integer profile : mProfileToConnectableDevicesMap.keySet()) {
+ BluetoothDevicesInfo info = mProfileToConnectableDevicesMap.get(profile);
+ buf.append(" \n**** profile = " + profile);
+ buf.append(", " + info.toDebugString());
+ }
+ return buf.toString();
+ }
+
/**
* Resets the {@link #mProfileToConnectableDevicesMap} to a clean and empty slate.
*/
@@ -795,8 +838,12 @@
}
removeDeviceFromProfile(device, profile);
}
+ } else if (bondState == BluetoothDevice.BOND_BONDED) {
+ // A device just paired. When it connects on HFP profile, then immediately initiate
+ // connections on PBAP and MAP. for now, maintain this fact in a data structure
+ // to be looked up when HFP profile connects.
+ mPairedButUnconnectedDevices.add(device);
}
-
}
/**
@@ -944,6 +991,130 @@
}
/**
+ * Checks if the Bluetooth profile service's proxy object is available.
+ * Proxy obj should be available before we can attempt to connect on that profile.
+ *
+ * @param profile The profile to check the presence of the proxy object
+ * @return True if the proxy obj exists. False otherwise.
+ */
+ private boolean isProxyAvailable(Integer profile) {
+ if (mCarBluetoothUserService == null) {
+ mCarBluetoothUserService = setupBluetoothUserService();
+ if (mCarBluetoothUserService == null) {
+ Log.d(TAG, "CarBluetoothUserSvc null. Car service not bound to PerUserCarSvc.");
+ return false;
+ }
+ }
+ try {
+ if (!mCarBluetoothUserService.isBluetoothConnectionProxyAvailable(profile)) {
+ // proxy unavailable.
+ if (DBG) {
+ Log.d(TAG, "Proxy for Bluetooth Profile Service Unavailable: " + profile);
+ }
+ return false;
+ }
+ } catch (RemoteException e) {
+ Log.e(TAG, "Car BT Service Remote Exception.");
+ return false;
+ }
+ return true;
+ }
+
+ /**
+ * Creates a device connection for the given profile.
+ *
+ * @param profile The profile on which the connection is being setup
+ * @param device The device for which the connection is to be made.
+ * @return true if the connection is setup successfully. False otherwise.
+ */
+ boolean connectToDeviceOnProfile(Integer profile, BluetoothDevice device) {
+ if (DBG) {
+ Log.d(TAG, "in connectToDeviceOnProfile for Profile:" + profile +
+ ", device: " + Utils.getDeviceDebugInfo(device));
+ }
+ if (!isProxyAvailable(profile)) {
+ if (DBG) {
+ Log.d(TAG, "No proxy available for Profile: " + profile);
+ }
+ return false;
+ }
+ BluetoothDevicesInfo devInfo = mProfileToConnectableDevicesMap.get(profile);
+ if (devInfo == null) {
+ if (DBG) {
+ Log.d(TAG, "devInfo NULL on Profile:" + profile);
+ }
+ return false;
+ }
+ int state = devInfo.getCurrentConnectionStateLocked(device);
+ if (state == BluetoothProfile.STATE_CONNECTED ||
+ state == BluetoothProfile.STATE_CONNECTING) {
+ if (DBG) {
+ Log.d(TAG, "device " + Utils.getDeviceDebugInfo(device) +
+ " is already connected/connecting on Profile:" + profile);
+ }
+ return true;
+ }
+ if (!devInfo.isProfileConnectableLocked()) {
+ if (DBG) {
+ Log.d(TAG, "isProfileConnectableLocked FALSE on Profile:" + profile +
+ " this means number of connections on this profile max'ed out or " +
+ " no more devices available to connect on this profile");
+ }
+ return false;
+ }
+ try {
+ if (mCarBluetoothUserService != null) {
+ mCarBluetoothUserService.bluetoothConnectToProfile((int) profile, device);
+ devInfo.setConnectionStateLocked(device, BluetoothProfile.STATE_CONNECTING);
+ // Increment the retry count & cache what is being connected to
+ // This method is already called from a synchronized context.
+ mConnectionInFlight.setBluetoothDevice(device);
+ mConnectionInFlight.setBluetoothProfile(profile);
+ devInfo.incrementRetryCountLocked();
+ if (DBG) {
+ Log.d(TAG, "Increment Retry to: " + devInfo.getRetryCountLocked() +
+ ", for Profile: " + profile + ", on device: " +
+ Utils.getDeviceDebugInfo(device));
+ }
+ return true;
+ } else {
+ Log.e(TAG, "CarBluetoothUserSvc null");
+ }
+ } catch (RemoteException e) {
+ Log.e(TAG, "Remote User Service stopped responding: " + e.getMessage());
+ }
+ return false;
+ }
+
+ /**
+ * Helper method to reset info in {@link #mConnectionInFlight} in the given
+ * {@link BluetoothDevicesInfo} object.
+ *
+ * @param devInfo the {@link BluetoothDevicesInfo} where the info is to be reset.
+ */
+ private void setProfileOnDeviceToUnavailable(BluetoothDevicesInfo devInfo) {
+ mConnectionInFlight.setBluetoothProfile(0);
+ mConnectionInFlight.setBluetoothDevice(null);
+ devInfo.setDeviceAvailableToConnectLocked(false);
+ }
+
+ boolean doesDeviceExistForProfile(Integer profile, BluetoothDevice device) {
+ BluetoothDevicesInfo devInfo = mProfileToConnectableDevicesMap.get(profile);
+ if (devInfo == null) {
+ if (DBG) {
+ Log.d(TAG, "devInfo NULL on Profile:" + profile);
+ }
+ return false;
+ }
+ boolean b = devInfo.checkDeviceInListLocked(device);
+ if (DBG) {
+ Log.d(TAG, "Is device " + Utils.getDeviceDebugInfo(device) +
+ " listed for profile " + profile + ": " + b);
+ }
+ return b;
+ }
+
+ /**
* Try to connect to the next device in the device list for the given profile.
*
* @param profile - profile to connect on
@@ -952,83 +1123,30 @@
*/
private boolean connectToNextDeviceInQueueLocked(Integer profile) {
// Get the Device Information for the given profile and find the next device to connect on
- boolean connecting = true;
- boolean proxyAvailable = true;
BluetoothDevice devToConnect = null;
BluetoothDevicesInfo devInfo = mProfileToConnectableDevicesMap.get(profile);
if (devInfo == null) {
Log.e(TAG, "Unexpected: No device Queue for this profile: " + profile);
return false;
}
- // Check if the Bluetooth profile service's proxy object is available before
- // attempting to connect.
- if (mCarBluetoothUserService == null) {
- mCarBluetoothUserService = setupBluetoothUserService();
- }
- if (mCarBluetoothUserService != null) {
- try {
- if (!mCarBluetoothUserService.isBluetoothConnectionProxyAvailable(profile)) {
- // proxy unavailable.
- if (DBG) {
- Log.d(TAG,
- "Proxy for Bluetooth Profile Service Unavailable: " + profile);
- }
- proxyAvailable = false;
- }
- } catch (RemoteException e) {
- Log.e(TAG, "Car BT Service Remote Exception.");
- proxyAvailable = false;
- }
- } else {
- Log.d(TAG, "CarBluetoothUserSvc null. Car service not bound to PerUserCarSvc.");
- proxyAvailable = false;
- }
- if (proxyAvailable) {
+ if (isProxyAvailable(profile)) {
// Get the next device in the device list for this profile.
devToConnect = devInfo.getNextDeviceInQueueLocked();
if (devToConnect != null) {
// deviceAvailable && proxyAvailable
- try {
- if (mCarBluetoothUserService != null) {
- mCarBluetoothUserService.bluetoothConnectToProfile((int) profile,
- devToConnect);
- } else {
- Log.e(TAG, "CarBluetoothUserSvc null");
- connecting = false;
- }
- } catch (RemoteException e) {
- Log.e(TAG, "Remote User Service stopped responding: " + e.getMessage());
- connecting = false;
- }
+ if (connectToDeviceOnProfile(profile, devToConnect)) return true;
} else {
// device unavailable
if (DBG) {
Log.d(TAG, "No paired nearby device to connect to for profile: " + profile);
}
- connecting = false;
}
- } else {
- connecting = false;
}
- if (connecting && devToConnect != null) {
- devInfo.setConnectionStateLocked(devToConnect, BluetoothProfile.STATE_CONNECTING);
- // Increment the retry count & cache what is being connected to
- // This method is already called from a synchronized context.
- mConnectionInFlight.setBluetoothDevice(devToConnect);
- mConnectionInFlight.setBluetoothProfile(profile);
- devInfo.incrementRetryCountLocked();
- if (DBG) {
- Log.d(TAG, "Increment Retry to: " + devInfo.getRetryCountLocked());
- }
- } else {
- // reset the mConnectionInFlight
- mConnectionInFlight.setBluetoothProfile(0);
- mConnectionInFlight.setBluetoothDevice(null);
- devInfo.setDeviceAvailableToConnectLocked(false);
- }
- return connecting;
+ // reset the mConnectionInFlight
+ setProfileOnDeviceToUnavailable(devInfo);
+ return false;
}
/**
@@ -1099,6 +1217,32 @@
+ deviceThatConnected);
}
+ // If the device just connected to HEADSET_CLIENT profile, initiate
+ // connections on PBAP & MAP profiles but let that begin after a timeout period.
+ // timeout allows A2DP profile to complete its connection, so that there is no race
+ // condition between
+ // Phone trying to connect on A2DP
+ // and, Car trying to connect on PBAP & MAP.
+ if (didConnect && profileToUpdate == BluetoothProfile.HEADSET_CLIENT) {
+ // Unlock the profiles PBAP, MAP in BluetoothDevicesInfo, so that they can be
+ // connected on.
+ for (Integer profile : Arrays.asList(BluetoothProfile.PBAP_CLIENT,
+ BluetoothProfile.MAP_CLIENT)) {
+ BluetoothDevicesInfo devInfo = mProfileToConnectableDevicesMap.get(profile);
+ if (devInfo == null) {
+ Log.e(TAG, "Unexpected: No device Queue for this profile: " + profile);
+ return false;
+ }
+ devInfo.setDeviceAvailableToConnectLocked(true);
+ }
+ if (DBG) {
+ Log.d(TAG, "connect to PBAP/MAP after disconnect: ");
+ }
+ mBluetoothAutoConnectStateMachine.sendMessageDelayed(
+ BluetoothAutoConnectStateMachine.CHECK_CLIENT_PROFILES, params,
+ BluetoothAutoConnectStateMachine.CONNECT_MORE_PROFILES_TIMEOUT_MS);
+ }
+
// If the connection update is on a different profile or device (a very rare possibility),
// it is handled automatically. Just logging it here.
if (DBG) {
@@ -1210,23 +1354,10 @@
if (mProfileToConnectableDevicesMap == null) {
return;
}
- for (BluetoothDevicesInfo devInfo : mProfileToConnectableDevicesMap.values()) {
- writer.print("Profile: " + devInfo.getProfileLocked() + "\t");
- writer.print(
- "Num of Paired devices: " + devInfo.getNumberOfPairedDevicesLocked() + "\t");
- writer.print("Active Connections: " + devInfo.getNumberOfActiveConnectionsLocked());
- writer.println("Num of paired devices: " + devInfo.getNumberOfPairedDevicesLocked());
+ for (Integer profile : mProfileToConnectableDevicesMap.keySet()) {
+ writer.print("Profile: " + Utils.getProfileName(profile) + "\t");
+ writer.print("\n" + mProfileToConnectableDevicesMap.get(profile).toDebugString());
writer.println();
- List<BluetoothDevicesInfo.DeviceInfo> deviceInfoList = devInfo.getDeviceInfoList();
- if (deviceInfoList != null) {
- for (BluetoothDevicesInfo.DeviceInfo devicesInfo : deviceInfoList) {
- if (devicesInfo.getBluetoothDevice() != null) {
- writer.print(devicesInfo.getBluetoothDevice() + ":");
- writer.print(devicesInfo.getConnectionState() + "\t");
- }
- }
- writer.println();
- }
}
}
@@ -1314,7 +1445,11 @@
KEY_BLUETOOTH_AUTOCONNECT_MESSAGING_DEVICES,
joinedDeviceNames, (int) userId);
break;
-
+ case BluetoothProfile.PAN:
+ Settings.Secure.putStringForUser(mContext.getContentResolver(),
+ KEY_BLUETOOTH_AUTOCONNECT_NETWORK_DEVICES,
+ joinedDeviceNames, (int) userId);
+ break;
}
}
return writeSuccess;
@@ -1371,6 +1506,9 @@
devices = Settings.Secure.getStringForUser(mContext.getContentResolver(),
KEY_BLUETOOTH_AUTOCONNECT_MESSAGING_DEVICES, (int) userId);
break;
+ case BluetoothProfile.PAN:
+ devices = Settings.Secure.getStringForUser(mContext.getContentResolver(),
+ KEY_BLUETOOTH_AUTOCONNECT_NETWORK_DEVICES, (int) userId);
default:
Log.e(TAG, "Unexpected profile");
break;
@@ -1418,7 +1556,7 @@
* Bluetooth profile. If there are tagged devices, update the BluetoothDevicesInfo so the
* policy can prioritize those devices when making connection attempts.
*
- * @param profile - Bluetooth Profile to check
+ * @param profile - Bluetooth Profile to check
* @param priority - Priority to check
*/
private void readAndTagDeviceWithPriorityFromSettings(int profile, int priority) {
@@ -1433,7 +1571,8 @@
priority);
if (deviceToClear != null) {
if (DBG) {
- Log.d(TAG, "Clearing priority for: " + deviceToClear.getAddress());
+ Log.d(TAG, "Clearing priority for: " +
+ Utils.getDeviceDebugInfo(deviceToClear));
}
devicesInfo.removeBluetoothDevicePriorityLocked(deviceToClear);
}
diff --git a/service/src/com/android/car/BluetoothDevicesInfo.java b/service/src/com/android/car/BluetoothDevicesInfo.java
index 4a0fee9..7681f16 100644
--- a/service/src/com/android/car/BluetoothDevicesInfo.java
+++ b/service/src/com/android/car/BluetoothDevicesInfo.java
@@ -26,6 +26,8 @@
import android.bluetooth.BluetoothProfile;
+import com.android.internal.annotations.VisibleForTesting;
+
/**
* BluetoothDevicesInfo contains all the information pertinent to connection on a Bluetooth Profile.
* It holds
@@ -46,7 +48,7 @@
public class BluetoothDevicesInfo {
private static final String TAG = "CarBluetoothDevicesInfo";
- private static final boolean DBG = false;
+ private static final boolean DBG = Utils.DBG;
private final int DEVICE_NOT_FOUND = -1;
private final int DEVICE_PRIORITY_UNDEFINED = -1;
// The device list and the connection state information together have all the information
@@ -248,7 +250,7 @@
* @param device - {@link BluetoothDevice} to look for
* @return true if found, false if not found
*/
- private boolean checkDeviceInListLocked(BluetoothDevice device) {
+ boolean checkDeviceInListLocked(BluetoothDevice device) {
boolean isPresent = false;
if (device == null) {
return isPresent;
@@ -714,7 +716,9 @@
if (DBG) {
Log.d(TAG, "Profile: " + mConnectionInfo.mProfile + " Num of connections: "
+ mConnectionInfo.mNumActiveConnections + " Conn Supported: "
- + mConnectionInfo.mNumConnectionsSupported);
+ + mConnectionInfo.mNumConnectionsSupported
+ + ", the flag: mDeviceAvailableToConnect = "
+ + mConnectionInfo.mDeviceAvailableToConnect);
}
if (mConnectionInfo.mDeviceAvailableToConnect &&
@@ -723,9 +727,11 @@
}
if (DBG) {
- Log.d(TAG, "Connected devices for profile " + mConnectionInfo.mProfile);
- for (BluetoothDevice device : getConnectedDevicesLocked()) {
- Log.d(TAG, device.getAddress());
+ if (mConnectionInfo.mDeviceAvailableToConnect) {
+ Log.d(TAG, "Connected devices for profile " + mConnectionInfo.mProfile);
+ for (BluetoothDevice device : getConnectedDevicesLocked()) {
+ Log.d(TAG, device.getAddress());
+ }
}
}
return false;
@@ -765,4 +771,39 @@
}
resetConnectionInfoLocked();
}
+
+ @VisibleForTesting
+ String toDebugString() {
+ StringBuilder buf = new StringBuilder();
+ buf.append("\tmDeviceAvailableToConnect = " + mConnectionInfo.mDeviceAvailableToConnect);
+ buf.append("\n\t#Paired Devices = " + getNumberOfPairedDevicesLocked());
+ buf.append(", #Active Connections = " + mConnectionInfo.mNumActiveConnections);
+ buf.append(", #Connections Supported = " + mConnectionInfo.mNumConnectionsSupported);
+ if (mDeviceInfoList != null) {
+ int i = 1;
+ for (DeviceInfo devInfo : mDeviceInfoList) {
+ buf.append("\n\t\tdevice# " + i++ +
+ " = " + Utils.getDeviceDebugInfo(devInfo.getBluetoothDevice()));
+ String s;
+ switch (devInfo.getConnectionState()) {
+ case BluetoothProfile.STATE_CONNECTING:
+ s = "STATE_CONNECTING";
+ break;
+ case BluetoothProfile.STATE_DISCONNECTED:
+ s = "STATE_DISCONNECTED";
+ break;
+ case BluetoothProfile.STATE_CONNECTED:
+ s = "STATE_CONNECTED";
+ break;
+ default:
+ s = "state_UNKNOWN";
+ }
+ buf.append(", " + s);
+ }
+ } else {
+ buf.append("\n\tno devices listed");
+ }
+ buf.append("\n");
+ return buf.toString();
+ }
}
diff --git a/service/src/com/android/car/CarAudioAttributesUtil.java b/service/src/com/android/car/CarAudioAttributesUtil.java
deleted file mode 100644
index 64d2571..0000000
--- a/service/src/com/android/car/CarAudioAttributesUtil.java
+++ /dev/null
@@ -1,197 +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.car.media.CarAudioManager;
-import android.media.AudioAttributes;
-import android.os.Bundle;
-
-/**
- * Utility class to map car usage into AudioAttributes and the other way around.
- */
-public class CarAudioAttributesUtil {
-
- public static final int CAR_AUDIO_USAGE_CARSERVICE_BOTTOM = 100;
- public static final int CAR_AUDIO_USAGE_CARSERVICE_CAR_PROXY = 101;
- public static final int CAR_AUDIO_USAGE_CARSERVICE_MEDIA_MUTE = 102;
-
- /** Bundle key for storing media type. */
- public static final String KEY_CAR_AUDIO_TYPE = "car_audio_type";
-
- private static final int CAR_AUDIO_TYPE_DEFAULT = 0;
- private static final int CAR_AUDIO_TYPE_VOICE_COMMAND = 1;
- private static final int CAR_AUDIO_TYPE_SAFETY_ALERT = 2;
- private static final int CAR_AUDIO_TYPE_RADIO = 3;
- private static final int CAR_AUDIO_TYPE_CARSERVICE_BOTTOM = 4;
- private static final int CAR_AUDIO_TYPE_CARSERVICE_CAR_PROXY = 5;
- private static final int CAR_AUDIO_TYPE_CARSERVICE_MEDIA_MUTE = 6;
- private static final int CAR_AUDIO_TYPE_EXTERNAL_SOURCE = 7;
-
- /** Bundle key for storing routing type which is String. */
- public static final String KEY_EXT_ROUTING_TYPE = "ext_routing_type";
-
- public static AudioAttributes getAudioAttributesForCarUsage(int carUsage) {
- switch (carUsage) {
- case CarAudioManager.CAR_AUDIO_USAGE_MUSIC:
- return createAudioAttributes(AudioAttributes.CONTENT_TYPE_MUSIC,
- AudioAttributes.USAGE_MEDIA);
- case CarAudioManager.CAR_AUDIO_USAGE_EXTERNAL_AUDIO_SOURCE: // default to radio
- case CarAudioManager.CAR_AUDIO_USAGE_RADIO:
- return createCustomAudioAttributes(CAR_AUDIO_TYPE_RADIO,
- AudioAttributes.CONTENT_TYPE_MUSIC, AudioAttributes.USAGE_MEDIA);
- case CarAudioManager.CAR_AUDIO_USAGE_NAVIGATION_GUIDANCE:
- return createAudioAttributes(AudioAttributes.CONTENT_TYPE_SPEECH,
- AudioAttributes.USAGE_ASSISTANCE_NAVIGATION_GUIDANCE);
- case CarAudioManager.CAR_AUDIO_USAGE_RINGTONE:
- return createAudioAttributes(AudioAttributes.CONTENT_TYPE_SONIFICATION,
- AudioAttributes.USAGE_NOTIFICATION_RINGTONE);
- case CarAudioManager.CAR_AUDIO_USAGE_VOICE_CALL:
- return createAudioAttributes(AudioAttributes.CONTENT_TYPE_SPEECH,
- AudioAttributes.USAGE_VOICE_COMMUNICATION);
- case CarAudioManager.CAR_AUDIO_USAGE_VOICE_COMMAND:
- return createCustomAudioAttributes(CAR_AUDIO_TYPE_VOICE_COMMAND,
- AudioAttributes.CONTENT_TYPE_SPEECH,
- AudioAttributes.USAGE_ASSISTANCE_NAVIGATION_GUIDANCE);
- case CarAudioManager.CAR_AUDIO_USAGE_ALARM:
- return createAudioAttributes(AudioAttributes.CONTENT_TYPE_SONIFICATION,
- AudioAttributes.USAGE_ALARM);
- case CarAudioManager.CAR_AUDIO_USAGE_NOTIFICATION:
- return createAudioAttributes(AudioAttributes.CONTENT_TYPE_SONIFICATION,
- AudioAttributes.USAGE_NOTIFICATION);
- case CarAudioManager.CAR_AUDIO_USAGE_SYSTEM_SOUND:
- return createAudioAttributes(AudioAttributes.CONTENT_TYPE_SONIFICATION,
- AudioAttributes.USAGE_ASSISTANCE_SONIFICATION);
- case CarAudioManager.CAR_AUDIO_USAGE_SYSTEM_SAFETY_ALERT:
- return createCustomAudioAttributes(CAR_AUDIO_TYPE_SAFETY_ALERT,
- AudioAttributes.CONTENT_TYPE_SONIFICATION,
- AudioAttributes.USAGE_NOTIFICATION);
- case CAR_AUDIO_USAGE_CARSERVICE_BOTTOM:
- return createCustomAudioAttributes(CAR_AUDIO_TYPE_CARSERVICE_BOTTOM,
- AudioAttributes.CONTENT_TYPE_UNKNOWN,
- AudioAttributes.USAGE_UNKNOWN);
- case CAR_AUDIO_USAGE_CARSERVICE_CAR_PROXY:
- return createCustomAudioAttributes(CAR_AUDIO_TYPE_CARSERVICE_CAR_PROXY,
- AudioAttributes.CONTENT_TYPE_UNKNOWN,
- AudioAttributes.USAGE_UNKNOWN);
- case CAR_AUDIO_USAGE_CARSERVICE_MEDIA_MUTE:
- return createCustomAudioAttributes(CAR_AUDIO_TYPE_CARSERVICE_MEDIA_MUTE,
- AudioAttributes.CONTENT_TYPE_MUSIC,
- AudioAttributes.USAGE_UNKNOWN);
- case CarAudioManager.CAR_AUDIO_USAGE_DEFAULT:
- default:
- return createAudioAttributes(AudioAttributes.CONTENT_TYPE_UNKNOWN,
- AudioAttributes.USAGE_UNKNOWN);
- }
- }
-
- public static int getCarUsageFromAudioAttributes(AudioAttributes attr) {
- int usage = attr.getUsage();
- Bundle bundle = attr.getBundle();
- int type = CAR_AUDIO_TYPE_DEFAULT;
- if (bundle != null) {
- type = bundle.getInt(KEY_CAR_AUDIO_TYPE, CAR_AUDIO_TYPE_DEFAULT);
- }
- switch (usage) {
- case AudioAttributes.USAGE_MEDIA:
- switch (type) {
- case CAR_AUDIO_TYPE_RADIO:
- return CarAudioManager.CAR_AUDIO_USAGE_RADIO;
- case CAR_AUDIO_TYPE_EXTERNAL_SOURCE:
- return CarAudioManager.CAR_AUDIO_USAGE_EXTERNAL_AUDIO_SOURCE;
- default:
- return CarAudioManager.CAR_AUDIO_USAGE_MUSIC;
- }
- case AudioAttributes.USAGE_ASSISTANCE_NAVIGATION_GUIDANCE:
- if (type == CAR_AUDIO_TYPE_VOICE_COMMAND) {
- return CarAudioManager.CAR_AUDIO_USAGE_VOICE_COMMAND;
- } else {
- return CarAudioManager.CAR_AUDIO_USAGE_NAVIGATION_GUIDANCE;
- }
- case AudioAttributes.USAGE_VOICE_COMMUNICATION:
- return CarAudioManager.CAR_AUDIO_USAGE_VOICE_CALL;
- case AudioAttributes.USAGE_NOTIFICATION_RINGTONE:
- return CarAudioManager.CAR_AUDIO_USAGE_RINGTONE;
- case AudioAttributes.USAGE_ALARM:
- return CarAudioManager.CAR_AUDIO_USAGE_ALARM;
- case AudioAttributes.USAGE_NOTIFICATION:
- if (type == CAR_AUDIO_TYPE_SAFETY_ALERT) {
- return CarAudioManager.CAR_AUDIO_USAGE_SYSTEM_SAFETY_ALERT;
- } else {
- return CarAudioManager.CAR_AUDIO_USAGE_NOTIFICATION;
- }
- case AudioAttributes.USAGE_ASSISTANCE_SONIFICATION:
- return CarAudioManager.CAR_AUDIO_USAGE_SYSTEM_SOUND;
- case AudioAttributes.USAGE_UNKNOWN:
- default: {
- switch (type) {
- case CAR_AUDIO_TYPE_CARSERVICE_BOTTOM:
- return CAR_AUDIO_USAGE_CARSERVICE_BOTTOM;
- case CAR_AUDIO_TYPE_CARSERVICE_CAR_PROXY:
- return CAR_AUDIO_USAGE_CARSERVICE_CAR_PROXY;
- case CAR_AUDIO_TYPE_CARSERVICE_MEDIA_MUTE:
- return CAR_AUDIO_USAGE_CARSERVICE_MEDIA_MUTE;
- default:
- return CarAudioManager.CAR_AUDIO_USAGE_DEFAULT;
- }
- }
- }
- }
-
- private static AudioAttributes createAudioAttributes(int contentType, int usage) {
- AudioAttributes.Builder builder = new AudioAttributes.Builder();
- return builder.setContentType(contentType).setUsage(usage).build();
- }
-
- private static AudioAttributes createCustomAudioAttributes(int carAudioType,
- int contentType, int usage) {
- AudioAttributes.Builder builder = new AudioAttributes.Builder();
- Bundle bundle = new Bundle();
- bundle.putInt(KEY_CAR_AUDIO_TYPE, carAudioType);
- return builder.setContentType(contentType).setUsage(usage).addBundle(bundle).build();
- }
-
- public static AudioAttributes getCarRadioAttributes(String radioType) {
- AudioAttributes.Builder builder = new AudioAttributes.Builder();
- Bundle bundle = new Bundle();
- bundle.putInt(KEY_CAR_AUDIO_TYPE, CAR_AUDIO_TYPE_RADIO);
- bundle.putString(KEY_EXT_ROUTING_TYPE, radioType);
- return builder.setContentType(AudioAttributes.CONTENT_TYPE_MUSIC).
- setUsage(AudioAttributes.USAGE_MEDIA).addBundle(bundle).build();
- }
-
- public static AudioAttributes getCarExtSourceAttributes(String externalSourceType) {
- AudioAttributes.Builder builder = new AudioAttributes.Builder();
- Bundle bundle = new Bundle();
- bundle.putInt(KEY_CAR_AUDIO_TYPE, CAR_AUDIO_TYPE_EXTERNAL_SOURCE);
- bundle.putString(KEY_EXT_ROUTING_TYPE, externalSourceType);
- return builder.setContentType(AudioAttributes.CONTENT_TYPE_MUSIC).
- setUsage(AudioAttributes.USAGE_MEDIA).addBundle(bundle).build();
- }
-
- /**
- * Get ext routing type from given AudioAttributes.
- * @param attr
- * @return {@link CarAudioManager#CAR_RADIO_TYPE_AM_FM} if ext routing info does not exist.
- */
- public static String getExtRouting(AudioAttributes attr) {
- Bundle bundle = attr.getBundle();
- String extRouting = CarAudioManager.CAR_RADIO_TYPE_AM_FM;
- if (bundle != null) {
- extRouting = bundle.getString(KEY_EXT_ROUTING_TYPE);
- }
- return extRouting;
- }
-}
diff --git a/service/src/com/android/car/CarAudioDeviceInfo.java b/service/src/com/android/car/CarAudioDeviceInfo.java
new file mode 100644
index 0000000..65e3510
--- /dev/null
+++ b/service/src/com/android/car/CarAudioDeviceInfo.java
@@ -0,0 +1,257 @@
+/*
+ * 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;
+
+import android.media.AudioDeviceInfo;
+import android.media.AudioDevicePort;
+import android.media.AudioFormat;
+import android.media.AudioGain;
+import android.media.AudioGainConfig;
+import android.media.AudioManager;
+import android.media.AudioPort;
+import android.util.Log;
+
+import com.android.internal.util.Preconditions;
+
+import java.io.PrintWriter;
+
+/**
+ * A helper class wraps {@link AudioDeviceInfo}, and helps get/set the gain on a specific port
+ * in terms of millibels.
+ * Note to the reader. For whatever reason, it seems that AudioGain contains only configuration
+ * information (min/max/step, etc) while the AudioGainConfig class contains the
+ * actual currently active gain value(s).
+ */
+/* package */ class CarAudioDeviceInfo {
+
+ private final AudioDeviceInfo mAudioDeviceInfo;
+ private final int mBusNumber;
+ private final int mSampleRate;
+ private final int mEncodingFormat;
+ private final int mChannelCount;
+ private final int mDefaultGain;
+ private final int mMaxGain;
+ private final int mMinGain;
+
+ /**
+ * We need to store the current gain because it is not accessible from the current
+ * audio engine implementation. It would be nice if AudioPort#activeConfig() would return it,
+ * but in the current implementation, that function actually works only for mixer ports.
+ */
+ private int mCurrentGain;
+
+ CarAudioDeviceInfo(AudioDeviceInfo audioDeviceInfo) {
+ mAudioDeviceInfo = audioDeviceInfo;
+ mBusNumber = parseDeviceAddress(audioDeviceInfo.getAddress());
+ mSampleRate = getMaxSampleRate(audioDeviceInfo);
+ mEncodingFormat = getEncodingFormat(audioDeviceInfo);
+ mChannelCount = getMaxChannels(audioDeviceInfo);
+ final AudioGain audioGain = Preconditions.checkNotNull(
+ getAudioGain(), "No audio gain on device port " + audioDeviceInfo);
+ mDefaultGain = audioGain.defaultValue();
+ mMaxGain = audioGain.maxValue();
+ mMinGain = audioGain.minValue();
+
+ mCurrentGain = -1; // Not initialized till explicitly set
+ }
+
+ AudioDeviceInfo getAudioDeviceInfo() {
+ return mAudioDeviceInfo;
+ }
+
+ AudioDevicePort getAudioDevicePort() {
+ return mAudioDeviceInfo.getPort();
+ }
+
+ int getBusNumber() {
+ return mBusNumber;
+ }
+
+ int getDefaultGain() {
+ return mDefaultGain;
+ }
+
+ int getMaxGain() {
+ return mMaxGain;
+ }
+
+ int getMinGain() {
+ return mMinGain;
+ }
+
+ int getSampleRate() {
+ return mSampleRate;
+ }
+
+ int getEncodingFormat() {
+ return mEncodingFormat;
+ }
+
+ int getChannelCount() {
+ return mChannelCount;
+ }
+
+ // Input is in millibels
+ void setCurrentGain(int gainInMillibels) {
+ // Clamp the incoming value to our valid range. Out of range values ARE legal input
+ if (gainInMillibels < mMinGain) {
+ gainInMillibels = mMinGain;
+ } else if (gainInMillibels > mMaxGain) {
+ gainInMillibels = mMaxGain;
+ }
+
+ // Push the new gain value down to our underlying port which will cause it to show up
+ // at the HAL.
+ AudioGain audioGain = getAudioGain();
+ if (audioGain == null) {
+ Log.e(CarLog.TAG_AUDIO, "getAudioGain() returned null.");
+ return;
+ }
+
+ // size of gain values is 1 in MODE_JOINT
+ AudioGainConfig audioGainConfig = audioGain.buildConfig(
+ AudioGain.MODE_JOINT,
+ audioGain.channelMask(),
+ new int[] { gainInMillibels },
+ 0);
+ if (audioGainConfig == null) {
+ Log.e(CarLog.TAG_AUDIO, "Failed to construct AudioGainConfig");
+ return;
+ }
+
+ int r = AudioManager.setAudioPortGain(getAudioDevicePort(), audioGainConfig);
+ if (r == AudioManager.SUCCESS) {
+ // Since we can't query for the gain on a device port later,
+ // we have to remember what we asked for
+ mCurrentGain = gainInMillibels;
+ } else {
+ Log.e(CarLog.TAG_AUDIO, "Failed to setAudioPortGain: " + r);
+ }
+ }
+
+ /**
+ * Parse device address. Expected format is BUS%d_%s, address, usage hint
+ * @return valid address (from 0 to positive) or -1 for invalid address.
+ */
+ private int parseDeviceAddress(String address) {
+ String[] words = address.split("_");
+ int addressParsed = -1;
+ if (words[0].toLowerCase().startsWith("bus")) {
+ try {
+ addressParsed = Integer.parseInt(words[0].substring(3));
+ } catch (NumberFormatException e) {
+ //ignore
+ }
+ }
+ if (addressParsed < 0) {
+ return -1;
+ }
+ return addressParsed;
+ }
+
+ private int getMaxSampleRate(AudioDeviceInfo info) {
+ int[] sampleRates = info.getSampleRates();
+ if (sampleRates == null || sampleRates.length == 0) {
+ return 48000;
+ }
+ int sampleRate = sampleRates[0];
+ for (int i = 1; i < sampleRates.length; i++) {
+ if (sampleRates[i] > sampleRate) {
+ sampleRate = sampleRates[i];
+ }
+ }
+ return sampleRate;
+ }
+
+ /** Always returns {@link AudioFormat#ENCODING_PCM_16BIT} as for now */
+ private int getEncodingFormat(AudioDeviceInfo info) {
+ return AudioFormat.ENCODING_PCM_16BIT;
+ }
+
+ /**
+ * Gets the maximum channel count for a given {@link AudioDeviceInfo}
+ *
+ * @param info {@link AudioDeviceInfo} instance to get maximum channel count for
+ * @return Maximum channel count for a given {@link AudioDeviceInfo},
+ * 1 (mono) if there is no channel masks configured
+ */
+ private int getMaxChannels(AudioDeviceInfo info) {
+ int numChannels = 1;
+ int[] channelMasks = info.getChannelMasks();
+ if (channelMasks == null) {
+ return numChannels;
+ }
+ for (int channelMask : channelMasks) {
+ int currentNumChannels = Integer.bitCount(channelMask);
+ if (currentNumChannels > numChannels) {
+ numChannels = currentNumChannels;
+ }
+ }
+ return numChannels;
+ }
+
+ /**
+ * @return {@link AudioGain} with {@link AudioGain#MODE_JOINT} on a given {@link AudioPort}.
+ * This is useful for inspecting the configuration data associated with this gain controller
+ * (min/max/step/default).
+ */
+ AudioGain getAudioGain() {
+ final AudioDevicePort audioPort = getAudioDevicePort();
+ if (audioPort != null && audioPort.gains().length > 0) {
+ for (AudioGain audioGain : audioPort.gains()) {
+ if ((audioGain.mode() & AudioGain.MODE_JOINT) != 0) {
+ return checkAudioGainConfiguration(audioGain);
+ }
+ }
+ }
+ return null;
+ }
+
+ /**
+ * Constraints applied to gain configuration, see also audio_policy_configuration.xml
+ */
+ private AudioGain checkAudioGainConfiguration(AudioGain audioGain) {
+ Preconditions.checkArgument(audioGain.maxValue() >= audioGain.minValue());
+ Preconditions.checkArgument((audioGain.defaultValue() >= audioGain.minValue())
+ && (audioGain.defaultValue() <= audioGain.maxValue()));
+ Preconditions.checkArgument(
+ ((audioGain.maxValue() - audioGain.minValue()) % audioGain.stepValue()) == 0);
+ Preconditions.checkArgument(
+ ((audioGain.defaultValue() - audioGain.minValue()) % audioGain.stepValue()) == 0);
+ return audioGain;
+ }
+
+ @Override
+ public String toString() {
+ return "bus number: " + mBusNumber
+ + " address: " + mAudioDeviceInfo.getAddress()
+ + " sampleRate: " + getSampleRate()
+ + " encodingFormat: " + getEncodingFormat()
+ + " channelCount: " + getChannelCount()
+ + " currentGain: " + mCurrentGain
+ + " maxGain: " + mMaxGain
+ + " minGain: " + mMinGain;
+ }
+
+ void dump(PrintWriter writer) {
+ writer.printf("Bus Number (%d) / address (%s)\n ",
+ mBusNumber, mAudioDeviceInfo.getAddress());
+ writer.printf("\tsample rate / encoding format / channel count: %d %d %d\n",
+ getSampleRate(), getEncodingFormat(), getChannelCount());
+ writer.printf("\tGain in millibel (min / max / default/ current): %d %d %d %d\n",
+ mMinGain, mMaxGain, mDefaultGain, mCurrentGain);
+ }
+}
diff --git a/service/src/com/android/car/CarAudioService.java b/service/src/com/android/car/CarAudioService.java
index f56b105..1b7ee67 100644
--- a/service/src/com/android/car/CarAudioService.java
+++ b/service/src/com/android/car/CarAudioService.java
@@ -15,1852 +15,859 @@
*/
package com.android.car;
+import android.annotation.NonNull;
+import android.annotation.Nullable;
import android.car.Car;
-import android.car.VehicleZoneUtil;
-import android.car.media.CarAudioManager;
-import android.car.media.CarAudioManager.OnParameterChangeListener;
+import android.car.media.CarAudioPatchHandle;
import android.car.media.ICarAudio;
-import android.car.media.ICarAudioCallback;
+import android.car.media.ICarVolumeCallback;
+import android.content.BroadcastReceiver;
import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
import android.content.pm.PackageManager;
-import android.content.res.Resources;
+import android.hardware.automotive.audiocontrol.V1_0.ContextNumber;
+import android.hardware.automotive.audiocontrol.V1_0.IAudioControl;
import android.media.AudioAttributes;
import android.media.AudioDeviceInfo;
-import android.media.AudioFocusInfo;
+import android.media.AudioDevicePort;
import android.media.AudioFormat;
+import android.media.AudioGain;
+import android.media.AudioGainConfig;
import android.media.AudioManager;
-import android.media.IVolumeController;
+import android.media.AudioPatch;
+import android.media.AudioPlaybackConfiguration;
+import android.media.AudioPortConfig;
+import android.media.AudioSystem;
import android.media.audiopolicy.AudioMix;
import android.media.audiopolicy.AudioMixingRule;
import android.media.audiopolicy.AudioPolicy;
-import android.media.audiopolicy.AudioPolicy.AudioPolicyFocusListener;
-import android.os.Handler;
-import android.os.HandlerThread;
+import android.os.IBinder;
import android.os.Looper;
-import android.os.Message;
import android.os.RemoteException;
+import android.telephony.TelephonyManager;
+import android.text.TextUtils;
import android.util.Log;
+import android.util.SparseArray;
+import android.util.SparseIntArray;
-import com.android.car.hal.AudioHalService;
-import com.android.car.hal.AudioHalService.AudioHalFocusListener;
-import com.android.internal.annotations.GuardedBy;
+import com.android.internal.util.Preconditions;
import java.io.PrintWriter;
+import java.util.ArrayList;
import java.util.Arrays;
-import java.util.HashMap;
import java.util.HashSet;
-import java.util.LinkedList;
-import java.util.Map;
-import java.util.Map.Entry;
+import java.util.List;
+import java.util.NoSuchElementException;
import java.util.Set;
+import java.util.stream.Collectors;
-public class CarAudioService extends ICarAudio.Stub implements CarServiceBase,
- AudioHalFocusListener, OnParameterChangeListener {
+public class CarAudioService extends ICarAudio.Stub implements CarServiceBase {
- public interface AudioContextChangeListener {
- /**
- * Notifies the current primary audio context (app holding focus).
- * If there is no active context, context will be 0.
- * Will use context like CarAudioManager.CAR_AUDIO_USAGE_*
- */
- void onContextChange(int primaryFocusContext, int primaryFocusPhysicalStream);
+ private static final int DEFAULT_AUDIO_USAGE = AudioAttributes.USAGE_MEDIA;
+
+ private static final int[] CONTEXT_NUMBERS = new int[] {
+ ContextNumber.MUSIC,
+ ContextNumber.NAVIGATION,
+ ContextNumber.VOICE_COMMAND,
+ ContextNumber.CALL_RING,
+ ContextNumber.CALL,
+ ContextNumber.ALARM,
+ ContextNumber.NOTIFICATION,
+ ContextNumber.SYSTEM_SOUND
+ };
+
+ private static final SparseIntArray USAGE_TO_CONTEXT = new SparseIntArray();
+
+ // For legacy stream type based volume control.
+ // Values in STREAM_TYPES and STREAM_TYPE_USAGES should be aligned.
+ private static final int[] STREAM_TYPES = new int[] {
+ AudioManager.STREAM_MUSIC,
+ AudioManager.STREAM_ALARM,
+ AudioManager.STREAM_RING
+ };
+ private static final int[] STREAM_TYPE_USAGES = new int[] {
+ AudioAttributes.USAGE_MEDIA,
+ AudioAttributes.USAGE_ALARM,
+ AudioAttributes.USAGE_NOTIFICATION_RINGTONE
+ };
+
+ static {
+ USAGE_TO_CONTEXT.put(AudioAttributes.USAGE_UNKNOWN, ContextNumber.MUSIC);
+ USAGE_TO_CONTEXT.put(AudioAttributes.USAGE_MEDIA, ContextNumber.MUSIC);
+ USAGE_TO_CONTEXT.put(AudioAttributes.USAGE_VOICE_COMMUNICATION, ContextNumber.CALL);
+ USAGE_TO_CONTEXT.put(AudioAttributes.USAGE_VOICE_COMMUNICATION_SIGNALLING,
+ ContextNumber.CALL);
+ USAGE_TO_CONTEXT.put(AudioAttributes.USAGE_ALARM, ContextNumber.ALARM);
+ USAGE_TO_CONTEXT.put(AudioAttributes.USAGE_NOTIFICATION, ContextNumber.NOTIFICATION);
+ USAGE_TO_CONTEXT.put(AudioAttributes.USAGE_NOTIFICATION_RINGTONE, ContextNumber.CALL_RING);
+ USAGE_TO_CONTEXT.put(AudioAttributes.USAGE_NOTIFICATION_COMMUNICATION_REQUEST,
+ ContextNumber.NOTIFICATION);
+ USAGE_TO_CONTEXT.put(AudioAttributes.USAGE_NOTIFICATION_COMMUNICATION_INSTANT,
+ ContextNumber.NOTIFICATION);
+ USAGE_TO_CONTEXT.put(AudioAttributes.USAGE_NOTIFICATION_COMMUNICATION_DELAYED,
+ ContextNumber.NOTIFICATION);
+ USAGE_TO_CONTEXT.put(AudioAttributes.USAGE_NOTIFICATION_EVENT, ContextNumber.NOTIFICATION);
+ USAGE_TO_CONTEXT.put(AudioAttributes.USAGE_ASSISTANCE_ACCESSIBILITY,
+ ContextNumber.VOICE_COMMAND);
+ USAGE_TO_CONTEXT.put(AudioAttributes.USAGE_ASSISTANCE_NAVIGATION_GUIDANCE,
+ ContextNumber.NAVIGATION);
+ USAGE_TO_CONTEXT.put(AudioAttributes.USAGE_ASSISTANCE_SONIFICATION,
+ ContextNumber.SYSTEM_SOUND);
+ USAGE_TO_CONTEXT.put(AudioAttributes.USAGE_GAME, ContextNumber.MUSIC);
+ USAGE_TO_CONTEXT.put(AudioAttributes.USAGE_VIRTUAL_SOURCE, ContextNumber.INVALID);
+ USAGE_TO_CONTEXT.put(AudioAttributes.USAGE_ASSISTANT, ContextNumber.VOICE_COMMAND);
}
- private final long mFocusResponseWaitTimeoutMs;
+ private final Object mImplLock = new Object();
- private final int mNumConsecutiveHalFailuresForCanError;
+ private final Context mContext;
+ private final TelephonyManager mTelephonyManager;
+ private final AudioManager mAudioManager;
+ private final boolean mUseDynamicRouting;
+ private final SparseIntArray mContextToBus = new SparseIntArray();
+ private final SparseArray<CarAudioDeviceInfo> mCarAudioDeviceInfos = new SparseArray<>();
- private static final String TAG_FOCUS = CarLog.TAG_AUDIO + ".FOCUS";
+ private final AudioPolicy.AudioPolicyVolumeCallback mAudioPolicyVolumeCallback =
+ new AudioPolicy.AudioPolicyVolumeCallback() {
+ @Override
+ public void onVolumeAdjustment(int adjustment) {
+ final int usage = getSuggestedAudioUsage();
+ Log.v(CarLog.TAG_AUDIO,
+ "onVolumeAdjustment: " + AudioManager.adjustToString(adjustment)
+ + " suggested usage: " + AudioAttributes.usageToString(usage));
+ final int groupId = getVolumeGroupIdForUsage(usage);
+ final int currentVolume = getGroupVolume(groupId);
+ final int flags = AudioManager.FLAG_FROM_KEY | AudioManager.FLAG_SHOW_UI;
+ switch (adjustment) {
+ case AudioManager.ADJUST_LOWER:
+ if (currentVolume > getGroupMinVolume(groupId)) {
+ setGroupVolume(groupId, currentVolume - 1, flags);
+ }
+ break;
+ case AudioManager.ADJUST_RAISE:
+ if (currentVolume < getGroupMaxVolume(groupId)) {
+ setGroupVolume(groupId, currentVolume + 1, flags);
+ }
+ break;
+ case AudioManager.ADJUST_MUTE:
+ mAudioManager.setMasterMute(true, flags);
+ callbackMasterMuteChange(flags);
+ break;
+ case AudioManager.ADJUST_UNMUTE:
+ mAudioManager.setMasterMute(false, flags);
+ callbackMasterMuteChange(flags);
+ break;
+ case AudioManager.ADJUST_TOGGLE_MUTE:
+ mAudioManager.setMasterMute(!mAudioManager.isMasterMute(), flags);
+ callbackMasterMuteChange(flags);
+ break;
+ case AudioManager.ADJUST_SAME:
+ default:
+ break;
+ }
+ }
+ };
- private static final boolean DBG = false;
- private static final boolean DBG_DYNAMIC_AUDIO_ROUTING = false;
+ private final BinderInterfaceContainer<ICarVolumeCallback> mVolumeCallbackContainer =
+ new BinderInterfaceContainer<>();
/**
- * For no focus play case, wait this much to send focus request. This ugly time is necessary
- * as focus could have been already requested by app but the event is not delivered to car
- * service yet. In such case, requesting focus in advance can lead into request with wrong
- * context. So let it wait for this much to make sure that focus change is delivered.
+ * Simulates {@link ICarVolumeCallback} when it's running in legacy mode.
*/
- private static final long NO_FOCUS_PLAY_WAIT_TIME_MS = 100;
+ private final BroadcastReceiver mLegacyVolumeChangedReceiver = new BroadcastReceiver() {
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ switch (intent.getAction()) {
+ case AudioManager.VOLUME_CHANGED_ACTION:
+ int streamType = intent.getIntExtra(AudioManager.EXTRA_VOLUME_STREAM_TYPE, -1);
+ int groupId = getVolumeGroupIdForStreamType(streamType);
+ if (groupId == -1) {
+ Log.w(CarLog.TAG_AUDIO, "Unknown stream type: " + streamType);
+ } else {
+ callbackGroupVolumeChange(groupId, 0);
+ }
+ break;
+ case AudioManager.MASTER_MUTE_CHANGED_ACTION:
+ callbackMasterMuteChange(0);
+ break;
+ }
+ }
+ };
- private static final String RADIO_ROUTING_SOURCE_PREFIX = "RADIO_";
-
- private final AudioHalService mAudioHal;
- private final Context mContext;
- private final HandlerThread mFocusHandlerThread;
- private final CarAudioFocusChangeHandler mFocusHandler;
- private final SystemFocusListener mSystemFocusListener;
- private final CarVolumeService mVolumeService;
- private final Object mLock = new Object();
- @GuardedBy("mLock")
private AudioPolicy mAudioPolicy;
- @GuardedBy("mLock")
- private FocusState mCurrentFocusState = FocusState.STATE_LOSS;
- /** Focus state received, but not handled yet. Once handled, this will be set to null. */
- @GuardedBy("mLock")
- private FocusState mFocusReceived = null;
- @GuardedBy("mLock")
- private FocusRequest mLastFocusRequestToCar = null;
- @GuardedBy("mLock")
- private LinkedList<AudioFocusInfo> mPendingFocusChanges = new LinkedList<>();
- @GuardedBy("mLock")
- private AudioFocusInfo mPrimaryFocusInfo = null;
- /** previous top which may be in ducking state */
- @GuardedBy("mLock")
- private AudioFocusInfo mSecondaryFocusInfo = null;
+ private CarVolumeGroup[] mCarVolumeGroups;
- private AudioRoutingPolicy mAudioRoutingPolicy;
- private final AudioManager mAudioManager;
- private final CanBusErrorNotifier mCanBusErrorNotifier;
- private final BottomAudioFocusListener mBottomAudioFocusListener =
- new BottomAudioFocusListener();
- private final CarProxyAndroidFocusListener mCarProxyAudioFocusListener =
- new CarProxyAndroidFocusListener();
- private final MediaMuteAudioFocusListener mMediaMuteAudioFocusListener =
- new MediaMuteAudioFocusListener();
-
- @GuardedBy("mLock")
- private boolean mRadioOrExtSourceActive = false;
- @GuardedBy("mLock")
- private int mCurrentAudioContexts = 0;
- @GuardedBy("mLock")
- private int mCurrentPrimaryAudioContext = 0;
- @GuardedBy("mLock")
- private int mCurrentPrimaryPhysicalStream = 0;
- @GuardedBy("mLock")
- private AudioContextChangeListener mAudioContextChangeListener;
- @GuardedBy("mLock")
- private CarAudioContextChangeHandler mCarAudioContextChangeHandler;
- @GuardedBy("mLock")
- private boolean mIsRadioExternal;
- @GuardedBy("mLock")
- private int mNumConsecutiveHalFailures;
-
- @GuardedBy("mLock")
- private boolean mExternalRoutingHintSupported;
- @GuardedBy("mLock")
- private Map<String, AudioHalService.ExtRoutingSourceInfo> mExternalRoutingTypes;
- @GuardedBy("mLock")
- private Set<String> mExternalRadioRoutingTypes;
- @GuardedBy("mLock")
- private String mDefaultRadioRoutingType;
- @GuardedBy("mLock")
- private Set<String> mExternalNonRadioRoutingTypes;
- @GuardedBy("mLock")
- private int mRadioPhysicalStream;
- @GuardedBy("mLock")
- private int[] mExternalRoutings = {0, 0, 0, 0};
- private int[] mExternalRoutingsScratch = {0, 0, 0, 0};
- private final int[] mExternalRoutingsForFocusRelease = {0, 0, 0, 0};
- private final ExtSourceInfo mExtSourceInfoScratch = new ExtSourceInfo();
- @GuardedBy("mLock")
- private int mSystemSoundPhysicalStream;
- @GuardedBy("mLock")
- private boolean mSystemSoundPhysicalStreamActive;
-
- private final boolean mUseDynamicRouting;
-
- private final AudioAttributes mAttributeBottom =
- CarAudioAttributesUtil.getAudioAttributesForCarUsage(
- CarAudioAttributesUtil.CAR_AUDIO_USAGE_CARSERVICE_BOTTOM);
- private final AudioAttributes mAttributeCarExternal =
- CarAudioAttributesUtil.getAudioAttributesForCarUsage(
- CarAudioAttributesUtil.CAR_AUDIO_USAGE_CARSERVICE_CAR_PROXY);
-
- @GuardedBy("mLock")
- private final BinderInterfaceContainer<ICarAudioCallback> mAudioParamListeners =
- new BinderInterfaceContainer<>();
- @GuardedBy("mLock")
- private HashSet<String> mAudioParamKeys;
-
- public CarAudioService(Context context, AudioHalService audioHal,
- CarInputService inputService, CanBusErrorNotifier errorNotifier) {
- mAudioHal = audioHal;
+ public CarAudioService(Context context) {
mContext = context;
- mFocusHandlerThread = new HandlerThread(CarLog.TAG_AUDIO);
- mSystemFocusListener = new SystemFocusListener();
- mFocusHandlerThread.start();
- mFocusHandler = new CarAudioFocusChangeHandler(mFocusHandlerThread.getLooper());
+ mTelephonyManager = (TelephonyManager) mContext.getSystemService(Context.TELEPHONY_SERVICE);
mAudioManager = (AudioManager) mContext.getSystemService(Context.AUDIO_SERVICE);
- mCanBusErrorNotifier = errorNotifier;
- Resources res = context.getResources();
- mFocusResponseWaitTimeoutMs = (long) res.getInteger(R.integer.audioFocusWaitTimeoutMs);
- mNumConsecutiveHalFailuresForCanError =
- (int) res.getInteger(R.integer.consecutiveHalFailures);
- mUseDynamicRouting = res.getBoolean(R.bool.audioUseDynamicRouting);
- mVolumeService = new CarVolumeService(mContext, this, mAudioHal, inputService);
+ mUseDynamicRouting = mContext.getResources().getBoolean(R.bool.audioUseDynamicRouting);
}
- @Override
- public AudioAttributes getAudioAttributesForCarUsage(int carUsage) {
- return CarAudioAttributesUtil.getAudioAttributesForCarUsage(carUsage);
- }
-
+ /**
+ * Dynamic routing and volume groups are set only if
+ * {@link #mUseDynamicRouting} is {@code true}. Otherwise, this service runs in legacy mode.
+ */
@Override
public void init() {
- AudioPolicy.Builder builder = new AudioPolicy.Builder(mContext);
- builder.setLooper(Looper.getMainLooper());
- boolean isFocusSupported = mAudioHal.isFocusSupported();
- if (isFocusSupported) {
- builder.setAudioPolicyFocusListener(mSystemFocusListener);
- FocusState currentState = FocusState.create(mAudioHal.getCurrentFocusState());
- int r = mAudioManager.requestAudioFocus(mBottomAudioFocusListener, mAttributeBottom,
- AudioManager.AUDIOFOCUS_GAIN, AudioManager.AUDIOFOCUS_FLAG_DELAY_OK);
- synchronized (mLock) {
- mCurrentFocusState = currentState;
- mCurrentAudioContexts = 0;
- }
- }
- int audioHwVariant = mAudioHal.getHwVariant();
- AudioRoutingPolicy audioRoutingPolicy = AudioRoutingPolicy.create(mContext, audioHwVariant);
- if (mUseDynamicRouting) {
- setupDynamicRouting(audioRoutingPolicy, builder);
- }
- AudioPolicy audioPolicy = null;
- if (isFocusSupported || mUseDynamicRouting) {
- audioPolicy = builder.build();
- }
- mAudioHal.setFocusListener(this);
- mAudioHal.setAudioRoutingPolicy(audioRoutingPolicy);
- mAudioHal.setOnParameterChangeListener(this);
- // get call outside lock as it can take time
- HashSet<String> externalRadioRoutingTypes = new HashSet<>();
- HashSet<String> externalNonRadioRoutingTypes = new HashSet<>();
- Map<String, AudioHalService.ExtRoutingSourceInfo> externalRoutingTypes =
- mAudioHal.getExternalAudioRoutingTypes();
- if (externalRoutingTypes != null) {
- for (String routingType : externalRoutingTypes.keySet()) {
- if (routingType.startsWith(RADIO_ROUTING_SOURCE_PREFIX)) {
- externalRadioRoutingTypes.add(routingType);
- } else {
- externalNonRadioRoutingTypes.add(routingType);
- }
- }
- }
- // select default radio routing. AM_FM -> AM_FM_HD -> whatever with AM or FM -> first one
- String defaultRadioRouting = null;
- if (externalRadioRoutingTypes.contains(CarAudioManager.CAR_RADIO_TYPE_AM_FM)) {
- defaultRadioRouting = CarAudioManager.CAR_RADIO_TYPE_AM_FM;
- } else if (externalRadioRoutingTypes.contains(CarAudioManager.CAR_RADIO_TYPE_AM_FM_HD)) {
- defaultRadioRouting = CarAudioManager.CAR_RADIO_TYPE_AM_FM_HD;
- } else {
- for (String radioType : externalRadioRoutingTypes) {
- // set to 1st one
- if (defaultRadioRouting == null) {
- defaultRadioRouting = radioType;
- }
- if (radioType.contains("AM") || radioType.contains("FM")) {
- defaultRadioRouting = radioType;
- break;
- }
- }
- }
- if (defaultRadioRouting == null) { // no radio type defined. fall back to AM_FM
- defaultRadioRouting = CarAudioManager.CAR_RADIO_TYPE_AM_FM;
- }
- synchronized (mLock) {
- if (audioPolicy != null) {
- mAudioPolicy = audioPolicy;
- }
- mRadioPhysicalStream = audioRoutingPolicy.getPhysicalStreamForLogicalStream(
- CarAudioManager.CAR_AUDIO_USAGE_RADIO);
- mSystemSoundPhysicalStream = audioRoutingPolicy.getPhysicalStreamForLogicalStream(
- CarAudioManager.CAR_AUDIO_USAGE_SYSTEM_SOUND);
- mSystemSoundPhysicalStreamActive = false;
- mAudioRoutingPolicy = audioRoutingPolicy;
- mIsRadioExternal = mAudioHal.isRadioExternal();
- if (externalRoutingTypes != null) {
- mExternalRoutingHintSupported = true;
- mExternalRoutingTypes = externalRoutingTypes;
+ synchronized (mImplLock) {
+ if (!mUseDynamicRouting) {
+ Log.i(CarLog.TAG_AUDIO, "Audio dynamic routing not configured, run in legacy mode");
+ setupLegacyVolumeChangedListener();
} else {
- mExternalRoutingHintSupported = false;
- mExternalRoutingTypes = new HashMap<>();
- }
- mExternalRadioRoutingTypes = externalRadioRoutingTypes;
- mExternalNonRadioRoutingTypes = externalNonRadioRoutingTypes;
- mDefaultRadioRoutingType = defaultRadioRouting;
- Arrays.fill(mExternalRoutings, 0);
- populateParameterKeysLocked();
- }
- mVolumeService.init();
-
- // Register audio policy only after this class is fully initialized.
- int r = mAudioManager.registerAudioPolicy(audioPolicy);
- if (r != 0) {
- throw new RuntimeException("registerAudioPolicy failed " + r);
- }
- }
-
- private void setupDynamicRouting(AudioRoutingPolicy audioRoutingPolicy,
- AudioPolicy.Builder audioPolicyBuilder) {
- AudioDeviceInfo[] deviceInfos = mAudioManager.getDevices(AudioManager.GET_DEVICES_OUTPUTS);
- if (deviceInfos.length == 0) {
- Log.e(CarLog.TAG_AUDIO, "setupDynamicRouting, no output device available, ignore");
- return;
- }
- int numPhysicalStreams = audioRoutingPolicy.getPhysicalStreamsCount();
- AudioDeviceInfo[] devicesToRoute = new AudioDeviceInfo[numPhysicalStreams];
- for (AudioDeviceInfo info : deviceInfos) {
- if (DBG_DYNAMIC_AUDIO_ROUTING) {
- Log.v(CarLog.TAG_AUDIO, String.format(
- "output device=%s id=%d name=%s addr=%s type=%s",
- info.toString(), info.getId(), info.getProductName(), info.getAddress(),
- info.getType()));
- }
- if (info.getType() == AudioDeviceInfo.TYPE_BUS) {
- int addressNumeric = parseDeviceAddress(info.getAddress());
- if (addressNumeric >= 0 && addressNumeric < numPhysicalStreams) {
- devicesToRoute[addressNumeric] = info;
- Log.i(CarLog.TAG_AUDIO, String.format(
- "valid bus found, devie=%s id=%d name=%s addr=%s",
- info.toString(), info.getId(), info.getProductName(), info.getAddress())
- );
- }
+ setupDynamicRouting();
+ setupVolumeGroups();
}
}
- for (int i = 0; i < numPhysicalStreams; i++) {
- AudioDeviceInfo info = devicesToRoute[i];
- if (info == null) {
- Log.e(CarLog.TAG_AUDIO, "setupDynamicRouting, cannot find device for address " + i);
- return;
- }
- int sampleRate = getMaxSampleRate(info);
- int channels = getMaxChannles(info);
- AudioFormat mixFormat = new AudioFormat.Builder()
- .setSampleRate(sampleRate)
- .setEncoding(AudioFormat.ENCODING_PCM_16BIT)
- .setChannelMask(channels)
- .build();
- Log.i(CarLog.TAG_AUDIO, String.format(
- "Physical stream %d, sampleRate:%d, channles:0x%s", i, sampleRate,
- Integer.toHexString(channels)));
- int[] logicalStreams = audioRoutingPolicy.getLogicalStreamsForPhysicalStream(i);
- AudioMixingRule.Builder mixingRuleBuilder = new AudioMixingRule.Builder();
- for (int logicalStream : logicalStreams) {
- mixingRuleBuilder.addRule(
- CarAudioAttributesUtil.getAudioAttributesForCarUsage(logicalStream),
- AudioMixingRule.RULE_MATCH_ATTRIBUTE_USAGE);
- }
- AudioMix audioMix = new AudioMix.Builder(mixingRuleBuilder.build())
- .setFormat(mixFormat)
- .setDevice(info)
- .setRouteFlags(AudioMix.ROUTE_FLAG_RENDER)
- .build();
- audioPolicyBuilder.addMix(audioMix);
- }
- }
-
- /**
- * Parse device address. Expected format is BUS%d_%s, address, usage hint
- * @return valid address (from 0 to positive) or -1 for invalid address.
- */
- private int parseDeviceAddress(String address) {
- String[] words = address.split("_");
- int addressParsed = -1;
- if (words[0].startsWith("BUS")) {
- try {
- addressParsed = Integer.parseInt(words[0].substring(3));
- } catch (NumberFormatException e) {
- //ignore
- }
- }
- if (addressParsed < 0) {
- return -1;
- }
- return addressParsed;
- }
-
- private int getMaxSampleRate(AudioDeviceInfo info) {
- int[] sampleRates = info.getSampleRates();
- if (sampleRates == null || sampleRates.length == 0) {
- return 48000;
- }
- int sampleRate = sampleRates[0];
- for (int i = 1; i < sampleRates.length; i++) {
- if (sampleRates[i] > sampleRate) {
- sampleRate = sampleRates[i];
- }
- }
- return sampleRate;
- }
-
- private int getMaxChannles(AudioDeviceInfo info) {
- int[] channelMasks = info.getChannelMasks();
- if (channelMasks == null) {
- return AudioFormat.CHANNEL_OUT_STEREO;
- }
- int channels = AudioFormat.CHANNEL_OUT_MONO;
- int numChannels = 1;
- for (int i = 0; i < channelMasks.length; i++) {
- int currentNumChannles = VehicleZoneUtil.getNumberOfZones(channelMasks[i]);
- if (currentNumChannles > numChannels) {
- numChannels = currentNumChannles;
- channels = channelMasks[i];
- }
- }
- return channels;
}
@Override
public void release() {
- mFocusHandler.cancelAll();
- mAudioManager.abandonAudioFocus(mBottomAudioFocusListener);
- mAudioManager.abandonAudioFocus(mCarProxyAudioFocusListener);
- AudioPolicy audioPolicy;
- synchronized (mLock) {
- mAudioParamKeys = null;
- mCurrentFocusState = FocusState.STATE_LOSS;
- mLastFocusRequestToCar = null;
- mPrimaryFocusInfo = null;
- mPendingFocusChanges.clear();
- mRadioOrExtSourceActive = false;
- if (mCarAudioContextChangeHandler != null) {
- mCarAudioContextChangeHandler.cancelAll();
- mCarAudioContextChangeHandler = null;
+ synchronized (mImplLock) {
+ if (mUseDynamicRouting) {
+ if (mAudioPolicy != null) {
+ mAudioManager.unregisterAudioPolicyAsync(mAudioPolicy);
+ mAudioPolicy = null;
+ }
+ } else {
+ mContext.unregisterReceiver(mLegacyVolumeChangedReceiver);
}
- mAudioContextChangeListener = null;
- mCurrentPrimaryAudioContext = 0;
- audioPolicy = mAudioPolicy;
- mAudioPolicy = null;
- mExternalRoutingTypes.clear();
- mExternalRadioRoutingTypes.clear();
- mExternalNonRadioRoutingTypes.clear();
- }
- if (audioPolicy != null) {
- mAudioManager.unregisterAudioPolicyAsync(audioPolicy);
- }
- mVolumeService.release();
- }
- public synchronized void setAudioContextChangeListener(Looper looper,
- AudioContextChangeListener listener) {
- if (looper == null || listener == null) {
- throw new IllegalArgumentException("looper or listener null");
+ mVolumeCallbackContainer.clear();
}
- if (mCarAudioContextChangeHandler != null) {
- mCarAudioContextChangeHandler.cancelAll();
- }
- mCarAudioContextChangeHandler = new CarAudioContextChangeHandler(looper);
- mAudioContextChangeListener = listener;
}
@Override
public void dump(PrintWriter writer) {
- synchronized (mLock) {
- writer.println("*CarAudioService*");
- writer.println(" mCurrentFocusState:" + mCurrentFocusState +
- " mLastFocusRequestToCar:" + mLastFocusRequestToCar);
- writer.println(" mCurrentAudioContexts:0x" +
- Integer.toHexString(mCurrentAudioContexts));
- writer.println(" mRadioOrExtSourceActive:" +
- mRadioOrExtSourceActive);
- writer.println(" mCurrentPrimaryAudioContext:" + mCurrentPrimaryAudioContext +
- " mCurrentPrimaryPhysicalStream:" + mCurrentPrimaryPhysicalStream);
- writer.println(" mIsRadioExternal:" + mIsRadioExternal);
- writer.println(" mNumConsecutiveHalFailures:" + mNumConsecutiveHalFailures);
- writer.println(" media muted:" + mMediaMuteAudioFocusListener.isMuted());
- writer.println(" mAudioPolicy:" + mAudioPolicy);
- mAudioRoutingPolicy.dump(writer);
- writer.println(" mExternalRoutingHintSupported:" + mExternalRoutingHintSupported);
- if (mExternalRoutingHintSupported) {
- writer.println(" mDefaultRadioRoutingType:" + mDefaultRadioRoutingType);
- writer.println(" Routing Types:");
- for (Entry<String, AudioHalService.ExtRoutingSourceInfo> entry :
- mExternalRoutingTypes.entrySet()) {
- writer.println(" type:" + entry.getKey() + " info:" + entry.getValue());
- }
- }
- if (mAudioParamKeys != null) {
- writer.println("** Audio parameter keys**");
- for (String key : mAudioParamKeys) {
- writer.println(" " + key);
- }
+ writer.println("*CarAudioService*");
+ writer.println("\tRun in legacy mode? " + (!mUseDynamicRouting));
+ writer.println("\tMaster mute? " + mAudioManager.isMasterMute());
+ // Empty line for comfortable reading
+ writer.println();
+ if (mUseDynamicRouting) {
+ for (CarVolumeGroup group : mCarVolumeGroups) {
+ group.dump(writer);
}
}
- writer.println("** Dump CarVolumeService**");
- mVolumeService.dump(writer);
}
+ /**
+ * @see {@link android.car.media.CarAudioManager#setGroupVolume(int, int, int)}
+ */
@Override
- public void onFocusChange(int focusState, int streams, int externalFocus) {
- synchronized (mLock) {
- mFocusReceived = FocusState.create(focusState, streams, externalFocus);
- // wake up thread waiting for focus response.
- mLock.notifyAll();
- }
- mFocusHandler.handleFocusChange();
- }
+ public void setGroupVolume(int groupId, int index, int flags) {
+ synchronized (mImplLock) {
+ enforcePermission(Car.PERMISSION_CAR_CONTROL_AUDIO_VOLUME);
- @Override
- public void onStreamStatusChange(int streamNumber, boolean streamActive) {
- if (DBG) {
- Log.d(TAG_FOCUS, "onStreamStatusChange stream:" + streamNumber + ", active:" +
- streamActive);
- }
- mFocusHandler.handleStreamStateChange(streamNumber, streamActive);
- }
-
- @Override
- public void setStreamVolume(int streamType, int index, int flags) {
- enforceAudioVolumePermission();
- mVolumeService.setStreamVolume(streamType, index, flags);
- }
-
- @Override
- public void setVolumeController(IVolumeController controller) {
- enforceAudioVolumePermission();
- mVolumeService.setVolumeController(controller);
- }
-
- @Override
- public int getStreamMaxVolume(int streamType) {
- enforceAudioVolumePermission();
- return mVolumeService.getStreamMaxVolume(streamType);
- }
-
- @Override
- public int getStreamMinVolume(int streamType) {
- enforceAudioVolumePermission();
- return mVolumeService.getStreamMinVolume(streamType);
- }
-
- @Override
- public int getStreamVolume(int streamType) {
- enforceAudioVolumePermission();
- return mVolumeService.getStreamVolume(streamType);
- }
-
- @Override
- public boolean isMediaMuted() {
- return mMediaMuteAudioFocusListener.isMuted();
- }
-
- @Override
- public boolean setMediaMute(boolean mute) {
- enforceAudioVolumePermission();
- boolean currentState = isMediaMuted();
- if (mute == currentState) {
- return currentState;
- }
- if (mute) {
- return mMediaMuteAudioFocusListener.mute();
- } else {
- return mMediaMuteAudioFocusListener.unMute();
- }
- }
-
- @Override
- public AudioAttributes getAudioAttributesForRadio(String radioType) {
- synchronized (mLock) {
- if (!mExternalRadioRoutingTypes.contains(radioType)) { // type not exist
- throw new IllegalArgumentException("Specified radio type is not available:" +
- radioType);
+ callbackGroupVolumeChange(groupId, flags);
+ // For legacy stream type based volume control
+ if (!mUseDynamicRouting) {
+ mAudioManager.setStreamVolume(STREAM_TYPES[groupId], index, flags);
+ return;
}
- }
- return CarAudioAttributesUtil.getCarRadioAttributes(radioType);
- }
- @Override
- public AudioAttributes getAudioAttributesForExternalSource(String externalSourceType) {
- synchronized (mLock) {
- if (!mExternalNonRadioRoutingTypes.contains(externalSourceType)) { // type not exist
- throw new IllegalArgumentException("Specified ext source type is not available:" +
- externalSourceType);
- }
- }
- return CarAudioAttributesUtil.getCarExtSourceAttributes(externalSourceType);
- }
-
- @Override
- public String[] getSupportedExternalSourceTypes() {
- synchronized (mLock) {
- return mExternalNonRadioRoutingTypes.toArray(
- new String[mExternalNonRadioRoutingTypes.size()]);
+ CarVolumeGroup group = getCarVolumeGroup(groupId);
+ group.setCurrentGainIndex(index);
}
}
- @Override
- public String[] getSupportedRadioTypes() {
- synchronized (mLock) {
- return mExternalRadioRoutingTypes.toArray(
- new String[mExternalRadioRoutingTypes.size()]);
- }
- }
-
- @Override
- public void onParameterChange(String parameters) {
- for (BinderInterfaceContainer.BinderInterface<ICarAudioCallback> client :
- mAudioParamListeners.getInterfaces()) {
+ private void callbackGroupVolumeChange(int groupId, int flags) {
+ for (BinderInterfaceContainer.BinderInterface<ICarVolumeCallback> callback :
+ mVolumeCallbackContainer.getInterfaces()) {
try {
- client.binderInterface.onParameterChange(parameters);
+ callback.binderInterface.onGroupVolumeChanged(groupId, flags);
} catch (RemoteException e) {
- // ignore. death handler will handle it.
+ Log.e(CarLog.TAG_AUDIO, "Failed to callback onGroupVolumeChanged", e);
}
}
}
- @Override
- public String[] getParameterKeys() {
- enforceAudioSettingsPermission();
- return mAudioHal.getAudioParameterKeys();
- }
-
- @Override
- public void setParameters(String parameters) {
- enforceAudioSettingsPermission();
- if (parameters == null) {
- throw new IllegalArgumentException("null parameters");
- }
- String[] keyValues = parameters.split(";");
- synchronized (mLock) {
- for (String keyValue : keyValues) {
- String[] keyValuePair = keyValue.split("=");
- if (keyValuePair.length != 2) {
- throw new IllegalArgumentException("Wrong audio parameter:" + parameters);
- }
- assertPamameterKeysLocked(keyValuePair[0]);
+ private void callbackMasterMuteChange(int flags) {
+ for (BinderInterfaceContainer.BinderInterface<ICarVolumeCallback> callback :
+ mVolumeCallbackContainer.getInterfaces()) {
+ try {
+ callback.binderInterface.onMasterMuteChanged(flags);
+ } catch (RemoteException e) {
+ Log.e(CarLog.TAG_AUDIO, "Failed to callback onMasterMuteChanged", e);
}
}
- mAudioHal.setAudioParameters(parameters);
- }
-
- @Override
- public String getParameters(String keys) {
- enforceAudioSettingsPermission();
- if (keys == null) {
- throw new IllegalArgumentException("null keys");
- }
- synchronized (mLock) {
- for (String key : keys.split(";")) {
- assertPamameterKeysLocked(key);
- }
- }
- return mAudioHal.getAudioParameters(keys);
- }
-
- @Override
- public void registerOnParameterChangeListener(ICarAudioCallback callback) {
- enforceAudioSettingsPermission();
- if (callback == null) {
- throw new IllegalArgumentException("callback null");
- }
- mAudioParamListeners.addBinder(callback);
- }
-
- @Override
- public void unregisterOnParameterChangeListener(ICarAudioCallback callback) {
- if (callback == null) {
- return;
- }
- mAudioParamListeners.removeBinder(callback);
- }
-
- private void populateParameterKeysLocked() {
- String[] keys = mAudioHal.getAudioParameterKeys();
- mAudioParamKeys = new HashSet<>();
- if (keys == null) { // not supported
- return;
- }
- for (String key : keys) {
- mAudioParamKeys.add(key);
- }
- }
-
- private void assertPamameterKeysLocked(String key) {
- if (!mAudioParamKeys.contains(key)) {
- throw new IllegalArgumentException("Audio parameter not available:" + key);
- }
- }
-
- private void enforceAudioSettingsPermission() {
- if (mContext.checkCallingOrSelfPermission(Car.PERMISSION_CAR_CONTROL_AUDIO_SETTINGS)
- != PackageManager.PERMISSION_GRANTED) {
- throw new SecurityException(
- "requires permission " + Car.PERMISSION_CAR_CONTROL_AUDIO_SETTINGS);
- }
}
/**
- * API for system to control mute with lock.
- * @param mute
- * @return the current mute state
+ * @see {@link android.car.media.CarAudioManager#getGroupMaxVolume(int)}
*/
- public void muteMediaWithLock(boolean lock) {
- mMediaMuteAudioFocusListener.mute(lock);
- }
+ @Override
+ public int getGroupMaxVolume(int groupId) {
+ synchronized (mImplLock) {
+ enforcePermission(Car.PERMISSION_CAR_CONTROL_AUDIO_VOLUME);
- public void unMuteMedia() {
- // unmute always done with lock
- mMediaMuteAudioFocusListener.unMute(true);
- }
-
- public AudioRoutingPolicy getAudioRoutingPolicy() {
- return mAudioRoutingPolicy;
- }
-
- private void enforceAudioVolumePermission() {
- if (mContext.checkCallingOrSelfPermission(Car.PERMISSION_CAR_CONTROL_AUDIO_VOLUME)
- != PackageManager.PERMISSION_GRANTED) {
- throw new SecurityException(
- "requires permission " + Car.PERMISSION_CAR_CONTROL_AUDIO_VOLUME);
- }
- }
-
- private void doHandleCarFocusChange() {
- int newFocusState = AudioHalService.VEHICLE_AUDIO_FOCUS_STATE_INVALID;
- AudioFocusInfo topInfo;
- boolean systemSoundActive = false;
- synchronized (mLock) {
- if (mFocusReceived == null) {
- // already handled
- return;
+ // For legacy stream type based volume control
+ if (!mUseDynamicRouting) {
+ return mAudioManager.getStreamMaxVolume(STREAM_TYPES[groupId]);
}
- if (mFocusReceived.equals(mCurrentFocusState)) {
- // no change
- mFocusReceived = null;
- return;
- }
- if (DBG) {
- Log.d(TAG_FOCUS, "focus change from car:" + mFocusReceived);
- }
- systemSoundActive = mSystemSoundPhysicalStreamActive;
- topInfo = mPrimaryFocusInfo;
- if (!mFocusReceived.equals(mCurrentFocusState.focusState)) {
- newFocusState = mFocusReceived.focusState;
- }
- mCurrentFocusState = mFocusReceived;
- mFocusReceived = null;
- if (mLastFocusRequestToCar != null &&
- (mLastFocusRequestToCar.focusRequest ==
- AudioHalService.VEHICLE_AUDIO_FOCUS_REQUEST_GAIN ||
- mLastFocusRequestToCar.focusRequest ==
- AudioHalService.VEHICLE_AUDIO_FOCUS_REQUEST_GAIN_TRANSIENT ||
- mLastFocusRequestToCar.focusRequest ==
- AudioHalService.VEHICLE_AUDIO_FOCUS_REQUEST_GAIN_TRANSIENT_MAY_DUCK) &&
- (mCurrentFocusState.streams & mLastFocusRequestToCar.streams) !=
- mLastFocusRequestToCar.streams) {
- Log.w(TAG_FOCUS, "streams mismatch, requested:0x" + Integer.toHexString(
- mLastFocusRequestToCar.streams) + " got:0x" +
- Integer.toHexString(mCurrentFocusState.streams));
- // treat it as focus loss as requested streams are not there.
- newFocusState = AudioHalService.VEHICLE_AUDIO_FOCUS_STATE_LOSS;
- }
- mLastFocusRequestToCar = null;
- if (mRadioOrExtSourceActive &&
- (mCurrentFocusState.externalFocus &
- AudioHalService.VEHICLE_AUDIO_EXT_FOCUS_CAR_PLAY_ONLY_FLAG) == 0) {
- // radio flag dropped
- newFocusState = AudioHalService.VEHICLE_AUDIO_FOCUS_STATE_LOSS;
- mRadioOrExtSourceActive = false;
- }
- if (newFocusState == AudioHalService.VEHICLE_AUDIO_FOCUS_STATE_LOSS ||
- newFocusState == AudioHalService.VEHICLE_AUDIO_FOCUS_STATE_LOSS_TRANSIENT ||
- newFocusState ==
- AudioHalService.VEHICLE_AUDIO_FOCUS_STATE_LOSS_TRANSIENT_EXLCUSIVE) {
- // clear second one as there can be no such item in these LOSS.
- mSecondaryFocusInfo = null;
- }
- }
- switch (newFocusState) {
- case AudioHalService.VEHICLE_AUDIO_FOCUS_STATE_GAIN:
- doHandleFocusGainFromCar(mCurrentFocusState, topInfo, systemSoundActive);
- break;
- case AudioHalService.VEHICLE_AUDIO_FOCUS_STATE_GAIN_TRANSIENT:
- doHandleFocusGainTransientFromCar(mCurrentFocusState, topInfo, systemSoundActive);
- break;
- case AudioHalService.VEHICLE_AUDIO_FOCUS_STATE_LOSS:
- doHandleFocusLossFromCar(mCurrentFocusState, topInfo);
- break;
- case AudioHalService.VEHICLE_AUDIO_FOCUS_STATE_LOSS_TRANSIENT:
- doHandleFocusLossTransientFromCar(mCurrentFocusState);
- break;
- case AudioHalService.VEHICLE_AUDIO_FOCUS_STATE_LOSS_TRANSIENT_CAN_DUCK:
- doHandleFocusLossTransientCanDuckFromCar(mCurrentFocusState);
- break;
- case AudioHalService.VEHICLE_AUDIO_FOCUS_STATE_LOSS_TRANSIENT_EXLCUSIVE:
- doHandleFocusLossTransientExclusiveFromCar(mCurrentFocusState);
- break;
- }
- }
- private void doHandleFocusGainFromCar(FocusState currentState, AudioFocusInfo topInfo,
- boolean systemSoundActive) {
- if (isFocusFromCarServiceBottom(topInfo)) {
- if (systemSoundActive) { // focus requested for system sound
- if (DBG) {
- Log.d(TAG_FOCUS, "focus gain due to system sound");
- }
- return;
- }
- Log.w(TAG_FOCUS, "focus gain from car:" + currentState +
- " while bottom listener is top");
- mFocusHandler.handleFocusReleaseRequest();
- } else {
- mAudioManager.abandonAudioFocus(mCarProxyAudioFocusListener);
- }
- }
-
- private void doHandleFocusGainTransientFromCar(FocusState currentState,
- AudioFocusInfo topInfo, boolean systemSoundActive) {
- if ((currentState.externalFocus &
- (AudioHalService.VEHICLE_AUDIO_EXT_FOCUS_CAR_PERMANENT_FLAG |
- AudioHalService.VEHICLE_AUDIO_EXT_FOCUS_CAR_TRANSIENT_FLAG)) == 0) {
- mAudioManager.abandonAudioFocus(mCarProxyAudioFocusListener);
- } else {
- if (isFocusFromCarServiceBottom(topInfo) || isFocusFromCarProxy(topInfo)) {
- if (systemSoundActive) { // focus requested for system sound
- if (DBG) {
- Log.d(TAG_FOCUS, "focus gain tr due to system sound");
- }
- return;
- }
- Log.w(TAG_FOCUS, "focus gain transient from car:" + currentState +
- " while bottom listener or car proxy is top");
- mFocusHandler.handleFocusReleaseRequest();
- }
- }
- }
-
- private void doHandleFocusLossFromCar(FocusState currentState, AudioFocusInfo topInfo) {
- if (DBG) {
- Log.d(TAG_FOCUS, "doHandleFocusLossFromCar current:" + currentState +
- " top:" + dumpAudioFocusInfo(topInfo));
- }
- if (isFocusFromCarProxy(topInfo)) {
- // already car proxy is top. Nothing to do.
- return;
- }
- boolean shouldRequestProxyFocus = false;
- if ((currentState.externalFocus &
- AudioHalService.VEHICLE_AUDIO_EXT_FOCUS_CAR_PERMANENT_FLAG) != 0) {
- // If car is playing something persistent, the car proxy should have focus
- shouldRequestProxyFocus = true;
- }
- if (!isFocusFromCarServiceBottom(topInfo)) {
- // If a car source was being ducked, it should get the primary focus back
- shouldRequestProxyFocus = true;
- }
- if (shouldRequestProxyFocus) {
- requestCarProxyFocus(AudioManager.AUDIOFOCUS_GAIN, 0);
- }
- }
-
- private void doHandleFocusLossTransientFromCar(FocusState currentState) {
- requestCarProxyFocus(AudioManager.AUDIOFOCUS_GAIN_TRANSIENT, 0);
- }
-
- private void doHandleFocusLossTransientCanDuckFromCar(FocusState currentState) {
- requestCarProxyFocus(AudioManager.AUDIOFOCUS_GAIN_TRANSIENT_MAY_DUCK, 0);
- }
-
- private void doHandleFocusLossTransientExclusiveFromCar(FocusState currentState) {
- requestCarProxyFocus(AudioManager.AUDIOFOCUS_GAIN_TRANSIENT,
- AudioManager.AUDIOFOCUS_FLAG_LOCK);
- }
-
- private void requestCarProxyFocus(int androidFocus, int flags) {
- mAudioManager.requestAudioFocus(mCarProxyAudioFocusListener, mAttributeCarExternal,
- androidFocus, flags, mAudioPolicy);
- }
-
- private void doHandleStreamStatusChange(int streamNumber, boolean streamActive) {
- synchronized (mLock) {
- if (streamNumber != mSystemSoundPhysicalStream) {
- return;
- }
- mSystemSoundPhysicalStreamActive = streamActive;
- }
- doHandleAndroidFocusChange(true /*triggeredByStreamChange*/);
- }
-
- private boolean checkFocusUsage(AudioFocusInfo info, int expectedUsage) {
- if (info == null) {
- return false;
- }
-
- AudioAttributes attributes = info.getAttributes();
- if (attributes == null) {
- return false;
- }
-
- int actualUsage = CarAudioAttributesUtil.getCarUsageFromAudioAttributes(attributes);
- if (actualUsage == expectedUsage) {
- return info.getPackageName().equals(mContext.getOpPackageName());
- }
- return false;
- }
-
- private boolean isFocusFromCarServiceBottom(AudioFocusInfo info) {
- return checkFocusUsage(info, CarAudioAttributesUtil.CAR_AUDIO_USAGE_CARSERVICE_BOTTOM);
- }
-
- private boolean isFocusFromCarProxy(AudioFocusInfo info) {
- return checkFocusUsage(info, CarAudioAttributesUtil.CAR_AUDIO_USAGE_CARSERVICE_CAR_PROXY);
- }
-
- private boolean isFocusFromExternalRadioOrExternalSource(AudioFocusInfo info) {
- if (info == null) {
- return false;
- }
-
- AudioAttributes attributes = info.getAttributes();
- if (attributes == null) {
- return false;
- }
-
- int focusUsage = CarAudioAttributesUtil.getCarUsageFromAudioAttributes(attributes);
- switch (focusUsage) {
- case CarAudioManager.CAR_AUDIO_USAGE_RADIO:
- return mIsRadioExternal;
- case CarAudioManager.CAR_AUDIO_USAGE_EXTERNAL_AUDIO_SOURCE:
- return true;
- default:
- return false;
+ CarVolumeGroup group = getCarVolumeGroup(groupId);
+ return group.getMaxGainIndex();
}
}
/**
- * Re-evaluate current focus state and send focus request to car if new focus was requested.
- * @return true if focus change was requested to car.
+ * @see {@link android.car.media.CarAudioManager#getGroupMinVolume(int)}
*/
- private boolean reevaluateCarAudioFocusAndSendFocusLocked() {
- if (mPrimaryFocusInfo == null) {
- if (mSystemSoundPhysicalStreamActive) {
- return requestFocusForSystemSoundOnlyCaseLocked();
- } else {
- requestFocusReleaseForSystemSoundLocked();
- return false;
- }
- }
- if (mPrimaryFocusInfo.getLossReceived() != 0) {
- // top one got loss. This should not happen.
- Log.e(TAG_FOCUS, "Top focus holder got loss " + dumpAudioFocusInfo(mPrimaryFocusInfo));
- return false;
- }
- if (isFocusFromCarServiceBottom(mPrimaryFocusInfo) || isFocusFromCarProxy(mPrimaryFocusInfo)) {
- // allow system sound only when car is not holding focus.
- if (mSystemSoundPhysicalStreamActive && isFocusFromCarServiceBottom(mPrimaryFocusInfo)) {
- return requestFocusForSystemSoundOnlyCaseLocked();
- }
- switch (mCurrentFocusState.focusState) {
- case AudioHalService.VEHICLE_AUDIO_FOCUS_STATE_GAIN:
- case AudioHalService.VEHICLE_AUDIO_FOCUS_STATE_GAIN_TRANSIENT:
- //should not have focus. So enqueue release
- mFocusHandler.handleFocusReleaseRequest();
- break;
- case AudioHalService.VEHICLE_AUDIO_FOCUS_STATE_LOSS:
- doHandleFocusLossFromCar(mCurrentFocusState, mPrimaryFocusInfo);
- break;
- case AudioHalService.VEHICLE_AUDIO_FOCUS_STATE_LOSS_TRANSIENT:
- doHandleFocusLossTransientFromCar(mCurrentFocusState);
- break;
- case AudioHalService.VEHICLE_AUDIO_FOCUS_STATE_LOSS_TRANSIENT_CAN_DUCK:
- doHandleFocusLossTransientCanDuckFromCar(mCurrentFocusState);
- break;
- case AudioHalService.VEHICLE_AUDIO_FOCUS_STATE_LOSS_TRANSIENT_EXLCUSIVE:
- doHandleFocusLossTransientExclusiveFromCar(mCurrentFocusState);
- break;
- }
- mRadioOrExtSourceActive = false;
- return false;
- }
- mFocusHandler.cancelFocusReleaseRequest();
- AudioAttributes attrib = mPrimaryFocusInfo.getAttributes();
- int logicalStreamTypeForTop = CarAudioAttributesUtil.getCarUsageFromAudioAttributes(attrib);
- int physicalStreamTypeForTop = mAudioRoutingPolicy.getPhysicalStreamForLogicalStream(
- (logicalStreamTypeForTop < CarAudioAttributesUtil.CAR_AUDIO_USAGE_CARSERVICE_BOTTOM)
- ? logicalStreamTypeForTop : CarAudioManager.CAR_AUDIO_USAGE_MUSIC);
+ @Override
+ public int getGroupMinVolume(int groupId) {
+ synchronized (mImplLock) {
+ enforcePermission(Car.PERMISSION_CAR_CONTROL_AUDIO_VOLUME);
- boolean muteMedia = false;
- String primaryExtSource = CarAudioAttributesUtil.getExtRouting(attrib);
- // update primary context and notify if necessary
- int primaryContext = AudioHalService.logicalStreamWithExtTypeToHalContextType(
- logicalStreamTypeForTop, primaryExtSource);
- if (logicalStreamTypeForTop ==
- CarAudioAttributesUtil.CAR_AUDIO_USAGE_CARSERVICE_MEDIA_MUTE) {
- muteMedia = true;
- }
- // other apps having focus
- int focusToRequest = AudioHalService.VEHICLE_AUDIO_FOCUS_REQUEST_RELEASE;
- int extFocus = AudioHalService.VEHICLE_AUDIO_EXT_FOCUS_NONE_FLAG;
- int streamsToRequest = 0x1 << physicalStreamTypeForTop;
- boolean primaryIsExternal = isFocusFromExternalRadioOrExternalSource(mPrimaryFocusInfo);
- if (primaryIsExternal) {
- streamsToRequest = 0;
- mRadioOrExtSourceActive = true;
- if (fixExtSourceAndContext(
- mExtSourceInfoScratch.set(primaryExtSource, primaryContext))) {
- primaryExtSource = mExtSourceInfoScratch.source;
- primaryContext = mExtSourceInfoScratch.context;
+ // For legacy stream type based volume control
+ if (!mUseDynamicRouting) {
+ return mAudioManager.getStreamMinVolume(STREAM_TYPES[groupId]);
}
- } else {
- mRadioOrExtSourceActive = false;
- primaryExtSource = null;
- }
- // save the current context now but it is sent to context change listener after focus
- // response from car
- if (mCurrentPrimaryAudioContext != primaryContext) {
- mCurrentPrimaryAudioContext = primaryContext;
- mCurrentPrimaryPhysicalStream = physicalStreamTypeForTop;
- }
- boolean secondaryIsExternal = false;
- int secondaryContext = 0;
- String secondaryExtSource = null;
- switch (mPrimaryFocusInfo.getGainRequest()) {
- case AudioManager.AUDIOFOCUS_GAIN:
- focusToRequest = AudioHalService.VEHICLE_AUDIO_FOCUS_REQUEST_GAIN;
- break;
- case AudioManager.AUDIOFOCUS_GAIN_TRANSIENT:
- case AudioManager.AUDIOFOCUS_GAIN_TRANSIENT_EXCLUSIVE:
- focusToRequest = AudioHalService.VEHICLE_AUDIO_FOCUS_REQUEST_GAIN_TRANSIENT;
- break;
- case AudioManager.AUDIOFOCUS_GAIN_TRANSIENT_MAY_DUCK:
- focusToRequest =
- AudioHalService.VEHICLE_AUDIO_FOCUS_REQUEST_GAIN_TRANSIENT_MAY_DUCK;
- if (mSecondaryFocusInfo == null) {
- break;
- }
- AudioAttributes secondAttrib = mSecondaryFocusInfo.getAttributes();
- if (secondAttrib == null) {
- break;
- }
- int logicalStreamTypeForSecond =
- CarAudioAttributesUtil.getCarUsageFromAudioAttributes(secondAttrib);
- if (logicalStreamTypeForSecond ==
- CarAudioAttributesUtil.CAR_AUDIO_USAGE_CARSERVICE_MEDIA_MUTE) {
- muteMedia = true;
- break;
- }
- secondaryIsExternal = isFocusFromExternalRadioOrExternalSource(mSecondaryFocusInfo);
- if (secondaryIsExternal) {
- secondaryExtSource = CarAudioAttributesUtil.getExtRouting(secondAttrib);
- secondaryContext = AudioHalService.logicalStreamWithExtTypeToHalContextType(
- logicalStreamTypeForSecond, secondaryExtSource);
- if (fixExtSourceAndContext(
- mExtSourceInfoScratch.set(secondaryExtSource, secondaryContext))) {
- secondaryExtSource = mExtSourceInfoScratch.source;
- secondaryContext = mExtSourceInfoScratch.context;
- }
- int secondaryExtPhysicalStreamFlag =
- getPhysicalStreamFlagForExtSourceLocked(secondaryExtSource);
- if ((secondaryExtPhysicalStreamFlag & streamsToRequest) != 0) {
- // secondary stream is the same as primary. cannot keep secondary
- secondaryIsExternal = false;
- secondaryContext = 0;
- secondaryExtSource = null;
- break;
- }
- mRadioOrExtSourceActive = true;
- } else {
- secondaryContext = AudioHalService.logicalStreamWithExtTypeToHalContextType(
- logicalStreamTypeForSecond, null);
- }
- switch (mCurrentFocusState.focusState) {
- case AudioHalService.VEHICLE_AUDIO_FOCUS_STATE_GAIN:
- streamsToRequest |= mCurrentFocusState.streams;
- focusToRequest = AudioHalService.VEHICLE_AUDIO_FOCUS_REQUEST_GAIN;
- break;
- case AudioHalService.VEHICLE_AUDIO_FOCUS_STATE_GAIN_TRANSIENT:
- streamsToRequest |= mCurrentFocusState.streams;
- focusToRequest = AudioHalService.VEHICLE_AUDIO_FOCUS_REQUEST_GAIN_TRANSIENT;
- break;
- case AudioHalService.VEHICLE_AUDIO_FOCUS_STATE_LOSS:
- case AudioHalService.VEHICLE_AUDIO_FOCUS_STATE_LOSS_TRANSIENT:
- case AudioHalService.VEHICLE_AUDIO_FOCUS_STATE_LOSS_TRANSIENT_CAN_DUCK:
- break;
- case AudioHalService.VEHICLE_AUDIO_FOCUS_STATE_LOSS_TRANSIENT_EXLCUSIVE:
- doHandleFocusLossTransientExclusiveFromCar(mCurrentFocusState);
- return false;
- }
- break;
- default:
- streamsToRequest = 0;
- break;
+ CarVolumeGroup group = getCarVolumeGroup(groupId);
+ return group.getMinGainIndex();
}
- int audioContexts = primaryContext | secondaryContext;
- if (muteMedia) {
- boolean addMute = true;
- if (primaryIsExternal) {
- if ((getPhysicalStreamFlagForExtSourceLocked(primaryExtSource) &
- (0x1 << mRadioPhysicalStream)) != 0) {
- // cannot mute as primary is media
- addMute = false;
- }
- } else if (secondaryIsExternal) {
- if ((getPhysicalStreamFlagForExtSourceLocked(secondaryExtSource) &
- (0x1 << mRadioPhysicalStream)) != 0) {
- mRadioOrExtSourceActive = false;
- }
- } else {
- mRadioOrExtSourceActive = false;
- }
- if (addMute) {
- audioContexts &= ~(AudioHalService.AUDIO_CONTEXT_RADIO_FLAG |
- AudioHalService.AUDIO_CONTEXT_MUSIC_FLAG |
- AudioHalService.AUDIO_CONTEXT_CD_ROM_FLAG |
- AudioHalService.AUDIO_CONTEXT_AUX_AUDIO_FLAG);
- extFocus = AudioHalService.VEHICLE_AUDIO_EXT_FOCUS_CAR_MUTE_MEDIA_FLAG;
- streamsToRequest &= ~(0x1 << mRadioPhysicalStream);
- }
- } else if (mRadioOrExtSourceActive) {
- boolean shouldDropSecondaryContext = false;
- if (primaryIsExternal) {
- int primaryExtPhysicalStreamFlag =
- getPhysicalStreamFlagForExtSourceLocked(primaryExtSource);
- if (secondaryIsExternal) {
- int secondaryPhysicalStreamFlag =
- getPhysicalStreamFlagForExtSourceLocked(secondaryExtSource);
- if (primaryExtPhysicalStreamFlag == secondaryPhysicalStreamFlag) {
- // overlap, drop secondary
- shouldDropSecondaryContext = true;
- secondaryExtSource = null;
- }
- streamsToRequest = 0;
- } else { // primary only
- if (streamsToRequest == primaryExtPhysicalStreamFlag) {
- // cannot keep secondary
- shouldDropSecondaryContext = true;
- }
- streamsToRequest &= ~primaryExtPhysicalStreamFlag;
- }
- }
- extFocus = AudioHalService.VEHICLE_AUDIO_EXT_FOCUS_CAR_PLAY_ONLY_FLAG;
- if (shouldDropSecondaryContext) {
- audioContexts &= ~secondaryContext;
- secondaryContext = 0;
- }
- } else if (streamsToRequest == 0) {
- if (mSystemSoundPhysicalStreamActive) {
- return requestFocusForSystemSoundOnlyCaseLocked();
- } else {
- mCurrentAudioContexts = 0;
- mFocusHandler.handleFocusReleaseRequest();
- return false;
- }
- }
- if (mSystemSoundPhysicalStreamActive) {
- boolean addSystemStream = true;
- if (primaryIsExternal && getPhysicalStreamNumberForExtSourceLocked(primaryExtSource) ==
- mSystemSoundPhysicalStream) {
- addSystemStream = false;
- }
- if (secondaryIsExternal && getPhysicalStreamNumberForExtSourceLocked(secondaryExtSource)
- == mSystemSoundPhysicalStream) {
- addSystemStream = false;
- }
- int systemSoundFlag = 0x1 << mSystemSoundPhysicalStream;
- // stream already added by focus. Cannot distinguish system sound play from other sound
- // in this stream.
- if ((streamsToRequest & systemSoundFlag) != 0) {
- addSystemStream = false;
- }
- if (addSystemStream) {
- streamsToRequest |= systemSoundFlag;
- audioContexts |= AudioHalService.AUDIO_CONTEXT_SYSTEM_SOUND_FLAG;
- if (focusToRequest == AudioHalService.VEHICLE_AUDIO_FOCUS_REQUEST_RELEASE) {
- focusToRequest =
- AudioHalService.VEHICLE_AUDIO_FOCUS_REQUEST_GAIN_TRANSIENT_NO_DUCK;
- }
- }
- }
- boolean routingHintChanged = sendExtRoutingHintToCarIfNecessaryLocked(primaryExtSource,
- secondaryExtSource);
- return sendFocusRequestToCarIfNecessaryLocked(focusToRequest, streamsToRequest, extFocus,
- audioContexts, routingHintChanged);
}
/**
- * Fix external source info if it is not valid.
- * @param extSourceInfo
- * @return true if value is not valid and was updated.
+ * @see {@link android.car.media.CarAudioManager#getGroupVolume(int)}
*/
- private boolean fixExtSourceAndContext(ExtSourceInfo extSourceInfo) {
- if (!mExternalRoutingTypes.containsKey(extSourceInfo.source)) {
- Log.w(CarLog.TAG_AUDIO, "External source not available:" + extSourceInfo.source);
- // fall back to radio
- extSourceInfo.source = mDefaultRadioRoutingType;
- extSourceInfo.context = AudioHalService.AUDIO_CONTEXT_RADIO_FLAG;
- return true;
- }
- if (extSourceInfo.context == AudioHalService.AUDIO_CONTEXT_RADIO_FLAG &&
- !extSourceInfo.source.startsWith(RADIO_ROUTING_SOURCE_PREFIX)) {
- Log.w(CarLog.TAG_AUDIO, "Expecting Radio source:" + extSourceInfo.source);
- extSourceInfo.source = mDefaultRadioRoutingType;
- return true;
- }
- return false;
- }
+ @Override
+ public int getGroupVolume(int groupId) {
+ synchronized (mImplLock) {
+ enforcePermission(Car.PERMISSION_CAR_CONTROL_AUDIO_VOLUME);
- private int getPhysicalStreamFlagForExtSourceLocked(String extSource) {
- return 0x1 << getPhysicalStreamNumberForExtSourceLocked(extSource);
- }
+ // For legacy stream type based volume control
+ if (!mUseDynamicRouting) {
+ return mAudioManager.getStreamVolume(STREAM_TYPES[groupId]);
+ }
- private int getPhysicalStreamNumberForExtSourceLocked(String extSource) {
- AudioHalService.ExtRoutingSourceInfo info = mExternalRoutingTypes.get(
- extSource);
- if (info != null) {
- return info.physicalStreamNumber;
- } else {
- return mRadioPhysicalStream;
+ CarVolumeGroup group = getCarVolumeGroup(groupId);
+ return group.getCurrentGainIndex();
}
}
- private boolean sendExtRoutingHintToCarIfNecessaryLocked(String primarySource,
- String secondarySource) {
- if (!mExternalRoutingHintSupported) {
- return false;
- }
- if (DBG) {
- Log.d(TAG_FOCUS, "Setting external routing hint, primary:" + primarySource +
- " secondary:" + secondarySource);
- }
- Arrays.fill(mExternalRoutingsScratch, 0);
- fillExtRoutingPositionLocked(mExternalRoutingsScratch, primarySource);
- fillExtRoutingPositionLocked(mExternalRoutingsScratch, secondarySource);
- if (Arrays.equals(mExternalRoutingsScratch, mExternalRoutings)) {
- return false;
- }
- System.arraycopy(mExternalRoutingsScratch, 0, mExternalRoutings, 0,
- mExternalRoutingsScratch.length);
- if (DBG) {
- Log.d(TAG_FOCUS, "Set values:" + Arrays.toString(mExternalRoutingsScratch));
- }
- try {
- mAudioHal.setExternalRoutingSource(mExternalRoutings);
- } catch (IllegalArgumentException e) {
- //ignore. can happen with mocking.
- return false;
- }
- return true;
+ private CarVolumeGroup getCarVolumeGroup(int groupId) {
+ Preconditions.checkNotNull(mCarVolumeGroups);
+ Preconditions.checkArgument(groupId >= 0 && groupId < mCarVolumeGroups.length,
+ "groupId out of range: " + groupId);
+ return mCarVolumeGroups[groupId];
}
- private void fillExtRoutingPositionLocked(int[] array, String extSource) {
- if (extSource == null) {
+ private void setupLegacyVolumeChangedListener() {
+ IntentFilter intentFilter = new IntentFilter();
+ intentFilter.addAction(AudioManager.VOLUME_CHANGED_ACTION);
+ intentFilter.addAction(AudioManager.MASTER_MUTE_CHANGED_ACTION);
+ mContext.registerReceiver(mLegacyVolumeChangedReceiver, intentFilter);
+ }
+
+ private void setupDynamicRouting() {
+ final IAudioControl audioControl = getAudioControl();
+ if (audioControl == null) {
return;
}
- AudioHalService.ExtRoutingSourceInfo info = mExternalRoutingTypes.get(
- extSource);
- if (info == null) {
- return;
+ AudioPolicy audioPolicy = getDynamicAudioPolicy(audioControl);
+ int r = mAudioManager.registerAudioPolicy(audioPolicy);
+ if (r != AudioManager.SUCCESS) {
+ throw new RuntimeException("registerAudioPolicy failed " + r);
}
- int pos = info.bitPosition;
- if (pos < 0) {
- return;
- }
- int index = pos / 32;
- int bitPosInInt = pos % 32;
- array[index] |= (0x1 << bitPosInInt);
+ mAudioPolicy = audioPolicy;
}
- private boolean requestFocusForSystemSoundOnlyCaseLocked() {
- int focusRequest = AudioHalService.VEHICLE_AUDIO_FOCUS_REQUEST_GAIN_TRANSIENT_NO_DUCK;
- int streamsToRequest = 0x1 << mSystemSoundPhysicalStream;
- int extFocus = 0;
- int audioContexts = AudioHalService.AUDIO_CONTEXT_SYSTEM_SOUND_FLAG;
- mCurrentPrimaryAudioContext = audioContexts;
- return sendFocusRequestToCarIfNecessaryLocked(focusRequest, streamsToRequest, extFocus,
- audioContexts, false /*forceSend*/);
- }
-
- private void requestFocusReleaseForSystemSoundLocked() {
- switch (mCurrentFocusState.focusState) {
- case AudioHalService.VEHICLE_AUDIO_FOCUS_STATE_GAIN:
- case AudioHalService.VEHICLE_AUDIO_FOCUS_STATE_GAIN_TRANSIENT:
- mFocusHandler.handleFocusReleaseRequest();
- default: // ignore
- break;
- }
- }
-
- private void doSendFocusRequestToCarLocked(int focusToRequest,
- int streamsToRequest, int extFocus, int audioContexts) {
- if (DBG) {
- Log.d(TAG_FOCUS, String.format("audio focus request. focusToRequest = %d, " +
- "streamsToRequest = 0x%x, extFocus = 0x%x, audioContexts = 0x%x",
- focusToRequest, streamsToRequest, extFocus, audioContexts));
- }
- try {
- mAudioHal.requestAudioFocusChange(
- focusToRequest,
- streamsToRequest,
- extFocus,
- audioContexts);
- } catch (IllegalArgumentException e) {
- // can happen when mocking ends. ignore. timeout will handle it properly.
- }
- try {
- mLock.wait(mFocusResponseWaitTimeoutMs);
- } catch (InterruptedException e) {
- // ignore
- }
- }
-
- private boolean sendFocusRequestToCarIfNecessaryLocked(int focusToRequest,
- int streamsToRequest, int extFocus, int audioContexts, boolean forceSend) {
- if (needsToSendFocusRequestLocked(focusToRequest, streamsToRequest, extFocus,
- audioContexts) || forceSend) {
- mLastFocusRequestToCar = FocusRequest.create(focusToRequest, streamsToRequest,
- extFocus);
- mCurrentAudioContexts = audioContexts;
- if (((mCurrentFocusState.streams & streamsToRequest) == streamsToRequest) &&
- ((mCurrentFocusState.streams & ~streamsToRequest) != 0)) {
- // stream is reduced, so do not release it immediately
- try {
- Thread.sleep(NO_FOCUS_PLAY_WAIT_TIME_MS);
- } catch (InterruptedException e) {
- // ignore
- }
+ private void setupVolumeGroups() {
+ Preconditions.checkArgument(mCarAudioDeviceInfos.size() > 0,
+ "No bus device is configured to setup volume groups");
+ final CarVolumeGroupsHelper helper = new CarVolumeGroupsHelper(
+ mContext, R.xml.car_volume_groups);
+ mCarVolumeGroups = helper.loadVolumeGroups();
+ for (CarVolumeGroup group : mCarVolumeGroups) {
+ for (int contextNumber : group.getContexts()) {
+ int busNumber = mContextToBus.get(contextNumber);
+ group.bind(contextNumber, busNumber, mCarAudioDeviceInfos.get(busNumber));
}
- if (DBG) {
- Log.d(TAG_FOCUS, "focus request to car:" + mLastFocusRequestToCar + " context:0x" +
- Integer.toHexString(audioContexts));
- }
- doSendFocusRequestToCarLocked(focusToRequest, streamsToRequest, extFocus,
- audioContexts);
- return true;
- }
- return false;
- }
- private boolean needsToSendFocusRequestLocked(int focusToRequest, int streamsToRequest,
- int extFocus, int audioContexts) {
- if (streamsToRequest != mCurrentFocusState.streams) {
- return true;
- }
- if (audioContexts != mCurrentAudioContexts) {
- return true;
- }
- if ((extFocus & mCurrentFocusState.externalFocus) != extFocus) {
- return true;
- }
- switch (focusToRequest) {
- case AudioHalService.VEHICLE_AUDIO_FOCUS_REQUEST_GAIN:
- if (mCurrentFocusState.focusState ==
- AudioHalService.VEHICLE_AUDIO_FOCUS_STATE_GAIN) {
- return false;
- }
- break;
- case AudioHalService.VEHICLE_AUDIO_FOCUS_REQUEST_GAIN_TRANSIENT:
- case AudioHalService.VEHICLE_AUDIO_FOCUS_REQUEST_GAIN_TRANSIENT_MAY_DUCK:
- case AudioHalService.VEHICLE_AUDIO_FOCUS_REQUEST_GAIN_TRANSIENT_NO_DUCK:
- if (mCurrentFocusState.focusState ==
- AudioHalService.VEHICLE_AUDIO_FOCUS_STATE_GAIN ||
- mCurrentFocusState.focusState ==
- AudioHalService.VEHICLE_AUDIO_FOCUS_STATE_GAIN_TRANSIENT) {
- return false;
- }
- break;
- case AudioHalService.VEHICLE_AUDIO_FOCUS_REQUEST_RELEASE:
- if (mCurrentFocusState.focusState ==
- AudioHalService.VEHICLE_AUDIO_FOCUS_STATE_LOSS ||
- mCurrentFocusState.focusState ==
- AudioHalService.VEHICLE_AUDIO_FOCUS_STATE_LOSS_TRANSIENT_EXLCUSIVE) {
- return false;
- }
- break;
- }
- return true;
- }
+ // Now that we have all our contexts, ensure the HAL gets our intial value
+ group.setCurrentGainIndex(group.getCurrentGainIndex());
- private void doHandleAndroidFocusChange(boolean triggeredByStreamChange) {
- boolean focusRequested = false;
- synchronized (mLock) {
- AudioFocusInfo newTopInfo = null;
- if (mPendingFocusChanges.isEmpty()) {
- if (!triggeredByStreamChange) {
- // no entry. It was handled already.
- if (DBG) {
- Log.d(TAG_FOCUS, "doHandleAndroidFocusChange, mPendingFocusChanges empty");
- }
- return;
- }
- } else {
- newTopInfo = mPendingFocusChanges.getFirst();
- mPendingFocusChanges.clear();
- if (mPrimaryFocusInfo != null &&
- newTopInfo.getClientId().equals(mPrimaryFocusInfo.getClientId()) &&
- newTopInfo.getGainRequest() == mPrimaryFocusInfo.getGainRequest() &&
- isAudioAttributesSame(
- newTopInfo.getAttributes(), mPrimaryFocusInfo.getAttributes()) &&
- !triggeredByStreamChange) {
- if (DBG) {
- Log.d(TAG_FOCUS, "doHandleAndroidFocusChange, no change in top state:" +
- dumpAudioFocusInfo(mPrimaryFocusInfo));
- }
- // already in top somehow, no need to make any change
- return;
- }
- }
- if (newTopInfo != null) {
- if (newTopInfo.getGainRequest() ==
- AudioManager.AUDIOFOCUS_GAIN_TRANSIENT_MAY_DUCK) {
- mSecondaryFocusInfo = mPrimaryFocusInfo;
- } else {
- mSecondaryFocusInfo = null;
- }
- if (DBG) {
- Log.d(TAG_FOCUS, "top focus changed to:" + dumpAudioFocusInfo(newTopInfo));
- }
- mPrimaryFocusInfo = newTopInfo;
- }
- focusRequested = handleCarFocusRequestAndResponseLocked();
+ Log.v(CarLog.TAG_AUDIO, "Processed volume group: " + group);
}
- // handle it if there was response or force handle it for timeout.
- if (focusRequested) {
- doHandleCarFocusChange();
- }
- }
-
- private boolean handleCarFocusRequestAndResponseLocked() {
- boolean focusRequested = reevaluateCarAudioFocusAndSendFocusLocked();
- if (DBG) {
- if (!focusRequested) {
- Log.i(TAG_FOCUS, "focus not requested for top focus:" +
- dumpAudioFocusInfo(mPrimaryFocusInfo) + " currentState:" + mCurrentFocusState);
- }
- }
- if (focusRequested) {
- if (mFocusReceived == null) {
- Log.w(TAG_FOCUS, "focus response timed out, request sent "
- + mLastFocusRequestToCar);
- // no response. so reset to loss.
- mFocusReceived = FocusState.STATE_LOSS;
- mCurrentAudioContexts = 0;
- mNumConsecutiveHalFailures++;
- mCurrentPrimaryAudioContext = 0;
- mCurrentPrimaryPhysicalStream = 0;
- } else {
- mNumConsecutiveHalFailures = 0;
- }
- // send context change after getting focus response.
- if (mCarAudioContextChangeHandler != null) {
- mCarAudioContextChangeHandler.requestContextChangeNotification(
- mAudioContextChangeListener, mCurrentPrimaryAudioContext,
- mCurrentPrimaryPhysicalStream);
- }
- checkCanStatus();
- }
- return focusRequested;
- }
-
- private void doHandleFocusRelease() {
- boolean sent = false;
- synchronized (mLock) {
- if (mCurrentFocusState != FocusState.STATE_LOSS) {
- if (DBG) {
- Log.d(TAG_FOCUS, "focus release to car");
- }
- mLastFocusRequestToCar = FocusRequest.STATE_RELEASE;
- sent = true;
- if (mExternalRoutingHintSupported) {
- mAudioHal.setExternalRoutingSource(mExternalRoutingsForFocusRelease);
- }
- doSendFocusRequestToCarLocked(AudioHalService.VEHICLE_AUDIO_FOCUS_REQUEST_RELEASE,
- 0, 0, 0);
- mCurrentPrimaryAudioContext = 0;
- mCurrentPrimaryPhysicalStream = 0;
- if (mCarAudioContextChangeHandler != null) {
- mCarAudioContextChangeHandler.requestContextChangeNotification(
- mAudioContextChangeListener, mCurrentPrimaryAudioContext,
- mCurrentPrimaryPhysicalStream);
- }
- } else if (DBG) {
- Log.d(TAG_FOCUS, "doHandleFocusRelease: do not send, already loss");
- }
- }
- // handle it if there was response.
- if (sent) {
- doHandleCarFocusChange();
- }
- }
-
- private void checkCanStatus() {
- if (mCanBusErrorNotifier == null) {
- // TODO(b/36189057): create CanBusErrorNotifier from unit-tests and remove this code
- return;
- }
-
- // If CAN bus recovers, message will be removed.
- if (mNumConsecutiveHalFailures >= mNumConsecutiveHalFailuresForCanError) {
- mCanBusErrorNotifier.reportFailure(this);
- } else {
- mCanBusErrorNotifier.removeFailureReport(this);
- }
- }
-
- private static boolean isAudioAttributesSame(AudioAttributes one, AudioAttributes two) {
- if (one.getContentType() != two.getContentType()) {
- return false;
- }
- if (one.getUsage() != two.getUsage()) {
- return false;
- }
- return true;
- }
-
- private static String dumpAudioFocusInfo(AudioFocusInfo info) {
- if (info == null) {
- return "null";
- }
- StringBuilder builder = new StringBuilder();
- builder.append("afi package:" + info.getPackageName());
- builder.append("client id:" + info.getClientId());
- builder.append(",gain:" + info.getGainRequest());
- builder.append(",loss:" + info.getLossReceived());
- builder.append(",flag:" + info.getFlags());
- AudioAttributes attrib = info.getAttributes();
- if (attrib != null) {
- builder.append("," + attrib.toString());
- }
- return builder.toString();
- }
-
- private class SystemFocusListener extends AudioPolicyFocusListener {
- @Override
- public void onAudioFocusGrant(AudioFocusInfo afi, int requestResult) {
- if (afi == null) {
- return;
- }
- if (DBG) {
- Log.d(TAG_FOCUS, "onAudioFocusGrant " + dumpAudioFocusInfo(afi) +
- " result:" + requestResult);
- }
- if (requestResult == AudioManager.AUDIOFOCUS_REQUEST_GRANTED) {
- synchronized (mLock) {
- mPendingFocusChanges.addFirst(afi);
- }
- mFocusHandler.handleAndroidFocusChange();
- }
- }
-
- @Override
- public void onAudioFocusLoss(AudioFocusInfo afi, boolean wasNotified) {
- if (DBG) {
- Log.d(TAG_FOCUS, "onAudioFocusLoss " + dumpAudioFocusInfo(afi) +
- " notified:" + wasNotified);
- }
- // ignore loss as tracking gain is enough. At least bottom listener will be
- // always there and getting focus grant. So it is safe to ignore this here.
+ // Perform validation after all volume groups are processed
+ if (!validateVolumeGroups()) {
+ throw new RuntimeException("Invalid volume groups configuration");
}
}
/**
- * Focus listener to take focus away from android apps as a proxy to car.
- */
- private class CarProxyAndroidFocusListener implements AudioManager.OnAudioFocusChangeListener {
- @Override
- public void onAudioFocusChange(int focusChange) {
- // Do not need to handle car's focus loss or gain separately. Focus monitoring
- // through system focus listener will take care all cases.
- }
- }
-
- /**
- * Focus listener kept at the bottom to check if there is any focus holder.
+ * Constraints applied here:
*
+ * - One context should not appear in two groups
+ * - All contexts are assigned
+ * - One bus should not appear in two groups
+ * - All gain controllers in the same group have same step value
+ *
+ * Note that it is fine that there are buses not appear in any group, those buses may be
+ * reserved for other usages.
+ * Step value validation is done in {@link CarVolumeGroup#bind(int, int, CarAudioDeviceInfo)}
+ *
+ * See also the car_volume_groups.xml configuration
*/
- private class BottomAudioFocusListener implements AudioManager.OnAudioFocusChangeListener {
- @Override
- public void onAudioFocusChange(int focusChange) {
- }
- }
-
- private class MediaMuteAudioFocusListener implements AudioManager.OnAudioFocusChangeListener {
-
- private final AudioAttributes mMuteAudioAttrib =
- CarAudioAttributesUtil.getAudioAttributesForCarUsage(
- CarAudioAttributesUtil.CAR_AUDIO_USAGE_CARSERVICE_MEDIA_MUTE);
-
- /** not muted */
- private final static int MUTE_STATE_UNMUTED = 0;
- /** muted. other app requesting focus GAIN will unmute it */
- private final static int MUTE_STATE_MUTED = 1;
- /** locked. only system can unlock and send it to muted or unmuted state */
- private final static int MUTE_STATE_LOCKED = 2;
-
- private int mMuteState = MUTE_STATE_UNMUTED;
-
- @Override
- public void onAudioFocusChange(int focusChange) {
- if (focusChange == AudioManager.AUDIOFOCUS_LOSS) {
- // mute does not persist when there is other media kind app taking focus
- unMute();
- }
- }
-
- public boolean mute() {
- return mute(false);
- }
-
- /**
- * Mute with optional lock
- * @param lock Take focus with lock. Normal apps cannot take focus. Setting this will
- * essentially mute all audio.
- * @return Final mute state
- */
- public synchronized boolean mute(boolean lock) {
- int result = AudioManager.AUDIOFOCUS_REQUEST_FAILED;
- boolean lockRequested = false;
- if (lock) {
- AudioPolicy audioPolicy = null;
- synchronized (CarAudioService.this) {
- audioPolicy = mAudioPolicy;
+ private boolean validateVolumeGroups() {
+ Set<Integer> contextSet = new HashSet<>();
+ Set<Integer> busNumberSet = new HashSet<>();
+ for (CarVolumeGroup group : mCarVolumeGroups) {
+ // One context should not appear in two groups
+ for (int context : group.getContexts()) {
+ if (contextSet.contains(context)) {
+ Log.e(CarLog.TAG_AUDIO, "Context appears in two groups: " + context);
+ return false;
}
- if (audioPolicy != null) {
- result = mAudioManager.requestAudioFocus(this, mMuteAudioAttrib,
- AudioManager.AUDIOFOCUS_GAIN_TRANSIENT,
- AudioManager.AUDIOFOCUS_FLAG_LOCK |
- AudioManager.AUDIOFOCUS_FLAG_DELAY_OK,
- audioPolicy);
- lockRequested = true;
+ contextSet.add(context);
+ }
+
+ // One bus should not appear in two groups
+ for (int busNumber : group.getBusNumbers()) {
+ if (busNumberSet.contains(busNumber)) {
+ Log.e(CarLog.TAG_AUDIO, "Bus appears in two groups: " + busNumber);
+ return false;
}
+ busNumberSet.add(busNumber);
}
- if (!lockRequested) {
- result = mAudioManager.requestAudioFocus(this, mMuteAudioAttrib,
- AudioManager.AUDIOFOCUS_GAIN_TRANSIENT,
- AudioManager.AUDIOFOCUS_FLAG_DELAY_OK);
- }
- if (result == AudioManager.AUDIOFOCUS_REQUEST_GRANTED ||
- result == AudioManager.AUDIOFOCUS_REQUEST_DELAYED) {
- if (lockRequested) {
- mMuteState = MUTE_STATE_LOCKED;
- } else {
- mMuteState = MUTE_STATE_MUTED;
- }
- } else {
- mMuteState = MUTE_STATE_UNMUTED;
- }
- return mMuteState != MUTE_STATE_UNMUTED;
}
- public boolean unMute() {
- return unMute(false);
- }
-
- /**
- * Unmute. If locked, unmute will only succeed when unlock is set to true.
- * @param unlock
- * @return Final mute state
- */
- public synchronized boolean unMute(boolean unlock) {
- if (!unlock && mMuteState == MUTE_STATE_LOCKED) {
- // cannot unlock
- return true;
- }
- mMuteState = MUTE_STATE_UNMUTED;
- mAudioManager.abandonAudioFocus(this);
+ // All contexts are assigned
+ if (contextSet.size() != CONTEXT_NUMBERS.length) {
+ Log.e(CarLog.TAG_AUDIO, "Some contexts are not assigned to group");
+ Log.e(CarLog.TAG_AUDIO, "Assigned contexts "
+ + Arrays.toString(contextSet.toArray(new Integer[contextSet.size()])));
+ Log.e(CarLog.TAG_AUDIO, "All contexts " + Arrays.toString(CONTEXT_NUMBERS));
return false;
}
- public synchronized boolean isMuted() {
- return mMuteState != MUTE_STATE_UNMUTED;
- }
+ return true;
}
- private class CarAudioContextChangeHandler extends Handler {
- private static final int MSG_CONTEXT_CHANGE = 0;
+ @Nullable
+ private AudioPolicy getDynamicAudioPolicy(@NonNull IAudioControl audioControl) {
+ AudioPolicy.Builder builder = new AudioPolicy.Builder(mContext);
+ builder.setLooper(Looper.getMainLooper());
- private CarAudioContextChangeHandler(Looper looper) {
- super(looper);
+ // 1st, enumerate all output bus device ports
+ AudioDeviceInfo[] deviceInfos = mAudioManager.getDevices(AudioManager.GET_DEVICES_OUTPUTS);
+ if (deviceInfos.length == 0) {
+ Log.e(CarLog.TAG_AUDIO, "getDynamicAudioPolicy, no output device available, ignore");
+ return null;
+ }
+ for (AudioDeviceInfo info : deviceInfos) {
+ Log.v(CarLog.TAG_AUDIO, String.format("output id=%d address=%s type=%s",
+ info.getId(), info.getAddress(), info.getType()));
+ if (info.getType() == AudioDeviceInfo.TYPE_BUS) {
+ final CarAudioDeviceInfo carInfo = new CarAudioDeviceInfo(info);
+ // See also the audio_policy_configuration.xml and getBusForContext in
+ // audio control HAL, the bus number should be no less than zero.
+ if (carInfo.getBusNumber() >= 0) {
+ mCarAudioDeviceInfos.put(carInfo.getBusNumber(), carInfo);
+ Log.i(CarLog.TAG_AUDIO, "Valid bus found " + carInfo);
+ }
+ }
}
- private void requestContextChangeNotification(AudioContextChangeListener listener,
- int primaryContext, int physicalStream) {
- Message msg = obtainMessage(MSG_CONTEXT_CHANGE, primaryContext, physicalStream,
- listener);
- sendMessage(msg);
+ // 2nd, map context to physical bus
+ try {
+ for (int contextNumber : CONTEXT_NUMBERS) {
+ int busNumber = audioControl.getBusForContext(contextNumber);
+ mContextToBus.put(contextNumber, busNumber);
+ CarAudioDeviceInfo info = mCarAudioDeviceInfos.get(busNumber);
+ if (info == null) {
+ Log.w(CarLog.TAG_AUDIO, "No bus configured for context: " + contextNumber);
+ }
+ }
+ } catch (RemoteException e) {
+ Log.e(CarLog.TAG_AUDIO, "Error mapping context to physical bus", e);
}
- private void cancelAll() {
- removeMessages(MSG_CONTEXT_CHANGE);
+ // 3rd, enumerate all physical buses and build the routing policy.
+ // Note that one can not register audio mix for same bus more than once.
+ for (int i = 0; i < mCarAudioDeviceInfos.size(); i++) {
+ int busNumber = mCarAudioDeviceInfos.keyAt(i);
+ boolean hasContext = false;
+ CarAudioDeviceInfo info = mCarAudioDeviceInfos.valueAt(i);
+ AudioFormat mixFormat = new AudioFormat.Builder()
+ .setSampleRate(info.getSampleRate())
+ .setEncoding(info.getEncodingFormat())
+ .setChannelMask(info.getChannelCount())
+ .build();
+ AudioMixingRule.Builder mixingRuleBuilder = new AudioMixingRule.Builder();
+ for (int j = 0; j < mContextToBus.size(); j++) {
+ if (mContextToBus.valueAt(j) == busNumber) {
+ hasContext = true;
+ int contextNumber = mContextToBus.keyAt(j);
+ int[] usages = getUsagesForContext(contextNumber);
+ for (int usage : usages) {
+ mixingRuleBuilder.addRule(
+ new AudioAttributes.Builder().setUsage(usage).build(),
+ AudioMixingRule.RULE_MATCH_ATTRIBUTE_USAGE);
+ }
+ Log.i(CarLog.TAG_AUDIO, "Bus number: " + busNumber
+ + " contextNumber: " + contextNumber
+ + " sampleRate: " + info.getSampleRate()
+ + " channels: " + info.getChannelCount()
+ + " usages: " + Arrays.toString(usages));
+ }
+ }
+ if (hasContext) {
+ // It's a valid case that an audio output bus is defined in
+ // audio_policy_configuration and no context is assigned to it.
+ // In such case, do not build a policy mix with zero rules.
+ AudioMix audioMix = new AudioMix.Builder(mixingRuleBuilder.build())
+ .setFormat(mixFormat)
+ .setDevice(info.getAudioDeviceInfo())
+ .setRouteFlags(AudioMix.ROUTE_FLAG_RENDER)
+ .build();
+ builder.addMix(audioMix);
+ }
}
- @Override
- public void handleMessage(Message msg) {
- switch (msg.what) {
- case MSG_CONTEXT_CHANGE: {
- AudioContextChangeListener listener = (AudioContextChangeListener) msg.obj;
- int context = msg.arg1;
- int physicalStream = msg.arg2;
- listener.onContextChange(context, physicalStream);
- } break;
+ // 4th, attach the {@link AudioPolicyVolumeCallback}
+ builder.setAudioPolicyVolumeCallback(mAudioPolicyVolumeCallback);
+
+ return builder.build();
+ }
+
+ private int[] getUsagesForContext(int contextNumber) {
+ final List<Integer> usages = new ArrayList<>();
+ for (int i = 0; i < USAGE_TO_CONTEXT.size(); i++) {
+ if (USAGE_TO_CONTEXT.valueAt(i) == contextNumber) {
+ usages.add(USAGE_TO_CONTEXT.keyAt(i));
+ }
+ }
+ return usages.stream().mapToInt(i -> i).toArray();
+ }
+
+ @Override
+ public void setFadeTowardFront(float value) {
+ synchronized (mImplLock) {
+ enforcePermission(Car.PERMISSION_CAR_CONTROL_AUDIO_VOLUME);
+ final IAudioControl audioControlHal = getAudioControl();
+ if (audioControlHal != null) {
+ try {
+ audioControlHal.setFadeTowardFront(value);
+ } catch (RemoteException e) {
+ Log.e(CarLog.TAG_AUDIO, "setFadeTowardFront failed", e);
+ }
}
}
}
- private class CarAudioFocusChangeHandler extends Handler {
- private static final int MSG_FOCUS_CHANGE = 0;
- private static final int MSG_STREAM_STATE_CHANGE = 1;
- private static final int MSG_ANDROID_FOCUS_CHANGE = 2;
- private static final int MSG_FOCUS_RELEASE = 3;
-
- /** Focus release is always delayed this much to handle repeated acquire / release. */
- private static final long FOCUS_RELEASE_DELAY_MS = 500;
-
- private CarAudioFocusChangeHandler(Looper looper) {
- super(looper);
- }
-
- private void handleFocusChange() {
- cancelFocusReleaseRequest();
- Message msg = obtainMessage(MSG_FOCUS_CHANGE);
- sendMessage(msg);
- }
-
- private void handleStreamStateChange(int streamNumber, boolean streamActive) {
- cancelFocusReleaseRequest();
- removeMessages(MSG_STREAM_STATE_CHANGE);
- Message msg = obtainMessage(MSG_STREAM_STATE_CHANGE, streamNumber,
- streamActive ? 1 : 0);
- sendMessageDelayed(msg,
- streamActive ? NO_FOCUS_PLAY_WAIT_TIME_MS : FOCUS_RELEASE_DELAY_MS);
- }
-
- private void handleAndroidFocusChange() {
- cancelFocusReleaseRequest();
- Message msg = obtainMessage(MSG_ANDROID_FOCUS_CHANGE);
- sendMessage(msg);
- }
-
- private void handleFocusReleaseRequest() {
- if (DBG) {
- Log.d(TAG_FOCUS, "handleFocusReleaseRequest");
- }
- cancelFocusReleaseRequest();
- Message msg = obtainMessage(MSG_FOCUS_RELEASE);
- sendMessageDelayed(msg, FOCUS_RELEASE_DELAY_MS);
- }
-
- private void cancelFocusReleaseRequest() {
- removeMessages(MSG_FOCUS_RELEASE);
- }
-
- private void cancelAll() {
- removeMessages(MSG_FOCUS_CHANGE);
- removeMessages(MSG_STREAM_STATE_CHANGE);
- removeMessages(MSG_ANDROID_FOCUS_CHANGE);
- removeMessages(MSG_FOCUS_RELEASE);
- }
-
- @Override
- public void handleMessage(Message msg) {
- switch (msg.what) {
- case MSG_FOCUS_CHANGE:
- doHandleCarFocusChange();
- break;
- case MSG_STREAM_STATE_CHANGE:
- doHandleStreamStatusChange(msg.arg1, msg.arg2 == 1);
- break;
- case MSG_ANDROID_FOCUS_CHANGE:
- doHandleAndroidFocusChange(false /* triggeredByStreamChange */);
- break;
- case MSG_FOCUS_RELEASE:
- doHandleFocusRelease();
- break;
+ @Override
+ public void setBalanceTowardRight(float value) {
+ synchronized (mImplLock) {
+ enforcePermission(Car.PERMISSION_CAR_CONTROL_AUDIO_VOLUME);
+ final IAudioControl audioControlHal = getAudioControl();
+ if (audioControlHal != null) {
+ try {
+ audioControlHal.setBalanceTowardRight(value);
+ } catch (RemoteException e) {
+ Log.e(CarLog.TAG_AUDIO, "setBalanceTowardRight failed", e);
+ }
}
}
}
- /** Wrapper class for holding the current focus state from car. */
- private static class FocusState {
- public final int focusState;
- public final int streams;
- public final int externalFocus;
+ /**
+ * @return Array of accumulated device addresses, empty array if we found nothing
+ */
+ @Override
+ public @NonNull String[] getExternalSources() {
+ synchronized (mImplLock) {
+ enforcePermission(Car.PERMISSION_CAR_CONTROL_AUDIO_SETTINGS);
+ List<String> sourceAddresses = new ArrayList<>();
- private FocusState(int focusState, int streams, int externalFocus) {
- this.focusState = focusState;
- this.streams = streams;
- this.externalFocus = externalFocus;
- }
-
- @Override
- public boolean equals(Object o) {
- if (this == o) {
- return true;
+ AudioDeviceInfo[] devices = mAudioManager.getDevices(AudioManager.GET_DEVICES_INPUTS);
+ if (devices.length == 0) {
+ Log.w(CarLog.TAG_AUDIO, "getExternalSources, no input devices found.");
}
- if (!(o instanceof FocusState)) {
- return false;
+
+ // Collect the list of non-microphone input ports
+ for (AudioDeviceInfo info : devices) {
+ switch (info.getType()) {
+ // TODO: Can we trim this set down? Especially duplicates like FM vs FM_TUNER?
+ case AudioDeviceInfo.TYPE_FM:
+ case AudioDeviceInfo.TYPE_FM_TUNER:
+ case AudioDeviceInfo.TYPE_TV_TUNER:
+ case AudioDeviceInfo.TYPE_HDMI:
+ case AudioDeviceInfo.TYPE_AUX_LINE:
+ case AudioDeviceInfo.TYPE_LINE_ANALOG:
+ case AudioDeviceInfo.TYPE_LINE_DIGITAL:
+ case AudioDeviceInfo.TYPE_USB_ACCESSORY:
+ case AudioDeviceInfo.TYPE_USB_DEVICE:
+ case AudioDeviceInfo.TYPE_USB_HEADSET:
+ case AudioDeviceInfo.TYPE_IP:
+ case AudioDeviceInfo.TYPE_BUS:
+ String address = info.getAddress();
+ if (TextUtils.isEmpty(address)) {
+ Log.w(CarLog.TAG_AUDIO,
+ "Discarded device with empty address, type=" + info.getType());
+ } else {
+ sourceAddresses.add(address);
+ }
+ }
}
- FocusState that = (FocusState) o;
- return this.focusState == that.focusState && this.streams == that.streams &&
- this.externalFocus == that.externalFocus;
- }
- @Override
- public String toString() {
- return "FocusState, state:" + focusState +
- " streams:0x" + Integer.toHexString(streams) +
- " externalFocus:0x" + Integer.toHexString(externalFocus);
+ return sourceAddresses.toArray(new String[sourceAddresses.size()]);
}
-
- public static FocusState create(int focusState, int streams, int externalAudios) {
- return new FocusState(focusState, streams, externalAudios);
- }
-
- public static FocusState create(int[] state) {
- return create(state[AudioHalService.FOCUS_STATE_ARRAY_INDEX_STATE],
- state[AudioHalService.FOCUS_STATE_ARRAY_INDEX_STREAMS],
- state[AudioHalService.FOCUS_STATE_ARRAY_INDEX_EXTERNAL_FOCUS]);
- }
-
- public static FocusState STATE_LOSS =
- new FocusState(AudioHalService.VEHICLE_AUDIO_FOCUS_STATE_LOSS, 0, 0);
}
- /** Wrapper class for holding the focus requested to car. */
- private static class FocusRequest {
- public final int focusRequest;
- public final int streams;
- public final int externalFocus;
-
- private FocusRequest(int focusRequest, int streams, int externalFocus) {
- this.focusRequest = focusRequest;
- this.streams = streams;
- this.externalFocus = externalFocus;
+ @Override
+ public CarAudioPatchHandle createAudioPatch(String sourceAddress,
+ @AudioAttributes.AttributeUsage int usage, int gainInMillibels) {
+ synchronized (mImplLock) {
+ enforcePermission(Car.PERMISSION_CAR_CONTROL_AUDIO_SETTINGS);
+ return createAudioPatchLocked(sourceAddress, usage, gainInMillibels);
}
-
- @Override
- public boolean equals(Object o) {
- if (this == o) {
- return true;
- }
- if (!(o instanceof FocusRequest)) {
- return false;
- }
- FocusRequest that = (FocusRequest) o;
- return this.focusRequest == that.focusRequest && this.streams == that.streams &&
- this.externalFocus == that.externalFocus;
- }
-
- @Override
- public String toString() {
- return "FocusRequest, request:" + focusRequest +
- " streams:0x" + Integer.toHexString(streams) +
- " externalFocus:0x" + Integer.toHexString(externalFocus);
- }
-
- public static FocusRequest create(int focusRequest, int streams, int externalFocus) {
- switch (focusRequest) {
- case AudioHalService.VEHICLE_AUDIO_FOCUS_REQUEST_RELEASE:
- return STATE_RELEASE;
- }
- return new FocusRequest(focusRequest, streams, externalFocus);
- }
-
- public static FocusRequest STATE_RELEASE =
- new FocusRequest(AudioHalService.VEHICLE_AUDIO_FOCUS_REQUEST_RELEASE, 0, 0);
}
- private static class ExtSourceInfo {
-
- public String source;
- public int context;
-
- public ExtSourceInfo set(String source, int context) {
- this.source = source;
- this.context = context;
- return this;
+ @Override
+ public void releaseAudioPatch(CarAudioPatchHandle carPatch) {
+ synchronized (mImplLock) {
+ enforcePermission(Car.PERMISSION_CAR_CONTROL_AUDIO_SETTINGS);
+ releaseAudioPatchLocked(carPatch);
}
}
+
+ private CarAudioPatchHandle createAudioPatchLocked(String sourceAddress,
+ @AudioAttributes.AttributeUsage int usage, int gainInMillibels) {
+ // Find the named source port
+ AudioDeviceInfo sourcePortInfo = null;
+ AudioDeviceInfo[] deviceInfos = mAudioManager.getDevices(AudioManager.GET_DEVICES_INPUTS);
+ for (AudioDeviceInfo info : deviceInfos) {
+ if (sourceAddress.equals(info.getAddress())) {
+ // This is the one for which we're looking
+ sourcePortInfo = info;
+ break;
+ }
+ }
+ Preconditions.checkNotNull(sourcePortInfo,
+ "Specified source is not available: " + sourceAddress);
+
+ // Find the output port associated with the given carUsage
+ AudioDevicePort sinkPort = Preconditions.checkNotNull(getAudioPort(usage),
+ "Sink not available for usage: " + AudioAttributes.usageToString(usage));
+
+ // {@link android.media.AudioPort#activeConfig()} is valid for mixer port only,
+ // since audio framework has no clue what's active on the device ports.
+ // Therefore we construct an empty / default configuration here, which the audio HAL
+ // implementation should ignore.
+ AudioPortConfig sinkConfig = sinkPort.buildConfig(0,
+ AudioFormat.CHANNEL_OUT_DEFAULT, AudioFormat.ENCODING_DEFAULT, null);
+ Log.d(CarLog.TAG_AUDIO, "createAudioPatch sinkConfig: " + sinkConfig);
+
+ // Configure the source port to match the output port except for a gain adjustment
+ final CarAudioDeviceInfo helper = new CarAudioDeviceInfo(sourcePortInfo);
+ AudioGain audioGain = Preconditions.checkNotNull(helper.getAudioGain(),
+ "Gain controller not available for source port");
+
+ // size of gain values is 1 in MODE_JOINT
+ AudioGainConfig audioGainConfig = audioGain.buildConfig(AudioGain.MODE_JOINT,
+ audioGain.channelMask(), new int[] { gainInMillibels }, 0);
+ // Construct an empty / default configuration excepts gain config here and it's up to the
+ // audio HAL how to interpret this configuration, which the audio HAL
+ // implementation should ignore.
+ AudioPortConfig sourceConfig = sourcePortInfo.getPort().buildConfig(0,
+ AudioFormat.CHANNEL_IN_DEFAULT, AudioFormat.ENCODING_DEFAULT, audioGainConfig);
+
+ // Create an audioPatch to connect the two ports
+ AudioPatch[] patch = new AudioPatch[] { null };
+ int result = AudioManager.createAudioPatch(patch,
+ new AudioPortConfig[] { sourceConfig },
+ new AudioPortConfig[] { sinkConfig });
+ if (result != AudioManager.SUCCESS) {
+ throw new RuntimeException("createAudioPatch failed with code " + result);
+ }
+
+ Preconditions.checkNotNull(patch[0],
+ "createAudioPatch didn't provide expected single handle");
+ Log.d(CarLog.TAG_AUDIO, "Audio patch created: " + patch[0]);
+ return new CarAudioPatchHandle(patch[0]);
+ }
+
+ private void releaseAudioPatchLocked(CarAudioPatchHandle carPatch) {
+ // NOTE: AudioPolicyService::removeNotificationClient will take care of this automatically
+ // if the client that created a patch quits.
+
+ // FIXME {@link AudioManager#listAudioPatches(ArrayList)} returns old generation of
+ // audio patches after creation
+ ArrayList<AudioPatch> patches = new ArrayList<>();
+ int result = AudioSystem.listAudioPatches(patches, new int[1]);
+ if (result != AudioManager.SUCCESS) {
+ throw new RuntimeException("listAudioPatches failed with code " + result);
+ }
+
+ // Look for a patch that matches the provided user side handle
+ for (AudioPatch patch : patches) {
+ if (carPatch.represents(patch)) {
+ // Found it!
+ result = AudioManager.releaseAudioPatch(patch);
+ if (result != AudioManager.SUCCESS) {
+ throw new RuntimeException("releaseAudioPatch failed with code " + result);
+ }
+ return;
+ }
+ }
+
+ // If we didn't find a match, then something went awry, but it's probably not fatal...
+ Log.e(CarLog.TAG_AUDIO, "releaseAudioPatch found no match for " + carPatch);
+ }
+
+ @Override
+ public int getVolumeGroupCount() {
+ synchronized (mImplLock) {
+ enforcePermission(Car.PERMISSION_CAR_CONTROL_AUDIO_VOLUME);
+
+ // For legacy stream type based volume control
+ if (!mUseDynamicRouting) return STREAM_TYPES.length;
+
+ return mCarVolumeGroups == null ? 0 : mCarVolumeGroups.length;
+ }
+ }
+
+ @Override
+ public int getVolumeGroupIdForUsage(@AudioAttributes.AttributeUsage int usage) {
+ synchronized (mImplLock) {
+ enforcePermission(Car.PERMISSION_CAR_CONTROL_AUDIO_VOLUME);
+
+ if (mCarVolumeGroups == null) {
+ return -1;
+ }
+
+ for (int i = 0; i < mCarVolumeGroups.length; i++) {
+ int[] contexts = mCarVolumeGroups[i].getContexts();
+ for (int context : contexts) {
+ if (USAGE_TO_CONTEXT.get(usage) == context) {
+ return i;
+ }
+ }
+ }
+ return -1;
+ }
+ }
+
+ @Override
+ public @NonNull int[] getUsagesForVolumeGroupId(int groupId) {
+ synchronized (mImplLock) {
+ enforcePermission(Car.PERMISSION_CAR_CONTROL_AUDIO_VOLUME);
+
+ // For legacy stream type based volume control
+ if (!mUseDynamicRouting) {
+ return new int[] { STREAM_TYPE_USAGES[groupId] };
+ }
+
+ CarVolumeGroup group = getCarVolumeGroup(groupId);
+ Set<Integer> contexts =
+ Arrays.stream(group.getContexts()).boxed().collect(Collectors.toSet());
+ final List<Integer> usages = new ArrayList<>();
+ for (int i = 0; i < USAGE_TO_CONTEXT.size(); i++) {
+ if (contexts.contains(USAGE_TO_CONTEXT.valueAt(i))) {
+ usages.add(USAGE_TO_CONTEXT.keyAt(i));
+ }
+ }
+ return usages.stream().mapToInt(i -> i).toArray();
+ }
+ }
+
+ /**
+ * See {@link android.car.media.CarAudioManager#registerVolumeCallback(IBinder)}
+ */
+ @Override
+ public void registerVolumeCallback(@NonNull IBinder binder) {
+ synchronized (mImplLock) {
+ enforcePermission(Car.PERMISSION_CAR_CONTROL_AUDIO_VOLUME);
+
+ mVolumeCallbackContainer.addBinder(ICarVolumeCallback.Stub.asInterface(binder));
+ }
+ }
+
+ /**
+ * See {@link android.car.media.CarAudioManager#unregisterVolumeCallback(IBinder)}
+ */
+ @Override
+ public void unregisterVolumeCallback(@NonNull IBinder binder) {
+ synchronized (mImplLock) {
+ enforcePermission(Car.PERMISSION_CAR_CONTROL_AUDIO_VOLUME);
+
+ mVolumeCallbackContainer.removeBinder(ICarVolumeCallback.Stub.asInterface(binder));
+ }
+ }
+
+ private void enforcePermission(String permissionName) {
+ if (mContext.checkCallingOrSelfPermission(permissionName)
+ != PackageManager.PERMISSION_GRANTED) {
+ throw new SecurityException("requires permission " + permissionName);
+ }
+ }
+
+ /**
+ * @return {@link AudioDevicePort} that handles the given car audio usage.
+ * Multiple usages may share one {@link AudioDevicePort}
+ */
+ private @Nullable AudioDevicePort getAudioPort(@AudioAttributes.AttributeUsage int usage) {
+ final int groupId = getVolumeGroupIdForUsage(usage);
+ final CarVolumeGroup group = Preconditions.checkNotNull(mCarVolumeGroups[groupId],
+ "Can not find CarVolumeGroup by usage: "
+ + AudioAttributes.usageToString(usage));
+ return group.getAudioDevicePortForContext(USAGE_TO_CONTEXT.get(usage));
+ }
+
+ /**
+ * @return The suggested {@link AudioAttributes} usage to which the volume key events apply
+ */
+ private @AudioAttributes.AttributeUsage int getSuggestedAudioUsage() {
+ int callState = mTelephonyManager.getCallState();
+ if (callState == TelephonyManager.CALL_STATE_RINGING) {
+ return AudioAttributes.USAGE_NOTIFICATION_RINGTONE;
+ } else if (callState == TelephonyManager.CALL_STATE_OFFHOOK) {
+ return AudioAttributes.USAGE_VOICE_COMMUNICATION;
+ } else {
+ List<AudioPlaybackConfiguration> playbacks = mAudioManager
+ .getActivePlaybackConfigurations()
+ .stream()
+ .filter(AudioPlaybackConfiguration::isActive)
+ .collect(Collectors.toList());
+ if (!playbacks.isEmpty()) {
+ // Get audio usage from active playbacks if there is any, last one if multiple
+ return playbacks.get(playbacks.size() - 1).getAudioAttributes().getUsage();
+ } else {
+ // TODO(b/72695246): Otherwise, get audio usage from foreground activity/window
+ return DEFAULT_AUDIO_USAGE;
+ }
+ }
+ }
+
+ /**
+ * Gets volume group by a given legacy stream type
+ * @param streamType Legacy stream type such as {@link AudioManager#STREAM_MUSIC}
+ * @return volume group id mapped from stream type
+ */
+ private int getVolumeGroupIdForStreamType(int streamType) {
+ int groupId = -1;
+ for (int i = 0; i < STREAM_TYPES.length; i++) {
+ if (streamType == STREAM_TYPES[i]) {
+ groupId = i;
+ break;
+ }
+ }
+ return groupId;
+ }
+
+ @Nullable
+ private static IAudioControl getAudioControl() {
+ try {
+ return IAudioControl.getService();
+ } catch (RemoteException e) {
+ Log.e(CarLog.TAG_AUDIO, "Failed to get IAudioControl service", e);
+ } catch (NoSuchElementException e) {
+ Log.e(CarLog.TAG_AUDIO, "IAudioControl service not registered yet");
+ }
+ return null;
+ }
}
diff --git a/service/src/com/android/car/CarBluetoothService.java b/service/src/com/android/car/CarBluetoothService.java
index 33d19c5..d36db43 100644
--- a/service/src/com/android/car/CarBluetoothService.java
+++ b/service/src/com/android/car/CarBluetoothService.java
@@ -24,6 +24,10 @@
import static android.car.settings.CarSettings.Secure
.KEY_BLUETOOTH_AUTOCONNECT_MUSIC_DEVICE_PRIORITY_1;
import static android.car.settings.CarSettings.Secure
+ .KEY_BLUETOOTH_AUTOCONNECT_NETWORK_DEVICE_PRIORITY_0;
+import static android.car.settings.CarSettings.Secure
+ .KEY_BLUETOOTH_AUTOCONNECT_NETWORK_DEVICE_PRIORITY_1;
+import static android.car.settings.CarSettings.Secure
.KEY_BLUETOOTH_AUTOCONNECT_PHONE_DEVICE_PRIORITY_0;
import static android.car.settings.CarSettings.Secure
.KEY_BLUETOOTH_AUTOCONNECT_PHONE_DEVICE_PRIORITY_1;
@@ -55,11 +59,11 @@
private final BluetoothDeviceConnectionPolicy mBluetoothDeviceConnectionPolicy;
private static final boolean DBG = false;
- public CarBluetoothService(Context context, CarCabinService carCabinService,
- CarSensorService carSensorService, PerUserCarServiceHelper userSwitchService) {
+ public CarBluetoothService(Context context, CarPropertyService carPropertyService,
+ PerUserCarServiceHelper userSwitchService, CarUxRestrictionsManagerService uxrService) {
mContext = context;
mBluetoothDeviceConnectionPolicy = BluetoothDeviceConnectionPolicy.create(mContext,
- carCabinService, carSensorService, userSwitchService, this);
+ carPropertyService, userSwitchService, uxrService, this);
}
@Override
@@ -185,6 +189,13 @@
? KEY_BLUETOOTH_AUTOCONNECT_MESSAGING_DEVICE_PRIORITY_0
: KEY_BLUETOOTH_AUTOCONNECT_MESSAGING_DEVICE_PRIORITY_1;
break;
+ case BluetoothProfile.PAN:
+ keyToQuery = (priorityToCheck
+ == CarBluetoothManager.BLUETOOTH_DEVICE_CONNECTION_PRIORITY_0)
+ ? KEY_BLUETOOTH_AUTOCONNECT_NETWORK_DEVICE_PRIORITY_0
+ : KEY_BLUETOOTH_AUTOCONNECT_NETWORK_DEVICE_PRIORITY_1;
+ break;
+
default:
if (DBG) {
Log.d(TAG, "Unknown Bluetooth profile");
@@ -232,6 +243,13 @@
? KEY_BLUETOOTH_AUTOCONNECT_PHONE_DEVICE_PRIORITY_0
: KEY_BLUETOOTH_AUTOCONNECT_PHONE_DEVICE_PRIORITY_1;
break;
+ case BluetoothProfile.PAN:
+ keyToLookup = (priority
+ == CarBluetoothManager.BLUETOOTH_DEVICE_CONNECTION_PRIORITY_0)
+ ? KEY_BLUETOOTH_AUTOCONNECT_NETWORK_DEVICE_PRIORITY_0
+ : KEY_BLUETOOTH_AUTOCONNECT_NETWORK_DEVICE_PRIORITY_1;
+ break;
+
default:
Log.e(TAG, "Unsupported Bluetooth profile to set priority to");
break;
diff --git a/service/src/com/android/car/CarBluetoothUserService.java b/service/src/com/android/car/CarBluetoothUserService.java
index 55365a0..1b94742 100644
--- a/service/src/com/android/car/CarBluetoothUserService.java
+++ b/service/src/com/android/car/CarBluetoothUserService.java
@@ -23,6 +23,7 @@
import android.bluetooth.BluetoothHeadsetClient;
import android.bluetooth.BluetoothMapClient;
import android.bluetooth.BluetoothPbapClient;
+import android.bluetooth.BluetoothPan;
import android.car.ICarBluetoothUserService;
import android.util.Log;
@@ -40,6 +41,7 @@
private BluetoothHeadsetClient mBluetoothHeadsetClient = null;
private BluetoothPbapClient mBluetoothPbapClient = null;
private BluetoothMapClient mBluetoothMapClient = null;
+ private BluetoothPan mBluetoothPan = null;
private List<Integer> mProfilesToConnect;
public CarBluetoothUserService(PerUserCarService service) {
@@ -49,7 +51,8 @@
BluetoothProfile.HEADSET_CLIENT,
BluetoothProfile.PBAP_CLIENT,
BluetoothProfile.A2DP_SINK,
- BluetoothProfile.MAP_CLIENT);
+ BluetoothProfile.MAP_CLIENT,
+ BluetoothProfile.PAN);
}
/**
@@ -95,6 +98,9 @@
if (mBluetoothMapClient != null) {
mBluetoothAdapter.closeProfileProxy(BluetoothProfile.MAP_CLIENT, mBluetoothMapClient);
}
+ if (mBluetoothPan != null) {
+ mBluetoothAdapter.closeProfileProxy(BluetoothProfile.PAN, mBluetoothPan);
+ }
}
/**
@@ -126,6 +132,11 @@
return true;
}
break;
+ case BluetoothProfile.PAN:
+ if (mBluetoothPan != null) {
+ return true;
+ }
+ break;
}
return false;
}
@@ -156,6 +167,9 @@
mBluetoothPbapClient.connect(device);
break;
+ case BluetoothProfile.PAN:
+ mBluetoothPan.connect(device);
+
default:
Log.d(TAG, "Unknown profile");
break;
@@ -219,6 +233,10 @@
mBluetoothMapClient = (BluetoothMapClient) proxy;
break;
+ case BluetoothProfile.PAN:
+ mBluetoothPan = (BluetoothPan) proxy;
+ break;
+
default:
if (DBG) {
Log.d(TAG, "Unhandled profile");
@@ -248,6 +266,10 @@
mBluetoothMapClient = null;
break;
+ case BluetoothProfile.PAN:
+ mBluetoothPan = null;
+ break;
+
default:
if (DBG) {
Log.d(TAG, "Unhandled profile");
diff --git a/service/src/com/android/car/CarCabinService.java b/service/src/com/android/car/CarCabinService.java
deleted file mode 100644
index cdf8635..0000000
--- a/service/src/com/android/car/CarCabinService.java
+++ /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.
- */
-
-package com.android.car;
-
-import android.car.Car;
-import android.content.Context;
-
-import com.android.car.hal.CabinHalService;
-
-public class CarCabinService extends CarPropertyServiceBase {
- private final static boolean DBG = false;
-
- public CarCabinService(Context context, CabinHalService cabinHal) {
- super(context, cabinHal, Car.PERMISSION_CAR_CABIN, DBG, CarLog.TAG_CABIN);
- }
-}
diff --git a/service/src/com/android/car/CarConfigurationService.java b/service/src/com/android/car/CarConfigurationService.java
new file mode 100644
index 0000000..3381aed
--- /dev/null
+++ b/service/src/com/android/car/CarConfigurationService.java
@@ -0,0 +1,183 @@
+/*
+ * 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;
+
+import android.annotation.Nullable;
+import android.annotation.RawRes;
+import android.car.settings.ICarConfigurationManager;
+import android.car.settings.SpeedBumpConfiguration;
+import android.content.Context;
+import android.util.Log;
+
+import com.android.internal.annotations.VisibleForTesting;
+
+import org.json.JSONException;
+import org.json.JSONObject;
+
+import java.io.PrintWriter;
+
+/**
+ * A service that will look at a default JSON configuration file on the system and parses out its
+ * results.
+ *
+ * <p>This service will look for the JSON file that is mapped to {@code R.raw.car_config}. If this
+ * value does not exist or is malformed, then this service will not fail; instead, it returns
+ * default values for various configurations.
+ */
+public class CarConfigurationService extends ICarConfigurationManager.Stub
+ implements CarServiceBase {
+ private static final String TAG = "CarConfigurationService";
+
+ // Keys for accessing data in the parsed JSON related to SpeedBump.
+ @VisibleForTesting
+ static final String SPEED_BUMP_CONFIG_KEY = "SpeedBump";
+ @VisibleForTesting
+ static final String SPEED_BUMP_ACQUIRED_PERMITS_PER_SECOND_KEY =
+ "acquiredPermitsPerSecond";
+ @VisibleForTesting
+ static final String SPEED_BUMP_MAX_PERMIT_POOL_KEY = "maxPermitPool";
+ @VisibleForTesting
+ static final String SPEED_BUMP_PERMIT_FILL_DELAY_KEY = "permitFillDelay";
+
+ // Default values for speed bump configuration.
+ @VisibleForTesting
+ static final double DEFAULT_SPEED_BUMP_ACQUIRED_PERMITS_PER_SECOND = 0.5d;
+ @VisibleForTesting
+ static final double DEFAULT_SPEED_BUMP_MAX_PERMIT_POOL = 5d;
+ @VisibleForTesting
+ static final long DEFAULT_SPEED_BUMP_PERMIT_FILL_DELAY = 600L;
+
+ private final Context mContext;
+ private final JsonReader mJsonReader;
+
+ @VisibleForTesting
+ @Nullable
+ JSONObject mConfigFile;
+
+ @Nullable
+ private SpeedBumpConfiguration mSpeedBumpConfiguration;
+
+ /**
+ * An interface that abstracts away the parsing of a JSON file. This interface allows the
+ * JSON file to be mocked away for testing.
+ */
+ @VisibleForTesting
+ interface JsonReader {
+ /**
+ * Returns the contents of the JSON file that is pointed to by the given {@code resId} as
+ * a string.
+ *
+ * @param context The current Context.
+ * @param resId The resource id of the JSON file.
+ * @return A string representation of the file or {@code null} if an error occurred.
+ */
+ @Nullable
+ String jsonFileToString(Context context, @RawRes int resId);
+ }
+
+ CarConfigurationService(Context context, JsonReader reader) {
+ mContext = context;
+ mJsonReader = reader;
+ }
+
+ /**
+ * Returns the configuration values for speed bump that is found in the configuration JSON on
+ * the system. If there was an error reading this JSON or the JSON did not contain
+ * speed bump configuration, then default values will be returned. This method does not return
+ * {@code null}.
+ */
+ @Override
+ public SpeedBumpConfiguration getSpeedBumpConfiguration() {
+ if (mSpeedBumpConfiguration == null) {
+ return getDefaultSpeedBumpConfiguration();
+ }
+ return mSpeedBumpConfiguration;
+ }
+
+ @Override
+ public synchronized void init() {
+ String jsonString = mJsonReader.jsonFileToString(mContext, R.raw.car_config);
+ if (jsonString != null) {
+ try {
+ mConfigFile = new JSONObject(jsonString);
+ } catch (JSONException e) {
+ Log.e(TAG, "Error reading JSON file", e);
+ }
+ }
+
+ mSpeedBumpConfiguration = createSpeedBumpConfiguration();
+ }
+
+ @Override
+ public synchronized void release() {
+ mConfigFile = null;
+ mSpeedBumpConfiguration = null;
+ }
+
+ @Override
+ public void dump(PrintWriter writer) {
+ writer.println("Config value initialized: " + (mConfigFile != null));
+ if (mConfigFile != null) {
+ try {
+ writer.println("Config: " + mConfigFile.toString(/* indentSpaces= */ 2));
+ } catch (JSONException e) {
+ Log.e(TAG, "Error printing JSON config", e);
+ writer.println("Config: " + mConfigFile);
+ }
+ }
+
+ writer.println("SpeedBumpConfig initialized: " + (mSpeedBumpConfiguration != null));
+ if (mSpeedBumpConfiguration != null) {
+ writer.println("SpeedBumpConfig: " + mSpeedBumpConfiguration);
+ }
+ }
+
+ /**
+ * Reads the configuration for speed bump off of the parsed JSON stored in {@link #mConfigFile}.
+ * If {@code mConfigFile} is {@code null} or a configuration does not exist for speed bump,
+ * then return the default configuration created by {@link #getDefaultSpeedBumpConfiguration()}.
+ */
+ private SpeedBumpConfiguration createSpeedBumpConfiguration() {
+ if (mConfigFile == null) {
+ return getDefaultSpeedBumpConfiguration();
+ }
+
+ try {
+ JSONObject speedBumpJson = mConfigFile.getJSONObject(SPEED_BUMP_CONFIG_KEY);
+
+ if (speedBumpJson != null) {
+ return new SpeedBumpConfiguration(
+ speedBumpJson.getDouble(SPEED_BUMP_ACQUIRED_PERMITS_PER_SECOND_KEY),
+ speedBumpJson.getDouble(SPEED_BUMP_MAX_PERMIT_POOL_KEY),
+ speedBumpJson.getLong(SPEED_BUMP_PERMIT_FILL_DELAY_KEY));
+ }
+ } catch (JSONException e) {
+ Log.e(TAG, "Error parsing SpeedBumpConfiguration; returning default values", e);
+ }
+
+ // If an error is encountered or the JSON does not contain an entry for speed bump
+ // configuration, then return default values.
+ return getDefaultSpeedBumpConfiguration();
+ }
+
+ private SpeedBumpConfiguration getDefaultSpeedBumpConfiguration() {
+ return new SpeedBumpConfiguration(
+ DEFAULT_SPEED_BUMP_ACQUIRED_PERMITS_PER_SECOND,
+ DEFAULT_SPEED_BUMP_MAX_PERMIT_POOL,
+ DEFAULT_SPEED_BUMP_PERMIT_FILL_DELAY);
+ }
+}
diff --git a/service/src/com/android/car/CarDiagnosticService.java b/service/src/com/android/car/CarDiagnosticService.java
index ff0b7a9..e23f9a1 100644
--- a/service/src/com/android/car/CarDiagnosticService.java
+++ b/service/src/com/android/car/CarDiagnosticService.java
@@ -411,6 +411,13 @@
diagnosticCapabilities.isFreezeFrameSupported();
}
+ public boolean isSelectiveClearFreezeFramesSupported() {
+ DiagnosticCapabilities diagnosticCapabilities =
+ getDiagnosticHal().getDiagnosticCapabilities();
+ return isClearFreezeFramesSupported() &&
+ diagnosticCapabilities.isSelectiveClearFreezeFramesSupported();
+ }
+
// ICarDiagnostic implementations
@Override
@@ -441,14 +448,18 @@
@Override
public boolean clearFreezeFrames(long... timestamps) {
mDiagnosticClearPermission.assertGranted();
- if (mDiagnosticHal.getDiagnosticCapabilities().isFreezeFrameClearSupported()) {
- mFreezeFrameDiagnosticRecords.lock();
- mDiagnosticHal.clearFreezeFrames(timestamps);
- mFreezeFrameDiagnosticRecords.clearEvents();
- mFreezeFrameDiagnosticRecords.unlock();
- return true;
+ if (!isClearFreezeFramesSupported())
+ return false;
+ if (timestamps != null && timestamps.length != 0) {
+ if (!isSelectiveClearFreezeFramesSupported()) {
+ return false;
+ }
}
- return false;
+ mFreezeFrameDiagnosticRecords.lock();
+ mDiagnosticHal.clearFreezeFrames(timestamps);
+ mFreezeFrameDiagnosticRecords.clearEvents();
+ mFreezeFrameDiagnosticRecords.unlock();
+ return true;
}
/**
@@ -458,6 +469,7 @@
* @param listener
* @return null if not found.
*/
+ @GuardedBy("mDiagnosticLock")
private CarDiagnosticService.DiagnosticClient findDiagnosticClientLocked(
ICarDiagnosticEventListener listener) {
IBinder binder = listener.asBinder();
diff --git a/service/src/com/android/car/CarDrivingStateService.java b/service/src/com/android/car/CarDrivingStateService.java
new file mode 100644
index 0000000..bc0fbc1
--- /dev/null
+++ b/service/src/com/android/car/CarDrivingStateService.java
@@ -0,0 +1,536 @@
+/*
+ * 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;
+
+import android.annotation.Nullable;
+import android.car.VehicleAreaType;
+import android.car.drivingstate.CarDrivingStateEvent;
+import android.car.drivingstate.CarDrivingStateEvent.CarDrivingState;
+import android.car.drivingstate.ICarDrivingState;
+import android.car.drivingstate.ICarDrivingStateChangeListener;
+import android.car.hardware.CarPropertyConfig;
+import android.car.hardware.CarPropertyValue;
+import android.car.hardware.property.CarPropertyEvent;
+import android.car.hardware.property.ICarPropertyEventListener;
+import android.content.Context;
+import android.hardware.automotive.vehicle.V2_0.VehicleGear;
+import android.hardware.automotive.vehicle.V2_0.VehicleProperty;
+import android.os.IBinder;
+import android.os.RemoteException;
+import android.os.SystemClock;
+import android.util.Log;
+
+import java.io.PrintWriter;
+import java.util.ArrayList;
+import java.util.LinkedList;
+import java.util.List;
+
+/**
+ * A service that infers the current driving state of the vehicle. It computes the driving state
+ * from listening to relevant properties from {@link CarPropertyService}
+ */
+public class CarDrivingStateService extends ICarDrivingState.Stub implements CarServiceBase {
+ private static final String TAG = "CarDrivingState";
+ private static final boolean DBG = false;
+ private static final int MAX_TRANSITION_LOG_SIZE = 20;
+ private static final int PROPERTY_UPDATE_RATE = 5; // Update rate in Hz
+ private static final int NOT_RECEIVED = -1;
+ private final Context mContext;
+ private CarPropertyService mPropertyService;
+ // List of clients listening to driving state events.
+ private final List<DrivingStateClient> mDrivingStateClients = new ArrayList<>();
+ // Array of properties that the service needs to listen to from CarPropertyService for deriving
+ // the driving state.
+ private static final int[] REQUIRED_PROPERTIES = {
+ VehicleProperty.PERF_VEHICLE_SPEED,
+ VehicleProperty.GEAR_SELECTION,
+ VehicleProperty.PARKING_BRAKE_ON};
+ private CarDrivingStateEvent mCurrentDrivingState;
+ // For dumpsys logging
+ private final LinkedList<Utils.TransitionLog> mTransitionLogs = new LinkedList<>();
+ private int mLastGear;
+ private long mLastGearTimestamp = NOT_RECEIVED;
+ private float mLastSpeed;
+ private long mLastSpeedTimestamp = NOT_RECEIVED;
+ private boolean mLastParkingBrakeState;
+ private long mLastParkingBrakeTimestamp = NOT_RECEIVED;
+ private List<Integer> mSupportedGears;
+
+ public CarDrivingStateService(Context context, CarPropertyService propertyService) {
+ mContext = context;
+ mPropertyService = propertyService;
+ mCurrentDrivingState = createDrivingStateEvent(CarDrivingStateEvent.DRIVING_STATE_UNKNOWN);
+ }
+
+ @Override
+ public synchronized void init() {
+ if (!checkPropertySupport()) {
+ Log.e(TAG, "init failure. Driving state will always be fully restrictive");
+ return;
+ }
+ subscribeToProperties();
+ mCurrentDrivingState = createDrivingStateEvent(inferDrivingStateLocked());
+ addTransitionLog(TAG + " Boot", CarDrivingStateEvent.DRIVING_STATE_UNKNOWN,
+ mCurrentDrivingState.eventValue, mCurrentDrivingState.timeStamp);
+ }
+
+ @Override
+ public synchronized void release() {
+ for (int property : REQUIRED_PROPERTIES) {
+ mPropertyService.unregisterListener(property, mICarPropertyEventListener);
+ }
+ for (DrivingStateClient client : mDrivingStateClients) {
+ client.listenerBinder.unlinkToDeath(client, 0);
+ }
+ mDrivingStateClients.clear();
+ mCurrentDrivingState = createDrivingStateEvent(CarDrivingStateEvent.DRIVING_STATE_UNKNOWN);
+ }
+
+ /**
+ * Checks if the {@link CarPropertyService} supports the required properties.
+ *
+ * @return {@code true} if supported, {@code false} if not
+ */
+ private synchronized boolean checkPropertySupport() {
+ List<CarPropertyConfig> configs = mPropertyService.getPropertyList();
+ for (int propertyId : REQUIRED_PROPERTIES) {
+ boolean found = false;
+ for (CarPropertyConfig config : configs) {
+ if (config.getPropertyId() == propertyId) {
+ found = true;
+ break;
+ }
+ }
+ if (!found) {
+ Log.e(TAG, "Required property not supported: " + propertyId);
+ return false;
+ }
+ }
+ return true;
+ }
+
+ /**
+ * Subscribe to the {@link CarPropertyService} for required sensors.
+ */
+ private synchronized void subscribeToProperties() {
+ for (int propertyId : REQUIRED_PROPERTIES) {
+ mPropertyService.registerListener(propertyId, PROPERTY_UPDATE_RATE,
+ mICarPropertyEventListener);
+ }
+
+ }
+
+ // Binder methods
+
+ /**
+ * Register a {@link ICarDrivingStateChangeListener} to be notified for changes to the driving
+ * state.
+ *
+ * @param listener {@link ICarDrivingStateChangeListener}
+ */
+ @Override
+ public synchronized void registerDrivingStateChangeListener(
+ ICarDrivingStateChangeListener listener) {
+ if (listener == null) {
+ if (DBG) {
+ Log.e(TAG, "registerDrivingStateChangeListener(): listener null");
+ }
+ throw new IllegalArgumentException("Listener is null");
+ }
+ // If a new client is registering, create a new DrivingStateClient and add it to the list
+ // of listening clients.
+ DrivingStateClient client = findDrivingStateClientLocked(listener);
+ if (client == null) {
+ client = new DrivingStateClient(listener);
+ try {
+ listener.asBinder().linkToDeath(client, 0);
+ } catch (RemoteException e) {
+ Log.e(TAG, "Cannot link death recipient to binder " + e);
+ return;
+ }
+ mDrivingStateClients.add(client);
+ }
+ }
+
+ /**
+ * Iterates through the list of registered Driving State Change clients -
+ * {@link DrivingStateClient} and finds if the given client is already registered.
+ *
+ * @param listener Listener to look for.
+ * @return the {@link DrivingStateClient} if found, null if not
+ */
+ @Nullable
+ private DrivingStateClient findDrivingStateClientLocked(
+ ICarDrivingStateChangeListener listener) {
+ IBinder binder = listener.asBinder();
+ // Find the listener by comparing the binder object they host.
+ for (DrivingStateClient client : mDrivingStateClients) {
+ if (client.isHoldingBinder(binder)) {
+ return client;
+ }
+ }
+ return null;
+ }
+
+ /**
+ * Unregister the given Driving State Change listener
+ *
+ * @param listener client to unregister
+ */
+ @Override
+ public synchronized void unregisterDrivingStateChangeListener(
+ ICarDrivingStateChangeListener listener) {
+ if (listener == null) {
+ Log.e(TAG, "unregisterDrivingStateChangeListener(): listener null");
+ throw new IllegalArgumentException("Listener is null");
+ }
+
+ DrivingStateClient client = findDrivingStateClientLocked(listener);
+ if (client == null) {
+ Log.e(TAG, "unregisterDrivingStateChangeListener(): listener was not previously "
+ + "registered");
+ return;
+ }
+ listener.asBinder().unlinkToDeath(client, 0);
+ mDrivingStateClients.remove(client);
+ }
+
+ /**
+ * Gets the current driving state
+ *
+ * @return {@link CarDrivingStateEvent} for the given event type
+ */
+ @Override
+ @Nullable
+ public synchronized CarDrivingStateEvent getCurrentDrivingState() {
+ return mCurrentDrivingState;
+ }
+
+ /**
+ * Class that holds onto client related information - listener interface, process that hosts the
+ * binder object etc.
+ * <p>
+ * It also registers for death notifications of the host.
+ */
+ private class DrivingStateClient implements IBinder.DeathRecipient {
+ private final IBinder listenerBinder;
+ private final ICarDrivingStateChangeListener listener;
+
+ public DrivingStateClient(ICarDrivingStateChangeListener l) {
+ listener = l;
+ listenerBinder = l.asBinder();
+ }
+
+ @Override
+ public void binderDied() {
+ if (DBG) {
+ Log.d(TAG, "Binder died " + listenerBinder);
+ }
+ listenerBinder.unlinkToDeath(this, 0);
+ synchronized (CarDrivingStateService.this) {
+ mDrivingStateClients.remove(this);
+ }
+ }
+
+ /**
+ * Returns if the given binder object matches to what this client info holds.
+ * Used to check if the listener asking to be registered is already registered.
+ *
+ * @return true if matches, false if not
+ */
+ public boolean isHoldingBinder(IBinder binder) {
+ return listenerBinder == binder;
+ }
+
+ /**
+ * Dispatch the events to the listener
+ *
+ * @param event {@link CarDrivingStateEvent}.
+ */
+ public void dispatchEventToClients(CarDrivingStateEvent event) {
+ if (event == null) {
+ return;
+ }
+ try {
+ listener.onDrivingStateChanged(event);
+ } catch (RemoteException e) {
+ if (DBG) {
+ Log.d(TAG, "Dispatch to listener failed");
+ }
+ }
+ }
+ }
+
+ @Override
+ public void dump(PrintWriter writer) {
+ writer.println("Driving state change log:");
+ for (Utils.TransitionLog tLog : mTransitionLogs) {
+ writer.println(tLog);
+ }
+ writer.println("Current Driving State: " + mCurrentDrivingState.eventValue);
+ if (mSupportedGears != null) {
+ writer.println("Supported gears:");
+ for (Integer gear : mSupportedGears) {
+ writer.print("Gear:" + gear);
+ }
+ }
+ }
+
+ /**
+ * {@link CarPropertyEvent} listener registered with the {@link CarPropertyService} for getting
+ * property change notifications.
+ */
+ private final ICarPropertyEventListener mICarPropertyEventListener =
+ new ICarPropertyEventListener.Stub() {
+ @Override
+ public void onEvent(List<CarPropertyEvent> events) throws RemoteException {
+ for (CarPropertyEvent event : events) {
+ handlePropertyEvent(event);
+ }
+ }
+ };
+
+ /**
+ * Handle events coming from {@link CarPropertyService}. Compute the driving state, map it to
+ * the corresponding UX Restrictions and dispatch the events to the registered clients.
+ */
+ private synchronized void handlePropertyEvent(CarPropertyEvent event) {
+ switch (event.getEventType()) {
+ case CarPropertyEvent.PROPERTY_EVENT_PROPERTY_CHANGE:
+ CarPropertyValue value = event.getCarPropertyValue();
+ int propId = value.getPropertyId();
+ long curTimestamp = value.getTimestamp();
+ Log.d(TAG, "Property Changed: propId=" + propId);
+ switch (propId) {
+ case VehicleProperty.PERF_VEHICLE_SPEED:
+ float curSpeed = (Float) value.getValue();
+ if (DBG) {
+ Log.d(TAG, "Speed: " + curSpeed + "@" + curTimestamp);
+ }
+ if (curTimestamp > mLastSpeedTimestamp) {
+ mLastSpeedTimestamp = curTimestamp;
+ mLastSpeed = curSpeed;
+ } else if (DBG) {
+ Log.d(TAG, "Ignoring speed with older timestamp:" + curTimestamp);
+ }
+ break;
+ case VehicleProperty.GEAR_SELECTION:
+ if (mSupportedGears == null) {
+ mSupportedGears = getSupportedGears();
+ }
+ int curGear = (Integer) value.getValue();
+ if (DBG) {
+ Log.d(TAG, "Gear: " + curGear + "@" + curTimestamp);
+ }
+ if (curTimestamp > mLastGearTimestamp) {
+ mLastGearTimestamp = curTimestamp;
+ mLastGear = (Integer) value.getValue();
+ } else if (DBG) {
+ Log.d(TAG, "Ignoring Gear with older timestamp:" + curTimestamp);
+ }
+ break;
+ case VehicleProperty.PARKING_BRAKE_ON:
+ boolean curParkingBrake = (boolean) value.getValue();
+ if (DBG) {
+ Log.d(TAG, "Parking Brake: " + curParkingBrake + "@" + curTimestamp);
+ }
+ if (curTimestamp > mLastParkingBrakeTimestamp) {
+ mLastParkingBrakeTimestamp = curTimestamp;
+ mLastParkingBrakeState = curParkingBrake;
+ } else if (DBG) {
+ Log.d(TAG, "Ignoring Parking Brake status with an older timestamp:"
+ + curTimestamp);
+ }
+ break;
+ default:
+ Log.e(TAG, "Received property event for unhandled propId=" + propId);
+ break;
+ }
+
+ int drivingState = inferDrivingStateLocked();
+ // Check if the driving state has changed. If it has, update our records and
+ // dispatch the new events to the listeners.
+ if (DBG) {
+ Log.d(TAG, "Driving state new->old " + drivingState + "->"
+ + mCurrentDrivingState.eventValue);
+ }
+ if (drivingState != mCurrentDrivingState.eventValue) {
+ addTransitionLog(TAG, mCurrentDrivingState.eventValue, drivingState,
+ System.currentTimeMillis());
+ // Update if there is a change in state.
+ mCurrentDrivingState = createDrivingStateEvent(drivingState);
+ if (DBG) {
+ Log.d(TAG, "dispatching to " + mDrivingStateClients.size() + " clients");
+ }
+ for (DrivingStateClient client : mDrivingStateClients) {
+ client.dispatchEventToClients(mCurrentDrivingState);
+ }
+ }
+ break;
+ default:
+ // Unhandled event
+ break;
+ }
+ }
+
+ private List<Integer> getSupportedGears() {
+ List<CarPropertyConfig> properyList = mPropertyService.getPropertyList();
+ for (CarPropertyConfig p : properyList) {
+ if (p.getPropertyId() == VehicleProperty.GEAR_SELECTION) {
+ return p.getConfigArray();
+ }
+ }
+ return null;
+ }
+
+ private void addTransitionLog(String name, int from, int to, long timestamp) {
+ if (mTransitionLogs.size() >= MAX_TRANSITION_LOG_SIZE) {
+ mTransitionLogs.remove();
+ }
+
+ Utils.TransitionLog tLog = new Utils.TransitionLog(name, from, to, timestamp);
+ mTransitionLogs.add(tLog);
+ }
+
+ /**
+ * Infers the current driving state of the car from the other Car Sensor properties like
+ * Current Gear, Speed etc.
+ *
+ * @return Current driving state
+ */
+ @CarDrivingState
+ private int inferDrivingStateLocked() {
+ updateVehiclePropertiesIfNeeded();
+ if (DBG) {
+ Log.d(TAG, "Last known Gear:" + mLastGear + " Last known speed:" + mLastSpeed);
+ }
+
+ /*
+ Logic to start off deriving driving state:
+ 1. If gear == parked, then Driving State is parked.
+ 2. If gear != parked,
+ 2a. if parking brake is applied, then Driving state is parked.
+ 2b. if parking brake is not applied or unknown/unavailable, then driving state
+ is still unknown.
+ 3. If driving state is unknown at the end of step 2,
+ 3a. if speed == 0, then driving state is idling
+ 3b. if speed != 0, then driving state is moving
+ 3c. if speed unavailable, then driving state is unknown
+ */
+
+ if (isVehicleKnownToBeParked()) {
+ return CarDrivingStateEvent.DRIVING_STATE_PARKED;
+ }
+
+ // We don't know if the vehicle is parked, let's look at the speed.
+ if (mLastSpeedTimestamp == NOT_RECEIVED || mLastSpeed < 0) {
+ return CarDrivingStateEvent.DRIVING_STATE_UNKNOWN;
+ } else if (mLastSpeed == 0f) {
+ return CarDrivingStateEvent.DRIVING_STATE_IDLING;
+ } else {
+ return CarDrivingStateEvent.DRIVING_STATE_MOVING;
+ }
+ }
+
+ /**
+ * Find if we have signals to know if the vehicle is parked
+ *
+ * @return true if we have enough information to say the vehicle is parked.
+ * false, if the vehicle is either not parked or if we don't have any information.
+ */
+ private boolean isVehicleKnownToBeParked() {
+ // If we know the gear is in park, return true
+ if (mLastGearTimestamp != NOT_RECEIVED && mLastGear == VehicleGear.GEAR_PARK) {
+ return true;
+ } else if (mLastParkingBrakeTimestamp != NOT_RECEIVED) {
+ // if gear is not in park or unknown, look for status of parking brake if transmission
+ // type is manual.
+ if (isCarManualTransmissionType()) {
+ return mLastParkingBrakeState;
+ }
+ }
+ // if neither information is available, return false to indicate we can't determine
+ // if the vehicle is parked.
+ return false;
+ }
+
+ /**
+ * If Supported gears information is available and GEAR_PARK is not one of the supported gears,
+ * transmission type is considered to be Manual. Automatic transmission is assumed otherwise.
+ */
+ private boolean isCarManualTransmissionType() {
+ if (mSupportedGears != null
+ && !mSupportedGears.isEmpty()
+ && !mSupportedGears.contains(VehicleGear.GEAR_PARK)) {
+ return true;
+ }
+ return false;
+ }
+
+ /**
+ * Try querying the gear selection and parking brake if we haven't received the event yet.
+ * This could happen if the gear change occurred before car service booted up like in the
+ * case of a HU restart in the middle of a drive. Since gear and parking brake are
+ * on-change only properties, we could be in this situation where we will have to query
+ * VHAL.
+ */
+ private void updateVehiclePropertiesIfNeeded() {
+ if (mLastGearTimestamp == NOT_RECEIVED) {
+ CarPropertyValue propertyValue = mPropertyService.getProperty(
+ VehicleProperty.GEAR_SELECTION,
+ VehicleAreaType.VEHICLE_AREA_TYPE_GLOBAL);
+ if (propertyValue != null) {
+ mLastGear = (Integer) propertyValue.getValue();
+ mLastGearTimestamp = propertyValue.getTimestamp();
+ if (DBG) {
+ Log.d(TAG, "updateVehiclePropertiesIfNeeded: gear:" + mLastGear);
+ }
+ }
+ }
+
+ if (mLastParkingBrakeTimestamp == NOT_RECEIVED) {
+ CarPropertyValue propertyValue = mPropertyService.getProperty(
+ VehicleProperty.PARKING_BRAKE_ON,
+ VehicleAreaType.VEHICLE_AREA_TYPE_GLOBAL);
+ if (propertyValue != null) {
+ mLastParkingBrakeState = (boolean) propertyValue.getValue();
+ mLastParkingBrakeTimestamp = propertyValue.getTimestamp();
+ if (DBG) {
+ Log.d(TAG, "updateVehiclePropertiesIfNeeded: brake:" + mLastParkingBrakeState);
+ }
+ }
+ }
+
+ if (mLastSpeedTimestamp == NOT_RECEIVED) {
+ CarPropertyValue propertyValue = mPropertyService.getProperty(
+ VehicleProperty.PERF_VEHICLE_SPEED,
+ VehicleAreaType.VEHICLE_AREA_TYPE_GLOBAL);
+ if (propertyValue != null) {
+ mLastSpeed = (float) propertyValue.getValue();
+ mLastSpeedTimestamp = propertyValue.getTimestamp();
+ if (DBG) {
+ Log.d(TAG, "updateVehiclePropertiesIfNeeded: speed:" + mLastSpeed);
+ }
+ }
+ }
+ }
+
+ private static CarDrivingStateEvent createDrivingStateEvent(int eventValue) {
+ return new CarDrivingStateEvent(eventValue, SystemClock.elapsedRealtimeNanos());
+ }
+
+}
diff --git a/service/src/com/android/car/CarHvacService.java b/service/src/com/android/car/CarHvacService.java
deleted file mode 100644
index e22a38d..0000000
--- a/service/src/com/android/car/CarHvacService.java
+++ /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.
- */
-
-package com.android.car;
-
-import android.car.Car;
-import android.content.Context;
-
-import com.android.car.hal.HvacHalService;
-
-public class CarHvacService extends CarPropertyServiceBase {
- private final static boolean DBG = false;
-
- public CarHvacService(Context context, HvacHalService hvacHal) {
- super(context, hvacHal, Car.PERMISSION_CAR_HVAC, DBG, CarLog.TAG_HVAC);
- }
-}
diff --git a/service/src/com/android/car/CarInfoService.java b/service/src/com/android/car/CarInfoService.java
deleted file mode 100644
index a05f343..0000000
--- a/service/src/com/android/car/CarInfoService.java
+++ /dev/null
@@ -1,84 +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;
-
-import android.car.CarInfoManager;
-import android.car.ICarInfo;
-import android.content.Context;
-import android.os.Bundle;
-import android.provider.Settings;
-
-import com.android.car.hal.InfoHalService;
-import com.android.car.internal.FeatureConfiguration;
-import com.android.car.internal.FeatureUtil;
-
-import java.io.PrintWriter;
-
-public class CarInfoService extends ICarInfo.Stub implements CarServiceBase {
-
- private final InfoHalService mInfoHal;
- private final Context mContext;
-
- public CarInfoService(Context context, InfoHalService infoHal) {
- mInfoHal = infoHal;
- mContext = context;
- }
-
- @Override
- public Bundle getBasicInfo() {
- return mInfoHal.getBasicInfo();
- }
-
- @Override
- public String getStringInfo(String key) {
- switch (key) {
- case CarInfoManager.INFO_KEY_PRODUCT_CONFIGURATION:
- FeatureUtil.assertFeature(
- FeatureConfiguration.ENABLE_PRODUCT_CONFIGURATION_INFO);
- // still protect with if-feature code. code under if can be dropped by
- // proguard if necessary.
- if (FeatureConfiguration.ENABLE_PRODUCT_CONFIGURATION_INFO) {
- //TODO get it from HAL layer
- return null;
- }
- break;
- default: // just throw exception
- break;
- }
- throw new IllegalArgumentException("Unsupported key:" + key);
- }
-
- @Override
- public void init() {
- Bundle info = mInfoHal.getBasicInfo();
- // do not update ID immediately even if user clears it.
- info.putString(CarInfoManager.BASIC_INFO_KEY_VEHICLE_ID,
- Settings.Secure.getString(mContext.getContentResolver(),
- Settings.Secure.ANDROID_ID));
- }
-
- @Override
- public synchronized void release() {
- //nothing to do
- }
-
- @Override
- public void dump(PrintWriter writer) {
- writer.println("*CarInfoService*");
- writer.println("**Check HAL dump");
- }
-}
-
diff --git a/service/src/com/android/car/CarInputService.java b/service/src/com/android/car/CarInputService.java
index b4846b7..1f67259 100644
--- a/service/src/com/android/car/CarInputService.java
+++ b/service/src/com/android/car/CarInputService.java
@@ -56,7 +56,33 @@
boolean onKeyEvent(KeyEvent event);
}
- private static final long LONG_PRESS_TIME_MS = 1000;
+ private static final class KeyPressTimer {
+ private static final long LONG_PRESS_TIME_MS = 1000;
+
+ private boolean mDown = false;
+ private long mDuration = -1;
+
+ synchronized void keyDown() {
+ mDown = true;
+ mDuration = SystemClock.elapsedRealtime();
+ }
+
+ synchronized void keyUp() {
+ if (!mDown) {
+ throw new IllegalStateException("key can't go up without being down");
+ }
+ mDuration = SystemClock.elapsedRealtime() - mDuration;
+ mDown = false;
+ }
+
+ synchronized boolean isLongPress() {
+ if (mDown) {
+ throw new IllegalStateException("can't query press length during key down");
+ }
+ return mDuration >= LONG_PRESS_TIME_MS;
+ }
+ }
+
private static final boolean DBG = false;
private final Context mContext;
@@ -66,20 +92,16 @@
private KeyEventListener mVoiceAssistantKeyListener;
private KeyEventListener mLongVoiceAssistantKeyListener;
- private long mLastVoiceKeyDownTime = 0;
- private long mLastCallKeyDownTime = 0;
+ private final KeyPressTimer mVoiceKeyTimer = new KeyPressTimer();
+ private final KeyPressTimer mCallKeyTimer = new KeyPressTimer();
private KeyEventListener mInstrumentClusterKeyListener;
- private KeyEventListener mVolumeKeyListener;
-
private ICarInputListener mCarInputListener;
private boolean mCarInputListenerBound = false;
private final Map<Integer, Set<Integer>> mHandledKeys = new HashMap<>();
- private int mKeyEventCount = 0;
-
private final Binder mCallback = new Binder() {
@Override
protected boolean onTransact(int code, Parcel data, Parcel reply, int flags) {
@@ -175,17 +197,13 @@
}
}
- public void setVolumeKeyListener(KeyEventListener listener) {
- synchronized (this) {
- mVolumeKeyListener = listener;
- }
- }
-
@Override
public void init() {
if (!mInputHalService.isKeyInputSupported()) {
Log.w(CarLog.TAG_INPUT, "Hal does not support key input.");
return;
+ } else if (DBG) {
+ Log.d(CarLog.TAG_INPUT, "Hal supports key input.");
}
@@ -199,7 +217,6 @@
mVoiceAssistantKeyListener = null;
mLongVoiceAssistantKeyListener = null;
mInstrumentClusterKeyListener = null;
- mKeyEventCount = 0;
if (mCarInputListenerBound) {
mContext.unbindService(mInputServiceConnection);
mCarInputListenerBound = false;
@@ -209,13 +226,7 @@
@Override
public void onKeyEvent(KeyEvent event, int targetDisplay) {
- synchronized (this) {
- mKeyEventCount++;
- }
- if (handleSystemEvent(event)) {
- // System event handled, nothing more to do here.
- return;
- }
+ // Give a car specific input listener the opportunity to intercept any input from the car
if (mCarInputListener != null && isCustomEventHandler(event, targetDisplay)) {
try {
mCarInputListener.onKeyEvent(event, targetDisplay);
@@ -226,6 +237,7 @@
return;
}
+ // Special case key code that have special "long press" handling for automotive
switch (event.getKeyCode()) {
case KeyEvent.KEYCODE_VOICE_ASSIST:
handleVoiceAssistKey(event);
@@ -236,6 +248,8 @@
default:
break;
}
+
+ // Allow specifically targeted keys to be routed to the cluster
if (targetDisplay == InputHalService.DISPLAY_INSTRUMENT_CLUSTER) {
handleInstrumentClusterKey(event);
} else {
@@ -251,46 +265,23 @@
return displaySet.contains(event.getKeyCode());
}
- private boolean handleSystemEvent(KeyEvent event) {
- switch (event.getKeyCode()) {
- case KeyEvent.KEYCODE_VOLUME_UP:
- case KeyEvent.KEYCODE_VOLUME_DOWN:
- handleVolumeKey(event);
- return true;
- default:
- return false;
- }
- }
-
private void handleVoiceAssistKey(KeyEvent event) {
int action = event.getAction();
if (action == KeyEvent.ACTION_DOWN) {
- long now = SystemClock.elapsedRealtime();
- synchronized (this) {
- mLastVoiceKeyDownTime = now;
- }
+ mVoiceKeyTimer.keyDown();
} else if (action == KeyEvent.ACTION_UP) {
- // if no listener, do not handle long press
- KeyEventListener listener = null;
- KeyEventListener shortPressListener = null;
- KeyEventListener longPressListener = null;
- long downTime;
+ mVoiceKeyTimer.keyUp();
+ final KeyEventListener listener;
+
synchronized (this) {
- shortPressListener = mVoiceAssistantKeyListener;
- longPressListener = mLongVoiceAssistantKeyListener;
- downTime = mLastVoiceKeyDownTime;
+ listener = (mVoiceKeyTimer.isLongPress()
+ ? mLongVoiceAssistantKeyListener : mVoiceAssistantKeyListener);
}
- if (shortPressListener == null && longPressListener == null) {
- launchDefaultVoiceAssistantHandler();
+
+ if (listener != null) {
+ listener.onKeyEvent(event);
} else {
- long duration = SystemClock.elapsedRealtime() - downTime;
- listener = (duration > LONG_PRESS_TIME_MS
- ? longPressListener : shortPressListener);
- if (listener != null) {
- listener.onKeyEvent(event);
- } else {
- launchDefaultVoiceAssistantHandler();
- }
+ launchDefaultVoiceAssistantHandler();
}
}
}
@@ -298,24 +289,15 @@
private void handleCallKey(KeyEvent event) {
int action = event.getAction();
if (action == KeyEvent.ACTION_DOWN) {
- // Only handle if it's ringing when button down.
- if (mTelecomManager != null && mTelecomManager.isRinging()) {
- Log.i(CarLog.TAG_INPUT, "call key while rinning. Answer the call!");
- mTelecomManager.acceptRingingCall();
- return;
- }
-
- long now = SystemClock.elapsedRealtime();
- synchronized (this) {
- mLastCallKeyDownTime = now;
- }
+ mCallKeyTimer.keyDown();
} else if (action == KeyEvent.ACTION_UP) {
- long downTime;
- synchronized (this) {
- downTime = mLastCallKeyDownTime;
- }
- long duration = SystemClock.elapsedRealtime() - downTime;
- if (duration > LONG_PRESS_TIME_MS) {
+ mCallKeyTimer.keyUp();
+
+ // Handle a phone call regardless of press length.
+ if (mTelecomManager != null && mTelecomManager.isRinging()) {
+ Log.i(CarLog.TAG_INPUT, "call key while ringing. Answer the call!");
+ mTelecomManager.acceptRingingCall();
+ } else if (mCallKeyTimer.isLongPress()) {
dialLastCallHandler();
} else {
launchDialerHandler();
@@ -359,16 +341,6 @@
listener.onKeyEvent(event);
}
- private void handleVolumeKey(KeyEvent event) {
- KeyEventListener listener;
- synchronized (this) {
- listener = mVolumeKeyListener;
- }
- if (listener != null) {
- listener.onKeyEvent(event);
- }
- }
-
private void handleMainDisplayKey(KeyEvent event) {
mInputManager.injectInputEvent(event, INJECT_INPUT_EVENT_MODE_ASYNC);
}
@@ -378,8 +350,6 @@
writer.println("*Input Service*");
writer.println("mCarInputListenerBound:" + mCarInputListenerBound);
writer.println("mCarInputListener:" + mCarInputListener);
- writer.println("mLastVoiceKeyDownTime:" + mLastVoiceKeyDownTime +
- ",mKeyEventCount:" + mKeyEventCount);
}
private boolean bindCarInputService() {
diff --git a/service/src/com/android/car/CarLocationService.java b/service/src/com/android/car/CarLocationService.java
new file mode 100644
index 0000000..6d93b40
--- /dev/null
+++ b/service/src/com/android/car/CarLocationService.java
@@ -0,0 +1,336 @@
+/*
+ * 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;
+
+import android.car.hardware.CarPropertyValue;
+import android.car.hardware.property.CarPropertyEvent;
+import android.car.hardware.property.ICarPropertyEventListener;
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.hardware.automotive.vehicle.V2_0.VehicleIgnitionState;
+import android.hardware.automotive.vehicle.V2_0.VehicleProperty;
+import android.location.Location;
+import android.location.LocationManager;
+import android.os.Handler;
+import android.os.HandlerThread;
+import android.os.RemoteException;
+import android.os.SystemClock;
+import android.util.AtomicFile;
+import android.util.JsonReader;
+import android.util.JsonWriter;
+import android.util.Log;
+
+import com.android.internal.annotations.VisibleForTesting;
+
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.io.OutputStreamWriter;
+import java.io.PrintWriter;
+import java.util.List;
+
+/**
+ * This service stores the last known location from {@link LocationManager} when a car is parked
+ * and restores the location when the car is powered on.
+ */
+public class CarLocationService extends BroadcastReceiver implements CarServiceBase,
+ CarPowerManagementService.PowerEventProcessingHandler {
+ private static final String TAG = "CarLocationService";
+ private static final String FILENAME = "location_cache.json";
+ private static final boolean DBG = false;
+ // The accuracy for the stored timestamp
+ private static final long GRANULARITY_ONE_DAY_MS = 24 * 60 * 60 * 1000L;
+ // The time-to-live for the cached location
+ private static final long TTL_THIRTY_DAYS_MS = 30 * GRANULARITY_ONE_DAY_MS;
+
+ // Used internally for mHandlerThread synchronization
+ private final Object mLock = new Object();
+
+ private final Context mContext;
+ private final CarPowerManagementService mCarPowerManagementService;
+ private final CarPropertyService mCarPropertyService;
+ private final CarPropertyEventListener mCarPropertyEventListener;
+ private int mTaskCount = 0;
+ private HandlerThread mHandlerThread;
+ private Handler mHandler;
+
+ public CarLocationService(Context context, CarPowerManagementService carPowerManagementService,
+ CarPropertyService carPropertyService) {
+ logd("constructed");
+ mContext = context;
+ mCarPowerManagementService = carPowerManagementService;
+ mCarPropertyService = carPropertyService;
+ mCarPropertyEventListener = new CarPropertyEventListener();
+ }
+
+ @Override
+ public void init() {
+ logd("init");
+ IntentFilter filter = new IntentFilter();
+ filter.addAction(Intent.ACTION_LOCKED_BOOT_COMPLETED);
+ filter.addAction(LocationManager.MODE_CHANGED_ACTION);
+ filter.addAction(LocationManager.GPS_ENABLED_CHANGE_ACTION);
+ mContext.registerReceiver(this, filter);
+ mCarPropertyService.registerListener(VehicleProperty.IGNITION_STATE, 0,
+ mCarPropertyEventListener);
+ mCarPowerManagementService.registerPowerEventProcessingHandler(this);
+ }
+
+ @Override
+ public void release() {
+ logd("release");
+ mCarPropertyService.unregisterListener(VehicleProperty.IGNITION_STATE,
+ mCarPropertyEventListener);
+ mContext.unregisterReceiver(this);
+ }
+
+ @Override
+ public void dump(PrintWriter writer) {
+ writer.println(TAG);
+ writer.println("Context: " + mContext);
+ writer.println("CarPropertyService: " + mCarPropertyService);
+ }
+
+ @Override
+ public long onPrepareShutdown(boolean shuttingDown) {
+ logd("onPrepareShutdown " + shuttingDown);
+ asyncOperation(() -> storeLocation());
+ return 0;
+ }
+
+ @Override
+ public void onPowerOn(boolean displayOn) { }
+
+ @Override
+ public int getWakeupTime() {
+ return 0;
+ }
+
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ logd("onReceive " + intent);
+ String action = intent.getAction();
+ if (action == Intent.ACTION_LOCKED_BOOT_COMPLETED) {
+ asyncOperation(() -> loadLocation());
+ } else {
+ LocationManager locationManager =
+ (LocationManager) mContext.getSystemService(Context.LOCATION_SERVICE);
+ if (action == LocationManager.MODE_CHANGED_ACTION) {
+ boolean locationEnabled = locationManager.isLocationEnabled();
+ logd("isLocationEnabled(): " + locationEnabled);
+ if (!locationEnabled) {
+ asyncOperation(() -> deleteCacheFile());
+ }
+ } else if (action == LocationManager.GPS_ENABLED_CHANGE_ACTION) {
+ boolean gpsEnabled =
+ locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER);
+ logd("isProviderEnabled('gps'): " + gpsEnabled);
+ if (!gpsEnabled) {
+ asyncOperation(() -> deleteCacheFile());
+ }
+ }
+ }
+ }
+
+ private void storeLocation() {
+ LocationManager locationManager =
+ (LocationManager) mContext.getSystemService(Context.LOCATION_SERVICE);
+ Location location = locationManager.getLastKnownLocation(LocationManager.GPS_PROVIDER);
+ if (location == null) {
+ logd("Not storing null location");
+ deleteCacheFile();
+ } else {
+ logd("Storing location: " + location);
+ AtomicFile atomicFile = new AtomicFile(mContext.getFileStreamPath(FILENAME));
+ FileOutputStream fos = null;
+ try {
+ fos = atomicFile.startWrite();
+ JsonWriter jsonWriter = new JsonWriter(new OutputStreamWriter(fos, "UTF-8"));
+ jsonWriter.beginObject();
+ jsonWriter.name("provider").value(location.getProvider());
+ jsonWriter.name("latitude").value(location.getLatitude());
+ jsonWriter.name("longitude").value(location.getLongitude());
+ if (location.hasAltitude()) {
+ jsonWriter.name("altitude").value(location.getAltitude());
+ }
+ if (location.hasSpeed()) {
+ jsonWriter.name("speed").value(location.getSpeed());
+ }
+ if (location.hasBearing()) {
+ jsonWriter.name("bearing").value(location.getBearing());
+ }
+ if (location.hasAccuracy()) {
+ jsonWriter.name("accuracy").value(location.getAccuracy());
+ }
+ if (location.hasVerticalAccuracy()) {
+ jsonWriter.name("verticalAccuracy").value(
+ location.getVerticalAccuracyMeters());
+ }
+ if (location.hasSpeedAccuracy()) {
+ jsonWriter.name("speedAccuracy").value(
+ location.getSpeedAccuracyMetersPerSecond());
+ }
+ if (location.hasBearingAccuracy()) {
+ jsonWriter.name("bearingAccuracy").value(
+ location.getBearingAccuracyDegrees());
+ }
+ if (location.isFromMockProvider()) {
+ jsonWriter.name("isFromMockProvider").value(true);
+ }
+ long currentTime = location.getTime();
+ // Round the time down to only be accurate within one day.
+ jsonWriter.name("captureTime").value(
+ currentTime - currentTime % GRANULARITY_ONE_DAY_MS);
+ jsonWriter.endObject();
+ jsonWriter.close();
+ atomicFile.finishWrite(fos);
+ } catch (IOException e) {
+ Log.e(TAG, "Unable to write to disk", e);
+ atomicFile.failWrite(fos);
+ }
+ }
+ }
+
+ private void loadLocation() {
+ Location location = readLocationFromCacheFile();
+ logd("Read location from " + location.getTime());
+ long currentTime = System.currentTimeMillis();
+ if (location.getTime() + TTL_THIRTY_DAYS_MS < currentTime) {
+ logd("Location expired.");
+ } else {
+ location.setTime(currentTime);
+ long elapsedTime = SystemClock.elapsedRealtimeNanos();
+ location.setElapsedRealtimeNanos(elapsedTime);
+ if (location.isComplete()) {
+ LocationManager locationManager =
+ (LocationManager) mContext.getSystemService(Context.LOCATION_SERVICE);
+ boolean success = locationManager.injectLocation(location);
+ logd("Injected location " + location + " with result " + success);
+ }
+ }
+ }
+
+ private Location readLocationFromCacheFile() {
+ Location location = new Location((String) null);
+ AtomicFile atomicFile = new AtomicFile(mContext.getFileStreamPath(FILENAME));
+ try {
+ FileInputStream fis = atomicFile.openRead();
+ JsonReader reader = new JsonReader(new InputStreamReader(fis, "UTF-8"));
+ reader.beginObject();
+ while (reader.hasNext()) {
+ String name = reader.nextName();
+ if (name.equals("provider")) {
+ location.setProvider(reader.nextString());
+ } else if (name.equals("latitude")) {
+ location.setLatitude(reader.nextDouble());
+ } else if (name.equals("longitude")) {
+ location.setLongitude(reader.nextDouble());
+ } else if (name.equals("altitude")) {
+ location.setAltitude(reader.nextDouble());
+ } else if (name.equals("speed")) {
+ location.setSpeed((float) reader.nextDouble());
+ } else if (name.equals("bearing")) {
+ location.setBearing((float) reader.nextDouble());
+ } else if (name.equals("accuracy")) {
+ location.setAccuracy((float) reader.nextDouble());
+ } else if (name.equals("verticalAccuracy")) {
+ location.setVerticalAccuracyMeters((float) reader.nextDouble());
+ } else if (name.equals("speedAccuracy")) {
+ location.setSpeedAccuracyMetersPerSecond((float) reader.nextDouble());
+ } else if (name.equals("bearingAccuracy")) {
+ location.setBearingAccuracyDegrees((float) reader.nextDouble());
+ } else if (name.equals("isFromMockProvider")) {
+ location.setIsFromMockProvider(reader.nextBoolean());
+ } else if (name.equals("captureTime")) {
+ location.setTime(reader.nextLong());
+ } else {
+ reader.skipValue();
+ }
+ }
+ reader.endObject();
+ fis.close();
+ deleteCacheFile();
+ } catch (FileNotFoundException e) {
+ Log.d(TAG, "Location cache file not found.");
+ } catch (IOException e) {
+ Log.e(TAG, "Unable to read from disk", e);
+ } catch (NumberFormatException | IllegalStateException e) {
+ Log.e(TAG, "Unexpected format", e);
+ }
+ return location;
+ }
+
+ private void deleteCacheFile() {
+ logd("Deleting cache file");
+ mContext.deleteFile(FILENAME);
+ }
+
+ @VisibleForTesting
+ void asyncOperation(Runnable operation) {
+ synchronized (mLock) {
+ // Create a new HandlerThread if this is the first task to queue.
+ if (++mTaskCount == 1) {
+ mHandlerThread = new HandlerThread("CarLocationServiceThread");
+ mHandlerThread.start();
+ mHandler = new Handler(mHandlerThread.getLooper());
+ }
+ }
+ mHandler.post(() -> {
+ try {
+ operation.run();
+ } finally {
+ synchronized (mLock) {
+ // Quit the thread when the task queue is empty.
+ if (--mTaskCount == 0) {
+ mHandler.getLooper().quit();
+ mHandler = null;
+ mHandlerThread = null;
+ }
+ }
+ }
+ });
+ }
+
+ private static void logd(String msg) {
+ if (DBG) {
+ Log.d(TAG, msg);
+ }
+ }
+
+ private class CarPropertyEventListener extends ICarPropertyEventListener.Stub {
+ @Override
+ public void onEvent(List<CarPropertyEvent> events) throws RemoteException {
+ for (CarPropertyEvent event : events) {
+ if (event.getEventType() == CarPropertyEvent.PROPERTY_EVENT_PROPERTY_CHANGE) {
+ CarPropertyValue value = event.getCarPropertyValue();
+ if (value.getPropertyId() == VehicleProperty.IGNITION_STATE) {
+ int ignitionState = (Integer) value.getValue();
+ logd("property ignition value: " + ignitionState);
+ if (ignitionState == VehicleIgnitionState.OFF) {
+ logd("ignition off");
+ asyncOperation(() -> storeLocation());
+ }
+ }
+ }
+ }
+ }
+ }
+}
diff --git a/service/src/com/android/car/CarLog.java b/service/src/com/android/car/CarLog.java
index d9600d6..97734a8 100644
--- a/service/src/com/android/car/CarLog.java
+++ b/service/src/com/android/car/CarLog.java
@@ -37,12 +37,12 @@
public static final String TAG_POWER = "CAR.POWER";
public static final String TAG_PROJECTION = "CAR.PROJECTION";
public static final String TAG_PROPERTY = "CAR.PROPERTY";
- public static final String TAG_RADIO = "CAR.RADIO";
public static final String TAG_SENSOR = "CAR.SENSOR";
public static final String TAG_SERVICE = "CAR.SERVICE";
public static final String TAG_SYS = "CAR.SYS";
public static final String TAG_TEST = "CAR.TEST";
public static final String TAG_DIAGNOSTIC = "CAR.DIAGNOSTIC";
+ public static final String TAG_STORAGE = "CAR.STORAGE";
public static String concatTag(String tagPrefix, Class clazz) {
String tag = tagPrefix + "." + clazz.getSimpleName();
diff --git a/service/src/com/android/car/CarNightService.java b/service/src/com/android/car/CarNightService.java
index 497f77c..e43ed3d 100644
--- a/service/src/com/android/car/CarNightService.java
+++ b/service/src/com/android/car/CarNightService.java
@@ -18,10 +18,12 @@
import android.annotation.IntDef;
import android.app.UiModeManager;
-import android.car.hardware.CarSensorEvent;
-import android.car.hardware.CarSensorManager;
-import android.car.hardware.ICarSensorEventListener;
+import android.car.hardware.CarPropertyValue;
+import android.car.hardware.property.CarPropertyEvent;
+import android.car.hardware.property.ICarPropertyEventListener;
import android.content.Context;
+import android.hardware.automotive.vehicle.V2_0.VehicleProperty;
+import android.os.RemoteException;
import android.util.Log;
import java.io.PrintWriter;
@@ -29,7 +31,6 @@
import java.lang.annotation.RetentionPolicy;
import java.util.List;
-
public class CarNightService implements CarServiceBase {
public static final boolean DBG = false;
@@ -46,32 +47,44 @@
private int mForcedMode = FORCED_SENSOR_MODE;
private final Context mContext;
private final UiModeManager mUiModeManager;
- private CarSensorService mCarSensorService;
+ private CarPropertyService mCarPropertyService;
- private final ICarSensorEventListener mICarSensorEventListener =
- new ICarSensorEventListener.Stub() {
+ private final ICarPropertyEventListener mICarPropertyEventListener =
+ new ICarPropertyEventListener.Stub() {
@Override
- public void onSensorChanged(List<CarSensorEvent> events) {
- if (!events.isEmpty()) {
- CarSensorEvent event = events.get(events.size() - 1);
- handleSensorEvent(event);
+ public void onEvent(List<CarPropertyEvent> events) throws RemoteException {
+ for (CarPropertyEvent event : events) {
+ handlePropertyEvent(event);
}
}
};
- public synchronized void handleSensorEvent(CarSensorEvent event) {
+ /**
+ * Handle CarPropertyEvents
+ * @param event
+ */
+ public synchronized void handlePropertyEvent(CarPropertyEvent event) {
if (event == null) {
return;
}
- if (event.sensorType == CarSensorManager.SENSOR_TYPE_NIGHT) {
- if (event.intValues[0] == 1) {
- mNightSetting = UiModeManager.MODE_NIGHT_YES;
- }
- else {
- mNightSetting = UiModeManager.MODE_NIGHT_NO;
- }
- if (mUiModeManager != null && (mForcedMode == FORCED_SENSOR_MODE)) {
- mUiModeManager.setNightMode(mNightSetting);
+ if (event.getEventType() == CarPropertyEvent.PROPERTY_EVENT_PROPERTY_CHANGE) {
+ // Only handle onChange events
+ CarPropertyValue value = event.getCarPropertyValue();
+ if (value.getPropertyId() == VehicleProperty.NIGHT_MODE) {
+ boolean nightMode = (Boolean) value.getValue();
+ if (nightMode) {
+ mNightSetting = UiModeManager.MODE_NIGHT_YES;
+ if (DBG) Log.d(CarLog.TAG_SENSOR, "CAR dayNight handleSensorEvent NIGHT");
+ } else {
+ mNightSetting = UiModeManager.MODE_NIGHT_NO;
+ if (DBG) Log.d(CarLog.TAG_SENSOR, "CAR dayNight handleSensorEvent DAY");
+ }
+ if (mUiModeManager != null && (mForcedMode == FORCED_SENSOR_MODE)) {
+ mUiModeManager.setNightMode(mNightSetting);
+ if (DBG) Log.d(CarLog.TAG_SENSOR, "CAR dayNight handleSensorEvent APPLIED");
+ } else {
+ if (DBG) Log.d(CarLog.TAG_SENSOR, "CAR dayNight handleSensorEvent IGNORED");
+ }
}
}
}
@@ -102,12 +115,12 @@
return mUiModeManager.getNightMode();
}
- CarNightService(Context context, CarSensorService sensorService) {
+ CarNightService(Context context, CarPropertyService propertyService) {
mContext = context;
- mCarSensorService = sensorService;
+ mCarPropertyService = propertyService;
mUiModeManager = (UiModeManager) mContext.getSystemService(Context.UI_MODE_SERVICE);
if (mUiModeManager == null) {
- Log.w(CarLog.TAG_SENSOR,"Failed to get UI_MODE_SERVICE");
+ Log.w(CarLog.TAG_SENSOR, "Failed to get UI_MODE_SERVICE");
}
}
@@ -116,11 +129,8 @@
if (DBG) {
Log.d(CarLog.TAG_SENSOR,"CAR dayNight init.");
}
- mCarSensorService.registerOrUpdateSensorListener(CarSensorManager.SENSOR_TYPE_NIGHT,
- CarSensorManager.SENSOR_RATE_NORMAL, mICarSensorEventListener);
- CarSensorEvent currentState = mCarSensorService.getLatestSensorEvent(
- CarSensorManager.SENSOR_TYPE_NIGHT);
- handleSensorEvent(currentState);
+ mCarPropertyService.registerListener(VehicleProperty.NIGHT_MODE, 0,
+ mICarPropertyEventListener);
}
@Override
@@ -130,8 +140,8 @@
@Override
public synchronized void dump(PrintWriter writer) {
writer.println("*DAY NIGHT POLICY*");
- writer.println("Mode:" + ((mNightSetting == UiModeManager.MODE_NIGHT_YES) ? "night" : "day")
- );
+ writer.println("Mode:" +
+ ((mNightSetting == UiModeManager.MODE_NIGHT_YES) ? "night" : "day"));
writer.println("Forced Mode? " + (mForcedMode == FORCED_SENSOR_MODE ? "false"
: (mForcedMode == FORCED_DAY_MODE ? "day" : "night")));
}
diff --git a/service/src/com/android/car/CarPowerManagementService.java b/service/src/com/android/car/CarPowerManagementService.java
index 4eb04b4..57ccf62 100644
--- a/service/src/com/android/car/CarPowerManagementService.java
+++ b/service/src/com/android/car/CarPowerManagementService.java
@@ -15,25 +15,36 @@
*/
package com.android.car;
+import android.car.Car;
+import android.car.hardware.power.CarPowerManager.CarPowerStateListener;
+import android.car.hardware.power.ICarPower;
+import android.car.hardware.power.ICarPowerStateListener;
+import android.content.Context;
import android.os.Handler;
import android.os.HandlerThread;
+import android.os.IBinder;
import android.os.Looper;
import android.os.Message;
+import android.os.RemoteCallbackList;
+import android.os.RemoteException;
import android.os.SystemClock;
import android.util.Log;
import com.android.car.hal.PowerHalService;
import com.android.car.hal.PowerHalService.PowerState;
+import com.android.car.systeminterface.SystemInterface;
import com.android.internal.annotations.GuardedBy;
import com.android.internal.annotations.VisibleForTesting;
import java.io.PrintWriter;
import java.util.LinkedList;
+import java.util.Map;
import java.util.Timer;
import java.util.TimerTask;
+import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.CopyOnWriteArrayList;
-public class CarPowerManagementService implements CarServiceBase,
+public class CarPowerManagementService extends ICarPower.Stub implements CarServiceBase,
PowerHalService.PowerEventListener {
/**
@@ -87,6 +98,7 @@
int getWakeupTime();
}
+ private final Context mContext;
private final PowerHalService mHal;
private final SystemInterface mSystemInterface;
@@ -94,6 +106,9 @@
new CopyOnWriteArrayList<>();
private final CopyOnWriteArrayList<PowerEventProcessingHandlerWrapper>
mPowerEventProcessingHandlers = new CopyOnWriteArrayList<>();
+ private final PowerManagerCallbackList mPowerManagerListeners = new PowerManagerCallbackList();
+ private final Map<IBinder, Integer> mPowerManagerListenerTokens = new ConcurrentHashMap<>();
+ private int mTokenValue = 1;
@GuardedBy("this")
private PowerState mCurrentState;
@@ -109,11 +124,29 @@
private HandlerThread mHandlerThread;
@GuardedBy("this")
private PowerHandler mHandler;
+ private int mBootReason;
+ private boolean mShutdownOnNextSuspend = false;
+ // TODO: Make this OEM configurable.
+ private final static int APP_EXTEND_MAX_MS = 10000;
private final static int SHUTDOWN_POLLING_INTERVAL_MS = 2000;
private final static int SHUTDOWN_EXTEND_MAX_MS = 5000;
- public CarPowerManagementService(PowerHalService powerHal, SystemInterface systemInterface) {
+ private class PowerManagerCallbackList extends RemoteCallbackList<ICarPowerStateListener> {
+ /**
+ * Old version of {@link #onCallbackDied(E, Object)} that
+ * does not provide a cookie.
+ */
+ @Override
+ public void onCallbackDied(ICarPowerStateListener listener) {
+ Log.i(CarLog.TAG_POWER, "binderDied " + listener.asBinder());
+ CarPowerManagementService.this.doUnregisterListener(listener);
+ }
+ }
+
+ public CarPowerManagementService(Context context, PowerHalService powerHal,
+ SystemInterface systemInterface) {
+ mContext = context;
mHal = powerHal;
mSystemInterface = systemInterface;
}
@@ -124,6 +157,7 @@
*/
@VisibleForTesting
protected CarPowerManagementService() {
+ mContext = null;
mHal = null;
mSystemInterface = null;
mHandlerThread = null;
@@ -174,6 +208,8 @@
mSystemInterface.stopDisplayStateMonitoring();
mListeners.clear();
mPowerEventProcessingHandlers.clear();
+ mPowerManagerListeners.kill();
+ mPowerManagerListenerTokens.clear();
mSystemInterface.releaseAllWakeLocks();
}
@@ -219,6 +255,11 @@
processingTime = Math.max(processingTime, wrapper.getProcessingTime());
}
}
+ synchronized (mPowerManagerListenerTokens) {
+ if (!mPowerManagerListenerTokens.isEmpty()) {
+ processingTime += APP_EXTEND_MAX_MS;
+ }
+ }
long now = SystemClock.elapsedRealtime();
long startTime;
boolean shouldShutdown = true;
@@ -231,7 +272,7 @@
if (mCurrentState.mState != PowerHalService.STATE_SHUTDOWN_PREPARE) {
return;
}
- if (mCurrentState.canEnterDeepSleep()) {
+ if (mCurrentState.canEnterDeepSleep() && !mShutdownOnNextSuspend) {
shouldShutdown = false;
if (mLastSleepEntryTime > mProcessingStartTime && mLastSleepEntryTime < now) {
// already slept
@@ -259,6 +300,11 @@
}
@Override
+ public void onBootReasonReceived(int bootReason) {
+ mBootReason = bootReason;
+ }
+
+ @Override
public void onApPowerStateChange(PowerState state) {
PowerHandler handler;
synchronized (this) {
@@ -328,6 +374,8 @@
processingTimeMs = handlerProcessingTime;
}
}
+ // Add time for powerManager events
+ processingTimeMs += sendPowerManagerEvent(shuttingDown);
return processingTimeMs;
}
@@ -336,7 +384,7 @@
mSystemInterface.setDisplayState(false);;
boolean shouldShutdown = true;
if (mHal.isDeepSleepAllowed() && mSystemInterface.isSystemSupportingDeepSleep() &&
- newState.canEnterDeepSleep()) {
+ newState.canEnterDeepSleep() && !mShutdownOnNextSuspend) {
Log.i(CarLog.TAG_POWER, "starting sleep");
shouldShutdown = false;
doHandlePreprocessing(shouldShutdown);
@@ -353,6 +401,7 @@
}
}
+ @GuardedBy("this")
private void releaseTimerLocked() {
if (mTimer != null) {
mTimer.cancel();
@@ -371,6 +420,8 @@
processingTimeMs = handlerProcessingTime;
}
}
+ // Add time for powerManager events
+ 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 +
@@ -393,6 +444,33 @@
}
}
+ private long sendPowerManagerEvent(boolean shuttingDown) {
+ long processingTimeMs = 0;
+ int newState = shuttingDown ? CarPowerStateListener.SHUTDOWN_ENTER :
+ CarPowerStateListener.SUSPEND_ENTER;
+ synchronized (mPowerManagerListenerTokens) {
+ mPowerManagerListenerTokens.clear();
+ int i = mPowerManagerListeners.beginBroadcast();
+ while (i-- > 0) {
+ try {
+ ICarPowerStateListener listener = mPowerManagerListeners.getBroadcastItem(i);
+ listener.onStateChanged(newState, mTokenValue);
+ mPowerManagerListenerTokens.put(listener.asBinder(), mTokenValue);
+ mTokenValue++;
+ } catch (RemoteException e) {
+ // Its likely the connection snapped. Let binder death handle the situation.
+ Log.e(CarLog.TAG_POWER, "onStateChanged calling failed: " + e);
+ }
+ }
+ mPowerManagerListeners.finishBroadcast();
+ if (!mPowerManagerListenerTokens.isEmpty()) {
+ Log.i(CarLog.TAG_POWER, "mPowerMangerListenerTokens not empty, add APP_EXTEND_MAX_MS");
+ processingTimeMs += APP_EXTEND_MAX_MS;
+ }
+ }
+ return processingTimeMs;
+ }
+
private void doHandleDeepSleep() {
// keep holding partial wakelock to prevent entering sleep before enterDeepSleep call
// enterDeepSleep should force sleep entry even if wake lock is kept.
@@ -410,11 +488,28 @@
synchronized (this) {
mLastSleepEntryTime = SystemClock.elapsedRealtime();
}
- mSystemInterface.enterDeepSleep(wakeupTimeSec);
+ if (mSystemInterface.enterDeepSleep(wakeupTimeSec) == false) {
+ // System did not suspend. Need to shutdown
+ // TODO: Shutdown gracefully
+ Log.e(CarLog.TAG_POWER, "Sleep did not succeed. Need to shutdown");
+ }
mHal.sendSleepExit();
for (PowerServiceEventListener listener : mListeners) {
listener.onSleepExit();
}
+ // Notify applications
+ int i = mPowerManagerListeners.beginBroadcast();
+ while (i-- > 0) {
+ try {
+ ICarPowerStateListener listener = mPowerManagerListeners.getBroadcastItem(i);
+ listener.onStateChanged(CarPowerStateListener.SUSPEND_EXIT, 0);
+ } catch (RemoteException e) {
+ // Its likely the connection snapped. Let binder death handle the situation.
+ Log.e(CarLog.TAG_POWER, "onStateChanged calling failed: " + e);
+ }
+ }
+ mPowerManagerListeners.finishBroadcast();
+
if (mSystemInterface.isWakeupCausedByTimer()) {
doHandlePreprocessing(false /*shuttingDown*/);
} else {
@@ -497,15 +592,19 @@
@Override
public void onDisplayBrightnessChange(int brightness) {
- // TODO bug: 32065231
+ PowerHandler handler;
+ synchronized (this) {
+ handler = mHandler;
+ }
+ handler.handleDisplayBrightnessChange(brightness);
}
private void doHandleDisplayBrightnessChange(int brightness) {
- //TODO bug: 32065231
+ mSystemInterface.setDisplayBrightness(brightness);
}
private void doHandleMainDisplayStateChange(boolean on) {
- //TODO bug: 32065231
+ Log.w(CarLog.TAG_POWER, "Unimplemented: doHandleMainDisplayStateChange() - on = " + on);
}
public void handleMainDisplayChanged(boolean on) {
@@ -516,10 +615,80 @@
handler.handleMainDisplayStateChange(on);
}
+ /**
+ * Send display brightness to VHAL.
+ * @param brightness value 0-100%
+ */
+ public void sendDisplayBrightness(int brightness) {
+ mHal.sendDisplayBrightness(brightness);
+ }
+
public synchronized Handler getHandler() {
return mHandler;
}
+ // Binder interface for CarPowerManager
+ @Override
+ public void registerListener(ICarPowerStateListener listener) {
+ ICarImpl.assertPermission(mContext, Car.PERMISSION_CAR_POWER);
+ mPowerManagerListeners.register(listener);
+ }
+
+ @Override
+ public void unregisterListener(ICarPowerStateListener listener) {
+ ICarImpl.assertPermission(mContext, Car.PERMISSION_CAR_POWER);
+ doUnregisterListener(listener);
+ }
+
+ private void doUnregisterListener(ICarPowerStateListener listener) {
+ boolean found = mPowerManagerListeners.unregister(listener);
+
+ if (found) {
+ // Remove outstanding token if there is one
+ IBinder binder = listener.asBinder();
+ synchronized (mPowerManagerListenerTokens) {
+ if (mPowerManagerListenerTokens.containsKey(binder)) {
+ int token = mPowerManagerListenerTokens.get(binder);
+ finishedLocked(binder, token);
+ }
+ }
+ }
+ }
+
+ @Override
+ public void requestShutdownOnNextSuspend() {
+ ICarImpl.assertPermission(mContext, Car.PERMISSION_CAR_POWER);
+ mShutdownOnNextSuspend = true;
+ }
+
+ @Override
+ public int getBootReason() {
+ ICarImpl.assertPermission(mContext, Car.PERMISSION_CAR_POWER);
+ // Return the most recent bootReason value
+ return mBootReason;
+ }
+
+ @Override
+ public void finished(ICarPowerStateListener listener, int token) {
+ ICarImpl.assertPermission(mContext, Car.PERMISSION_CAR_POWER);
+ synchronized (mPowerManagerListenerTokens) {
+ finishedLocked(listener.asBinder(), token);
+ }
+ }
+
+ private void finishedLocked(IBinder binder, int token) {
+ int currentToken = mPowerManagerListenerTokens.get(binder);
+ if (currentToken == token) {
+ mPowerManagerListenerTokens.remove(binder);
+ 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");
+ notifyPowerEventProcessingCompletion(null);
+ }
+ }
+ }
+
private class PowerHandler extends Handler {
private final int MSG_POWER_STATE_CHANGE = 0;
diff --git a/service/src/com/android/car/CarPropertyService.java b/service/src/com/android/car/CarPropertyService.java
new file mode 100644
index 0000000..68c4b8c
--- /dev/null
+++ b/service/src/com/android/car/CarPropertyService.java
@@ -0,0 +1,386 @@
+/*
+ * 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;
+
+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.CarPropertyEvent;
+import android.car.hardware.property.ICarProperty;
+import android.car.hardware.property.ICarPropertyEventListener;
+import android.content.Context;
+import android.os.IBinder;
+import android.os.RemoteException;
+import android.util.Log;
+import android.util.Pair;
+import android.util.SparseArray;
+
+import com.android.car.hal.PropertyHalService;
+
+import java.io.PrintWriter;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.CopyOnWriteArrayList;
+
+/**
+ * This class implements the binder interface for ICarProperty.aidl to make it easier to create
+ * multiple managers that deal with Vehicle Properties. To create a new service, simply extend
+ * this class and call the super() constructor with the appropriate arguments for the new service.
+ * {@link CarHvacService} shows the basic usage.
+ */
+public class CarPropertyService extends ICarProperty.Stub
+ implements CarServiceBase, PropertyHalService.PropertyHalListener {
+ private static final boolean DBG = true;
+ private static final String TAG = "Property.service";
+ private final Context mContext;
+ private final Map<IBinder, Client> mClientMap = new ConcurrentHashMap<>();
+ private Map<Integer, CarPropertyConfig<?>> mConfigs;
+ private final PropertyHalService mHal;
+ private boolean mListenerIsSet = false;
+ private final Map<Integer, List<Client>> mPropIdClientMap = new ConcurrentHashMap<>();
+ private final Object mLock = new Object();
+
+ public CarPropertyService(Context context, PropertyHalService hal) {
+ if (DBG) {
+ Log.d(TAG, "CarPropertyService started!");
+ }
+ mHal = hal;
+ mContext = context;
+ }
+
+ // Helper class to keep track of listeners to this service
+ private class Client implements IBinder.DeathRecipient {
+ private final ICarPropertyEventListener mListener;
+ private final IBinder mListenerBinder;
+ private final SparseArray<Float> mRateMap = new SparseArray<Float>(); // key is propId
+
+ Client(ICarPropertyEventListener listener) {
+ mListener = listener;
+ mListenerBinder = listener.asBinder();
+
+ try {
+ mListenerBinder.linkToDeath(this, 0);
+ } catch (RemoteException e) {
+ Log.e(TAG, "Failed to link death for recipient. " + e);
+ throw new IllegalStateException(Car.CAR_NOT_CONNECTED_EXCEPTION_MSG);
+ }
+ mClientMap.put(mListenerBinder, this);
+ }
+
+ void addProperty(int propId, float rate) {
+ mRateMap.put(propId, rate);
+ }
+
+ /**
+ * Client died. Remove the listener from HAL service and unregister if this is the last
+ * client.
+ */
+ @Override
+ public void binderDied() {
+ if (DBG) {
+ Log.d(TAG, "binderDied " + mListenerBinder);
+ }
+
+ for (int i = 0; i < mRateMap.size(); i++) {
+ int propId = mRateMap.keyAt(i);
+ CarPropertyService.this.unregisterListenerBinderLocked(propId, mListenerBinder);
+ }
+ this.release();
+ }
+
+ ICarPropertyEventListener getListener() {
+ return mListener;
+ }
+
+ IBinder getListenerBinder() {
+ return mListenerBinder;
+ }
+
+ float getRate(int propId) {
+ // Return 0 if no key found, since that is the slowest rate.
+ return mRateMap.get(propId, (float) 0);
+ }
+
+ void release() {
+ mListenerBinder.unlinkToDeath(this, 0);
+ mClientMap.remove(mListenerBinder);
+ }
+
+ void removeProperty(int propId) {
+ mRateMap.remove(propId);
+ if (mRateMap.size() == 0) {
+ // Last property was released, remove the client.
+ this.release();
+ }
+ }
+ }
+
+ @Override
+ public void init() {
+ }
+
+ @Override
+ public void release() {
+ for (Client c : mClientMap.values()) {
+ c.release();
+ }
+ mClientMap.clear();
+ mPropIdClientMap.clear();
+ mHal.setListener(null);
+ mListenerIsSet = false;
+ }
+
+ @Override
+ public void dump(PrintWriter writer) {
+ }
+
+ @Override
+ public void registerListener(int propId, float rate, ICarPropertyEventListener listener) {
+ if (DBG) {
+ Log.d(TAG, "registerListener: propId=0x" + toHexString(propId) + " rate=" + rate);
+ }
+ if (mConfigs.get(propId) == null) {
+ // Do not attempt to register an invalid propId
+ Log.e(TAG, "registerListener: propId is not in config list: " + propId);
+ return;
+ }
+ ICarImpl.assertPermission(mContext, mHal.getReadPermission(propId));
+ if (listener == null) {
+ Log.e(TAG, "registerListener: Listener is null.");
+ throw new IllegalArgumentException("listener cannot be null.");
+ }
+
+ IBinder listenerBinder = listener.asBinder();
+
+ synchronized (mLock) {
+ // Get the client for this listener
+ Client client = mClientMap.get(listenerBinder);
+ if (client == null) {
+ client = new Client(listener);
+ }
+ client.addProperty(propId, rate);
+ // Insert the client into the propId --> clients map
+ List<Client> clients = mPropIdClientMap.get(propId);
+ if (clients == null) {
+ clients = new CopyOnWriteArrayList<Client>();
+ mPropIdClientMap.put(propId, clients);
+ }
+ if (!clients.contains(client)) {
+ clients.add(client);
+ }
+ // Set the HAL listener if necessary
+ if (!mListenerIsSet) {
+ mHal.setListener(this);
+ }
+ // Set the new rate
+ if (rate > mHal.getSampleRate(propId)) {
+ mHal.subscribeProperty(propId, rate);
+ }
+ }
+
+ // Send the latest value(s) to the registering listener only
+ List<CarPropertyEvent> events = new LinkedList<CarPropertyEvent>();
+ for (int areaId : mConfigs.get(propId).getAreaIds()) {
+ CarPropertyValue value = mHal.getProperty(propId, areaId);
+ CarPropertyEvent event = new CarPropertyEvent(
+ CarPropertyEvent.PROPERTY_EVENT_PROPERTY_CHANGE, value);
+ events.add(event);
+ }
+ try {
+ listener.onEvent(events);
+ } catch (RemoteException ex) {
+ // If we cannot send a record, its likely the connection snapped. Let the binder
+ // death handle the situation.
+ Log.e(TAG, "onEvent calling failed: " + ex);
+ }
+ }
+
+ @Override
+ public void unregisterListener(int propId, ICarPropertyEventListener listener) {
+ if (DBG) {
+ Log.d(TAG, "unregisterListener propId=0x" + toHexString(propId));
+ }
+ ICarImpl.assertPermission(mContext, mHal.getReadPermission(propId));
+ if (listener == null) {
+ Log.e(TAG, "unregisterListener: Listener is null.");
+ throw new IllegalArgumentException("Listener is null");
+ }
+
+ IBinder listenerBinder = listener.asBinder();
+ synchronized (mLock) {
+ unregisterListenerBinderLocked(propId, listenerBinder);
+ }
+ }
+
+ private void unregisterListenerBinderLocked(int propId, IBinder listenerBinder) {
+ Client client = mClientMap.get(listenerBinder);
+ List<Client> propertyClients = mPropIdClientMap.get(propId);
+ if (mConfigs.get(propId) == null) {
+ // Do not attempt to register an invalid propId
+ Log.e(TAG, "unregisterListener: propId is not in config list:0x" + toHexString(propId));
+ return;
+ }
+ if ((client == null) || (propertyClients == null)) {
+ Log.e(TAG, "unregisterListenerBinderLocked: Listener was not previously registered.");
+ } else {
+ if (propertyClients.remove(client)) {
+ client.removeProperty(propId);
+ } else {
+ Log.e(TAG, "unregisterListenerBinderLocked: Listener was not registered for "
+ + "propId=0x" + toHexString(propId));
+ }
+
+ if (propertyClients.isEmpty()) {
+ // Last listener for this property unsubscribed. Clean up
+ mHal.unsubscribeProperty(propId);
+ mPropIdClientMap.remove(propId);
+ if (mPropIdClientMap.isEmpty()) {
+ // No more properties are subscribed. Turn off the listener.
+ mHal.setListener(null);
+ mListenerIsSet = false;
+ }
+ } else {
+ // Other listeners are still subscribed. Calculate the new rate
+ float maxRate = 0;
+ for (Client c : propertyClients) {
+ float rate = c.getRate(propId);
+ if (rate > maxRate) {
+ maxRate = rate;
+ }
+ }
+ // Set the new rate
+ mHal.subscribeProperty(propId, maxRate);
+ }
+ }
+ }
+
+ /**
+ * Return the list of properties that the caller may access.
+ */
+ @Override
+ public List<CarPropertyConfig> getPropertyList() {
+ List<CarPropertyConfig> returnList = new ArrayList<CarPropertyConfig>();
+ if (mConfigs == null) {
+ // Cache the configs list to avoid subsequent binder calls
+ mConfigs = mHal.getPropertyList();
+ }
+ for (CarPropertyConfig c : mConfigs.values()) {
+ if (ICarImpl.hasPermission(mContext, mHal.getReadPermission(c.getPropertyId()))) {
+ // Only add properties the list if the process has permissions to read it
+ returnList.add(c);
+ }
+ }
+ if (DBG) {
+ Log.d(TAG, "getPropertyList returns " + returnList.size() + " configs");
+ }
+ return returnList;
+ }
+
+ @Override
+ public CarPropertyValue getProperty(int prop, int zone) {
+ if (mConfigs.get(prop) == null) {
+ // Do not attempt to register an invalid propId
+ Log.e(TAG, "getProperty: propId is not in config list:0x" + toHexString(prop));
+ return null;
+ }
+ ICarImpl.assertPermission(mContext, mHal.getReadPermission(prop));
+ return mHal.getProperty(prop, zone);
+ }
+
+ @Override
+ public void setProperty(CarPropertyValue prop) {
+ int propId = prop.getPropertyId();
+ if (mConfigs.get(propId) == null) {
+ // Do not attempt to register an invalid propId
+ Log.e(TAG, "setProperty: propId is not in config list:0x" + toHexString(propId));
+ return;
+ }
+ ICarImpl.assertPermission(mContext, mHal.getWritePermission(propId));
+ mHal.setProperty(prop);
+ }
+
+ // Implement PropertyHalListener interface
+ @Override
+ public void onPropertyChange(List<CarPropertyEvent> events) {
+ Map<IBinder, Pair<ICarPropertyEventListener, List<CarPropertyEvent>>> eventsToDispatch =
+ new HashMap<>();
+
+ for (CarPropertyEvent event : events) {
+ int propId = event.getCarPropertyValue().getPropertyId();
+ List<Client> clients = mPropIdClientMap.get(propId);
+ if (clients == null) {
+ Log.e(TAG, "onPropertyChange: no listener registered for propId=0x"
+ + toHexString(propId));
+ continue;
+ }
+
+ for (Client c : clients) {
+ IBinder listenerBinder = c.getListenerBinder();
+ Pair<ICarPropertyEventListener, List<CarPropertyEvent>> p =
+ eventsToDispatch.get(listenerBinder);
+ if (p == null) {
+ // Initialize the linked list for the listener
+ p = new Pair<>(c.getListener(), new LinkedList<CarPropertyEvent>());
+ eventsToDispatch.put(listenerBinder, p);
+ }
+ p.second.add(event);
+ }
+ }
+ // Parse the dispatch list to send events
+ for (Pair<ICarPropertyEventListener, List<CarPropertyEvent>> p: eventsToDispatch.values()) {
+ try {
+ p.first.onEvent(p.second);
+ } catch (RemoteException ex) {
+ // If we cannot send a record, its likely the connection snapped. Let binder
+ // death handle the situation.
+ Log.e(TAG, "onEvent calling failed: " + ex);
+ }
+ }
+ }
+
+ @Override
+ public void onPropertySetError(int property, int area) {
+ List<Client> clients = mPropIdClientMap.get(property);
+ if (clients != null) {
+ List<CarPropertyEvent> eventList = new LinkedList<>();
+ eventList.add(createErrorEvent(property, area));
+ for (Client c : clients) {
+ try {
+ c.getListener().onEvent(eventList);
+ } catch (RemoteException ex) {
+ // If we cannot send a record, its likely the connection snapped. Let the binder
+ // death handle the situation.
+ Log.e(TAG, "onEvent calling failed: " + ex);
+ }
+ }
+ } else {
+ Log.e(TAG, "onPropertySetError called with no listener registered for propId=0x"
+ + toHexString(property));
+ }
+ }
+
+ private static CarPropertyEvent createErrorEvent(int property, int area) {
+ return new CarPropertyEvent(CarPropertyEvent.PROPERTY_EVENT_ERROR,
+ new CarPropertyValue<>(property, area, null));
+ }
+}
diff --git a/service/src/com/android/car/CarPropertyServiceBase.java b/service/src/com/android/car/CarPropertyServiceBase.java
deleted file mode 100644
index 02ab7c9..0000000
--- a/service/src/com/android/car/CarPropertyServiceBase.java
+++ /dev/null
@@ -1,233 +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.car.Car;
-import android.car.hardware.CarPropertyConfig;
-import android.car.hardware.CarPropertyValue;
-import android.car.hardware.property.CarPropertyEvent;
-import android.car.hardware.property.ICarProperty;
-import android.car.hardware.property.ICarPropertyEventListener;
-import android.content.Context;
-import android.os.IBinder;
-import android.os.RemoteException;
-import android.util.Log;
-
-import com.android.car.hal.PropertyHalServiceBase;
-
-import java.io.PrintWriter;
-import java.util.List;
-import java.util.Map;
-import java.util.concurrent.ConcurrentHashMap;
-
-/**
- * This class implements the binder interface for ICarProperty.aidl to make it easier to create
- * multiple managers that deal with Vehicle Properties. To create a new service, simply extend
- * this class and call the super() constructor with the appropriate arguments for the new service.
- * {@link CarHvacService} shows the basic usage.
- */
-public class CarPropertyServiceBase extends ICarProperty.Stub
- implements CarServiceBase, PropertyHalServiceBase.PropertyHalListener {
- private final Context mContext;
- private final boolean mDbg;
- private final Map<IBinder, PropertyDeathRecipient> mDeathRecipientMap =
- new ConcurrentHashMap<>();
- private final PropertyHalServiceBase mHal;
- private final Map<IBinder, ICarPropertyEventListener> mListenersMap = new ConcurrentHashMap<>();
- private final String mPermission;
- private final String mTag;
-
- private final Object mLock = new Object();
-
- public CarPropertyServiceBase(Context context, PropertyHalServiceBase hal, String permission,
- boolean dbg, String tag) {
- mContext = context;
- mHal = hal;
- mPermission = permission;
- mDbg = dbg;
- mTag = tag + ".service";
- }
-
- class PropertyDeathRecipient implements IBinder.DeathRecipient {
- private IBinder mListenerBinder;
-
- PropertyDeathRecipient(IBinder listenerBinder) {
- mListenerBinder = listenerBinder;
- }
-
- /**
- * Client died. Remove the listener from HAL service and unregister if this is the last
- * client.
- */
- @Override
- public void binderDied() {
- if (mDbg) {
- Log.d(mTag, "binderDied " + mListenerBinder);
- }
- CarPropertyServiceBase.this.unregisterListenerLocked(mListenerBinder);
- }
-
- void release() {
- mListenerBinder.unlinkToDeath(this, 0);
- }
- }
-
- @Override
- public void init() {
- }
-
- @Override
- public void release() {
- for (PropertyDeathRecipient recipient : mDeathRecipientMap.values()) {
- recipient.release();
- }
- mDeathRecipientMap.clear();
- mListenersMap.clear();
- }
-
- @Override
- public void dump(PrintWriter writer) {
- }
-
- @Override
- public void registerListener(ICarPropertyEventListener listener) {
- if (mDbg) {
- Log.d(mTag, "registerListener");
- }
- ICarImpl.assertPermission(mContext, mPermission);
- if (listener == null) {
- Log.e(mTag, "registerListener: Listener is null.");
- throw new IllegalArgumentException("listener cannot be null.");
- }
-
- IBinder listenerBinder = listener.asBinder();
-
- synchronized (mLock) {
- if (mListenersMap.containsKey(listenerBinder)) {
- // Already registered, nothing to do.
- return;
- }
-
- PropertyDeathRecipient deathRecipient = new PropertyDeathRecipient(listenerBinder);
- try {
- listenerBinder.linkToDeath(deathRecipient, 0);
- } catch (RemoteException e) {
- Log.e(mTag, "Failed to link death for recipient. " + e);
- throw new IllegalStateException(Car.CAR_NOT_CONNECTED_EXCEPTION_MSG);
- }
- mDeathRecipientMap.put(listenerBinder, deathRecipient);
-
- if (mListenersMap.isEmpty()) {
- mHal.setListener(this);
- }
-
- mListenersMap.put(listenerBinder, listener);
- }
- }
-
- @Override
- public void unregisterListener(ICarPropertyEventListener listener) {
- if (mDbg) {
- Log.d(mTag, "unregisterListener");
- }
- ICarImpl.assertPermission(mContext, mPermission);
- if (listener == null) {
- Log.e(mTag, "unregisterListener: Listener is null.");
- throw new IllegalArgumentException("Listener is null");
- }
-
- IBinder listenerBinder = listener.asBinder();
- synchronized (mLock) {
- if (!mListenersMap.containsKey(listenerBinder)) {
- Log.e(mTag, "unregisterListener: Listener was not previously registered.");
- }
- unregisterListenerLocked(listenerBinder);
- }
- }
-
- // Removes the listenerBinder from the current state.
- // The function assumes that binder will exist both in listeners and death recipients list.
- private void unregisterListenerLocked(IBinder listenerBinder) {
- boolean found = mListenersMap.remove(listenerBinder) != null;
-
- if (found) {
- mDeathRecipientMap.get(listenerBinder).release();
- mDeathRecipientMap.remove(listenerBinder);
- }
-
- if (mListenersMap.isEmpty()) {
- mHal.setListener(null);
- }
- }
-
- @Override
- public List<CarPropertyConfig> getPropertyList() {
- ICarImpl.assertPermission(mContext, mPermission);
- return mHal.getPropertyList();
- }
-
- @Override
- public CarPropertyValue getProperty(int prop, int zone) {
- ICarImpl.assertPermission(mContext, mPermission);
- return mHal.getProperty(prop, zone);
- }
-
- @Override
- public void setProperty(CarPropertyValue prop) {
- ICarImpl.assertPermission(mContext, mPermission);
- mHal.setProperty(prop);
- }
-
- private ICarPropertyEventListener[] getListeners() {
- synchronized (mLock) {
- int size = mListenersMap.values().size();
- return mListenersMap.values().toArray(new ICarPropertyEventListener[size]);
- }
- }
-
- // Implement PropertyHalListener interface
- @Override
- public void onPropertyChange(CarPropertyEvent event) {
- for (ICarPropertyEventListener listener : getListeners()) {
- try {
- listener.onEvent(event);
- } catch (RemoteException ex) {
- // If we could not send a record, its likely the connection snapped. Let the binder
- // death handle the situation.
- Log.e(mTag, "onEvent calling failed: " + ex);
- }
- }
- }
-
- @Override
- public void onPropertySetError(int property, int area) {
- for (ICarPropertyEventListener listener : getListeners()) {
- try {
- listener.onEvent(createErrorEvent(property, area));
- } catch (RemoteException ex) {
- // If we could not send a record, its likely the connection snapped. Let the binder
- // death handle the situation.
- Log.e(mTag, "onEvent calling failed: " + ex);
- }
- }
- }
-
- private static CarPropertyEvent createErrorEvent(int property, int area) {
- return new CarPropertyEvent(CarPropertyEvent.PROPERTY_EVENT_ERROR,
- new CarPropertyValue<>(property, area, null));
- }
-}
diff --git a/service/src/com/android/car/CarRadioService.java b/service/src/com/android/car/CarRadioService.java
deleted file mode 100644
index d12c9ae..0000000
--- a/service/src/com/android/car/CarRadioService.java
+++ /dev/null
@@ -1,210 +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;
-
-import android.car.Car;
-import android.car.hardware.radio.CarRadioEvent;
-import android.car.hardware.radio.CarRadioPreset;
-import android.car.hardware.radio.ICarRadio;
-import android.car.hardware.radio.ICarRadioEventListener;
-import android.content.Context;
-import android.content.pm.PackageManager;
-import android.os.IBinder;
-import android.os.Process;
-import android.os.RemoteException;
-import android.util.Log;
-
-import com.android.car.hal.RadioHalService;
-
-import java.io.PrintWriter;
-import java.util.HashMap;
-
-public class CarRadioService extends ICarRadio.Stub
- implements CarServiceBase, RadioHalService.RadioListener {
- public static boolean DBG = false;
- public static String TAG = CarLog.TAG_RADIO + ".CarRadioService";
-
- private RadioHalService mRadioHal;
- private final HashMap<IBinder, ICarRadioEventListener> mListenersMap =
- new HashMap<IBinder, ICarRadioEventListener>();
- private final HashMap<IBinder, RadioDeathRecipient> mDeathRecipientMap =
- new HashMap<IBinder, RadioDeathRecipient>();
- private final Context mContext;
-
- public CarRadioService(Context context, RadioHalService radioHal) {
- mRadioHal = radioHal;
- mContext = context;
- }
-
- class RadioDeathRecipient implements IBinder.DeathRecipient {
- private String TAG = CarRadioService.TAG + ".RadioDeathRecipient";
- private IBinder mListenerBinder;
-
- RadioDeathRecipient(IBinder listenerBinder) {
- mListenerBinder = listenerBinder;
- }
-
- /**
- * Client died. Remove the listener from HAL service and unregister if this is the last
- * client.
- */
- @Override
- public void binderDied() {
- if (DBG) {
- Log.d(TAG, "binderDied " + mListenerBinder);
- }
- mListenerBinder.unlinkToDeath(this, 0);
- CarRadioService.this.unregisterListenerLocked(mListenerBinder);
- }
-
- void release() {
- mListenerBinder.unlinkToDeath(this, 0);
- }
- }
-
- @Override
- public synchronized void init() {
- }
-
- @Override
- public synchronized void release() {
- for (IBinder listenerBinder : mListenersMap.keySet()) {
- RadioDeathRecipient deathRecipient = mDeathRecipientMap.get(listenerBinder);
- deathRecipient.release();
- }
- mDeathRecipientMap.clear();
- mListenersMap.clear();
- }
-
- @Override
- public void dump(PrintWriter writer) {
- }
-
- @Override
- public int getPresetCount() {
- return mRadioHal.getPresetCount();
- }
-
- @Override
- public synchronized void registerListener(ICarRadioEventListener listener) {
- if (DBG) {
- Log.d(TAG, "registerListener");
- }
- if (listener == null) {
- Log.e(TAG, "registerListener: Listener is null.");
- throw new IllegalStateException("listener cannot be null.");
- }
-
- IBinder listenerBinder = listener.asBinder();
- if (mListenersMap.containsKey(listenerBinder)) {
- // Already registered, nothing to do.
- return;
- }
-
- RadioDeathRecipient deathRecipient = new RadioDeathRecipient(listenerBinder);
- try {
- listenerBinder.linkToDeath(deathRecipient, 0);
- } catch (RemoteException e) {
- Log.e(TAG, "Failed to link death for recipient. " + e);
- throw new IllegalStateException(Car.CAR_NOT_CONNECTED_EXCEPTION_MSG);
- }
- mDeathRecipientMap.put(listenerBinder, deathRecipient);
-
- if (mListenersMap.isEmpty()) {
- mRadioHal.registerListener(this);
- }
-
- mListenersMap.put(listenerBinder, listener);
- }
-
- @Override
- public synchronized void unregisterListener(ICarRadioEventListener listener) {
- if (DBG) {
- Log.d(TAG, "unregisterListener");
- }
-
- if (listener == null) {
- Log.e(TAG, "unregisterListener: Listener is null.");
- throw new IllegalArgumentException("Listener is null");
- }
-
- IBinder listenerBinder = listener.asBinder();
- if (!mListenersMap.containsKey(listenerBinder)) {
- Log.e(TAG, "unregisterListener: Listener was not previously registered.");
- }
- unregisterListenerLocked(listenerBinder);
- }
-
- // Removes the listenerBinder from the current state.
- // The function assumes that the binder will exist both in listeners and death recipients list.
- private void unregisterListenerLocked(IBinder listenerBinder) {
- Object status = mListenersMap.remove(listenerBinder);
- if (status == null) throw new IllegalStateException(
- "Map must contain the event listener.");
-
- // If there is a state muck up, the release() call will throw an exception automagically.
- mDeathRecipientMap.get(listenerBinder).release();
- mDeathRecipientMap.remove(listenerBinder);
-
- if (mListenersMap.isEmpty()) {
- mRadioHal.unregisterListener();
- }
- }
-
- @Override
- public CarRadioPreset getPreset(int index) {
- if (DBG) {
- Log.d(TAG, "getPreset " + index);
- }
- return mRadioHal.getRadioPreset(index);
- }
-
- @Override
- public boolean setPreset(CarRadioPreset preset) {
- checkRadioPremissions();
- if (DBG) {
- Log.d(TAG, "setPreset " + preset);
- }
- boolean status = mRadioHal.setRadioPreset(preset);
- if (status == false) {
- Log.e(TAG, "setPreset failed!");
- }
- return status;
- }
-
- @Override
- public synchronized void onEvent(CarRadioEvent event) {
- for (ICarRadioEventListener l : mListenersMap.values()) {
- try {
- l.onEvent(event);
- } catch (RemoteException ex) {
- // If we could not send a record, its likely the connection snapped. Let the binder
- // death handle the situation.
- Log.e(TAG, "onEvent calling failed: " + ex);
- }
- }
- }
-
- private void checkRadioPremissions() {
- if (getCallingUid() != Process.SYSTEM_UID &&
- mContext.checkCallingOrSelfPermission(Car.PERMISSION_CAR_RADIO) !=
- PackageManager.PERMISSION_GRANTED) {
- throw new SecurityException("requires system app or " +
- Car.PERMISSION_CAR_RADIO);
- }
- }
-}
diff --git a/service/src/com/android/car/CarSensorEventFactory.java b/service/src/com/android/car/CarSensorEventFactory.java
index 6497e16..dc45f8c 100644
--- a/service/src/com/android/car/CarSensorEventFactory.java
+++ b/service/src/com/android/car/CarSensorEventFactory.java
@@ -19,6 +19,8 @@
import android.car.hardware.CarSensorEvent;
import android.hardware.automotive.vehicle.V2_0.VehiclePropValue;
+import java.util.List;
+
//TODO add memory pool and recycling
public class CarSensorEventFactory {
@@ -35,13 +37,30 @@
return event;
}
+ /**
+ * Create int64 vector event
+ * @param sensorType
+ * @param timestamp
+ * @param value
+ *
+ * @return CarSensorEvent
+ */
+ public static CarSensorEvent createInt64VecEvent(int sensorType, long timestamp,
+ List<Long> value) {
+ CarSensorEvent event = new CarSensorEvent(sensorType, timestamp, 0, 0, value.size());
+ for (int i = 0; i < value.size(); i++) {
+ event.longValues[i] = value.get(i);
+ }
+ return event;
+ }
+
public static CarSensorEvent createFloatEvent(int sensorType, long timestamp, float value) {
CarSensorEvent event = new CarSensorEvent(sensorType, timestamp, 1, 0, 0);
event.floatValues[0] = value;
return event;
}
- public static CarSensorEvent createComplexEvent(int sensorType, long timestamp,
+ public static CarSensorEvent createMixedEvent(int sensorType, long timestamp,
VehiclePropValue v) {
int numFloats = v.value.floatValues.size();
int numInts = v.value.int32Values.size();
diff --git a/service/src/com/android/car/CarSensorService.java b/service/src/com/android/car/CarSensorService.java
deleted file mode 100644
index 171a8c4..0000000
--- a/service/src/com/android/car/CarSensorService.java
+++ /dev/null
@@ -1,967 +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;
-
-import android.car.Car;
-import android.car.hardware.CarSensorConfig;
-import android.car.hardware.CarSensorEvent;
-import android.car.hardware.CarSensorManager;
-import android.car.hardware.ICarSensor;
-import android.car.hardware.ICarSensorEventListener;
-import android.content.Context;
-import android.content.pm.PackageManager;
-import android.os.Binder;
-import android.os.Handler;
-import android.os.HandlerThread;
-import android.os.IBinder;
-import android.os.Looper;
-import android.os.Message;
-import android.os.Process;
-import android.os.RemoteException;
-import android.os.SystemClock;
-import android.util.ArrayMap;
-import android.util.Log;
-import android.util.SparseArray;
-import android.util.SparseBooleanArray;
-
-import static com.android.car.Listeners.ClientWithRate;
-import com.android.car.hal.SensorBase;
-import com.android.car.hal.SensorHalService.SensorListener;
-import com.google.android.collect.Lists;
-
-import com.android.car.hal.SensorHalService;
-import com.android.car.hal.SensorHalServiceBase;
-import com.android.internal.annotations.GuardedBy;
-
-import java.io.PrintWriter;
-import java.util.Arrays;
-import java.util.ConcurrentModificationException;
-import java.util.LinkedList;
-import java.util.List;
-import java.util.concurrent.TimeUnit;
-import java.util.concurrent.atomic.AtomicBoolean;
-import java.util.concurrent.locks.ReentrantLock;
-
-
-public class CarSensorService extends ICarSensor.Stub
- implements CarServiceBase, SensorHalService.SensorListener {
-
- /**
- * Abstraction for logical sensor which is not physical sensor but presented as sensor to
- * upper layer. Currently {@link CarSensorManager#SENSOR_TYPE_NIGHT} and
- * {@link CarSensorManager#SENSOR_TYPE_DRIVING_STATUS} falls into this category.
- * Implementation can call {@link CarSensorService#onSensorData(CarSensorEvent)} when there
- * is state change for the given sensor after {@link SensorHalServiceBase#init()}
- * is called.
- */
- public static abstract class LogicalSensor implements SensorBase {
- private final LinkedList<CarSensorEvent> mDispatchQ = new LinkedList<>();
-
- /** Sensor service is ready and all vehicle sensors are available. */
- public abstract void onSensorServiceReady();
-
- /**
- * Utility to help service to send one event as listener only takes list form.
- * @param listener
- * @param event
- */
- protected void dispatchCarSensorEvent(SensorListener listener, CarSensorEvent event) {
- synchronized (mDispatchQ) {
- mDispatchQ.add(event);
- listener.onSensorEvents(mDispatchQ);
- mDispatchQ.clear();
- }
- }
- }
-
- /**
- * When set, sensor service sets its own dispatching rate limit.
- * VehicleNetworkService is already doing this, so not necessary to set it for now.
- */
- private static final boolean ENABLE_DISPATCHING_LIMIT = false;
-
- /** {@link #mSensorLock} is not waited forever for handling disconnection */
- private static final long MAX_SENSOR_LOCK_WAIT_MS = 1000;
-
- /** lock to access sensor structures */
- private final ReentrantLock mSensorLock = new ReentrantLock();
- /** hold clients callback */
- @GuardedBy("mSensorLock")
- private final LinkedList<SensorClient> mClients = new LinkedList<>();
-
- /** key: sensor type. */
- @GuardedBy("mSensorLock")
- private final SparseArray<Listeners<SensorClient>> mSensorListeners = new SparseArray<>();
- /** key: sensor type. */
- @GuardedBy("mSensorLock")
- private final SparseArray<SensorRecord> mSensorRecords = new SparseArray<>();
-
- private final SensorHalService mSensorHal;
- private int[] mCarProvidedSensors;
- private int[] mSupportedSensors;
- private final AtomicBoolean mSensorDiscovered = new AtomicBoolean(false);
-
- private final Context mContext;
-
- private final DrivingStatePolicy mDrivingStatePolicy;
- private boolean mUseDefaultDrivingPolicy = true;
- private final DayNightModePolicy mDayNightModePolicy;
- private boolean mUseDefaultDayNightModePolicy = true;
-
- private final HandlerThread mHandlerThread;
- private final SensorDispatchHandler mSensorDispatchHandler;
-
- public CarSensorService(Context context, SensorHalService sensorHal) {
- mContext = context;
- if (ENABLE_DISPATCHING_LIMIT) {
- mHandlerThread = new HandlerThread("SENSOR", Process.THREAD_PRIORITY_AUDIO);
- mHandlerThread.start();
- mSensorDispatchHandler = new SensorDispatchHandler(mHandlerThread.getLooper());
- } else {
- mHandlerThread = null;
- mSensorDispatchHandler = null;
- }
- // This triggers sensor hal init as well.
- mSensorHal = sensorHal;
- mDrivingStatePolicy = new DrivingStatePolicy(context, this);
- mDayNightModePolicy = new DayNightModePolicy(context);
- }
-
- @Override
- public void init() {
- mSensorLock.lock();
- try {
- mSensorHal.registerSensorListener(this);
- mCarProvidedSensors = mSensorHal.getSupportedSensors();
- mSupportedSensors = refreshSupportedSensorsLocked();
-
- addNewSensorRecordLocked(CarSensorManager.SENSOR_TYPE_DRIVING_STATUS,
- getInitialDrivingStatus());
- addNewSensorRecordLocked(CarSensorManager.SENSOR_TYPE_NIGHT, getInitialNightMode());
- addNewSensorRecordLocked(CarSensorManager.SENSOR_TYPE_IGNITION_STATE,
- getInitialIgnitionState());
-
- notifyDefaultPoliciesLocked();
- } finally {
- mSensorLock.unlock();
- }
- }
-
- private CarSensorEvent getInitialIgnitionState() {
- return mSensorHal.getCurrentSensorValue(CarSensorManager.SENSOR_TYPE_IGNITION_STATE);
- }
-
- private CarSensorEvent getInitialNightMode() {
- CarSensorEvent event = null;
- if (mUseDefaultDayNightModePolicy) {
- mDayNightModePolicy.init();
- mDayNightModePolicy.registerSensorListener(this);
- } else {
- event = mSensorHal.getCurrentSensorValue(CarSensorManager.SENSOR_TYPE_NIGHT);
- Log.i(CarLog.TAG_SENSOR, "initial daynight: "
- + ((event == null) ? "not ready" : + event.intValues[0]));
- }
- if (event == null) {
- event = DayNightModePolicy.getDefaultValue(CarSensorManager.SENSOR_TYPE_NIGHT);
- if (!mUseDefaultDayNightModePolicy) {
- Log.w(CarLog.TAG_SENSOR, "Default daynight set as sensor not ready");
- }
- }
- return event;
- }
-
- private CarSensorEvent getInitialDrivingStatus() {
- CarSensorEvent event = null;
- if (mUseDefaultDrivingPolicy) {
- mDrivingStatePolicy.init();
- mDrivingStatePolicy.registerSensorListener(this);
- } else {
- event = mSensorHal.getCurrentSensorValue(
- CarSensorManager.SENSOR_TYPE_DRIVING_STATUS);
- Log.i(CarLog.TAG_SENSOR, "initial driving status:" + ((event == null)?
- "not ready" : " 0x" + Integer.toHexString(event.intValues[0])));
- }
- if (event == null) {
- event = DrivingStatePolicy.getDefaultValue(
- CarSensorManager.SENSOR_TYPE_DRIVING_STATUS);
- if (!mUseDefaultDrivingPolicy) {
- Log.w(CarLog.TAG_SENSOR, "Default driving status set as sensor not ready");
- }
- }
- return event;
- }
-
- private void addNewSensorRecordLocked(int type, CarSensorEvent event) {
- SensorRecord record = new SensorRecord();
- record.lastEvent = event;
- mSensorRecords.put(type,record);
- }
-
- @Override
- public void release() {
- if (mHandlerThread != null) {
- mHandlerThread.quit();
- }
- tryHoldSensorLock();
- try {
- if (mUseDefaultDrivingPolicy) {
- mDrivingStatePolicy.release();
- }
- if (mUseDefaultDayNightModePolicy) {
- mDayNightModePolicy.release();
- }
- for (int i = mSensorListeners.size() - 1; i >= 0; --i) {
- Listeners listener = mSensorListeners.valueAt(i);
- listener.release();
- }
- mSensorListeners.clear();
- mSensorRecords.clear();
- mClients.clear();
- } finally {
- releaseSensorLockSafely();
- }
- }
-
- private void tryHoldSensorLock() {
- try {
- mSensorLock.tryLock(MAX_SENSOR_LOCK_WAIT_MS, TimeUnit.MILLISECONDS);
- } catch (InterruptedException e) {
- //ignore
- }
- }
-
- private void releaseSensorLockSafely() {
- if (mSensorLock.isHeldByCurrentThread()) {
- mSensorLock.unlock();
- }
- }
-
- private void notifyDefaultPoliciesLocked() {
- if (mUseDefaultDrivingPolicy) {
- mDrivingStatePolicy.onSensorServiceReady();
- }
- if (mUseDefaultDayNightModePolicy) {
- mDayNightModePolicy.onSensorServiceReady();
- }
- }
-
- private void processSensorData(List<CarSensorEvent> events) {
- ArrayMap<SensorClient, List<CarSensorEvent>> eventsByClient = new ArrayMap<>();
-
- mSensorLock.lock();
- for (CarSensorEvent event: events) {
- SensorRecord record = mSensorRecords.get(event.sensorType);
- if (record != null) {
- if (record.lastEvent == null) {
- record.lastEvent = event;
- } else if (record.lastEvent.timestamp < event.timestamp) {
- record.lastEvent = event;
- //TODO recycle event, bug: 32094595
- } else { // wrong timestamp, throw away this.
- //TODO recycle new event, bug: 32094595
- continue;
- }
-
- Listeners<SensorClient> listeners = mSensorListeners.get(event.sensorType);
- if (listeners == null) {
- continue;
- }
-
- for (ClientWithRate<SensorClient> clientWithRate : listeners.getClients()) {
- SensorClient client = clientWithRate.getClient();
- List<CarSensorEvent> clientEvents = eventsByClient.get(client);
- if (clientEvents == null) {
- clientEvents = new LinkedList<>();
- eventsByClient.put(client, clientEvents);
- }
- clientEvents.add(event);
- }
- }
- }
- mSensorLock.unlock();
-
- for (ArrayMap.Entry<SensorClient, List<CarSensorEvent>> entry : eventsByClient.entrySet()) {
- SensorClient client = entry.getKey();
- List<CarSensorEvent> clientEvents = entry.getValue();
-
- client.dispatchSensorUpdate(clientEvents);
- }
- }
-
- /**
- * Received sensor data from car.
- */
- @Override
- public void onSensorEvents(List<CarSensorEvent> events) {
- if (ENABLE_DISPATCHING_LIMIT) {
- mSensorDispatchHandler.handleSensorEvents(events);
- } else {
- processSensorData(events);
- }
- }
-
- @Override
- public int[] getSupportedSensors() {
- mSensorLock.lock();
- int[] supportedSensors = mSupportedSensors;
- mSensorLock.unlock();
- return supportedSensors;
- }
-
- @Override
- public boolean registerOrUpdateSensorListener(int sensorType, int rate,
- ICarSensorEventListener listener) {
- boolean shouldStartSensors = false;
- SensorRecord sensorRecord = null;
- SensorClient sensorClient = null;
- Integer oldRate = null;
- Listeners<SensorClient> sensorListeners = null;
- mSensorLock.lock();
- try {
- sensorRecord = mSensorRecords.get(sensorType);
- if (sensorRecord == null) {
- if (Log.isLoggable(CarLog.TAG_SENSOR, Log.INFO)) {
- Log.i(CarLog.TAG_SENSOR, "Requested sensor " + sensorType + " not supported");
- }
- return false;
- }
- if (Binder.getCallingUid() != Process.myUid()) {
- switch (getSensorPermission(sensorType)) {
- case PackageManager.PERMISSION_DENIED:
- throw new SecurityException("client does not have permission:"
- + getPermissionName(sensorType)
- + " pid:" + Binder.getCallingPid()
- + " uid:" + Binder.getCallingUid());
- case PackageManager.PERMISSION_GRANTED:
- break;
- }
- }
- if (Log.isLoggable(CarLog.TAG_SENSOR, Log.DEBUG)) {
- Log.d(CarLog.TAG_SENSOR, "registerOrUpdateSensorListener " + sensorType + " " +
- listener);
- }
- sensorClient = findSensorClientLocked(listener);
- ClientWithRate<SensorClient> sensorClientWithRate = null;
- sensorListeners = mSensorListeners.get(sensorType);
- if (sensorClient == null) {
- sensorClient = new SensorClient(listener);
- try {
- listener.asBinder().linkToDeath(sensorClient, 0);
- } catch (RemoteException e) {
- if (Log.isLoggable(CarLog.TAG_SENSOR, Log.INFO)) {
- Log.i(CarLog.TAG_SENSOR, "Adding listener failed.");
- }
- return false;
- }
- mClients.add(sensorClient);
- }
- // If we have a cached event for this sensor, send the event.
- SensorRecord record = mSensorRecords.get(sensorType);
- if (record != null && record.lastEvent != null) {
- sensorClient.dispatchSensorUpdate(Lists.newArrayList(record.lastEvent));
- }
- if (sensorListeners == null) {
- sensorListeners = new Listeners<>(rate);
- mSensorListeners.put(sensorType, sensorListeners);
- shouldStartSensors = true;
- } else {
- oldRate = sensorListeners.getRate();
- sensorClientWithRate = sensorListeners.findClientWithRate(sensorClient);
- }
- if (sensorClientWithRate == null) {
- sensorClientWithRate = new ClientWithRate<>(sensorClient, rate);
- sensorListeners.addClientWithRate(sensorClientWithRate);
- } else {
- sensorClientWithRate.setRate(rate);
- }
- if (sensorListeners.getRate() > rate) {
- sensorListeners.setRate(rate);
- shouldStartSensors = sensorSupportRate(sensorType);
- }
- sensorClient.addSensor(sensorType);
- } finally {
- mSensorLock.unlock();
- }
- // start sensor outside lock as it can take time.
- if (shouldStartSensors) {
- if (!startSensor(sensorRecord, sensorType, rate)) {
- // failed. so remove from active sensor list.
- mSensorLock.lock();
- try {
- sensorClient.removeSensor(sensorType);
- if (oldRate != null) {
- sensorListeners.setRate(oldRate);
- } else {
- mSensorListeners.remove(sensorType);
- }
- } finally {
- mSensorLock.unlock();
- }
- return false;
- }
- }
- return true;
- }
-
- private boolean sensorSupportRate(int sensorType) {
- switch (sensorType) {
- case CarSensorManager.SENSOR_TYPE_CAR_SPEED:
- case CarSensorManager.SENSOR_TYPE_RPM:
- case CarSensorManager.SENSOR_TYPE_WHEEL_TICK_DISTANCE:
- return true;
- case CarSensorManager.SENSOR_TYPE_ODOMETER:
- case CarSensorManager.SENSOR_TYPE_FUEL_LEVEL:
- case CarSensorManager.SENSOR_TYPE_PARKING_BRAKE:
- case CarSensorManager.SENSOR_TYPE_GEAR:
- case CarSensorManager.SENSOR_TYPE_NIGHT:
- case CarSensorManager.SENSOR_TYPE_DRIVING_STATUS:
- case CarSensorManager.SENSOR_TYPE_ENVIRONMENT:
- return false;
- default:
- Log.w(CarLog.TAG_SENSOR, "sensorSupportRate not listed sensor:" + sensorType);
- return false;
- }
- }
-
- private int getSensorPermission(int sensorType) {
- String permission = getPermissionName(sensorType);
- int result = PackageManager.PERMISSION_GRANTED;
- if (permission != null) {
- return mContext.checkCallingOrSelfPermission(permission);
- }
- // If no permission is required, return granted.
- return result;
- }
-
- //TODO handle per property OEM permission. bug: 32094983
- private String getPermissionName(int sensorType) {
- if ((sensorType >= CarSensorManager.SENSOR_TYPE_VENDOR_EXTENSION_START) &&
- (sensorType >= CarSensorManager.SENSOR_TYPE_VENDOR_EXTENSION_END)) {
- return Car.PERMISSION_VENDOR_EXTENSION;
- }
- String permission = null;
- switch (sensorType) {
- case CarSensorManager.SENSOR_TYPE_CAR_SPEED:
- case CarSensorManager.SENSOR_TYPE_WHEEL_TICK_DISTANCE:
- permission = Car.PERMISSION_SPEED;
- break;
- case CarSensorManager.SENSOR_TYPE_ODOMETER:
- permission = Car.PERMISSION_MILEAGE;
- break;
- case CarSensorManager.SENSOR_TYPE_FUEL_LEVEL:
- permission = Car.PERMISSION_FUEL;
- break;
- case CarSensorManager.SENSOR_TYPE_ABS_ACTIVE:
- case CarSensorManager.SENSOR_TYPE_TRACTION_CONTROL_ACTIVE:
- permission = Car.PERMISSION_VEHICLE_DYNAMICS_STATE;
- break;
- default:
- break;
- }
- return permission;
- }
-
- private boolean startSensor(SensorRecord record, int sensorType, int rate) {
- //TODO handle sensor rate properly. bug: 32095903
- //Some sensors which report only when there is change should be always set with maximum
- //rate. For now, set every sensor to the maximum.
- if (Log.isLoggable(CarLog.TAG_SENSOR, Log.VERBOSE)) {
- Log.v(CarLog.TAG_SENSOR, "startSensor " + sensorType + " with rate " + rate);
- }
- SensorBase sensorHal = getSensorHal(sensorType);
- if (sensorHal != null) {
- if (!sensorHal.isReady()) {
- Log.w(CarLog.TAG_SENSOR, "Sensor channel not available.");
- return false;
- }
- if (record.enabled) {
- return true;
- }
- if (sensorHal.requestSensorStart(sensorType, 0)) {
- record.enabled = true;
- return true;
- }
- }
- Log.w(CarLog.TAG_SENSOR, "requestSensorStart failed, sensor type:" + sensorType);
- return false;
- }
-
- @Override
- public void unregisterSensorListener(int sensorType, ICarSensorEventListener listener) {
- boolean shouldStopSensor = false;
- boolean shouldRestartSensor = false;
- SensorRecord record = null;
- int newRate = 0;
- mSensorLock.lock();
- try {
- record = mSensorRecords.get(sensorType);
- if (record == null) {
- // unregister not supported sensor. ignore.
- if (Log.isLoggable(CarLog.TAG_SENSOR, Log.DEBUG)) {
- Log.d(CarLog.TAG_SENSOR, "unregister for unsupported sensor");
- }
- return;
- }
- SensorClient sensorClient = findSensorClientLocked(listener);
- if (sensorClient == null) {
- // never registered or already unregistered.
- if (Log.isLoggable(CarLog.TAG_SENSOR, Log.DEBUG)) {
- Log.d(CarLog.TAG_SENSOR, "unregister for not existing client");
- }
- return;
- }
- sensorClient.removeSensor(sensorType);
- if (sensorClient.getNumberOfActiveSensor() == 0) {
- sensorClient.release();
- mClients.remove(sensorClient);
- }
- Listeners<SensorClient> sensorListeners = mSensorListeners.get(sensorType);
- if (sensorListeners == null) {
- // sensor not active
- if (Log.isLoggable(CarLog.TAG_SENSOR, Log.DEBUG)) {
- Log.d(CarLog.TAG_SENSOR, "unregister for non-active sensor");
- }
- return;
- }
- ClientWithRate<SensorClient> clientWithRate =
- sensorListeners.findClientWithRate(sensorClient);
- if (clientWithRate == null) {
- if (Log.isLoggable(CarLog.TAG_SENSOR, Log.DEBUG)) {
- Log.d(CarLog.TAG_SENSOR, "unregister for not registered sensor");
- }
- return;
- }
- sensorListeners.removeClientWithRate(clientWithRate);
- if (sensorListeners.getNumberOfClients() == 0) {
- shouldStopSensor = true;
- mSensorListeners.remove(sensorType);
- } else if (sensorListeners.updateRate()) { // rate changed
- newRate = sensorListeners.getRate();
- shouldRestartSensor = sensorSupportRate(sensorType);
- }
- if (Log.isLoggable(CarLog.TAG_SENSOR, Log.DEBUG)) {
- Log.d(CarLog.TAG_SENSOR, "unregister succeeded");
- }
- } finally {
- mSensorLock.unlock();
- }
- if (shouldStopSensor) {
- stopSensor(record, sensorType);
- } else if (shouldRestartSensor) {
- startSensor(record, sensorType, newRate);
- }
- }
-
- @Override
- public CarSensorConfig getSensorConfig(int sensorType) {
- if (Binder.getCallingUid() != Process.myUid()) {
- switch (getSensorPermission(sensorType)) {
- case PackageManager.PERMISSION_DENIED:
- throw new SecurityException("client does not have permission:"
- + getPermissionName(sensorType)
- + " pid:" + Binder.getCallingPid()
- + " uid:" + Binder.getCallingUid());
- case PackageManager.PERMISSION_GRANTED:
- break;
- }
- }
- return(mSensorHal.getSensorConfig(sensorType));
- }
-
- private void stopSensor(SensorRecord record, int sensorType) {
- if (Log.isLoggable(CarLog.TAG_SENSOR, Log.DEBUG)) {
- Log.d(CarLog.TAG_SENSOR, "stopSensor " + sensorType);
- }
- SensorBase sensorHal = getSensorHal(sensorType);
- if (sensorHal == null || !sensorHal.isReady()) {
- Log.w(CarLog.TAG_SENSOR, "Sensor channel not available.");
- return;
- }
- if (!record.enabled) {
- return;
- }
- record.enabled = false;
- // make lastEvent invalid as old data can be sent to client when subscription is restarted
- // later.
- record.lastEvent = null;
- if (Log.isLoggable(CarLog.TAG_SENSOR, Log.DEBUG)) {
- Log.d(CarLog.TAG_SENSOR, "stopSensor requestStop " + sensorType);
- }
- sensorHal.requestSensorStop(sensorType);
- }
-
- private SensorBase getSensorHal(int sensorType) {
- try {
- mSensorLock.lock();
- switch (sensorType) {
- case CarSensorManager.SENSOR_TYPE_DRIVING_STATUS:
- if (mUseDefaultDrivingPolicy) {
- return mDrivingStatePolicy;
- }
- break;
- case CarSensorManager.SENSOR_TYPE_NIGHT:
- if (mUseDefaultDayNightModePolicy) {
- return mDayNightModePolicy;
- }
- break;
- }
- return mSensorHal;
- } finally {
- mSensorLock.unlock();
- }
- }
-
- @Override
- public CarSensorEvent getLatestSensorEvent(int sensorType) {
- SensorRecord record = null;
- mSensorLock.lock();
- try {
- record = mSensorRecords.get(sensorType);
- } finally {
- mSensorLock.unlock();
- }
- if (record != null) {
- return record.lastEvent;
- }
- return null;
- }
-
- private int[] refreshSupportedSensorsLocked() {
- int numCarSensors = (mCarProvidedSensors == null) ? 0 : mCarProvidedSensors.length;
- for (int i = 0; i < numCarSensors; i++) {
- int sensor = mCarProvidedSensors[i];
- if (sensor == CarSensorManager.SENSOR_TYPE_DRIVING_STATUS) {
- mUseDefaultDrivingPolicy = false;
- } else if (sensor == CarSensorManager.SENSOR_TYPE_NIGHT) {
- mUseDefaultDayNightModePolicy = false;
- }
- }
- int totalNumSensors = numCarSensors;
- if (mUseDefaultDrivingPolicy) {
- totalNumSensors++;
- }
- if (mUseDefaultDayNightModePolicy) {
- totalNumSensors++;
- }
- // Two logical sensors are always added.
- int[] supportedSensors = new int[totalNumSensors];
- int index = 0;
- if (mUseDefaultDrivingPolicy) {
- supportedSensors[index] = CarSensorManager.SENSOR_TYPE_DRIVING_STATUS;
- index++;
- }
- if (mUseDefaultDayNightModePolicy) {
- supportedSensors[index] = CarSensorManager.SENSOR_TYPE_NIGHT;
- index++;
- }
-
- for (int i = 0; i < numCarSensors; i++) {
- int sensor = mCarProvidedSensors[i];
-
- if (mSensorRecords.get(sensor) == null) {
- SensorRecord record = new SensorRecord();
- mSensorRecords.put(sensor, record);
- }
- supportedSensors[index] = sensor;
- index++;
- }
-
- return supportedSensors;
- }
-
- private boolean isSensorRealLocked(int sensorType) {
- if (mCarProvidedSensors != null) {
- for (int sensor : mCarProvidedSensors) {
- if (sensor == sensorType ) {
- return true;
- }
- }
- }
- return false;
- }
-
- /**
- * Find SensorClient from client list and return it.
- * This should be called with mClients locked.
- * @param listener
- * @return null if not found.
- */
- private SensorClient findSensorClientLocked(ICarSensorEventListener listener) {
- IBinder binder = listener.asBinder();
- for (SensorClient sensorClient : mClients) {
- if (sensorClient.isHoldingListenerBinder(binder)) {
- return sensorClient;
- }
- }
- return null;
- }
-
- private void removeClient(SensorClient sensorClient) {
- mSensorLock.lock();
- try {
- for (int sensor: sensorClient.getSensorArray()) {
- unregisterSensorListener(sensor,
- sensorClient.getICarSensorEventListener());
- }
- mClients.remove(sensorClient);
- } finally {
- mSensorLock.unlock();
- }
- }
-
- private class SensorDispatchHandler extends Handler {
- private static final long SENSOR_DISPATCH_MIN_INTERVAL_MS = 16; // over 60Hz
-
- private static final int MSG_SENSOR_DATA = 0;
-
- private long mLastSensorDispatchTime = -1;
- private int mFreeListIndex = 0;
- private final LinkedList<CarSensorEvent>[] mSensorDataList = new LinkedList[2];
-
- private SensorDispatchHandler(Looper looper) {
- super(looper);
- for (int i = 0; i < mSensorDataList.length; i++) {
- mSensorDataList[i] = new LinkedList<CarSensorEvent>();
- }
- }
-
- private synchronized void handleSensorEvents(List<CarSensorEvent> data) {
- LinkedList<CarSensorEvent> list = mSensorDataList[mFreeListIndex];
- list.addAll(data);
- requestDispatchLocked();
- }
-
- private synchronized void handleSensorEvent(CarSensorEvent event) {
- LinkedList<CarSensorEvent> list = mSensorDataList[mFreeListIndex];
- list.add(event);
- requestDispatchLocked();
- }
-
- private void requestDispatchLocked() {
- Message msg = obtainMessage(MSG_SENSOR_DATA);
- long now = SystemClock.uptimeMillis();
- long delta = now - mLastSensorDispatchTime;
- if (delta > SENSOR_DISPATCH_MIN_INTERVAL_MS) {
- sendMessage(msg);
- } else {
- sendMessageDelayed(msg, SENSOR_DISPATCH_MIN_INTERVAL_MS - delta);
- }
- }
-
- @Override
- public void handleMessage(Message msg) {
- switch (msg.what) {
- case MSG_SENSOR_DATA:
- doHandleSensorData();
- break;
- default:
- break;
- }
- }
-
- private void doHandleSensorData() {
- List<CarSensorEvent> listToDispatch = null;
- synchronized (this) {
- mLastSensorDispatchTime = SystemClock.uptimeMillis();
- int nonFreeListIndex = mFreeListIndex ^ 0x1;
- List<CarSensorEvent> nonFreeList = mSensorDataList[nonFreeListIndex];
- List<CarSensorEvent> freeList = mSensorDataList[mFreeListIndex];
- if (nonFreeList.size() > 0) {
- Log.w(CarLog.TAG_SENSOR, "non free list not empty");
- // copy again, but this should not be normal case
- nonFreeList.addAll(freeList);
- listToDispatch = nonFreeList;
- freeList.clear();
- } else if (freeList.size() > 0) {
- listToDispatch = freeList;
- mFreeListIndex = nonFreeListIndex;
- }
- }
- // leave this part outside lock so that time-taking dispatching can be done without
- // blocking sensor event notification.
- if (listToDispatch != null) {
- processSensorData(listToDispatch);
- listToDispatch.clear();
- }
- }
-
- }
-
- /** internal instance for pending client request */
- private class SensorClient implements Listeners.IListener {
- /** callback for sensor events */
- private final ICarSensorEventListener mListener;
- private final SparseBooleanArray mActiveSensors = new SparseBooleanArray();
-
- /** when false, it is already released */
- private volatile boolean mActive = true;
-
- SensorClient(ICarSensorEventListener listener) {
- this.mListener = listener;
- }
-
- @Override
- public boolean equals(Object o) {
- if (o instanceof SensorClient &&
- mListener.asBinder() == ((SensorClient) o).mListener.asBinder()) {
- return true;
- }
- return false;
- }
-
- boolean isHoldingListenerBinder(IBinder listenerBinder) {
- return mListener.asBinder() == listenerBinder;
- }
-
- void addSensor(int sensor) {
- mActiveSensors.put(sensor, true);
- }
-
- void removeSensor(int sensor) {
- mActiveSensors.delete(sensor);
- }
-
- int getNumberOfActiveSensor() {
- return mActiveSensors.size();
- }
-
- int[] getSensorArray() {
- int[] sensors = new int[mActiveSensors.size()];
- for (int i = sensors.length - 1; i >= 0; --i) {
- sensors[i] = mActiveSensors.keyAt(i);
- }
- return sensors;
- }
-
- ICarSensorEventListener getICarSensorEventListener() {
- return mListener;
- }
-
- /**
- * Client dead. should remove all sensor requests from client
- */
- @Override
- public void binderDied() {
- mListener.asBinder().unlinkToDeath(this, 0);
- removeClient(this);
- }
-
- void dispatchSensorUpdate(List<CarSensorEvent> events) {
- if (events.size() == 0) {
- return;
- }
- if (mActive) {
- try {
- mListener.onSensorChanged(events);
- } catch (RemoteException e) {
- //ignore. crash will be handled by death handler
- }
- } else {
- if (Log.isLoggable(CarLog.TAG_SENSOR, Log.DEBUG)) {
- Log.d(CarLog.TAG_SENSOR, "sensor update while client is already released");
- }
- }
- }
-
- @Override
- public void release() {
- if (mActive) {
- mListener.asBinder().unlinkToDeath(this, 0);
- mActiveSensors.clear();
- mActive = false;
- }
- }
- }
-
- private static class SensorRecord {
- /** Record the lastly received sensor event */
- CarSensorEvent lastEvent = null;
- /** sensor was enabled by at least one client */
- boolean enabled = false;
- }
-
- @Override
- public void dump(PrintWriter writer) {
- writer.println("*CarSensorService*");
- writer.println("supported sensors:" + Arrays.toString(mSupportedSensors));
- writer.println("**last events for sensors**");
- if (mSensorRecords != null) {
- try {
- int sensorRecordSize = mSensorRecords.size();
- for (int i = 0; i < sensorRecordSize; i++) {
- int sensor = mSensorRecords.keyAt(i);
- SensorRecord record = mSensorRecords.get(sensor);
- if (record != null && record.lastEvent != null) {
- writer.println("sensor: " + sensor
- + " active: " + record.enabled);
- writer.println(" " + record.lastEvent.toString());
- }
- Listeners listeners = mSensorListeners.get(sensor);
- if (listeners != null) {
- writer.println(" rate: " + listeners.getRate());
- }
- }
- } catch (ConcurrentModificationException e) {
- writer.println("concurrent modification happened");
- }
- } else {
- writer.println("null records");
- }
- writer.println("**clients**");
- try {
- for (SensorClient client: mClients) {
- if (client != null) {
- try {
- writer.println("binder:" + client.mListener
- + " active sensors:" + Arrays.toString(client.getSensorArray()));
- } catch (ConcurrentModificationException e) {
- writer.println("concurrent modification happened");
- }
- } else {
- writer.println("null client");
- }
- }
- } catch (ConcurrentModificationException e) {
- writer.println("concurrent modification happened");
- }
- writer.println("**sensor listeners**");
- try {
- int sensorListenerSize = mSensorListeners.size();
- for (int i = 0; i < sensorListenerSize; i++) {
- int sensor = mSensorListeners.keyAt(i);
- Listeners sensorListeners = mSensorListeners.get(sensor);
- if (sensorListeners != null) {
- writer.println(" Sensor:" + sensor
- + " num client:" + sensorListeners.getNumberOfClients()
- + " rate:" + sensorListeners.getRate());
- }
- }
- } catch (ConcurrentModificationException e) {
- writer.println("concurrent modification happened");
- }
- writer.println("mUseDefaultDrivingPolicy:" + mUseDefaultDrivingPolicy +
- ",mUseDefaultDayNightModePolicy" + mUseDefaultDayNightModePolicy);
- writer.println("**driving policy**");
- if (mUseDefaultDrivingPolicy) {
- mDrivingStatePolicy.dump(writer);
- }
- writer.println("**day/night policy**");
- if (mUseDefaultDayNightModePolicy) {
- mDayNightModePolicy.dump(writer);
- }
- }
-}
diff --git a/service/src/com/android/car/CarService.java b/service/src/com/android/car/CarService.java
index 87e891e..47d3137 100644
--- a/service/src/com/android/car/CarService.java
+++ b/service/src/com/android/car/CarService.java
@@ -13,6 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
+
package com.android.car;
import static android.os.SystemClock.elapsedRealtime;
@@ -27,10 +28,13 @@
import android.os.IBinder;
import android.os.IHwBinder.DeathRecipient;
import android.os.RemoteException;
+import android.os.ServiceManager;
import android.os.SystemClock;
import android.os.SystemProperties;
import android.util.Log;
+import com.android.car.systeminterface.SystemInterface;
+
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.util.RingBufferIndices;
@@ -85,16 +89,23 @@
Log.i(CarLog.TAG_SERVICE, "Connected to " + mVehicleInterfaceName);
- mICarImpl = new ICarImpl(this, mVehicle, SystemInterface.getDefault(this),
- mCanBusErrorNotifier);
+ mICarImpl = new ICarImpl(this,
+ mVehicle,
+ SystemInterface.Builder.defaultSystemInterface(this).build(),
+ mCanBusErrorNotifier,
+ mVehicleInterfaceName);
mICarImpl.init();
SystemProperties.set("boot.car_service_created", "1");
linkToDeath(mVehicle, mVehicleDeathRecipient);
+ ServiceManager.addService("car_service", mICarImpl);
super.onCreate();
}
+ // onDestroy is best-effort and might not get called on shutdown/reboot. As such it is not
+ // suitable for permanently saving state or other need-to-happen operation. If you have a
+ // cleanup task that you want to make sure happens on shutdown/reboot, see OnShutdownReboot.
@Override
public void onDestroy() {
Log.i(CarLog.TAG_SERVICE, "Service onDestroy");
@@ -126,24 +137,10 @@
@Override
protected void dump(FileDescriptor fd, PrintWriter writer, String[] args) {
- if (checkCallingOrSelfPermission(android.Manifest.permission.DUMP)
- != PackageManager.PERMISSION_GRANTED) {
- writer.println("Permission Denial: can't dump CarService from from pid="
- + Binder.getCallingPid() + ", uid=" + Binder.getCallingUid()
- + " without permission " + android.Manifest.permission.DUMP);
- return;
- }
- if (args == null || args.length == 0) {
- writer.println("*dump car service*");
- writer.println("Vehicle HAL Interface: " + mVehicleInterfaceName);
- mICarImpl.dump(writer);
-
- writer.println("**Debug info**");
- writer.println("Vehicle HAL reconnected: "
- + mVehicleDeathRecipient.deathCount + " times.");
- } else {
- mICarImpl.execShellCmd(args, writer);
- }
+ // historically, the way to get a dumpsys from CarService has been to use
+ // "dumpsys activity service com.android.car/.CarService" - leaving this
+ // as a forward to car_service makes the previously well-known command still work
+ mICarImpl.dump(fd, writer, args);
}
@Nullable
diff --git a/service/src/com/android/car/CarStorageMonitoringService.java b/service/src/com/android/car/CarStorageMonitoringService.java
new file mode 100644
index 0000000..80434c1
--- /dev/null
+++ b/service/src/com/android/car/CarStorageMonitoringService.java
@@ -0,0 +1,648 @@
+/*
+ * 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.android.car;
+
+import android.car.Car;
+import android.car.storagemonitoring.CarStorageMonitoringManager;
+import android.car.storagemonitoring.ICarStorageMonitoring;
+import android.car.storagemonitoring.IIoStatsListener;
+import android.car.storagemonitoring.IoStats;
+import android.car.storagemonitoring.IoStatsEntry;
+import android.car.storagemonitoring.IoStatsEntry.Metrics;
+import android.car.storagemonitoring.LifetimeWriteInfo;
+import android.car.storagemonitoring.UidIoRecord;
+import android.car.storagemonitoring.WearEstimate;
+import android.car.storagemonitoring.WearEstimateChange;
+import android.content.ActivityNotFoundException;
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.Intent;
+import android.content.res.Resources;
+import android.os.RemoteCallbackList;
+import android.os.RemoteException;
+import android.util.JsonWriter;
+import android.util.Log;
+import android.util.SparseArray;
+
+import com.android.car.internal.CarPermission;
+import com.android.car.storagemonitoring.IoStatsTracker;
+import com.android.car.storagemonitoring.UidIoStatsProvider;
+import com.android.car.storagemonitoring.WearEstimateRecord;
+import com.android.car.storagemonitoring.WearHistory;
+import com.android.car.storagemonitoring.WearInformation;
+import com.android.car.storagemonitoring.WearInformationProvider;
+import com.android.car.systeminterface.SystemInterface;
+
+import org.json.JSONArray;
+import org.json.JSONException;
+import org.json.JSONObject;
+
+import java.io.File;
+import java.io.FileWriter;
+import java.io.IOException;
+import java.io.PrintWriter;
+import java.nio.file.Files;
+import java.time.Duration;
+import java.time.Instant;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Objects;
+import java.util.Optional;
+import java.util.stream.Collectors;
+import java.util.stream.IntStream;
+
+public class CarStorageMonitoringService extends ICarStorageMonitoring.Stub
+ implements CarServiceBase {
+ public static final String INTENT_EXCESSIVE_IO =
+ CarStorageMonitoringManager.INTENT_EXCESSIVE_IO;
+
+ public static final long SHUTDOWN_COST_INFO_MISSING =
+ CarStorageMonitoringManager.SHUTDOWN_COST_INFO_MISSING;
+
+ private static final boolean DBG = false;
+ private static final String TAG = CarLog.TAG_STORAGE;
+ private static final int MIN_WEAR_ESTIMATE_OF_CONCERN = 80;
+
+ static final String UPTIME_TRACKER_FILENAME = "service_uptime";
+ static final String WEAR_INFO_FILENAME = "wear_info";
+ static final String LIFETIME_WRITES_FILENAME = "lifetime_write";
+
+ private final WearInformationProvider[] mWearInformationProviders;
+ private final Context mContext;
+ private final File mUptimeTrackerFile;
+ private final File mWearInfoFile;
+ private final File mLifetimeWriteFile;
+ private final OnShutdownReboot mOnShutdownReboot;
+ private final SystemInterface mSystemInterface;
+ private final UidIoStatsProvider mUidIoStatsProvider;
+ private final SlidingWindow<IoStats> mIoStatsSamples;
+ private final RemoteCallbackList<IIoStatsListener> mListeners;
+ private final Object mIoStatsSamplesLock = new Object();
+ private final Configuration mConfiguration;
+
+ private final CarPermission mStorageMonitoringPermission;
+
+ private UptimeTracker mUptimeTracker = null;
+ private Optional<WearInformation> mWearInformation = Optional.empty();
+ private List<WearEstimateChange> mWearEstimateChanges = Collections.emptyList();
+ private List<IoStatsEntry> mBootIoStats = Collections.emptyList();
+ private IoStatsTracker mIoStatsTracker = null;
+ private boolean mInitialized = false;
+
+ private long mShutdownCostInfo = SHUTDOWN_COST_INFO_MISSING;
+ private String mShutdownCostMissingReason;
+
+ public CarStorageMonitoringService(Context context, SystemInterface systemInterface) {
+ mContext = context;
+ Resources resources = mContext.getResources();
+ mConfiguration = new Configuration(resources);
+
+ if (Log.isLoggable(TAG, Log.DEBUG)) {
+ Log.d(TAG, "service configuration: " + mConfiguration);
+ }
+
+ mUidIoStatsProvider = systemInterface.getUidIoStatsProvider();
+ mUptimeTrackerFile = new File(systemInterface.getFilesDir(), UPTIME_TRACKER_FILENAME);
+ mWearInfoFile = new File(systemInterface.getFilesDir(), WEAR_INFO_FILENAME);
+ mLifetimeWriteFile = new File(systemInterface.getFilesDir(), LIFETIME_WRITES_FILENAME);
+ mOnShutdownReboot = new OnShutdownReboot(mContext);
+ mSystemInterface = systemInterface;
+ mWearInformationProviders = systemInterface.getFlashWearInformationProviders();
+ mStorageMonitoringPermission =
+ new CarPermission(mContext, Car.PERMISSION_STORAGE_MONITORING);
+ mWearEstimateChanges = Collections.emptyList();
+ mIoStatsSamples = new SlidingWindow<>(mConfiguration.ioStatsNumSamplesToStore);
+ mListeners = new RemoteCallbackList<>();
+ systemInterface.scheduleActionForBootCompleted(this::doInitServiceIfNeeded,
+ Duration.ofSeconds(10));
+ }
+
+ private Optional<WearInformation> loadWearInformation() {
+ for (WearInformationProvider provider : mWearInformationProviders) {
+ WearInformation wearInfo = provider.load();
+ if (wearInfo != null) {
+ Log.d(TAG, "retrieved wear info " + wearInfo + " via provider " + provider);
+ return Optional.of(wearInfo);
+ }
+ }
+
+ Log.d(TAG, "no wear info available");
+ return Optional.empty();
+ }
+
+ private WearHistory loadWearHistory() {
+ if (mWearInfoFile.exists()) {
+ try {
+ WearHistory wearHistory = WearHistory.fromJson(mWearInfoFile);
+ Log.d(TAG, "retrieved wear history " + wearHistory);
+ return wearHistory;
+ } catch (IOException | JSONException e) {
+ Log.e(TAG, "unable to read wear info file " + mWearInfoFile, e);
+ }
+ }
+
+ Log.d(TAG, "no wear history available");
+ return new WearHistory();
+ }
+
+ // returns true iff a new event was added (and hence the history needs to be saved)
+ private boolean addEventIfNeeded(WearHistory wearHistory) {
+ if (!mWearInformation.isPresent()) return false;
+
+ WearInformation wearInformation = mWearInformation.get();
+ WearEstimate lastWearEstimate;
+ WearEstimate currentWearEstimate = wearInformation.toWearEstimate();
+
+ if (wearHistory.size() == 0) {
+ lastWearEstimate = WearEstimate.UNKNOWN_ESTIMATE;
+ } else {
+ lastWearEstimate = wearHistory.getLast().getNewWearEstimate();
+ }
+
+ if (currentWearEstimate.equals(lastWearEstimate)) return false;
+
+ WearEstimateRecord newRecord = new WearEstimateRecord(lastWearEstimate,
+ currentWearEstimate,
+ mUptimeTracker.getTotalUptime(),
+ Instant.now());
+ Log.d(TAG, "new wear record generated " + newRecord);
+ wearHistory.add(newRecord);
+ return true;
+ }
+
+ private void storeWearHistory(WearHistory wearHistory) {
+ try (JsonWriter jsonWriter = new JsonWriter(new FileWriter(mWearInfoFile))) {
+ wearHistory.writeToJson(jsonWriter);
+ } catch (IOException e) {
+ Log.e(TAG, "unable to write wear info file" + mWearInfoFile, e);
+ }
+ }
+
+ @Override
+ public void init() {
+ Log.d(TAG, "CarStorageMonitoringService init()");
+
+ mUptimeTracker = new UptimeTracker(mUptimeTrackerFile,
+ mConfiguration.uptimeIntervalBetweenUptimeDataWriteMs,
+ mSystemInterface);
+ }
+
+ private void launchWearChangeActivity() {
+ final String activityPath = mConfiguration.activityHandlerForFlashWearChanges;
+ if (activityPath.isEmpty()) return;
+ try {
+ final ComponentName activityComponent =
+ Objects.requireNonNull(ComponentName.unflattenFromString(activityPath));
+ Intent intent = new Intent();
+ intent.setComponent(activityComponent);
+ intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+ mContext.startActivity(intent);
+ } catch (ActivityNotFoundException | NullPointerException e) {
+ Log.e(TAG,
+ "value of activityHandlerForFlashWearChanges invalid non-empty string " +
+ activityPath, e);
+ }
+ }
+
+ private static void logOnAdverseWearLevel(WearInformation wearInformation) {
+ if (wearInformation.preEolInfo > WearInformation.PRE_EOL_INFO_NORMAL ||
+ Math.max(wearInformation.lifetimeEstimateA,
+ wearInformation.lifetimeEstimateB) >= MIN_WEAR_ESTIMATE_OF_CONCERN) {
+ Log.w(TAG, "flash storage reached wear a level that requires attention: "
+ + wearInformation);
+ }
+ }
+
+ private SparseArray<UidIoRecord> loadNewIoStats() {
+ SparseArray<UidIoRecord> ioRecords = mUidIoStatsProvider.load();
+ return (ioRecords == null ? new SparseArray<>() : ioRecords);
+ }
+
+ private void collectNewIoMetrics() {
+ IoStats ioStats;
+
+ mIoStatsTracker.update(loadNewIoStats());
+ synchronized (mIoStatsSamplesLock) {
+ ioStats = new IoStats(
+ SparseArrayStream.valueStream(mIoStatsTracker.getCurrentSample())
+ .collect(Collectors.toList()),
+ mSystemInterface.getUptime());
+ mIoStatsSamples.add(ioStats);
+ }
+
+ if (DBG) {
+ SparseArray<IoStatsEntry> currentSample = mIoStatsTracker.getCurrentSample();
+ if (currentSample.size() == 0) {
+ Log.d(TAG, "no new I/O stat data");
+ } else {
+ SparseArrayStream.valueStream(currentSample).forEach(
+ uidIoStats -> Log.d(TAG, "updated I/O stat data: " + uidIoStats));
+ }
+ }
+
+ dispatchNewIoEvent(ioStats);
+ if (needsExcessiveIoBroadcast()) {
+ Log.d(TAG, "about to send " + INTENT_EXCESSIVE_IO);
+ sendExcessiveIoBroadcast();
+ }
+ }
+
+ private void sendExcessiveIoBroadcast() {
+ Log.w(TAG, "sending " + INTENT_EXCESSIVE_IO);
+
+ final String receiverPath = mConfiguration.intentReceiverForUnacceptableIoMetrics;
+ if (receiverPath.isEmpty()) return;
+
+ final ComponentName receiverComponent;
+ try {
+ receiverComponent = Objects.requireNonNull(
+ ComponentName.unflattenFromString(receiverPath));
+ } catch (NullPointerException e) {
+ Log.e(TAG, "value of intentReceiverForUnacceptableIoMetrics non-null but invalid:"
+ + receiverPath, e);
+ return;
+ }
+
+ Intent intent = new Intent(INTENT_EXCESSIVE_IO);
+ intent.setComponent(receiverComponent);
+ intent.addFlags(Intent.FLAG_RECEIVER_FOREGROUND);
+ mContext.sendBroadcast(intent, mStorageMonitoringPermission.toString());
+ }
+
+ private boolean needsExcessiveIoBroadcast() {
+ synchronized (mIoStatsSamplesLock) {
+ return mIoStatsSamples.count((IoStats delta) -> {
+ Metrics total = delta.getTotals();
+ final boolean tooManyBytesWritten =
+ (total.bytesWrittenToStorage > mConfiguration.acceptableBytesWrittenPerSample);
+ final boolean tooManyFsyncCalls =
+ (total.fsyncCalls > mConfiguration.acceptableFsyncCallsPerSample);
+ return tooManyBytesWritten || tooManyFsyncCalls;
+ }) > mConfiguration.maxExcessiveIoSamplesInWindow;
+ }
+ }
+
+ private void dispatchNewIoEvent(IoStats delta) {
+ final int listenersCount = mListeners.beginBroadcast();
+ IntStream.range(0, listenersCount).forEach(
+ i -> {
+ try {
+ mListeners.getBroadcastItem(i).onSnapshot(delta);
+ } catch (RemoteException e) {
+ Log.w(TAG, "failed to dispatch snapshot", e);
+ }
+ });
+ mListeners.finishBroadcast();
+ }
+
+ private synchronized void doInitServiceIfNeeded() {
+ if (mInitialized) return;
+
+ Log.d(TAG, "initializing CarStorageMonitoringService");
+
+ mWearInformation = loadWearInformation();
+
+ // TODO(egranata): can this be done lazily?
+ final WearHistory wearHistory = loadWearHistory();
+ final boolean didWearChangeHappen = addEventIfNeeded(wearHistory);
+ if (didWearChangeHappen) {
+ storeWearHistory(wearHistory);
+ }
+ Log.d(TAG, "wear history being tracked is " + wearHistory);
+ mWearEstimateChanges = wearHistory.toWearEstimateChanges(
+ mConfiguration.acceptableHoursPerOnePercentFlashWear);
+
+ mOnShutdownReboot.addAction((c, i) -> logLifetimeWrites())
+ .addAction((c, i) -> release());
+
+ mWearInformation.ifPresent(CarStorageMonitoringService::logOnAdverseWearLevel);
+
+ if (didWearChangeHappen) {
+ launchWearChangeActivity();
+ }
+
+ long bootUptime = mSystemInterface.getUptime();
+ mBootIoStats = SparseArrayStream.valueStream(loadNewIoStats())
+ .map(record -> {
+ // at boot, assume all UIDs have been running for as long as the system has
+ // been up, since we don't really know any better
+ IoStatsEntry stats = new IoStatsEntry(record, bootUptime);
+ if (DBG) {
+ Log.d(TAG, "loaded boot I/O stat data: " + stats);
+ }
+ return stats;
+ }).collect(Collectors.toList());
+
+ mIoStatsTracker = new IoStatsTracker(mBootIoStats,
+ mConfiguration.ioStatsRefreshRateMs,
+ mSystemInterface.getSystemStateInterface());
+
+ if (mConfiguration.ioStatsNumSamplesToStore > 0) {
+ mSystemInterface.scheduleAction(this::collectNewIoMetrics,
+ mConfiguration.ioStatsRefreshRateMs);
+ } else {
+ Log.i(TAG, "service configuration disabled I/O sample window. not collecting samples");
+ }
+
+ mShutdownCostInfo = computeShutdownCost();
+ Log.d(TAG, "calculated data written in last shutdown was " +
+ mShutdownCostInfo + " bytes");
+ mLifetimeWriteFile.delete();
+
+ Log.i(TAG, "CarStorageMonitoringService is up");
+
+ mInitialized = true;
+ }
+
+ private long computeShutdownCost() {
+ List<LifetimeWriteInfo> shutdownWrites = loadLifetimeWrites();
+ if (shutdownWrites.isEmpty()) {
+ Log.d(TAG, "lifetime write data from last shutdown missing");
+ mShutdownCostMissingReason = "no historical writes stored at last shutdown";
+ return SHUTDOWN_COST_INFO_MISSING;
+ }
+ List<LifetimeWriteInfo> currentWrites =
+ Arrays.asList(mSystemInterface.getLifetimeWriteInfoProvider().load());
+ if (currentWrites.isEmpty()) {
+ Log.d(TAG, "current lifetime write data missing");
+ mShutdownCostMissingReason = "current write data cannot be obtained";
+ return SHUTDOWN_COST_INFO_MISSING;
+ }
+
+ long shutdownCost = 0;
+
+ Map<String, Long> shutdownLifetimeWrites = new HashMap<>();
+ shutdownWrites.forEach(li ->
+ shutdownLifetimeWrites.put(li.partition, li.writtenBytes));
+
+ // for every partition currently available, look for it in the shutdown data
+ for(int i = 0; i < currentWrites.size(); ++i) {
+ LifetimeWriteInfo li = currentWrites.get(i);
+ // if this partition was not available when we last shutdown the system, then
+ // just pretend we had written the same amount of data then as we have now
+ final long writtenAtShutdown =
+ shutdownLifetimeWrites.getOrDefault(li.partition, li.writtenBytes);
+ final long costDelta = li.writtenBytes - writtenAtShutdown;
+ if (costDelta >= 0) {
+ Log.d(TAG, "partition " + li.partition + " had " + costDelta +
+ " bytes written to it during shutdown");
+ shutdownCost += costDelta;
+ } else {
+ // the counter of written bytes should be monotonic; a decrease might mean
+ // corrupt data, improper shutdown or that the kernel in use does not
+ // have proper monotonic guarantees on the lifetime write data. If any of these
+ // occur, it's probably safer to just bail out and say we don't know
+ mShutdownCostMissingReason = li.partition + " has a negative write amount (" +
+ costDelta + " bytes)";
+ Log.e(TAG, "partition " + li.partition + " reported " + costDelta +
+ " bytes written to it during shutdown. assuming we can't" +
+ " determine proper shutdown information.");
+ return SHUTDOWN_COST_INFO_MISSING;
+ }
+ }
+
+ return shutdownCost;
+ }
+
+ private List<LifetimeWriteInfo> loadLifetimeWrites() {
+ if (!mLifetimeWriteFile.exists() || !mLifetimeWriteFile.isFile()) {
+ Log.d(TAG, "lifetime write file missing or inaccessible " + mLifetimeWriteFile);
+ return Collections.emptyList();
+ }
+ try {
+ JSONObject jsonObject = new JSONObject(
+ new String(Files.readAllBytes(mLifetimeWriteFile.toPath())));
+
+ JSONArray jsonArray = jsonObject.getJSONArray("lifetimeWriteInfo");
+
+ List<LifetimeWriteInfo> result = new ArrayList<>();
+ for (int i = 0; i < jsonArray.length(); ++i) {
+ result.add(new LifetimeWriteInfo(jsonArray.getJSONObject(i)));
+ }
+ return result;
+ } catch (JSONException | IOException e) {
+ Log.e(TAG, "lifetime write file does not contain valid JSON", e);
+ return Collections.emptyList();
+ }
+ }
+
+ private void logLifetimeWrites() {
+ try {
+ LifetimeWriteInfo[] lifetimeWriteInfos =
+ mSystemInterface.getLifetimeWriteInfoProvider().load();
+ JsonWriter jsonWriter = new JsonWriter(new FileWriter(mLifetimeWriteFile));
+ jsonWriter.beginObject();
+ jsonWriter.name("lifetimeWriteInfo").beginArray();
+ for (LifetimeWriteInfo writeInfo : lifetimeWriteInfos) {
+ Log.d(TAG, "storing lifetime write info " + writeInfo);
+ writeInfo.writeToJson(jsonWriter);
+ }
+ jsonWriter.endArray().endObject();
+ jsonWriter.close();
+ } catch (IOException e) {
+ Log.e(TAG, "unable to save lifetime write info on shutdown", e);
+ }
+ }
+
+ @Override
+ public void release() {
+ Log.i(TAG, "tearing down CarStorageMonitoringService");
+ if (mUptimeTracker != null) {
+ mUptimeTracker.onDestroy();
+ }
+ mOnShutdownReboot.clearActions();
+ mListeners.kill();
+ }
+
+ @Override
+ public void dump(PrintWriter writer) {
+ doInitServiceIfNeeded();
+
+ writer.println("*CarStorageMonitoringService*");
+ writer.println("last wear information retrieved: " +
+ mWearInformation.map(WearInformation::toString).orElse("missing"));
+ writer.println("wear change history: " +
+ mWearEstimateChanges.stream()
+ .map(WearEstimateChange::toString)
+ .collect(Collectors.joining("\n")));
+ writer.println("boot I/O stats: " +
+ mBootIoStats.stream()
+ .map(IoStatsEntry::toString)
+ .collect(Collectors.joining("\n")));
+ writer.println("aggregate I/O stats: " +
+ SparseArrayStream.valueStream(mIoStatsTracker.getTotal())
+ .map(IoStatsEntry::toString)
+ .collect(Collectors.joining("\n")));
+ writer.println("I/O stats snapshots: ");
+ synchronized (mIoStatsSamplesLock) {
+ writer.println(
+ mIoStatsSamples.stream().map(
+ sample -> sample.getStats().stream()
+ .map(IoStatsEntry::toString)
+ .collect(Collectors.joining("\n")))
+ .collect(Collectors.joining("\n------\n")));
+ }
+ if (mShutdownCostInfo < 0) {
+ writer.print("last shutdown cost: missing. ");
+ if (mShutdownCostMissingReason != null && !mShutdownCostMissingReason.isEmpty()) {
+ writer.println("reason: " + mShutdownCostMissingReason);
+ }
+ } else {
+ writer.println("last shutdown cost: " + mShutdownCostInfo + " bytes, estimated");
+ }
+ }
+
+ // ICarStorageMonitoring implementation
+
+ @Override
+ public int getPreEolIndicatorStatus() {
+ mStorageMonitoringPermission.assertGranted();
+ doInitServiceIfNeeded();
+
+ return mWearInformation.map(wi -> wi.preEolInfo)
+ .orElse(WearInformation.UNKNOWN_PRE_EOL_INFO);
+ }
+
+ @Override
+ public WearEstimate getWearEstimate() {
+ mStorageMonitoringPermission.assertGranted();
+ doInitServiceIfNeeded();
+
+ return mWearInformation.map(wi ->
+ new WearEstimate(wi.lifetimeEstimateA,wi.lifetimeEstimateB)).orElse(
+ WearEstimate.UNKNOWN_ESTIMATE);
+ }
+
+ @Override
+ public List<WearEstimateChange> getWearEstimateHistory() {
+ mStorageMonitoringPermission.assertGranted();
+ doInitServiceIfNeeded();
+
+ return mWearEstimateChanges;
+ }
+
+ @Override
+ public List<IoStatsEntry> getBootIoStats() {
+ mStorageMonitoringPermission.assertGranted();
+ doInitServiceIfNeeded();
+
+ return mBootIoStats;
+ }
+
+ @Override
+ public List<IoStatsEntry> getAggregateIoStats() {
+ mStorageMonitoringPermission.assertGranted();
+ doInitServiceIfNeeded();
+
+ return SparseArrayStream.valueStream(mIoStatsTracker.getTotal())
+ .collect(Collectors.toList());
+ }
+
+ @Override
+ public long getShutdownDiskWriteAmount() {
+ mStorageMonitoringPermission.assertGranted();
+ doInitServiceIfNeeded();
+
+ return mShutdownCostInfo;
+ }
+
+ @Override
+ public List<IoStats> getIoStatsDeltas() {
+ mStorageMonitoringPermission.assertGranted();
+ doInitServiceIfNeeded();
+
+ synchronized (mIoStatsSamplesLock) {
+ return mIoStatsSamples.stream().collect(Collectors.toList());
+ }
+ }
+
+ @Override
+ public void registerListener(IIoStatsListener listener) {
+ mStorageMonitoringPermission.assertGranted();
+ doInitServiceIfNeeded();
+
+ mListeners.register(listener);
+ }
+
+ @Override
+ public void unregisterListener(IIoStatsListener listener) {
+ mStorageMonitoringPermission.assertGranted();
+ // no need to initialize service if unregistering
+
+ mListeners.unregister(listener);
+ }
+
+ private static final class Configuration {
+ final long acceptableBytesWrittenPerSample;
+ final int acceptableFsyncCallsPerSample;
+ final int acceptableHoursPerOnePercentFlashWear;
+ final String activityHandlerForFlashWearChanges;
+ final String intentReceiverForUnacceptableIoMetrics;
+ final int ioStatsNumSamplesToStore;
+ final int ioStatsRefreshRateMs;
+ final int maxExcessiveIoSamplesInWindow;
+ final long uptimeIntervalBetweenUptimeDataWriteMs;
+
+ Configuration(Resources resources) throws Resources.NotFoundException {
+ ioStatsNumSamplesToStore = resources.getInteger(R.integer.ioStatsNumSamplesToStore);
+ acceptableBytesWrittenPerSample =
+ 1024 * resources.getInteger(R.integer.acceptableWrittenKBytesPerSample);
+ acceptableFsyncCallsPerSample =
+ resources.getInteger(R.integer.acceptableFsyncCallsPerSample);
+ maxExcessiveIoSamplesInWindow =
+ resources.getInteger(R.integer.maxExcessiveIoSamplesInWindow);
+ uptimeIntervalBetweenUptimeDataWriteMs =
+ 60 * 60 * 1000 *
+ resources.getInteger(R.integer.uptimeHoursIntervalBetweenUptimeDataWrite);
+ acceptableHoursPerOnePercentFlashWear =
+ resources.getInteger(R.integer.acceptableHoursPerOnePercentFlashWear);
+ ioStatsRefreshRateMs =
+ 1000 * resources.getInteger(R.integer.ioStatsRefreshRateSeconds);
+ activityHandlerForFlashWearChanges =
+ resources.getString(R.string.activityHandlerForFlashWearChanges);
+ intentReceiverForUnacceptableIoMetrics =
+ resources.getString(R.string.intentReceiverForUnacceptableIoMetrics);
+ }
+
+ @Override
+ public String toString() {
+ return String.format(
+ "acceptableBytesWrittenPerSample = %d, " +
+ "acceptableFsyncCallsPerSample = %d, " +
+ "acceptableHoursPerOnePercentFlashWear = %d, " +
+ "activityHandlerForFlashWearChanges = %s, " +
+ "intentReceiverForUnacceptableIoMetrics = %s, " +
+ "ioStatsNumSamplesToStore = %d, " +
+ "ioStatsRefreshRateMs = %d, " +
+ "maxExcessiveIoSamplesInWindow = %d, " +
+ "uptimeIntervalBetweenUptimeDataWriteMs = %d",
+ acceptableBytesWrittenPerSample,
+ acceptableFsyncCallsPerSample,
+ acceptableHoursPerOnePercentFlashWear,
+ activityHandlerForFlashWearChanges,
+ intentReceiverForUnacceptableIoMetrics,
+ ioStatsNumSamplesToStore,
+ ioStatsRefreshRateMs,
+ maxExcessiveIoSamplesInWindow,
+ uptimeIntervalBetweenUptimeDataWriteMs);
+ }
+ }
+}
diff --git a/service/src/com/android/car/CarTestService.java b/service/src/com/android/car/CarTestService.java
index ec1606c..8c3f64d 100644
--- a/service/src/com/android/car/CarTestService.java
+++ b/service/src/com/android/car/CarTestService.java
@@ -100,7 +100,7 @@
}
if (mTokens.size() == 0) {
- mICarImpl.init();
+ CarServiceUtils.runOnMain(mICarImpl::init);
}
}
diff --git a/service/src/com/android/car/CarUxRestrictionsManagerService.java b/service/src/com/android/car/CarUxRestrictionsManagerService.java
new file mode 100644
index 0000000..23c4d32
--- /dev/null
+++ b/service/src/com/android/car/CarUxRestrictionsManagerService.java
@@ -0,0 +1,450 @@
+/*
+ * 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;
+
+import android.annotation.Nullable;
+import android.car.drivingstate.CarDrivingStateEvent;
+import android.car.drivingstate.CarDrivingStateEvent.CarDrivingState;
+import android.car.drivingstate.CarUxRestrictions;
+import android.car.drivingstate.ICarDrivingStateChangeListener;
+import android.car.drivingstate.ICarUxRestrictionsChangeListener;
+import android.car.drivingstate.ICarUxRestrictionsManager;
+import android.car.hardware.CarPropertyValue;
+import android.car.hardware.property.CarPropertyEvent;
+import android.car.hardware.property.ICarPropertyEventListener;
+import android.content.Context;
+import android.hardware.automotive.vehicle.V2_0.VehicleProperty;
+import android.os.IBinder;
+import android.os.RemoteException;
+import android.util.Log;
+
+import org.xmlpull.v1.XmlPullParserException;
+
+import java.io.IOException;
+import java.io.PrintWriter;
+import java.util.ArrayList;
+import java.util.LinkedList;
+import java.util.List;
+
+/**
+ * A service that listens to current driving state of the vehicle and maps it to the
+ * appropriate UX restrictions for that driving state.
+ */
+public class CarUxRestrictionsManagerService extends ICarUxRestrictionsManager.Stub implements
+ CarServiceBase {
+ private static final String TAG = "CarUxR";
+ private static final boolean DBG = false;
+ private static final int MAX_TRANSITION_LOG_SIZE = 20;
+ private static final int PROPERTY_UPDATE_RATE = 5; // Update rate in Hz
+ private static final float SPEED_NOT_AVAILABLE = -1.0F;
+ private final Context mContext;
+ private final CarDrivingStateService mDrivingStateService;
+ private final CarPropertyService mCarPropertyService;
+ private final CarUxRestrictionsServiceHelper mHelper;
+ // List of clients listening to UX restriction events.
+ private final List<UxRestrictionsClient> mUxRClients = new ArrayList<>();
+ private CarUxRestrictions mCurrentUxRestrictions;
+ private float mCurrentMovingSpeed;
+ private boolean mFallbackToDefaults;
+ // For dumpsys logging
+ private final LinkedList<Utils.TransitionLog> mTransitionLogs = new LinkedList<>();
+
+
+ public CarUxRestrictionsManagerService(Context context, CarDrivingStateService drvService,
+ CarPropertyService propertyService) {
+ mContext = context;
+ mDrivingStateService = drvService;
+ mCarPropertyService = propertyService;
+ mHelper = new CarUxRestrictionsServiceHelper(mContext, R.xml.car_ux_restrictions_map);
+ // Unrestricted until driving state information is received. During boot up, we don't want
+ // everything to be blocked until data is available from CarPropertyManager. If we start
+ // driving and we don't get speed or gear information, we have bigger problems.
+ mCurrentUxRestrictions = mHelper.createUxRestrictionsEvent(false,
+ CarUxRestrictions.UX_RESTRICTIONS_BASELINE);
+ }
+
+ @Override
+ public synchronized void init() {
+ try {
+ if (!mHelper.loadUxRestrictionsFromXml()) {
+ Log.e(TAG, "Error reading Ux Restrictions Mapping. Falling back to defaults");
+ mFallbackToDefaults = true;
+ }
+ } catch (IOException | XmlPullParserException e) {
+ Log.e(TAG, "Exception reading UX restrictions XML mapping", e);
+ mFallbackToDefaults = true;
+ }
+ // subscribe to driving State
+ mDrivingStateService.registerDrivingStateChangeListener(
+ mICarDrivingStateChangeEventListener);
+ // subscribe to property service for speed
+ mCarPropertyService.registerListener(VehicleProperty.PERF_VEHICLE_SPEED,
+ PROPERTY_UPDATE_RATE, mICarPropertyEventListener);
+ initializeUxRestrictions();
+ }
+
+ // Update current restrictions by getting the current driving state and speed.
+ private void initializeUxRestrictions() {
+ CarDrivingStateEvent currentDrivingStateEvent =
+ mDrivingStateService.getCurrentDrivingState();
+ // if we don't have enough information from the CarPropertyService to compute the UX
+ // restrictions, then leave the UX restrictions unchanged from what it was initialized to
+ // in the constructor.
+ if (currentDrivingStateEvent == null || currentDrivingStateEvent.eventValue
+ == CarDrivingStateEvent.DRIVING_STATE_UNKNOWN) {
+ return;
+ }
+ int currentDrivingState = currentDrivingStateEvent.eventValue;
+ Float currentSpeed = getCurrentSpeed();
+ if (currentSpeed == SPEED_NOT_AVAILABLE) {
+ return;
+ }
+ // At this point the underlying CarPropertyService has provided us enough information to
+ // compute the UX restrictions that could be potentially different from the initial UX
+ // restrictions.
+ handleDispatchUxRestrictions(currentDrivingState, currentSpeed);
+ }
+
+ private Float getCurrentSpeed() {
+ CarPropertyValue value = mCarPropertyService.getProperty(VehicleProperty.PERF_VEHICLE_SPEED,
+ 0);
+ if (value != null) {
+ return (Float) value.getValue();
+ }
+ return SPEED_NOT_AVAILABLE;
+ }
+
+ @Override
+ public synchronized void release() {
+ for (UxRestrictionsClient client : mUxRClients) {
+ client.listenerBinder.unlinkToDeath(client, 0);
+ }
+ mUxRClients.clear();
+ mDrivingStateService.unregisterDrivingStateChangeListener(
+ mICarDrivingStateChangeEventListener);
+ }
+
+ // Binder methods
+
+ /**
+ * Register a {@link ICarUxRestrictionsChangeListener} to be notified for changes to the UX
+ * restrictions
+ *
+ * @param listener listener to register
+ */
+ @Override
+ public synchronized void registerUxRestrictionsChangeListener(
+ ICarUxRestrictionsChangeListener listener) {
+ if (listener == null) {
+ if (DBG) {
+ Log.e(TAG, "registerUxRestrictionsChangeListener(): listener null");
+ }
+ throw new IllegalArgumentException("Listener is null");
+ }
+ // If a new client is registering, create a new DrivingStateClient and add it to the list
+ // of listening clients.
+ UxRestrictionsClient client = findUxRestrictionsClient(listener);
+ if (client == null) {
+ client = new UxRestrictionsClient(listener);
+ try {
+ listener.asBinder().linkToDeath(client, 0);
+ } catch (RemoteException e) {
+ Log.e(TAG, "Cannot link death recipient to binder " + e);
+ }
+ mUxRClients.add(client);
+ }
+ return;
+ }
+
+ /**
+ * Iterates through the list of registered UX Restrictions clients -
+ * {@link UxRestrictionsClient} and finds if the given client is already registered.
+ *
+ * @param listener Listener to look for.
+ * @return the {@link UxRestrictionsClient} if found, null if not
+ */
+ @Nullable
+ private UxRestrictionsClient findUxRestrictionsClient(
+ ICarUxRestrictionsChangeListener listener) {
+ IBinder binder = listener.asBinder();
+ for (UxRestrictionsClient client : mUxRClients) {
+ if (client.isHoldingBinder(binder)) {
+ return client;
+ }
+ }
+ return null;
+ }
+
+ /**
+ * Unregister the given UX Restrictions listener
+ *
+ * @param listener client to unregister
+ */
+ @Override
+ public synchronized void unregisterUxRestrictionsChangeListener(
+ ICarUxRestrictionsChangeListener listener) {
+ if (listener == null) {
+ Log.e(TAG, "unregisterUxRestrictionsChangeListener(): listener null");
+ throw new IllegalArgumentException("Listener is null");
+ }
+
+ UxRestrictionsClient client = findUxRestrictionsClient(listener);
+ if (client == null) {
+ Log.e(TAG, "unregisterUxRestrictionsChangeListener(): listener was not previously "
+ + "registered");
+ return;
+ }
+ listener.asBinder().unlinkToDeath(client, 0);
+ mUxRClients.remove(client);
+ }
+
+ /**
+ * Gets the current UX restrictions
+ *
+ * @return {@link CarUxRestrictions} for the given event type
+ */
+ @Override
+ @Nullable
+ public synchronized CarUxRestrictions getCurrentUxRestrictions() {
+ return mCurrentUxRestrictions;
+ }
+
+ /**
+ * Class that holds onto client related information - listener interface, process that hosts the
+ * binder object etc.
+ * It also registers for death notifications of the host.
+ */
+ private class UxRestrictionsClient implements IBinder.DeathRecipient {
+ private final IBinder listenerBinder;
+ private final ICarUxRestrictionsChangeListener listener;
+
+ public UxRestrictionsClient(ICarUxRestrictionsChangeListener l) {
+ listener = l;
+ listenerBinder = l.asBinder();
+ }
+
+ @Override
+ public void binderDied() {
+ if (DBG) {
+ Log.d(TAG, "Binder died " + listenerBinder);
+ }
+ listenerBinder.unlinkToDeath(this, 0);
+ synchronized (CarUxRestrictionsManagerService.this) {
+ mUxRClients.remove(this);
+ }
+ }
+
+ /**
+ * Returns if the given binder object matches to what this client info holds.
+ * Used to check if the listener asking to be registered is already registered.
+ *
+ * @return true if matches, false if not
+ */
+ public boolean isHoldingBinder(IBinder binder) {
+ return listenerBinder == binder;
+ }
+
+ /**
+ * Dispatch the event to the listener
+ *
+ * @param event {@link CarUxRestrictions}.
+ */
+ public void dispatchEventToClients(CarUxRestrictions event) {
+ if (event == null) {
+ return;
+ }
+ try {
+ listener.onUxRestrictionsChanged(event);
+ } catch (RemoteException e) {
+ if (DBG) {
+ Log.d(TAG, "Dispatch to listener failed");
+ }
+ }
+ }
+ }
+
+ @Override
+ public void dump(PrintWriter writer) {
+ writer.println(
+ "Requires DO? " + mCurrentUxRestrictions.isRequiresDistractionOptimization());
+ writer.println("Current UXR: " + mCurrentUxRestrictions.getActiveRestrictions());
+ mHelper.dump(writer);
+ writer.println("UX Restriction change log:");
+ for (Utils.TransitionLog tlog : mTransitionLogs) {
+ writer.println(tlog);
+ }
+ }
+
+ /**
+ * {@link CarDrivingStateEvent} listener registered with the {@link CarDrivingStateService}
+ * for getting driving state change notifications.
+ */
+ private final ICarDrivingStateChangeListener mICarDrivingStateChangeEventListener =
+ new ICarDrivingStateChangeListener.Stub() {
+ @Override
+ public void onDrivingStateChanged(CarDrivingStateEvent event) {
+ if (DBG) {
+ Log.d(TAG, "Driving State Changed:" + event.eventValue);
+ }
+ handleDrivingStateEvent(event);
+ }
+ };
+
+ /**
+ * Handle the driving state change events coming from the {@link CarDrivingStateService}.
+ * Map the driving state to the corresponding UX Restrictions and dispatch the
+ * UX Restriction change to the registered clients.
+ */
+ private synchronized void handleDrivingStateEvent(CarDrivingStateEvent event) {
+ if (event == null) {
+ return;
+ }
+ int drivingState = event.eventValue;
+ Float speed = getCurrentSpeed();
+
+ if (speed != SPEED_NOT_AVAILABLE) {
+ mCurrentMovingSpeed = speed;
+ } else if (drivingState == CarDrivingStateEvent.DRIVING_STATE_PARKED
+ || drivingState == CarDrivingStateEvent.DRIVING_STATE_UNKNOWN) {
+ // If speed is unavailable, but the driving state is parked or unknown, it can still be
+ // handled.
+ if (DBG) {
+ Log.d(TAG, "Speed null when driving state is: " + drivingState);
+ }
+ mCurrentMovingSpeed = 0;
+ } else {
+ // If we get here with driving state != parked or unknown && speed == null,
+ // something is wrong. CarDrivingStateService could not have inferred idling or moving
+ // when speed is not available
+ Log.e(TAG, "Unexpected: Speed null when driving state is: " + drivingState);
+ return;
+ }
+ handleDispatchUxRestrictions(drivingState, mCurrentMovingSpeed);
+ }
+
+ /**
+ * {@link CarPropertyEvent} listener registered with the {@link CarPropertyService} for getting
+ * speed change notifications.
+ */
+ private final ICarPropertyEventListener mICarPropertyEventListener =
+ new ICarPropertyEventListener.Stub() {
+ @Override
+ public void onEvent(List<CarPropertyEvent> events) throws RemoteException {
+ for (CarPropertyEvent event : events) {
+ if ((event.getEventType()
+ == CarPropertyEvent.PROPERTY_EVENT_PROPERTY_CHANGE)
+ && (event.getCarPropertyValue().getPropertyId()
+ == VehicleProperty.PERF_VEHICLE_SPEED)) {
+ handleSpeedChange((Float) event.getCarPropertyValue().getValue());
+ }
+ }
+ }
+ };
+
+ private synchronized void handleSpeedChange(float newSpeed) {
+ if (newSpeed == mCurrentMovingSpeed) {
+ // Ignore if speed hasn't changed
+ return;
+ }
+ int currentDrivingState = mDrivingStateService.getCurrentDrivingState().eventValue;
+ if (currentDrivingState != CarDrivingStateEvent.DRIVING_STATE_MOVING) {
+ // Ignore speed changes if the vehicle is not moving
+ return;
+ }
+ mCurrentMovingSpeed = newSpeed;
+ handleDispatchUxRestrictions(currentDrivingState, newSpeed);
+ }
+
+ /**
+ * Handle dispatching UX restrictions change.
+ *
+ * @param currentDrivingState driving state of the vehicle
+ * @param speed speed of the vehicle
+ */
+ private synchronized void handleDispatchUxRestrictions(@CarDrivingState int currentDrivingState,
+ float speed) {
+ CarUxRestrictions uxRestrictions;
+ // Get UX restrictions from the parsed configuration XML or fall back to defaults if not
+ // available.
+ if (mFallbackToDefaults) {
+ uxRestrictions = getDefaultRestrictions(currentDrivingState);
+ } else {
+ uxRestrictions = mHelper.getUxRestrictions(currentDrivingState, speed);
+ }
+
+ if (DBG) {
+ Log.d(TAG, String.format("DO old->new: %b -> %b",
+ mCurrentUxRestrictions.isRequiresDistractionOptimization(),
+ uxRestrictions.isRequiresDistractionOptimization()));
+ Log.d(TAG, String.format("UxR old->new: 0x%x -> 0x%x",
+ mCurrentUxRestrictions.getActiveRestrictions(),
+ uxRestrictions.getActiveRestrictions()));
+ }
+
+ if (mCurrentUxRestrictions.isSameRestrictions(uxRestrictions)) {
+ // Ignore dispatching if the restrictions has not changed.
+ return;
+ }
+ // for dumpsys logging
+ StringBuilder extraInfo = new StringBuilder();
+ extraInfo.append(
+ mCurrentUxRestrictions.isRequiresDistractionOptimization() ? "DO -> "
+ : "No DO -> ");
+ extraInfo.append(
+ uxRestrictions.isRequiresDistractionOptimization() ? "DO" : "No DO");
+ addTransitionLog(TAG, mCurrentUxRestrictions.getActiveRestrictions(),
+ uxRestrictions.getActiveRestrictions(), System.currentTimeMillis(),
+ extraInfo.toString());
+
+ mCurrentUxRestrictions = uxRestrictions;
+ if (DBG) {
+ Log.d(TAG, "dispatching to " + mUxRClients.size() + " clients");
+ }
+ for (UxRestrictionsClient client : mUxRClients) {
+ client.dispatchEventToClients(uxRestrictions);
+ }
+ }
+
+ private CarUxRestrictions getDefaultRestrictions(@CarDrivingState int drivingState) {
+ int restrictions;
+ boolean requiresOpt = false;
+ switch (drivingState) {
+ case CarDrivingStateEvent.DRIVING_STATE_PARKED:
+ restrictions = CarUxRestrictions.UX_RESTRICTIONS_BASELINE;
+ break;
+ case CarDrivingStateEvent.DRIVING_STATE_IDLING:
+ restrictions = CarUxRestrictions.UX_RESTRICTIONS_BASELINE;
+ requiresOpt = true;
+ break;
+ case CarDrivingStateEvent.DRIVING_STATE_MOVING:
+ default:
+ restrictions = CarUxRestrictions.UX_RESTRICTIONS_FULLY_RESTRICTED;
+ requiresOpt = true;
+ }
+ return mHelper.createUxRestrictionsEvent(requiresOpt, restrictions);
+ }
+
+ private void addTransitionLog(String name, int from, int to, long timestamp, String extra) {
+ if (mTransitionLogs.size() >= MAX_TRANSITION_LOG_SIZE) {
+ mTransitionLogs.remove();
+ }
+
+ Utils.TransitionLog tLog = new Utils.TransitionLog(name, from, to, timestamp, extra);
+ mTransitionLogs.add(tLog);
+ }
+
+}
diff --git a/service/src/com/android/car/CarUxRestrictionsServiceHelper.java b/service/src/com/android/car/CarUxRestrictionsServiceHelper.java
new file mode 100644
index 0000000..236d915
--- /dev/null
+++ b/service/src/com/android/car/CarUxRestrictionsServiceHelper.java
@@ -0,0 +1,469 @@
+/*
+ * 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;
+
+import android.annotation.Nullable;
+import android.annotation.XmlRes;
+import android.car.drivingstate.CarDrivingStateEvent;
+import android.car.drivingstate.CarDrivingStateEvent.CarDrivingState;
+import android.car.drivingstate.CarUxRestrictions;
+import android.content.Context;
+import android.content.res.TypedArray;
+import android.content.res.XmlResourceParser;
+import android.os.SystemClock;
+import android.util.AttributeSet;
+import android.util.Log;
+import android.util.Pair;
+import android.util.Xml;
+
+import org.xmlpull.v1.XmlPullParserException;
+
+import java.io.IOException;
+import java.io.PrintWriter;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * Helper class to {@link CarUxRestrictionsManagerService} and it takes care of the foll:
+ * <ol>
+ * <li>Parses the given XML resource and builds a hashmap to store the driving state to UX
+ * restrictions mapping information provided in the XML.</li>
+ * <li>Finds the UX restrictions for the given driving state and speed from the data structure it
+ * built above.</li>
+ * </ol>
+ */
+/* package */ class CarUxRestrictionsServiceHelper {
+ private static final String TAG = "UxRServiceHelper";
+ private static final int UX_RESTRICTIONS_UNKNOWN = -1;
+ // XML tags to parse
+ private static final String ROOT_ELEMENT = "UxRestrictions";
+ private static final String RESTRICTION_MAPPING = "RestrictionMapping";
+ private static final String RESTRICTION_PARAMETERS = "RestrictionParameters";
+ private static final String DRIVING_STATE = "DrivingState";
+ private static final String RESTRICTIONS = "Restrictions";
+ private static final String STRING_RESTRICTIONS = "StringRestrictions";
+ private static final String CONTENT_RESTRICTIONS = "ContentRestrictions";
+
+ /* Hashmap that maps driving state to RestrictionsInfo.
+ RestrictionsInfo maintains a list of RestrictionsPerSpeedRange.
+ The list size will be one for Parked and Idling states, but could be more than one
+ for Moving state, if moving state supports multiple speed ranges.*/
+ private Map<Integer, RestrictionsInfo> mRestrictionsMap = new HashMap<>();
+ private RestrictionParameters mRestrictionParameters = new RestrictionParameters();
+ private final Context mContext;
+ @XmlRes
+ private final int mXmlResource;
+
+ CarUxRestrictionsServiceHelper(Context context, @XmlRes int xmlRes) {
+ mContext = context;
+ mXmlResource = xmlRes;
+ }
+
+ /**
+ * Loads the UX restrictions related information from the XML resource.
+ *
+ * @return true if successful, false if the XML is malformed
+ */
+ public boolean loadUxRestrictionsFromXml() throws IOException, XmlPullParserException {
+ mRestrictionsMap.clear();
+ XmlResourceParser parser = mContext.getResources().getXml(mXmlResource);
+ AttributeSet attrs = Xml.asAttributeSet(parser);
+ int type;
+ // Traverse till we get to the first tag
+ while ((type = parser.next()) != XmlResourceParser.END_DOCUMENT
+ && type != XmlResourceParser.START_TAG) {
+ }
+ if (!ROOT_ELEMENT.equals(parser.getName())) {
+ Log.e(TAG, "XML root element invalid: " + parser.getName());
+ return false;
+ }
+
+ // Traverse till the end and every time we hit a start tag, check for the type of the tag
+ // and load the corresponding information.
+ while (parser.getEventType() != XmlResourceParser.END_DOCUMENT) {
+ if (parser.next() == XmlResourceParser.START_TAG) {
+ switch (parser.getName()) {
+ case RESTRICTION_MAPPING:
+ if (!mapDrivingStateToRestrictions(parser, attrs)) {
+ return false;
+ }
+ break;
+ case RESTRICTION_PARAMETERS:
+ if (!parseRestrictionParameters(parser, attrs)) {
+ // Failure to parse is automatically handled by falling back to
+ // defaults. Just log the information here
+ if (Log.isLoggable(TAG, Log.INFO)) {
+ Log.i(TAG,
+ "Error reading restrictions parameters. Falling back to "
+ + "platform defaults.");
+ }
+ }
+ break;
+ default:
+ Log.w(TAG, "Unknown class:" + parser.getName());
+ }
+ }
+ }
+ return true;
+ }
+
+ /**
+ * Parses the information in the <restrictionMapping> tag to construct the mapping from
+ * driving state to UX restrictions.
+ */
+ private boolean mapDrivingStateToRestrictions(XmlResourceParser parser, AttributeSet attrs)
+ throws IOException, XmlPullParserException {
+ if (parser == null || attrs == null) {
+ Log.e(TAG, "Invalid arguments");
+ return false;
+ }
+ // The parser should be at the <RestrictionMapping> tag at this point.
+ if (!RESTRICTION_MAPPING.equals(parser.getName())) {
+ Log.e(TAG, "Parser not at RestrictionMapping element: " + parser.getName());
+ return false;
+ }
+ if (!traverseToTag(parser, DRIVING_STATE)) {
+ Log.e(TAG, "No <" + DRIVING_STATE + "> tag in XML");
+ return false;
+ }
+ // Handle all the <DrivingState> tags.
+ while (DRIVING_STATE.equals(parser.getName())) {
+ if (parser.getEventType() == XmlResourceParser.START_TAG) {
+ // 1. Get the driving state attributes: driving state and speed range
+ TypedArray a = mContext.getResources().obtainAttributes(attrs,
+ R.styleable.UxRestrictions_DrivingState);
+ int drivingState = a
+ .getInt(R.styleable.UxRestrictions_DrivingState_state,
+ CarDrivingStateEvent.DRIVING_STATE_UNKNOWN);
+ float minSpeed = a
+ .getFloat(
+ R.styleable
+ .UxRestrictions_DrivingState_minSpeed,
+ RestrictionsPerSpeedRange.SPEED_INVALID);
+ float maxSpeed = a
+ .getFloat(
+ R.styleable
+ .UxRestrictions_DrivingState_maxSpeed,
+ RestrictionsPerSpeedRange.SPEED_INVALID);
+ a.recycle();
+
+ // 2. Traverse to the <Restrictions> tag
+ if (!traverseToTag(parser, RESTRICTIONS)) {
+ Log.e(TAG, "No <" + RESTRICTIONS + "> tag in XML");
+ return false;
+ }
+
+ // 3. Parse the restrictions for this driving state
+ Pair<Boolean, Integer> restrictions = parseRestrictions(parser, attrs);
+ if (Log.isLoggable(TAG, Log.DEBUG)) {
+ Log.d(TAG, "Map " + drivingState + " : " + restrictions);
+ }
+
+ // Update the hashmap if the driving state and restrictions info are valid.
+ if (drivingState != CarDrivingStateEvent.DRIVING_STATE_UNKNOWN
+ && restrictions != null) {
+ addToRestrictionsMap(drivingState, minSpeed, maxSpeed, restrictions.first,
+ restrictions.second);
+ }
+ }
+ parser.next();
+ }
+ return true;
+ }
+
+ /**
+ * Parses the <restrictions> tag nested with the <drivingState>. This provides the restrictions
+ * for the enclosing driving state.
+ */
+ @Nullable
+ private Pair<Boolean, Integer> parseRestrictions(XmlResourceParser parser, AttributeSet attrs)
+ throws IOException, XmlPullParserException {
+ int restrictions = UX_RESTRICTIONS_UNKNOWN;
+ boolean requiresOpt = true;
+ if (parser == null || attrs == null) {
+ Log.e(TAG, "Invalid Arguments");
+ return null;
+ }
+
+ while (RESTRICTIONS.equals(parser.getName())
+ && parser.getEventType() == XmlResourceParser.START_TAG) {
+ TypedArray a = mContext.getResources().obtainAttributes(attrs,
+ R.styleable.UxRestrictions_Restrictions);
+ restrictions = a.getInt(
+ R.styleable.UxRestrictions_Restrictions_uxr,
+ CarUxRestrictions.UX_RESTRICTIONS_FULLY_RESTRICTED);
+ requiresOpt = a.getBoolean(
+ R.styleable.UxRestrictions_Restrictions_requiresDistractionOptimization, true);
+ a.recycle();
+ parser.next();
+ }
+ return new Pair<>(requiresOpt, restrictions);
+ }
+
+ private void addToRestrictionsMap(int drivingState, float minSpeed, float maxSpeed,
+ boolean requiresOpt, int restrictions) {
+ RestrictionsPerSpeedRange res = new RestrictionsPerSpeedRange(minSpeed, maxSpeed,
+ restrictions, requiresOpt);
+ RestrictionsInfo restrictionsList = mRestrictionsMap.get(drivingState);
+ if (restrictionsList == null) {
+ restrictionsList = new RestrictionsInfo();
+ }
+ restrictionsList.addRestrictions(res);
+ mRestrictionsMap.put(drivingState, restrictionsList);
+ }
+
+ private boolean traverseToTag(XmlResourceParser parser, String tag)
+ throws IOException, XmlPullParserException {
+ if (tag == null || parser == null) {
+ return false;
+ }
+ int type;
+ while ((type = parser.next()) != XmlResourceParser.END_DOCUMENT) {
+ if (type == XmlResourceParser.START_TAG && parser.getName().equals(tag)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ /**
+ * Parses the information in the <RestrictionParameters> tag to read the parameters for the
+ * applicable UX restrictions
+ */
+ private boolean parseRestrictionParameters(XmlResourceParser parser, AttributeSet attrs)
+ throws IOException, XmlPullParserException {
+ if (parser == null || attrs == null) {
+ Log.e(TAG, "Invalid arguments");
+ return false;
+ }
+ // The parser should be at the <RestrictionParameters> tag at this point.
+ if (!RESTRICTION_PARAMETERS.equals(parser.getName())) {
+ Log.e(TAG, "Parser not at RestrictionParameters element: " + parser.getName());
+ return false;
+ }
+ while (parser.getEventType() != XmlResourceParser.END_DOCUMENT) {
+ int type = parser.next();
+ // Break if we have parsed all <RestrictionParameters>
+ if (type == XmlResourceParser.END_TAG && RESTRICTION_PARAMETERS.equals(
+ parser.getName())) {
+ return true;
+ }
+ if (type == XmlResourceParser.START_TAG) {
+ TypedArray a = null;
+ switch (parser.getName()) {
+ case STRING_RESTRICTIONS:
+ a = mContext.getResources().obtainAttributes(attrs,
+ R.styleable.UxRestrictions_StringRestrictions);
+ mRestrictionParameters.mMaxStringLength = a
+ .getInt(R.styleable.UxRestrictions_StringRestrictions_maxLength,
+ UX_RESTRICTIONS_UNKNOWN);
+
+ break;
+ case CONTENT_RESTRICTIONS:
+ a = mContext.getResources().obtainAttributes(attrs,
+ R.styleable.UxRestrictions_ContentRestrictions);
+ mRestrictionParameters.mMaxCumulativeContentItems = a.getInt(R.styleable
+ .UxRestrictions_ContentRestrictions_maxCumulativeItems,
+ UX_RESTRICTIONS_UNKNOWN);
+ mRestrictionParameters.mMaxContentDepth = a
+ .getInt(R.styleable.UxRestrictions_ContentRestrictions_maxDepth,
+ UX_RESTRICTIONS_UNKNOWN);
+ break;
+ default:
+ if (Log.isLoggable(TAG, Log.DEBUG)) {
+ Log.d(TAG, "Unsupported Restriction Parameters in XML: "
+ + parser.getName());
+ }
+ break;
+ }
+ if (a != null) {
+ a.recycle();
+ }
+ }
+ }
+ return true;
+ }
+
+ /**
+ * Dump the driving state to UX restrictions mapping.
+ */
+ public void dump(PrintWriter writer) {
+ for (Integer state : mRestrictionsMap.keySet()) {
+ RestrictionsInfo list = mRestrictionsMap.get(state);
+ writer.println("===========================================");
+ writer.println("Driving State to UXR");
+ if (list != null && list.mRestrictionsList != null) {
+ writer.println("State:" + getDrivingStateName(state) + " num restrictions:"
+ + list.mRestrictionsList.size());
+ for (RestrictionsPerSpeedRange r : list.mRestrictionsList) {
+ writer.println(
+ "Speed Range: " + r.mMinSpeed + "-" + r.mMaxSpeed + " Requires DO? "
+ + r.mRequiresDistractionOptimization + " Restrictions: 0x"
+ + Integer.toHexString(r.mRestrictions));
+ writer.println("===========================================");
+ }
+ }
+ }
+ writer.println("Max String length: " + mRestrictionParameters.mMaxStringLength);
+ writer.println(
+ "Max Cumul Content Items: " + mRestrictionParameters.mMaxCumulativeContentItems);
+ writer.println("Max Content depth: " + mRestrictionParameters.mMaxContentDepth);
+ }
+
+ private static String getDrivingStateName(int state) {
+ switch (state) {
+ case 0:
+ return "parked";
+ case 1:
+ return "idling";
+ case 2:
+ return "moving";
+ default:
+ return "unknown";
+ }
+ }
+
+ /**
+ * Get the UX restrictions for the given driving state and speed.
+ *
+ * @param drivingState driving state of the vehicle
+ * @param currentSpeed speed of the vehicle
+ * @return UX restrictions for the given driving state and speed.
+ */
+ public CarUxRestrictions getUxRestrictions(@CarDrivingState int drivingState,
+ float currentSpeed) {
+ RestrictionsPerSpeedRange restrictions;
+ RestrictionsInfo restrictionsList = mRestrictionsMap.get(drivingState);
+ // If the XML hasn't been parsed or if the given driving state is not supported in the
+ // XML, return fully restricted.
+ if (restrictionsList == null || restrictionsList.mRestrictionsList == null
+ || restrictionsList.mRestrictionsList.isEmpty()) {
+ return createUxRestrictionsEvent(true,
+ CarUxRestrictions.UX_RESTRICTIONS_FULLY_RESTRICTED);
+ }
+ // For Parked and Idling, the restrictions list will have only one item, since multiple
+ // speed ranges don't make sense in those driving states.
+ if (restrictionsList.mRestrictionsList.size() == 1) {
+ restrictions = restrictionsList.mRestrictionsList.get(0);
+ } else {
+ restrictions = restrictionsList.findRestrictions(currentSpeed);
+ }
+ if (restrictions != null) {
+ return createUxRestrictionsEvent(restrictions.mRequiresDistractionOptimization,
+ restrictions.mRestrictions);
+ } else {
+ return createUxRestrictionsEvent(true,
+ CarUxRestrictions.UX_RESTRICTIONS_FULLY_RESTRICTED);
+ }
+ }
+
+ /* package */ CarUxRestrictions createUxRestrictionsEvent(boolean requiresOpt,
+ @CarUxRestrictions.CarUxRestrictionsInfo int uxr) {
+ // In case the UXR is not baseline, set requiresDistractionOptimization to true since it
+ // doesn't make sense to have an active non baseline restrictions without
+ // requiresDistractionOptimization set to true.
+ if (uxr != CarUxRestrictions.UX_RESTRICTIONS_BASELINE) {
+ requiresOpt = true;
+ }
+ CarUxRestrictions.Builder builder = new CarUxRestrictions.Builder(requiresOpt, uxr,
+ SystemClock.elapsedRealtimeNanos());
+ if (mRestrictionParameters.mMaxStringLength != UX_RESTRICTIONS_UNKNOWN) {
+ builder.setMaxStringLength(mRestrictionParameters.mMaxStringLength);
+ }
+ if (mRestrictionParameters.mMaxCumulativeContentItems != UX_RESTRICTIONS_UNKNOWN) {
+ builder.setMaxCumulativeContentItems(
+ mRestrictionParameters.mMaxCumulativeContentItems);
+ }
+ if (mRestrictionParameters.mMaxContentDepth != UX_RESTRICTIONS_UNKNOWN) {
+ builder.setMaxContentDepth(mRestrictionParameters.mMaxContentDepth);
+ }
+ return builder.build();
+ }
+
+ /**
+ * Container for the UX restrictions that could be parametrized
+ */
+ private class RestrictionParameters {
+ int mMaxStringLength = UX_RESTRICTIONS_UNKNOWN;
+ int mMaxCumulativeContentItems = UX_RESTRICTIONS_UNKNOWN;
+ int mMaxContentDepth = UX_RESTRICTIONS_UNKNOWN;
+ }
+
+ /**
+ * Container for UX restrictions for a speed range.
+ * Speed range is valid only for the {@link CarDrivingStateEvent#DRIVING_STATE_MOVING}.
+ */
+ private class RestrictionsPerSpeedRange {
+ static final int SPEED_INVALID = -1;
+ final float mMinSpeed;
+ final float mMaxSpeed;
+ final int mRestrictions;
+ final boolean mRequiresDistractionOptimization;
+
+ RestrictionsPerSpeedRange(float minSpeed, float maxSpeed, int restrictions,
+ boolean requiresOpt) {
+ mMinSpeed = minSpeed;
+ mMaxSpeed = maxSpeed;
+ mRestrictions = restrictions;
+ mRequiresDistractionOptimization = requiresOpt;
+ }
+
+ /**
+ * Return if the given speed is in the range of ( {@link #mMinSpeed}, {@link #mMaxSpeed}
+ *
+ * @param speed Speed to check
+ * @return true if in range false if not.
+ */
+ boolean includes(float speed) {
+ if (mMinSpeed != SPEED_INVALID && mMaxSpeed == SPEED_INVALID) {
+ // This is for a range [minSpeed, infinity). If maxSpeed
+ // is invalid and mMinSpeed is a valid, this represents a
+ // anything greater than mMinSpeed.
+ return speed >= mMinSpeed;
+ } else {
+ return speed >= mMinSpeed && speed < mMaxSpeed;
+ }
+ }
+ }
+
+ /**
+ * Container for a list of {@link RestrictionsPerSpeedRange} per driving state.
+ */
+ private class RestrictionsInfo {
+ private List<RestrictionsPerSpeedRange> mRestrictionsList = new ArrayList<>();
+
+ void addRestrictions(RestrictionsPerSpeedRange r) {
+ mRestrictionsList.add(r);
+ }
+
+ /**
+ * Find the restrictions for the given speed. It finds the range that the given speed falls
+ * in and gets the restrictions for that speed.
+ */
+ @Nullable
+ RestrictionsPerSpeedRange findRestrictions(float speed) {
+ for (RestrictionsPerSpeedRange r : mRestrictionsList) {
+ if (r.includes(speed)) {
+ return r;
+ }
+ }
+ return null;
+ }
+ }
+}
diff --git a/service/src/com/android/car/CarVendorExtensionService.java b/service/src/com/android/car/CarVendorExtensionService.java
deleted file mode 100644
index 2e2d074..0000000
--- a/service/src/com/android/car/CarVendorExtensionService.java
+++ /dev/null
@@ -1,34 +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.car.Car;
-import android.content.Context;
-
-import com.android.car.hal.VendorExtensionHalService;
-
-/**
- * Service responsible for handling custom properties that were defined in vehicle HAL by OEMs.
- */
-public class CarVendorExtensionService extends CarPropertyServiceBase {
-
- private final static boolean DEBUG = false;
-
- public CarVendorExtensionService(Context context, VendorExtensionHalService vendorHal) {
- super(context, vendorHal, Car.PERMISSION_VENDOR_EXTENSION, DEBUG, CarLog.TAG_VENDOR_EXT);
- }
-}
diff --git a/service/src/com/android/car/CarVolumeControllerFactory.java b/service/src/com/android/car/CarVolumeControllerFactory.java
deleted file mode 100644
index c83ef93..0000000
--- a/service/src/com/android/car/CarVolumeControllerFactory.java
+++ /dev/null
@@ -1,697 +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.content.Context;
-import android.hardware.automotive.vehicle.V2_0.VehicleAudioContextFlag;
-import android.media.AudioManager;
-import android.media.IAudioService;
-import android.media.IVolumeController;
-import android.os.Handler;
-import android.os.HandlerThread;
-import android.os.Looper;
-import android.os.Message;
-import android.os.RemoteCallbackList;
-import android.os.RemoteException;
-import android.os.ServiceManager;
-import android.provider.Settings;
-import android.telecom.TelecomManager;
-import android.util.ArrayMap;
-import android.util.Log;
-import android.util.SparseArray;
-import android.view.KeyEvent;
-
-import com.android.car.CarVolumeService.CarVolumeController;
-import com.android.car.hal.AudioHalService;
-import com.android.internal.annotations.GuardedBy;
-
-import java.io.PrintWriter;
-import java.util.Map;
-
-/**
- * A factory class to create {@link com.android.car.CarVolumeService.CarVolumeController} based
- * on car properties.
- */
-public class CarVolumeControllerFactory {
- // STOPSHIP if true.
- private static final boolean DBG = false;
-
- public static CarVolumeController createCarVolumeController(Context context,
- CarAudioService audioService, AudioHalService audioHal, CarInputService inputService) {
- final boolean volumeSupported = audioHal.isAudioVolumeSupported();
-
- // Case 1: Car Audio Module does not support volume controls
- if (!volumeSupported) {
- return new SimpleCarVolumeController(context);
- }
- return new CarExternalVolumeController(context, audioService, audioHal, inputService);
- }
-
- public static boolean interceptVolKeyBeforeDispatching(Context context) {
- Log.d(CarLog.TAG_AUDIO, "interceptVolKeyBeforeDispatching");
-
- TelecomManager telecomManager = (TelecomManager)
- context.getSystemService(Context.TELECOM_SERVICE);
- if (telecomManager != null && telecomManager.isRinging()) {
- // If an incoming call is ringing, either VOLUME key means
- // "silence ringer". This is consistent with current android phone's behavior
- Log.i(CarLog.TAG_AUDIO, "interceptKeyBeforeQueueing:"
- + " VOLUME key-down while ringing: Silence ringer!");
-
- // Silence the ringer. (It's safe to call this
- // even if the ringer has already been silenced.)
- telecomManager.silenceRinger();
- return true;
- }
- return false;
- }
-
- public static boolean isVolumeKey(KeyEvent event) {
- return event.getKeyCode() == KeyEvent.KEYCODE_VOLUME_DOWN
- || event.getKeyCode() == KeyEvent.KEYCODE_VOLUME_UP;
- }
-
- /**
- * To control volumes through {@link android.media.AudioManager} when car audio module does not
- * support volume controls.
- */
- public static final class SimpleCarVolumeController extends CarVolumeController {
- private final AudioManager mAudioManager;
- private final Context mContext;
-
- public SimpleCarVolumeController(Context context) {
- mAudioManager = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE);
- mContext = context;
- }
-
- @Override
- void init() {
- }
-
- @Override
- void release() {
- }
-
- @Override
- public void setStreamVolume(int stream, int index, int flags) {
- if (DBG) {
- Log.d(CarLog.TAG_AUDIO, "setStreamVolume " + stream + " " + index + " " + flags);
- }
- mAudioManager.setStreamVolume(stream, index, flags);
- }
-
- @Override
- public int getStreamVolume(int stream) {
- return mAudioManager.getStreamVolume(stream);
- }
-
- @Override
- public void setVolumeController(IVolumeController controller) {
- mAudioManager.setVolumeController(controller);
- }
-
- @Override
- public int getStreamMaxVolume(int stream) {
- return mAudioManager.getStreamMaxVolume(stream);
- }
-
- @Override
- public int getStreamMinVolume(int stream) {
- return mAudioManager.getStreamMinVolume(stream);
- }
-
- @Override
- public boolean onKeyEvent(KeyEvent event) {
- if (!isVolumeKey(event)) {
- return false;
- }
- handleVolumeKeyDefault(event);
- return true;
- }
-
- @Override
- public void dump(PrintWriter writer) {
- writer.println("Volume controller:" + SimpleCarVolumeController.class.getSimpleName());
- // nothing else to dump
- }
-
- private void handleVolumeKeyDefault(KeyEvent event) {
- if (event.getAction() != KeyEvent.ACTION_DOWN
- || interceptVolKeyBeforeDispatching(mContext)) {
- return;
- }
-
- boolean volUp = event.getKeyCode() == KeyEvent.KEYCODE_VOLUME_UP;
- int flags = AudioManager.FLAG_SHOW_UI | AudioManager.FLAG_PLAY_SOUND
- | AudioManager.FLAG_FROM_KEY;
- IAudioService audioService = getAudioService();
- String pkgName = mContext.getOpPackageName();
- try {
- if (audioService != null) {
- audioService.adjustSuggestedStreamVolume(
- volUp ? AudioManager.ADJUST_RAISE : AudioManager.ADJUST_LOWER,
- AudioManager.USE_DEFAULT_STREAM_TYPE, flags, pkgName, CarLog.TAG_INPUT);
- }
- } catch (RemoteException e) {
- Log.e(CarLog.TAG_INPUT, "Error calling android audio service.", e);
- }
- }
-
- private static IAudioService getAudioService() {
- IAudioService audioService = IAudioService.Stub.asInterface(
- ServiceManager.checkService(Context.AUDIO_SERVICE));
- if (audioService == null) {
- Log.w(CarLog.TAG_INPUT, "Unable to find IAudioService interface.");
- }
- return audioService;
- }
- }
-
- /**
- * The car volume controller to use when the car audio modules supports volume controls.
- *
- * Depending on whether the car support audio context and has persistent memory, we need to
- * handle per context volume change properly.
- *
- * Regardless whether car supports audio context or not, we need to keep per audio context
- * volume internally. If we only support single channel, then we only send the volume change
- * event when that stream is in focus; Otherwise, we need to adjust the stream volume either on
- * software mixer level or send it the car audio module if the car support audio context
- * and multi channel. TODO: Add support for multi channel. bug: 32095376
- *
- * Per context volume should be persisted, so the volumes can stay the same across boots.
- * Depending on the hardware property, this can be persisted on car side (or/and android side).
- * TODO: we need to define one single source of truth if the car has memory. bug: 32091839
- */
- public static class CarExternalVolumeController extends CarVolumeController
- implements CarInputService.KeyEventListener, AudioHalService.AudioHalVolumeListener,
- CarAudioService.AudioContextChangeListener {
- private static final String TAG = CarLog.TAG_AUDIO + ".VolCtrl";
- private static final int MSG_UPDATE_VOLUME = 0;
- private static final int MSG_UPDATE_HAL = 1;
- private static final int MSG_SUPPRESS_UI_FOR_VOLUME = 2;
- private static final int MSG_VOLUME_UI_RESTORE = 3;
-
- // within 5 seconds after a UI invisible volume change (e.g., due to audio context change,
- // or explicitly flag), we will not show UI in respond to that particular volume changes
- // events from HAL (context and volume index must match).
- private static final int HIDE_VOLUME_UI_MILLISECONDS = 5 * 1000; // 5 seconds
-
- private final Context mContext;
- private final AudioRoutingPolicy mPolicy;
- private final AudioHalService mHal;
- private final CarInputService mInputService;
- private final CarAudioService mAudioService;
-
- private int mSupportedAudioContext;
-
- private boolean mHasExternalMemory;
- private boolean mMasterVolumeOnly;
-
- @GuardedBy("this")
- private int mCurrentContext = CarVolumeService.DEFAULT_CAR_AUDIO_CONTEXT;
- // current logical volume, the key is car audio context
- @GuardedBy("this")
- private final SparseArray<Integer> mCurrentCarContextVolume =
- new SparseArray<>(VolumeUtils.CAR_AUDIO_CONTEXT.length);
- // stream volume limit, the key is car audio context type
- @GuardedBy("this")
- private final SparseArray<Integer> mCarContextVolumeMax =
- new SparseArray<>(VolumeUtils.CAR_AUDIO_CONTEXT.length);
- // stream volume limit, the key is car audio context type
- @GuardedBy("this")
- private final RemoteCallbackList<IVolumeController> mVolumeControllers =
- new RemoteCallbackList<>();
- @GuardedBy("this")
- private int[] mSuppressUiForVolume = new int[2];
- @GuardedBy("this")
- private boolean mShouldSuppress = false;
- private HandlerThread mVolumeThread;
- private Handler mHandler;
-
- /**
- * Convert an car context to the car stream.
- *
- * @return If car supports audio context, then it returns the car audio context. Otherwise,
- * it returns the physical stream that maps to this logical stream.
- */
- private int carContextToCarStream(int carContext) {
- if (mSupportedAudioContext == 0) {
- int physicalStream = mPolicy.getPhysicalStreamForLogicalStream(
- AudioHalService.carContextToCarUsage(carContext));
- return physicalStream;
- } else {
- return carContext == VehicleAudioContextFlag.UNKNOWN_FLAG ?
- mCurrentContext : carContext;
- }
- }
-
- private void writeVolumeToSettings(int carContext, int volume) {
- String key = VolumeUtils.CAR_AUDIO_CONTEXT_SETTINGS.get(carContext);
- if (key != null) {
- Settings.Global.putInt(mContext.getContentResolver(), key, volume);
- }
- }
-
- /**
- * All updates to external components should be posted to this handler to avoid holding
- * the internal lock while sending updates.
- */
- private final class VolumeHandler extends Handler {
- public VolumeHandler(Looper looper) {
- super(looper);
- }
- @Override
- public void handleMessage(Message msg) {
- int stream;
- int volume;
- switch (msg.what) {
- case MSG_UPDATE_VOLUME:
- // arg1 is car context
- stream = msg.arg1;
- volume = (int) msg.obj;
- int flag = msg.arg2;
- synchronized (CarExternalVolumeController.this) {
- // the suppressed stream is sending us update....
- if (mShouldSuppress && stream == mSuppressUiForVolume[0]) {
- // the volume matches, we want to suppress it
- if (volume == mSuppressUiForVolume[1]) {
- if (DBG) {
- Log.d(TAG, "Suppress Volume UI for stream "
- + stream + " volume: " + volume);
- }
- flag &= ~AudioManager.FLAG_SHOW_UI;
- }
- // No matter if the volume matches or not, we will stop suppressing
- // UI for this stream now. After an audio context switch, user may
- // quickly turn the nob, -1 and +1, it ends the same volume,
- // but we should show the UI for both.
- removeMessages(MSG_VOLUME_UI_RESTORE);
- mShouldSuppress = false;
- }
- }
- final int size = mVolumeControllers.beginBroadcast();
- try {
- for (int i = 0; i < size; i++) {
- try {
- mVolumeControllers.getBroadcastItem(i).volumeChanged(
- VolumeUtils.carContextToAndroidStream(stream), flag);
- } catch (RemoteException ignored) {
- }
- }
- } finally {
- mVolumeControllers.finishBroadcast();
- }
- break;
- case MSG_UPDATE_HAL:
- stream = msg.arg1;
- volume = msg.arg2;
- synchronized (CarExternalVolumeController.this) {
- if (mMasterVolumeOnly) {
- stream = 0;
- }
- }
- mHal.setStreamVolume(stream, volume);
- break;
- case MSG_SUPPRESS_UI_FOR_VOLUME:
- if (DBG) {
- Log.d(TAG, "Suppress stream volume " + msg.arg1 + " " + msg.arg2);
- }
- synchronized (CarExternalVolumeController.this) {
- mShouldSuppress = true;
- mSuppressUiForVolume[0] = msg.arg1;
- mSuppressUiForVolume[1] = msg.arg2;
- }
- removeMessages(MSG_VOLUME_UI_RESTORE);
- sendMessageDelayed(obtainMessage(MSG_VOLUME_UI_RESTORE),
- HIDE_VOLUME_UI_MILLISECONDS);
- break;
- case MSG_VOLUME_UI_RESTORE:
- if (DBG) {
- Log.d(TAG, "Volume Ui suppress expired");
- }
- synchronized (CarExternalVolumeController.this) {
- mShouldSuppress = false;
- }
- break;
- default:
- break;
- }
- }
- }
-
- public CarExternalVolumeController(Context context, CarAudioService audioService,
- AudioHalService hal, CarInputService inputService) {
- mContext = context;
- mAudioService = audioService;
- mPolicy = audioService.getAudioRoutingPolicy();
- mHal = hal;
- mInputService = inputService;
- }
-
- @Override
- void init() {
- mSupportedAudioContext = mHal.getSupportedAudioVolumeContexts();
- mHasExternalMemory = mHal.isExternalAudioVolumePersistent();
- mMasterVolumeOnly = mHal.isAudioVolumeMasterOnly();
- synchronized (this) {
- mVolumeThread = new HandlerThread(TAG);
- mVolumeThread.start();
- mHandler = new VolumeHandler(mVolumeThread.getLooper());
- initVolumeLimitLocked();
- initCurrentVolumeLocked();
- }
- mInputService.setVolumeKeyListener(this);
- mHal.setVolumeListener(this);
- mAudioService.setAudioContextChangeListener(Looper.getMainLooper(), this);
- }
-
- @Override
- void release() {
- synchronized (this) {
- if (mVolumeThread != null) {
- mVolumeThread.quit();
- }
- }
- }
-
- private void initVolumeLimitLocked() {
- for (int i : VolumeUtils.CAR_AUDIO_CONTEXT) {
- int carStream = carContextToCarStream(i);
- Integer volumeMax = mHal.getStreamMaxVolume(carStream);
- int max = volumeMax == null ? 0 : volumeMax;
- if (max < 0) {
- max = 0;
- }
- // get default stream volume limit first.
- mCarContextVolumeMax.put(i, max);
- }
- }
-
- private void initCurrentVolumeLocked() {
- if (mHasExternalMemory) {
- // TODO: read per context volume from audio hal. bug: 32091839
- } else {
- // when vhal does not work, get call can take long. For that case,
- // for the same physical streams, cache initial get results
- Map<Integer, Integer> volumesPerCarStream =
- new ArrayMap<>(VolumeUtils.CAR_AUDIO_CONTEXT.length);
- for (int i : VolumeUtils.CAR_AUDIO_CONTEXT) {
- String key = VolumeUtils.CAR_AUDIO_CONTEXT_SETTINGS.get(i);
- if (key != null) {
- int vol = Settings.Global.getInt(mContext.getContentResolver(), key, -1);
- if (vol >= 0) {
- // Read valid volume for this car context from settings and continue;
- mCurrentCarContextVolume.put(i, vol);
- if (DBG) {
- Log.d(TAG, "init volume from settings, car audio context: "
- + i + " volume: " + vol);
- }
- continue;
- }
- }
-
- // There is no settings for this car context. Use the current physical car
- // stream volume as initial value instead, and put the volume into settings.
- int carStream = carContextToCarStream(i);
- Integer volume = volumesPerCarStream.get(carStream);
- if (volume == null) {
- volume = Integer.valueOf(mHal.getStreamVolume(mMasterVolumeOnly ? 0 :
- carStream));
- volumesPerCarStream.put(carStream, volume);
- }
- mCurrentCarContextVolume.put(i, volume);
- writeVolumeToSettings(i, volume);
- if (DBG) {
- Log.d(TAG, "init volume from physical stream," +
- " car audio context: " + i + " volume: " + volume);
- }
- }
- }
- }
-
- @Override
- public void setStreamVolume(int stream, int index, int flags) {
- synchronized (this) {
- int carContext;
- // Currently car context and android logical stream are not
- // one-to-one mapping. In this API, Android side asks us to change a logical stream
- // volume. If the current car audio context maps to this logical stream, then we
- // change the volume for the current car audio context. Otherwise, we change the
- // volume for the primary mapped car audio context.
- if (VolumeUtils.carContextToAndroidStream(mCurrentContext) == stream) {
- carContext = mCurrentContext;
- } else {
- carContext = VolumeUtils.androidStreamToCarContext(stream);
- }
- if (DBG) {
- Log.d(TAG, "Receive setStreamVolume logical stream: " + stream + " index: "
- + index + " flags: " + flags + " maps to car context: " + carContext);
- }
- setStreamVolumeInternalLocked(carContext, index, flags);
- }
- }
-
- private void setStreamVolumeInternalLocked(int carContext, int index, int flags) {
- if (mCarContextVolumeMax.get(carContext) == null) {
- Log.e(TAG, "Stream type not supported " + carContext);
- return;
- }
- int limit = mCarContextVolumeMax.get(carContext);
- if (index > limit) {
- Log.w(TAG, "Volume exceeds volume limit. context: " + carContext
- + " index: " + index + " limit: " + limit);
- index = limit;
- }
-
- if (index < 0) {
- index = 0;
- }
-
- if (mCurrentCarContextVolume.get(carContext) == index) {
- return;
- }
-
- int carStream = carContextToCarStream(carContext);
- if (DBG) {
- Log.d(TAG, "Change car stream volume, stream: " + carStream + " volume:" + index);
- }
- // For single channel, only adjust the volume when the audio context is the current one.
- if (mCurrentContext == carContext) {
- if (DBG) {
- Log.d(TAG, "Sending volume change to HAL");
- }
- mHandler.sendMessage(mHandler.obtainMessage(MSG_UPDATE_HAL, carStream, index));
- if ((flags & AudioManager.FLAG_SHOW_UI) != 0) {
- if (mShouldSuppress && mSuppressUiForVolume[0] == carContext) {
- // In this case, the caller explicitly says "Show_UI" for the same context.
- // We will respect the flag, and let the UI show.
- mShouldSuppress = false;
- mHandler.removeMessages(MSG_VOLUME_UI_RESTORE);
- }
- } else {
- mHandler.sendMessage(mHandler.obtainMessage(MSG_SUPPRESS_UI_FOR_VOLUME,
- carContext, index));
- }
- }
- // Record the current volume internally.
- mCurrentCarContextVolume.put(carContext, index);
- writeVolumeToSettings(mCurrentContext, index);
- }
-
- @Override
- public int getStreamVolume(int stream) {
- synchronized (this) {
- if (VolumeUtils.carContextToAndroidStream(mCurrentContext) == stream) {
- return mCurrentCarContextVolume.get(mCurrentContext);
- }
- return mCurrentCarContextVolume.get(VolumeUtils.androidStreamToCarContext(stream));
- }
- }
-
- @Override
- public void setVolumeController(IVolumeController controller) {
- synchronized (this) {
- mVolumeControllers.register(controller);
- }
- }
-
- @Override
- public void onVolumeChange(int carStream, int volume, int volumeState) {
- synchronized (this) {
- int flag = getVolumeUpdateFlag(true);
- if (DBG) {
- Log.d(TAG, "onVolumeChange carStream: " + carStream + " volume: " + volume
- + " volumeState: " + volumeState
- + " suppressUI? " + mShouldSuppress
- + " stream: " + mSuppressUiForVolume[0]
- + " volume: " + mSuppressUiForVolume[1]);
- }
- int currentCarStream = carContextToCarStream(mCurrentContext);
- if (mMasterVolumeOnly) { //for master volume only H/W, always assume current stream
- carStream = currentCarStream;
- }
-
- // Map the UNKNOWN context to the current context.
- if (mSupportedAudioContext != 0
- && carStream == VehicleAudioContextFlag.UNKNOWN_FLAG) {
- carStream = mCurrentContext;
- }
-
- if (currentCarStream == carStream) {
- mCurrentCarContextVolume.put(mCurrentContext, volume);
- writeVolumeToSettings(mCurrentContext, volume);
- mHandler.sendMessage(
- mHandler.obtainMessage(MSG_UPDATE_VOLUME, mCurrentContext, flag,
- new Integer(volume)));
- } else {
- // Hal is telling us a car stream volume has changed, but it is not the current
- // stream.
- // TODO: b/63778359
- Log.w(TAG, "Car stream" + carStream
- + " volume changed, but it is not current stream, ignored.");
- }
- }
- }
-
- private int getVolumeUpdateFlag(boolean showUi) {
- return showUi? AudioManager.FLAG_SHOW_UI : 0;
- }
-
- @Override
- public void onVolumeLimitChange(int streamNumber, int volume) {
- // TODO: How should this update be sent to SystemUI? bug: 32095237
- // maybe send a volume update without showing UI.
- synchronized (this) {
- initVolumeLimitLocked();
- }
- }
-
- @Override
- public int getStreamMaxVolume(int stream) {
- synchronized (this) {
- if (VolumeUtils.carContextToAndroidStream(mCurrentContext) == stream) {
- return mCarContextVolumeMax.get(mCurrentContext);
- } else {
- return mCarContextVolumeMax.get(VolumeUtils.androidStreamToCarContext(stream));
- }
- }
- }
-
- @Override
- public int getStreamMinVolume(int stream) {
- return 0; // Min value is always zero.
- }
-
- @Override
- public boolean onKeyEvent(KeyEvent event) {
- if (!isVolumeKey(event)) {
- return false;
- }
- final boolean down = event.getAction() == KeyEvent.ACTION_DOWN;
- if (DBG) {
- Log.d(TAG, "Receive volume keyevent " + event.toString());
- }
- // TODO: properly handle long press on volume key, bug: 32095989
- if (!down || interceptVolKeyBeforeDispatching(mContext)) {
- return true;
- }
-
- synchronized (this) {
- int currentVolume = mCurrentCarContextVolume.get(mCurrentContext);
- switch (event.getKeyCode()) {
- case KeyEvent.KEYCODE_VOLUME_UP:
- setStreamVolumeInternalLocked(mCurrentContext, currentVolume + 1,
- getVolumeUpdateFlag(true));
- break;
- case KeyEvent.KEYCODE_VOLUME_DOWN:
- setStreamVolumeInternalLocked(mCurrentContext, currentVolume - 1,
- getVolumeUpdateFlag(true));
- break;
- }
- }
- return true;
- }
-
- @Override
- public void onContextChange(int primaryFocusContext, int primaryFocusPhysicalStream) {
- synchronized (this) {
- if(DBG) {
- Log.d(TAG, "Audio context changed from " + mCurrentContext + " to: "
- + primaryFocusContext + " physical: " + primaryFocusPhysicalStream);
- }
- // if primaryFocusContext is 0, it means nothing is playing or holding focus,
- // we will keep the last focus context and if the user changes the volume
- // it will go to the last audio context.
- if (primaryFocusContext == mCurrentContext || primaryFocusContext == 0) {
- return;
- }
- int oldContext = mCurrentContext;
- mCurrentContext = primaryFocusContext;
- // if car supports audio context and has external memory, then we don't need to do
- // anything.
- if(mSupportedAudioContext != 0 && mHasExternalMemory) {
- if (DBG) {
- Log.d(TAG, "Car support audio context and has external memory," +
- " no volume change needed from car service");
- }
- return;
- }
-
- // Otherwise, we need to tell Hal what the correct volume is for the new context.
- int currentVolume = mCurrentCarContextVolume.get(primaryFocusContext);
-
- int carStreamNumber = (mSupportedAudioContext == 0) ? primaryFocusPhysicalStream :
- primaryFocusContext;
- if (DBG) {
- Log.d(TAG, "Change volume from: "
- + mCurrentCarContextVolume.get(oldContext)
- + " to: "+ currentVolume);
- }
- mHandler.sendMessage(mHandler.obtainMessage(MSG_UPDATE_HAL, carStreamNumber,
- currentVolume));
- mHandler.sendMessage(mHandler.obtainMessage(MSG_SUPPRESS_UI_FOR_VOLUME,
- mCurrentContext, currentVolume));
- }
- }
-
- @Override
- public void dump(PrintWriter writer) {
- writer.println("Volume controller:" +
- CarExternalVolumeController.class.getSimpleName());
- synchronized (this) {
- writer.println("mSupportedAudioContext:0x" +
- Integer.toHexString(mSupportedAudioContext) +
- ",mHasExternalMemory:" + mHasExternalMemory +
- ",mMasterVolumeOnly:" + mMasterVolumeOnly);
- writer.println("mCurrentContext:0x" + Integer.toHexString(mCurrentContext));
- writer.println("mCurrentCarContextVolume:");
- dumpVolumes(writer, mCurrentCarContextVolume);
- writer.println("mCarContextVolumeMax:");
- dumpVolumes(writer, mCarContextVolumeMax);
- writer.println("Number of volume controllers:" +
- mVolumeControllers.getRegisteredCallbackCount());
- }
- }
-
- private void dumpVolumes(PrintWriter writer, SparseArray<Integer> array) {
- for (int i = 0; i < array.size(); i++) {
- writer.println("0x" + Integer.toHexString(array.keyAt(i)) + ":" + array.valueAt(i));
- }
- }
- }
-}
diff --git a/service/src/com/android/car/CarVolumeGroup.java b/service/src/com/android/car/CarVolumeGroup.java
new file mode 100644
index 0000000..448979b
--- /dev/null
+++ b/service/src/com/android/car/CarVolumeGroup.java
@@ -0,0 +1,210 @@
+/*
+ * 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;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.car.media.CarAudioManager;
+import android.content.ContentResolver;
+import android.content.Context;
+import android.hardware.automotive.audiocontrol.V1_0.ContextNumber;
+import android.media.AudioDevicePort;
+import android.provider.Settings;
+import android.util.SparseArray;
+import android.util.SparseIntArray;
+
+import com.android.internal.util.Preconditions;
+
+import java.io.PrintWriter;
+import java.util.Arrays;
+
+/**
+ * A class encapsulates a volume group in car.
+ *
+ * Volume in a car is controlled by group. A group holds one or more car audio contexts.
+ * Call {@link CarAudioManager#getVolumeGroupCount()} to get the count of {@link CarVolumeGroup}
+ * supported in a car.
+ */
+/* package */ final class CarVolumeGroup {
+
+ private final ContentResolver mContentResolver;
+ private final int mId;
+ private final int[] mContexts;
+ private final SparseIntArray mContextToBus = new SparseIntArray();
+ private final SparseArray<CarAudioDeviceInfo> mBusToCarAudioDeviceInfos = new SparseArray<>();
+
+ private int mDefaultGain = Integer.MIN_VALUE;
+ private int mMaxGain = Integer.MIN_VALUE;
+ private int mMinGain = Integer.MAX_VALUE;
+ private int mStepSize = 0;
+ private int mStoredGainIndex;
+ private int mCurrentGainIndex = -1;
+
+ CarVolumeGroup(Context context, int id, @NonNull int[] contexts) {
+ mContentResolver = context.getContentResolver();
+ mId = id;
+ mContexts = contexts;
+
+ mStoredGainIndex = Settings.Global.getInt(mContentResolver,
+ CarAudioManager.getVolumeSettingsKeyForGroup(mId), -1);;
+ }
+
+ int getId() {
+ return mId;
+ }
+
+ int[] getContexts() {
+ return mContexts;
+ }
+
+ int[] getBusNumbers() {
+ final int[] busNumbers = new int[mBusToCarAudioDeviceInfos.size()];
+ for (int i = 0; i < busNumbers.length; i++) {
+ busNumbers[i] = mBusToCarAudioDeviceInfos.keyAt(i);
+ }
+ return busNumbers;
+ }
+
+ /**
+ * Binds the context number to physical bus number and audio device port information.
+ * Because this may change the groups min/max values, thus invalidating an index computed from
+ * a gain before this call, all calls to this function must happen at startup before any
+ * set/getGainIndex calls.
+ *
+ * @param contextNumber Context number as defined in audio control HAL
+ * @param busNumber Physical bus number for the audio device port
+ * @param info {@link CarAudioDeviceInfo} instance relates to the physical bus
+ */
+ void bind(int contextNumber, int busNumber, CarAudioDeviceInfo info) {
+ if (mBusToCarAudioDeviceInfos.size() == 0) {
+ mStepSize = info.getAudioGain().stepValue();
+ } else {
+ Preconditions.checkArgument(
+ info.getAudioGain().stepValue() == mStepSize,
+ "Gain controls within one group must have same step value");
+ }
+
+ mContextToBus.put(contextNumber, busNumber);
+ mBusToCarAudioDeviceInfos.put(busNumber, info);
+
+ if (info.getDefaultGain() > mDefaultGain) {
+ // We're arbitrarily selecting the highest bus default gain as the group's default.
+ mDefaultGain = info.getDefaultGain();
+ }
+ if (info.getMaxGain() > mMaxGain) {
+ mMaxGain = info.getMaxGain();
+ }
+ if (info.getMinGain() < mMinGain) {
+ mMinGain = info.getMinGain();
+ }
+ if (mStoredGainIndex < getMinGainIndex() || mStoredGainIndex > getMaxGainIndex()) {
+ // We expected to load a value from last boot, but if we didn't (perhaps this is the
+ // first boot ever?), then use the highest "default" we've seen to initialize
+ // ourselves.
+ mCurrentGainIndex = getIndexForGain(mDefaultGain);
+ } else {
+ // Just use the gain index we stored last time the gain was set (presumably during our
+ // last boot cycle).
+ mCurrentGainIndex = mStoredGainIndex;
+ }
+ }
+
+ int getDefaultGainIndex() {
+ return getIndexForGain(mDefaultGain);
+ }
+
+ int getMaxGainIndex() {
+ return getIndexForGain(mMaxGain);
+ }
+
+ int getMinGainIndex() {
+ return getIndexForGain(mMinGain);
+ }
+
+ int getCurrentGainIndex() {
+ return mCurrentGainIndex;
+ }
+
+ void setCurrentGainIndex(int gainIndex) {
+ int gainInMillibels = getGainForIndex(gainIndex);
+
+ Preconditions.checkArgument(
+ gainInMillibels >= mMinGain && gainInMillibels <= mMaxGain,
+ "Gain out of range (" +
+ mMinGain + ":" +
+ mMaxGain +") " +
+ gainInMillibels + "index " +
+ gainIndex);
+
+ for (int i = 0; i < mBusToCarAudioDeviceInfos.size(); i++) {
+ CarAudioDeviceInfo info = mBusToCarAudioDeviceInfos.valueAt(i);
+ info.setCurrentGain(gainInMillibels);
+ }
+
+ mCurrentGainIndex = gainIndex;
+ Settings.Global.putInt(mContentResolver,
+ CarAudioManager.getVolumeSettingsKeyForGroup(mId), gainIndex);
+ }
+
+ // Given a group level gain index, return the computed gain in millibells
+ // TODO (randolphs) If we ever want to add index to gain curves other than lock-stepped
+ // linear, this would be the place to do it.
+ private int getGainForIndex(int gainIndex) {
+ return mMinGain + gainIndex * mStepSize;
+ }
+
+ // TODO (randolphs) if we ever went to a non-linear index to gain curve mapping, we'd need to
+ // revisit this as it assumes (at the least) that getGainForIndex is reversible. Luckily,
+ // this is an internal implementation details we could factor out if/when necessary.
+ private int getIndexForGain(int gainInMillibel) {
+ return (gainInMillibel - mMinGain) / mStepSize;
+ }
+
+ @Nullable
+ AudioDevicePort getAudioDevicePortForContext(int contextNumber) {
+ final int busNumber = mContextToBus.get(contextNumber, -1);
+ if (busNumber < 0 || mBusToCarAudioDeviceInfos.get(busNumber) == null) {
+ return null;
+ }
+ return mBusToCarAudioDeviceInfos.get(busNumber).getAudioDevicePort();
+ }
+
+ @Override
+ public String toString() {
+ return "CarVolumeGroup id: " + mId
+ + " currentGainIndex: " + mCurrentGainIndex
+ + " contexts: " + Arrays.toString(mContexts)
+ + " buses: " + Arrays.toString(getBusNumbers());
+ }
+
+ void dump(PrintWriter writer) {
+ writer.println("CarVolumeGroup " + mId);
+ writer.printf("\tGain in millibel (min / max / default/ current): %d %d %d %d\n",
+ mMinGain, mMaxGain, mDefaultGain, getGainForIndex(mCurrentGainIndex));
+ writer.printf("\tGain in index (min / max / default / current): %d %d %d %d\n",
+ getMinGainIndex(), getMaxGainIndex(), getDefaultGainIndex(), mCurrentGainIndex);
+ for (int i = 0; i < mContextToBus.size(); i++) {
+ writer.printf("\tContext: %s -> Bus: %d\n",
+ ContextNumber.toString(mContextToBus.keyAt(i)), mContextToBus.valueAt(i));
+ }
+ for (int i = 0; i < mBusToCarAudioDeviceInfos.size(); i++) {
+ mBusToCarAudioDeviceInfos.valueAt(i).dump(writer);
+ }
+ // Empty line for comfortable reading
+ writer.println();
+ }
+}
diff --git a/service/src/com/android/car/CarVolumeGroupsHelper.java b/service/src/com/android/car/CarVolumeGroupsHelper.java
new file mode 100644
index 0000000..af2c6dd
--- /dev/null
+++ b/service/src/com/android/car/CarVolumeGroupsHelper.java
@@ -0,0 +1,99 @@
+/*
+ * 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;
+
+import android.annotation.XmlRes;
+import android.content.Context;
+import android.content.res.TypedArray;
+import android.content.res.XmlResourceParser;
+import android.util.AttributeSet;
+import android.util.Log;
+import android.util.Xml;
+
+import org.xmlpull.v1.XmlPullParserException;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
+
+/* package */ class CarVolumeGroupsHelper {
+
+ private static final String TAG_VOLUME_GROUPS = "volumeGroups";
+ private static final String TAG_GROUP = "group";
+ private static final String TAG_CONTEXT = "context";
+
+ private final Context mContext;
+ private final @XmlRes int mXmlConfiguration;
+
+ CarVolumeGroupsHelper(Context context, @XmlRes int xmlConfiguration) {
+ mContext = context;
+ mXmlConfiguration = xmlConfiguration;
+ }
+
+ CarVolumeGroup[] loadVolumeGroups() {
+ List<CarVolumeGroup> carVolumeGroups = new ArrayList<>();
+ try (XmlResourceParser parser = mContext.getResources().getXml(mXmlConfiguration)) {
+ AttributeSet attrs = Xml.asAttributeSet(parser);
+ int type;
+ // Traverse to the first start tag
+ while ((type=parser.next()) != XmlResourceParser.END_DOCUMENT
+ && type != XmlResourceParser.START_TAG) {
+ }
+
+ if (!TAG_VOLUME_GROUPS.equals(parser.getName())) {
+ throw new RuntimeException("Meta-data does not start with volumeGroups tag");
+ }
+ int outerDepth = parser.getDepth();
+ int id = 0;
+ while ((type=parser.next()) != XmlResourceParser.END_DOCUMENT
+ && (type != XmlResourceParser.END_TAG || parser.getDepth() > outerDepth)) {
+ if (type == XmlResourceParser.END_TAG) {
+ continue;
+ }
+ if (TAG_GROUP.equals(parser.getName())) {
+ carVolumeGroups.add(parseVolumeGroup(id, attrs, parser));
+ id++;
+ }
+ }
+ } catch (Exception e) {
+ Log.e(CarLog.TAG_AUDIO, "Error parsing volume groups configuration", e);
+ }
+ return carVolumeGroups.toArray(new CarVolumeGroup[carVolumeGroups.size()]);
+ }
+
+ private CarVolumeGroup parseVolumeGroup(int id, AttributeSet attrs, XmlResourceParser parser)
+ throws XmlPullParserException, IOException {
+ int type;
+
+ List<Integer> contexts = new ArrayList<>();
+ int innerDepth = parser.getDepth();
+ while ((type=parser.next()) != XmlResourceParser.END_DOCUMENT
+ && (type != XmlResourceParser.END_TAG || parser.getDepth() > innerDepth)) {
+ if (type == XmlResourceParser.END_TAG) {
+ continue;
+ }
+ if (TAG_CONTEXT.equals(parser.getName())) {
+ TypedArray c = mContext.getResources().obtainAttributes(
+ attrs, R.styleable.volumeGroups_context);
+ contexts.add(c.getInt(R.styleable.volumeGroups_context_context, -1));
+ c.recycle();
+ }
+ }
+
+ return new CarVolumeGroup(mContext, id,
+ contexts.stream().mapToInt(i -> i).filter(i -> i >= 0).toArray());
+ }
+}
diff --git a/service/src/com/android/car/CarVolumeService.java b/service/src/com/android/car/CarVolumeService.java
deleted file mode 100644
index 702b8dc..0000000
--- a/service/src/com/android/car/CarVolumeService.java
+++ /dev/null
@@ -1,122 +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;
-
-import android.content.Context;
-import android.hardware.automotive.vehicle.V2_0.VehicleAudioContextFlag;
-import android.media.AudioAttributes;
-import android.media.IVolumeController;
-
-import com.android.car.hal.AudioHalService;
-
-import java.io.PrintWriter;
-
-/**
- * Handles car volume controls.
- *
- * It delegates to a {@link com.android.car.CarVolumeService.CarVolumeController} to do proper
- * volume controls based on different car properties.
- *
- * @hide
- */
-public class CarVolumeService {
- private static final String TAG = "CarVolumeService";
-
- public static int DEFAULT_CAR_AUDIO_CONTEXT =
- VehicleAudioContextFlag.MUSIC_FLAG;
- private final Context mContext;
- private final AudioHalService mAudioHal;
- private final CarAudioService mAudioService;
- private final CarInputService mInputService;
-
- private CarVolumeController mCarVolumeController;
-
- private IVolumeController mIVolumeController;
-
- public static int androidStreamToCarUsage(int logicalAndroidStream) {
- return CarAudioAttributesUtil.getCarUsageFromAudioAttributes(
- new AudioAttributes.Builder()
- .setLegacyStreamType(logicalAndroidStream).build());
- }
-
- public CarVolumeService(Context context, CarAudioService audioService, AudioHalService audioHal,
- CarInputService inputService) {
- mContext = context;
- mAudioHal = audioHal;
- mAudioService = audioService;
- mInputService = inputService;
- }
-
- public synchronized void init() {
- mCarVolumeController = CarVolumeControllerFactory.createCarVolumeController(mContext,
- mAudioService, mAudioHal, mInputService);
-
- mCarVolumeController.init();
- if (mIVolumeController != null) {
- mCarVolumeController.setVolumeController(mIVolumeController);
- }
- mInputService.setVolumeKeyListener(mCarVolumeController);
- }
-
- public synchronized void release() {
- mCarVolumeController.release();
- }
-
- public void setStreamVolume(int streamType, int index, int flags) {
- getController().setStreamVolume(streamType, index, flags);
- }
-
- public synchronized void setVolumeController(IVolumeController controller) {
- mIVolumeController = controller;
- getController().setVolumeController(controller);
- }
-
- public int getStreamMaxVolume(int stream) {
- return getController().getStreamMaxVolume(stream);
- }
-
- public int getStreamMinVolume(int stream) {
- return getController().getStreamMinVolume(stream);
- }
-
- public int getStreamVolume(int stream) {
- return getController().getStreamVolume(stream);
- }
-
- public void dump(PrintWriter writer) {
- mCarVolumeController.dump(writer);
- }
-
- private synchronized CarVolumeController getController() {
- return mCarVolumeController;
- }
-
- /**
- * Abstraction layer for volume controls, so that we don't have if-else check for audio
- * properties everywhere.
- */
- public static abstract class CarVolumeController implements CarInputService.KeyEventListener {
- abstract void init();
- abstract void release();
- abstract public void setStreamVolume(int stream, int index, int flags);
- abstract public void setVolumeController(IVolumeController controller);
- abstract public int getStreamMaxVolume(int stream);
- abstract public int getStreamMinVolume(int stream);
- abstract public int getStreamVolume(int stream);
- abstract public void dump(PrintWriter writer);
- }
-}
diff --git a/service/src/com/android/car/DayNightModePolicy.java b/service/src/com/android/car/DayNightModePolicy.java
deleted file mode 100644
index 48072eb..0000000
--- a/service/src/com/android/car/DayNightModePolicy.java
+++ /dev/null
@@ -1,97 +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;
-
-import android.car.hardware.CarSensorEvent;
-import android.car.hardware.CarSensorManager;
-import android.content.Context;
-import android.util.Log;
-
-import com.android.car.hal.SensorHalService.SensorListener;
-import java.io.PrintWriter;
-
-//TODO implement default one based on time or other sensors. bug: 32066909
-public class DayNightModePolicy extends CarSensorService.LogicalSensor {
-
- private final Context mContext;
- private SensorListener mSensorListener;
- private boolean mIsReady = false;
- private boolean mStarted = false;
-
- private static final int[] SUPPORTED_SENSORS = { CarSensorManager.SENSOR_TYPE_NIGHT };
-
- public DayNightModePolicy(Context context) {
- mContext = context;
- }
-
- @Override
- public synchronized void init() {
- mIsReady = true;
- }
-
- @Override
- public synchronized void release() {
- }
-
- public static CarSensorEvent getDefaultValue(int sensorType) {
- // There's a race condition and timestamp from vehicle HAL could be slightly less
- // then current call to SystemClock.elapsedRealtimeNanos() will return.
- // We want vehicle HAL value always override this default value so we set timestamp to 0.
- return createEvent(true /* isNight */, 0 /* timestamp */);
- }
-
- public synchronized void registerSensorListener(SensorListener listener) {
- mSensorListener = listener;
- }
-
- @Override
- public synchronized void onSensorServiceReady() {
- }
-
- @Override
- public synchronized boolean isReady() {
- return mIsReady;
- }
-
- @Override
- public synchronized int[] getSupportedSensors() {
- return SUPPORTED_SENSORS;
- }
-
- @Override
- public synchronized boolean requestSensorStart(int sensorType, int rate) {
- mStarted = true;
- Log.w(CarLog.TAG_SENSOR,
- "DayNightModePolicy.requestSensorStart, default policy not implemented");
- return false;
- }
-
- @Override
- public synchronized void requestSensorStop(int sensorType) {
- }
-
- private static CarSensorEvent createEvent(boolean isNight, long timestamp) {
- CarSensorEvent event = new CarSensorEvent(CarSensorManager.SENSOR_TYPE_NIGHT,
- timestamp, 0, 1, 0);
- event.intValues[0] = isNight ? 1 : 0;
- return event;
- }
-
- @Override
- public synchronized void dump(PrintWriter writer) {
- }
-}
diff --git a/service/src/com/android/car/DrivingStatePolicy.java b/service/src/com/android/car/DrivingStatePolicy.java
deleted file mode 100644
index 37bbbc0..0000000
--- a/service/src/com/android/car/DrivingStatePolicy.java
+++ /dev/null
@@ -1,212 +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;
-
-import android.car.hardware.CarSensorEvent;
-import android.car.hardware.CarSensorManager;
-import android.car.hardware.ICarSensorEventListener;
-import android.content.Context;
-import android.os.SystemClock;
-import android.util.Log;
-
-import com.android.car.hal.SensorHalService.SensorListener;
-import java.io.PrintWriter;
-import java.util.List;
-
-
-/**
- * Logical sensor implementing driving state policy. This policy sets only two states:
- * no restriction vs fully restrictive. To enter no restriction state, speed should be zero
- * while either parking brake is applied or transmission gear is in P.
- */
-public class DrivingStatePolicy extends CarSensorService.LogicalSensor {
-
- private final Context mContext;
- private CarSensorService mSensorService;
- private int mDrivingState = CarSensorEvent.DRIVE_STATUS_FULLY_RESTRICTED;
- private SensorListener mSensorListener;
- private boolean mIsReady = false;
- private boolean mStarted = false;
-
- private static final int[] SUPPORTED_SENSORS = { CarSensorManager.SENSOR_TYPE_DRIVING_STATUS };
-
- private final ICarSensorEventListener mICarSensorEventListener =
- new ICarSensorEventListener.Stub() {
- @Override
- public void onSensorChanged(List<CarSensorEvent> events) {
- for (CarSensorEvent event: events) {
- handleSensorEvent(event);
- }
- }
- };
-
- public DrivingStatePolicy(Context context, CarSensorService sensorService) {
- mContext = context;
- mSensorService = sensorService;
- }
-
- @Override
- public void init() {
- mIsReady = true;
- }
-
- @Override
- public synchronized void onSensorServiceReady() {
- int sensorList[] = mSensorService.getSupportedSensors();
- boolean hasSpeed = subscribeIfSupportedLocked(sensorList,
- CarSensorManager.SENSOR_TYPE_CAR_SPEED, CarSensorManager.SENSOR_RATE_FASTEST);
- if (!hasSpeed) {
- Log.w(CarLog.TAG_SENSOR,
- "No speed sensor from car. Driving state will be always fully restrictive");
- }
- boolean hasParkingBrake = subscribeIfSupportedLocked(sensorList,
- CarSensorManager.SENSOR_TYPE_PARKING_BRAKE, CarSensorManager.SENSOR_RATE_FASTEST);
- boolean hasGear = subscribeIfSupportedLocked(sensorList, CarSensorManager.SENSOR_TYPE_GEAR,
- CarSensorManager.SENSOR_RATE_FASTEST);
- if (!hasParkingBrake && !hasGear) {
- Log.w(CarLog.TAG_SENSOR,
- "No brake info from car. Driving state will be always fully restrictive");
- }
- }
-
- @Override
- public void release() {
- }
-
- public static CarSensorEvent getDefaultValue(int sensorType) {
- if (sensorType != CarSensorManager.SENSOR_TYPE_DRIVING_STATUS) {
- Log.w(CarLog.TAG_SENSOR, "getDefaultValue to DrivingStatePolicy with sensorType:" +
- sensorType);
- return null;
- }
- // There's a race condition and timestamp from vehicle HAL could be slightly less
- // then current call to SystemClock.elapsedRealtimeNanos() will return.
- // We want vehicle HAL value always override this default value so we set timestamp to 0.
- return createEvent(CarSensorEvent.DRIVE_STATUS_FULLY_RESTRICTED, 0 /* timestamp */);
- }
-
- public synchronized void registerSensorListener(SensorListener listener) {
- mSensorListener = listener;
- }
-
- @Override
- public synchronized boolean isReady() {
- return mIsReady;
- }
-
- @Override
- public int[] getSupportedSensors() {
- return SUPPORTED_SENSORS;
- }
-
- @Override
- public synchronized boolean requestSensorStart(int sensorType, int rate) {
- mStarted = true;
- dispatchCarSensorEvent(mSensorListener, createEvent(mDrivingState));
- return true;
- }
-
- @Override
- public synchronized void requestSensorStop(int sensorType) {
- mStarted = false;
- }
-
- @Override
- public void dump(PrintWriter writer) {
- }
-
- private boolean subscribeIfSupportedLocked(int sensorList[], int sensorType, int rate) {
- if (!CarSensorManager.isSensorSupported(sensorList, sensorType)) {
- Log.i(CarLog.TAG_SENSOR, "Sensor not supported:" + sensorType);
- return false;
- }
- return mSensorService.registerOrUpdateSensorListener(sensorType, rate,
- mICarSensorEventListener);
- }
-
- private synchronized void handleSensorEvent(CarSensorEvent event) {
- switch (event.sensorType) {
- case CarSensorManager.SENSOR_TYPE_PARKING_BRAKE:
- case CarSensorManager.SENSOR_TYPE_GEAR:
- case CarSensorManager.SENSOR_TYPE_CAR_SPEED:
- int drivingState = recalcDrivingStateLocked();
- if (drivingState != mDrivingState && mSensorListener != null) {
- mDrivingState = drivingState;
- dispatchCarSensorEvent(mSensorListener, createEvent(mDrivingState));
- }
- break;
- default:
- break;
- }
- }
-
- private int recalcDrivingStateLocked() {
- int drivingState = CarSensorEvent.DRIVE_STATUS_FULLY_RESTRICTED;
- CarSensorEvent lastParkingBrake = mSensorService.getLatestSensorEvent(
- CarSensorManager.SENSOR_TYPE_PARKING_BRAKE);
- CarSensorEvent lastGear = mSensorService.getLatestSensorEvent(
- CarSensorManager.SENSOR_TYPE_GEAR);
- CarSensorEvent lastSpeed = mSensorService.getLatestSensorEvent(
- CarSensorManager.SENSOR_TYPE_CAR_SPEED);
- if (lastSpeed != null && lastSpeed.floatValues[0] == 0f) { // stopped
- if (lastParkingBrake == null && isParkingBrakeApplied(lastParkingBrake)) {
- if (lastGear != null && isGearInParkingOrNeutral(lastGear)) {
- drivingState = CarSensorEvent.DRIVE_STATUS_UNRESTRICTED;
- }
- } else { // parking brake not applied or not available
- if (lastGear != null && isGearInParking(lastGear)) { // gear in P
- drivingState = CarSensorEvent.DRIVE_STATUS_UNRESTRICTED;
- }
- }
- } // else moving, full restriction
- return drivingState;
- }
-
- private boolean isSpeedZero(CarSensorEvent event) {
- return event.floatValues[0] == 0f;
- }
-
- private boolean isParkingBrakeApplied(CarSensorEvent event) {
- return event.intValues[0] == 1;
- }
-
- private boolean isGearInParkingOrNeutral(CarSensorEvent event) {
- int gear = event.intValues[0];
- return (gear == CarSensorEvent.GEAR_NEUTRAL) ||
- (gear == CarSensorEvent.GEAR_PARK);
- }
-
- private boolean isGearInParking(CarSensorEvent event) {
- int gear = event.intValues[0];
- return gear == CarSensorEvent.GEAR_PARK;
- }
-
- private static CarSensorEvent createEvent(int drivingState) {
- return createEvent(drivingState, SystemClock.elapsedRealtimeNanos());
- }
-
- private static CarSensorEvent createEvent(int drivingState, long timestamp) {
- CarSensorEvent event = new CarSensorEvent(
- CarSensorManager.SENSOR_TYPE_DRIVING_STATUS,
- timestamp,
- 0 /* float values */,
- 1 /* int values */,
- 0 /* long values */);
- event.intValues[0] = drivingState;
- return event;
- }
-}
diff --git a/service/src/com/android/car/FastPairProvider.java b/service/src/com/android/car/FastPairProvider.java
new file mode 100644
index 0000000..ff59732
--- /dev/null
+++ b/service/src/com/android/car/FastPairProvider.java
@@ -0,0 +1,125 @@
+/*
+ * 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;
+
+import android.bluetooth.BluetoothAdapter;
+import android.bluetooth.BluetoothManager;
+
+import android.bluetooth.le.AdvertiseCallback;
+import android.bluetooth.le.AdvertiseData;
+import android.bluetooth.le.AdvertiseSettings;
+import android.bluetooth.le.BluetoothLeAdvertiser;
+import android.content.Context;
+import android.content.res.Resources;
+import android.os.ParcelUuid;
+import android.util.Log;
+
+import java.nio.ByteBuffer;
+import java.nio.ByteOrder;
+import java.util.Arrays;
+
+/**
+ * An advertiser for the Bluetooth LE based Fast Pair service.
+ * FastPairProvider enables easy Bluetooth pairing between a peripheral and a phone participating in
+ * the Fast Pair Seeker role. When the seeker finds a compatible peripheral a notification prompts
+ * the user to begin pairing if desired. A peripheral should call startAdvertising when it is
+ * appropriate to pair, and stopAdvertising when pairing is complete or it is no longer appropriate
+ * to pair.
+ */
+class FastPairProvider {
+
+ private static final String TAG = "FastPairProvider";
+ private static final boolean DBG = Utils.DBG;
+
+ // Service ID assigned for FastPair.
+ private static final ParcelUuid FastPairServiceUuid = ParcelUuid
+ .fromString("0000FE2C-0000-1000-8000-00805f9b34fb");
+
+ private AdvertiseSettings mSettings;
+ private AdvertiseData mData;
+ private BluetoothLeAdvertiser mBluetoothLeAdvertiser;
+ private AdvertiseCallback mAdvertiseCallback;
+
+
+ FastPairProvider(Context context) {
+ Resources res = context.getResources();
+ int modelId = res.getInteger(R.integer.fastPairModelId);
+ if (modelId == 0) {
+ Log.w(TAG, "Model ID undefined, disabling");
+ return;
+ }
+
+ BluetoothManager bluetoothManager = (BluetoothManager) context.getSystemService(
+ Context.BLUETOOTH_SERVICE);
+ if (bluetoothManager != null) {
+ BluetoothAdapter bluetoothAdapter = bluetoothManager.getAdapter();
+ if (bluetoothAdapter != null) {
+ mBluetoothLeAdvertiser = bluetoothAdapter.getBluetoothLeAdvertiser();
+ }
+ }
+
+ AdvertiseSettings.Builder settingsBuilder = new AdvertiseSettings.Builder();
+ settingsBuilder.setAdvertiseMode(AdvertiseSettings.ADVERTISE_MODE_LOW_LATENCY);
+ settingsBuilder.setTxPowerLevel(AdvertiseSettings.ADVERTISE_TX_POWER_HIGH);
+ settingsBuilder.setConnectable(true);
+ settingsBuilder.setTimeout(0);
+ mSettings = settingsBuilder.build();
+
+ AdvertiseData.Builder dataBuilder = new AdvertiseData.Builder();
+ ByteBuffer modelIdBytes = ByteBuffer.allocate(4).order(ByteOrder.LITTLE_ENDIAN).putInt(
+ modelId);
+ byte[] fastPairServiceData = Arrays.copyOfRange(modelIdBytes.array(), 0, 3);
+ dataBuilder.addServiceData(FastPairServiceUuid, fastPairServiceData);
+ dataBuilder.setIncludeTxPowerLevel(true).build();
+ mData = dataBuilder.build();
+
+ mAdvertiseCallback = new FastPairAdvertiseCallback();
+ }
+
+ /* register the BLE advertisement using the model id provided during construction */
+ boolean startAdvertising() {
+ if (mBluetoothLeAdvertiser != null) {
+ mBluetoothLeAdvertiser.startAdvertising(mSettings, mData, mAdvertiseCallback);
+ return true;
+ }
+ return false;
+ }
+
+ /* unregister the BLE advertisement. */
+ boolean stopAdvertising() {
+ if (mBluetoothLeAdvertiser != null) {
+ mBluetoothLeAdvertiser.stopAdvertising(mAdvertiseCallback);
+ return true;
+ }
+ return false;
+ }
+
+ /* Callback to handle status when advertising starts. */
+ private class FastPairAdvertiseCallback extends AdvertiseCallback {
+ @Override
+ public void onStartFailure(int errorCode) {
+ super.onStartFailure(errorCode);
+ if (DBG) Log.d(TAG, "Advertising failed");
+ }
+
+ @Override
+ public void onStartSuccess(AdvertiseSettings settingsInEffect) {
+ super.onStartSuccess(settingsInEffect);
+ if (DBG) Log.d(TAG, "Advertising successfully started");
+ }
+ }
+}
diff --git a/service/src/com/android/car/GarageModeService.java b/service/src/com/android/car/GarageModeService.java
index 02d31ad..0ccddf1 100644
--- a/service/src/com/android/car/GarageModeService.java
+++ b/service/src/com/android/car/GarageModeService.java
@@ -24,6 +24,7 @@
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;
@@ -35,7 +36,9 @@
import com.android.internal.annotations.VisibleForTesting;
import java.io.PrintWriter;
-import java.util.Calendar;
+import java.lang.RuntimeException;
+import java.util.Map;
+import java.util.HashMap;
import static android.car.settings.GarageModeSettingsObserver.GARAGE_MODE_ENABLED_URI;
import static android.car.settings.GarageModeSettingsObserver.GARAGE_MODE_MAINTENANCE_WINDOW_URI;
@@ -83,10 +86,6 @@
@GuardedBy("this")
private GarageModePolicy mPolicy;
@GuardedBy("this")
- private int mWakeUpHour = 0;
- @GuardedBy("this")
- private int mWakeUpMin = 0;
- @GuardedBy("this")
private boolean mGarageModeEnabled;
@@ -94,9 +93,13 @@
private final GarageModeSettingsObserver mContentObserver;
private DeviceIdleControllerWrapper mDeviceIdleController;
- private final GarageModeHandler mHandler = new GarageModeHandler();
+ private final GarageModeHandler mHandler;
private class GarageModeHandler extends Handler {
+ public GarageModeHandler(Looper looper) {
+ super(looper);
+ }
+
@Override
public void handleMessage(Message msg) {
switch (msg.what) {
@@ -112,14 +115,15 @@
}
public GarageModeService(Context context, CarPowerManagementService powerManagementService) {
- this(context, powerManagementService, null);
+ this(context, powerManagementService, null, Looper.myLooper());
}
@VisibleForTesting
protected GarageModeService(Context context, CarPowerManagementService powerManagementService,
- DeviceIdleControllerWrapper deviceIdleController) {
+ DeviceIdleControllerWrapper deviceIdleController, Looper looper) {
mContext = context;
mPowerManagementService = powerManagementService;
+ mHandler = new GarageModeHandler(looper);
if (deviceIdleController == null) {
mDeviceIdleController = new DefaultDeviceIdleController();
} else {
@@ -135,14 +139,20 @@
@Override
public void init() {
+ init(mContext.getResources().getStringArray(R.array.config_garageModeCadence),
+ PreferenceManager.getDefaultSharedPreferences(
+ mContext.createDeviceProtectedStorageContext()));
+ }
+
+ @VisibleForTesting
+ protected void init(String[] policyArray, SharedPreferences prefs) {
logd("init GarageMode");
- mSharedPreferences = PreferenceManager.getDefaultSharedPreferences(
- mContext.createDeviceProtectedStorageContext());
+ mSharedPreferences = prefs;
final int index = mSharedPreferences.getInt(KEY_GARAGE_MODE_INDEX, 0);
synchronized (this) {
mMaintenanceActive = mDeviceIdleController.startTracking(this);
mGarageModeIndex = index;
- readPolicyLocked();
+ readPolicyLocked(policyArray);
readFromSettingsLocked(CarSettings.Global.KEY_GARAGE_MODE_MAINTENANCE_WINDOW,
CarSettings.Global.KEY_GARAGE_MODE_ENABLED,
CarSettings.Global.KEY_GARAGE_MODE_WAKE_UP_TIME);
@@ -151,6 +161,10 @@
mPowerManagementService.registerPowerEventProcessingHandler(this);
}
+ public boolean isInGarageMode() {
+ return mInGarageMode;
+ }
+
@Override
public void release() {
logd("release GarageModeService");
@@ -162,7 +176,6 @@
public void dump(PrintWriter writer) {
writer.println("mGarageModeIndex: " + mGarageModeIndex);
writer.println("inGarageMode? " + mInGarageMode);
- writer.println("GarageModeTime: " + mWakeUpHour + ":" + mWakeUpMin);
writer.println("GarageModeEnabled " + mGarageModeEnabled);
writer.println("GarageModeTimeWindow " + mMaintenanceWindow + " ms");
}
@@ -204,7 +217,7 @@
if (!mGarageModeEnabled) {
return 0;
}
- return mPolicy.getNextWakeUpTime(mGarageModeIndex, mWakeUpHour, mWakeUpMin);
+ return mPolicy.getNextWakeUpTime(mGarageModeIndex);
}
}
@@ -228,10 +241,10 @@
}
}
- private void readPolicyLocked() {
+ @GuardedBy("this")
+ private void readPolicyLocked(String[] policyArray) {
logd("readPolicy");
- // TODO: define a xml schema for policy and read it from system dir. bug: 32096969
- mPolicy = new DefaultGarageModePolicy();
+ mPolicy = new GarageModePolicy(policyArray);
}
private void writeToPref(int index) {
@@ -264,24 +277,15 @@
}
}
- public abstract static class GarageModePolicy {
- abstract public int getNextWakeUpTime(int index, int hour, int min);
- /**
- * Returns number of seconds between now to 1am {@param numDays} days later.
- */
- public static int nextWakeUpSeconds(int numDays, int hour, int min) {
- // TODO: Should select a random time within a window. bug: 32096386
- // This is to avoid all cars update at the same time.
- Calendar next = Calendar.getInstance();
- next.add(Calendar.DATE, numDays);
- next.set(Calendar.HOUR_OF_DAY, hour);
- next.set(Calendar.MINUTE, min);
- next.set(Calendar.SECOND, 0);
+ static final class WakeupTime {
+ int mWakeupTime;
+ int mNumAttempts;
- Calendar now = Calendar.getInstance();
- return (next.get(Calendar.MILLISECOND) - now.get(Calendar.MILLISECOND)) / 1000;
+ WakeupTime(int wakeupTime, int numAttempts) {
+ mWakeupTime = wakeupTime;
+ mNumAttempts = numAttempts;
}
- }
+ };
/**
* Default garage mode policy.
@@ -289,25 +293,87 @@
* 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.
*/
- private static class DefaultGarageModePolicy extends GarageModePolicy {
- private static final int COL_INDEX = 0;
- private static final int COL_WAKEUP_TIME = 1;
+ @VisibleForTesting
+ static final class GarageModePolicy {
+ private static final Map<String, Integer> TIME_UNITS_LOOKUP;
+ static {
+ TIME_UNITS_LOOKUP = new HashMap<String, Integer>();
+ TIME_UNITS_LOOKUP.put("m", 60);
+ TIME_UNITS_LOOKUP.put("h", 3600);
+ TIME_UNITS_LOOKUP.put("d", 86400);
+ }
+ protected WakeupTime[] mWakeupTime;
- private static final int[][] WAKE_UP_TIME = new int[][] {
- {7 /*index <= 7*/, 1 /* wake up the next day */},
- {11 /* 7 < index <= 11 */, 7 /* wake up the next week */},
- {Integer.MAX_VALUE /* index > 11 */, 30 /* wake up the next month */}
- };
+ public GarageModePolicy(String[] policy) {
+ if (policy == null || policy.length == 0) {
+ throw new RuntimeException("Must include valid policy.");
+ }
- @Override
- public int getNextWakeUpTime(int index, int hour, int min) {
- for (int i = 0; i < WAKE_UP_TIME.length; i++) {
- if (index <= WAKE_UP_TIME[i][COL_INDEX]) {
- return nextWakeUpSeconds(WAKE_UP_TIME[i][COL_WAKEUP_TIME], hour, min);
+ WakeupTime[] parsedWakeupTime = new WakeupTime[policy.length];
+ for (int i = 0; i < policy.length; i++) {
+ String[] splitString = policy[i].split(",");
+ if (splitString.length != 2) {
+ throw new RuntimeException("Bad policy format: " + policy[i]);
+ }
+
+ int wakeupTimeMs = 0;
+ int numAttempts = 0;
+ String wakeupTime = splitString[0];
+ if (wakeupTime.isEmpty()) {
+ throw new RuntimeException("Missing wakeup time: " + policy[i]);
+ }
+ String wakeupTimeValue = wakeupTime.substring(0, wakeupTime.length() - 1);
+
+ if (wakeupTimeValue.isEmpty()) {
+ throw new RuntimeException("Missing wakeup time value: " + wakeupTime);
+ }
+ try {
+ int timeCount = Integer.parseInt(wakeupTimeValue);
+ if (timeCount <= 0) {
+ throw new RuntimeException("Wakeup time must be > 0: " + timeCount);
+ }
+
+ // Last character indicates minutes, hours, or days.
+ Integer multiplier = TIME_UNITS_LOOKUP.get(
+ wakeupTime.substring(wakeupTime.length() - 1));
+ if (multiplier == null) {
+ throw new RuntimeException("Bad wakeup time units: " + wakeupTime);
+ }
+
+ wakeupTimeMs = timeCount * multiplier;
+ } catch (NumberFormatException e) {
+ throw new RuntimeException("Bad wakeup time value: " + wakeupTimeValue);
+ }
+ try {
+ numAttempts = Integer.parseInt(splitString[1]);
+ if (numAttempts <= 0) {
+ throw new RuntimeException(
+ "Number of attempts must be > 0: " + numAttempts);
+ }
+ } catch (NumberFormatException e) {
+ throw new RuntimeException("Bad number of attempts: " + splitString[1]);
+ }
+
+ parsedWakeupTime[i] = new WakeupTime(wakeupTimeMs, numAttempts);
+ }
+ mWakeupTime = parsedWakeupTime;
+ }
+
+ public int getNextWakeUpTime(int index) {
+ if (mWakeupTime == null) {
+ Log.e(TAG, "Could not parse policy.");
+ return 0;
+ }
+
+ for (int i = 0; i < mWakeupTime.length; i++) {
+ if (index < mWakeupTime[i].mNumAttempts) {
+ return mWakeupTime[i].mWakeupTime;
+ } else {
+ index -= mWakeupTime[i].mNumAttempts;
}
}
- Log.w(TAG, "Integer.MAX number of wake ups... How long have we been sleeping? ");
+ Log.w(TAG, "No more garage mode wake ups scheduled; been sleeping too long.");
return 0;
}
}
@@ -357,6 +423,7 @@
}
}
+ @GuardedBy("this")
private void readFromSettingsLocked(String... keys) {
for (String key : keys) {
switch (key) {
@@ -364,13 +431,6 @@
mGarageModeEnabled =
Settings.Global.getInt(mContext.getContentResolver(), key, 1) == 1;
break;
- case CarSettings.Global.KEY_GARAGE_MODE_WAKE_UP_TIME:
- int time[] = CarApiUtil.decodeGarageTimeSetting(
- Settings.Global.getString(mContext.getContentResolver(),
- CarSettings.Global.KEY_GARAGE_MODE_WAKE_UP_TIME));
- mWakeUpHour = time[0];
- mWakeUpMin = time[1];
- break;
case CarSettings.Global.KEY_GARAGE_MODE_MAINTENANCE_WINDOW:
mMaintenanceWindow = Settings.Global.getInt(
mContext.getContentResolver(), key,
@@ -393,8 +453,8 @@
readFromSettingsLocked(CarSettings.Global.KEY_GARAGE_MODE_MAINTENANCE_WINDOW);
}
logd(String.format(
- "onSettingsChanged %s. enabled: %s, wakeUpTime: %d:%d, windowSize: %d",
- uri, mGarageModeEnabled, mWakeUpHour, mWakeUpMin, mMaintenanceWindow));
+ "onSettingsChanged %s. enabled: %s, windowSize: %d",
+ uri, mGarageModeEnabled, mMaintenanceWindow));
}
}
}
diff --git a/service/src/com/android/car/ICarImpl.java b/service/src/com/android/car/ICarImpl.java
index bd42454..ce5ea75 100644
--- a/service/src/com/android/car/ICarImpl.java
+++ b/service/src/com/android/car/ICarImpl.java
@@ -16,28 +16,35 @@
package com.android.car;
+import android.annotation.MainThread;
import android.app.UiModeManager;
import android.car.Car;
import android.car.ICar;
-import android.car.annotation.FutureFeature;
import android.car.cluster.renderer.IInstrumentClusterNavigation;
+import android.car.user.CarUserManagerHelper;
import android.content.Context;
import android.content.pm.PackageManager;
import android.hardware.automotive.vehicle.V2_0.IVehicle;
+import android.hardware.automotive.vehicle.V2_0.VehicleArea;
import android.os.Binder;
+import android.os.Build;
import android.os.IBinder;
import android.os.Process;
import android.os.Trace;
import android.util.Log;
import android.util.Slog;
import android.util.TimingsTraceLog;
+
import com.android.car.cluster.InstrumentClusterService;
import com.android.car.hal.VehicleHal;
import com.android.car.internal.FeatureConfiguration;
-import com.android.car.internal.FeatureUtil;
import com.android.car.pm.CarPackageManagerService;
+import com.android.car.systeminterface.SystemInterface;
+import com.android.car.user.CarUserService;
import com.android.internal.annotations.GuardedBy;
import com.android.internal.car.ICarServiceHelper;
+
+import java.io.FileDescriptor;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.Arrays;
@@ -52,29 +59,32 @@
private final Context mContext;
private final VehicleHal mHal;
+ private final SystemInterface mSystemInterface;
+
private final SystemActivityMonitoringService mSystemActivityMonitoringService;
private final CarPowerManagementService mCarPowerManagementService;
private final CarPackageManagerService mCarPackageManagerService;
private final CarInputService mCarInputService;
- private final CarSensorService mCarSensorService;
- private final CarInfoService mCarInfoService;
+ private final CarDrivingStateService mCarDrivingStateService;
+ private final CarUxRestrictionsManagerService mCarUXRestrictionsService;
private final CarAudioService mCarAudioService;
private final CarProjectionService mCarProjectionService;
- private final CarCabinService mCarCabinService;
- private final CarHvacService mCarHvacService;
- private final CarRadioService mCarRadioService;
+ private final CarPropertyService mCarPropertyService;
private final CarNightService mCarNightService;
private final AppFocusService mAppFocusService;
private final GarageModeService mGarageModeService;
private final InstrumentClusterService mInstrumentClusterService;
+ private final CarLocationService mCarLocationService;
private final SystemStateControllerService mSystemStateControllerService;
- private final CarVendorExtensionService mCarVendorExtensionService;
private final CarBluetoothService mCarBluetoothService;
private final PerUserCarServiceHelper mPerUserCarServiceHelper;
- private CarDiagnosticService mCarDiagnosticService;
- @FutureFeature
+ private final CarDiagnosticService mCarDiagnosticService;
+ private final CarStorageMonitoringService mCarStorageMonitoringService;
+ private final CarConfigurationService mCarConfigurationService;
+
+ private final CarUserManagerHelper mUserManagerHelper;
+ private CarUserService mCarUserService;
private VmsSubscriberService mVmsSubscriberService;
- @FutureFeature
private VmsPublisherService mVmsPublisherService;
private final CarServiceBase[] mAllServices;
@@ -82,7 +92,7 @@
private static final String TAG = "ICarImpl";
private static final String VHAL_TIMING_TAG = "VehicleHalTiming";
private static final TimingsTraceLog mBootTiming = new TimingsTraceLog(VHAL_TIMING_TAG,
- Trace.TRACE_TAG_HAL);
+ Trace.TRACE_TAG_HAL);
/** Test only service. Populate it only when necessary. */
@GuardedBy("this")
@@ -91,73 +101,83 @@
@GuardedBy("this")
private ICarServiceHelper mICarServiceHelper;
+ private final String mVehicleInterfaceName;
+
public ICarImpl(Context serviceContext, IVehicle vehicle, SystemInterface systemInterface,
- CanBusErrorNotifier errorNotifier) {
+ CanBusErrorNotifier errorNotifier, String vehicleInterfaceName) {
mContext = serviceContext;
+ mSystemInterface = systemInterface;
mHal = new VehicleHal(vehicle);
+ mVehicleInterfaceName = vehicleInterfaceName;
mSystemActivityMonitoringService = new SystemActivityMonitoringService(serviceContext);
- mCarPowerManagementService = new CarPowerManagementService(
- mHal.getPowerHal(), systemInterface);
- mCarSensorService = new CarSensorService(serviceContext, mHal.getSensorHal());
- mCarPackageManagerService = new CarPackageManagerService(serviceContext, mCarSensorService,
+ mCarPowerManagementService = new CarPowerManagementService(mContext, mHal.getPowerHal(),
+ systemInterface);
+ mCarPropertyService = new CarPropertyService(serviceContext, mHal.getPropertyHal());
+ mCarDrivingStateService = new CarDrivingStateService(serviceContext, mCarPropertyService);
+ mCarUXRestrictionsService = new CarUxRestrictionsManagerService(serviceContext,
+ mCarDrivingStateService, mCarPropertyService);
+ mCarPackageManagerService = new CarPackageManagerService(serviceContext,
+ mCarUXRestrictionsService,
mSystemActivityMonitoringService);
mCarInputService = new CarInputService(serviceContext, mHal.getInputHal());
mCarProjectionService = new CarProjectionService(serviceContext, mCarInputService);
mGarageModeService = new GarageModeService(mContext, mCarPowerManagementService);
- mCarInfoService = new CarInfoService(serviceContext, mHal.getInfoHal());
+ mCarLocationService = new CarLocationService(mContext, mCarPowerManagementService,
+ mCarPropertyService);
mAppFocusService = new AppFocusService(serviceContext, mSystemActivityMonitoringService);
- mCarAudioService = new CarAudioService(serviceContext, mHal.getAudioHal(),
- mCarInputService, errorNotifier);
- mCarCabinService = new CarCabinService(serviceContext, mHal.getCabinHal());
- mCarHvacService = new CarHvacService(serviceContext, mHal.getHvacHal());
- mCarRadioService = new CarRadioService(serviceContext, mHal.getRadioHal());
- mCarNightService = new CarNightService(serviceContext, mCarSensorService);
+ mCarAudioService = new CarAudioService(serviceContext);
+ mCarNightService = new CarNightService(serviceContext, mCarPropertyService);
mInstrumentClusterService = new InstrumentClusterService(serviceContext,
mAppFocusService, mCarInputService);
mSystemStateControllerService = new SystemStateControllerService(serviceContext,
mCarPowerManagementService, mCarAudioService, this);
- mCarVendorExtensionService = new CarVendorExtensionService(serviceContext,
- mHal.getVendorExtensionHal());
mPerUserCarServiceHelper = new PerUserCarServiceHelper(serviceContext);
- mCarBluetoothService = new CarBluetoothService(serviceContext, mCarCabinService,
- mCarSensorService, mPerUserCarServiceHelper);
- if (FeatureConfiguration.ENABLE_VEHICLE_MAP_SERVICE) {
- mVmsSubscriberService = new VmsSubscriberService(serviceContext, mHal.getVmsHal());
- mVmsPublisherService = new VmsPublisherService(serviceContext, mHal.getVmsHal());
- }
+ mCarBluetoothService = new CarBluetoothService(serviceContext, mCarPropertyService,
+ mPerUserCarServiceHelper, mCarUXRestrictionsService);
+ mVmsSubscriberService = new VmsSubscriberService(serviceContext, mHal.getVmsHal());
+ mVmsPublisherService = new VmsPublisherService(serviceContext, mHal.getVmsHal());
mCarDiagnosticService = new CarDiagnosticService(serviceContext, mHal.getDiagnosticHal());
+ mCarStorageMonitoringService = new CarStorageMonitoringService(serviceContext,
+ systemInterface);
+ mCarConfigurationService =
+ new CarConfigurationService(serviceContext, new JsonReaderImpl());
+ mUserManagerHelper = new CarUserManagerHelper(serviceContext);
// Be careful with order. Service depending on other service should be inited later.
- List<CarServiceBase> allServices = new ArrayList<>(Arrays.asList(
- mSystemActivityMonitoringService,
- mCarPowerManagementService,
- mCarSensorService,
- mCarPackageManagerService,
- mCarInputService,
- mGarageModeService,
- mCarInfoService,
- mAppFocusService,
- mCarAudioService,
- mCarCabinService,
- mCarHvacService,
- mCarRadioService,
- mCarNightService,
- mInstrumentClusterService,
- mCarProjectionService,
- mSystemStateControllerService,
- mCarVendorExtensionService,
- mCarBluetoothService,
- mCarDiagnosticService,
- mPerUserCarServiceHelper
- ));
- if (FeatureConfiguration.ENABLE_VEHICLE_MAP_SERVICE) {
- allServices.add(mVmsSubscriberService);
- allServices.add(mVmsPublisherService);
+ List<CarServiceBase> allServices = new ArrayList<>();
+ allServices.add(mSystemActivityMonitoringService);
+ allServices.add(mCarPowerManagementService);
+ allServices.add(mCarPropertyService);
+ allServices.add(mCarDrivingStateService);
+ allServices.add(mCarUXRestrictionsService);
+ allServices.add(mCarPackageManagerService);
+ allServices.add(mCarInputService);
+ allServices.add(mCarLocationService);
+ allServices.add(mGarageModeService);
+ allServices.add(mAppFocusService);
+ allServices.add(mCarAudioService);
+ allServices.add(mCarNightService);
+ allServices.add(mInstrumentClusterService);
+ allServices.add(mCarProjectionService);
+ allServices.add(mSystemStateControllerService);
+ allServices.add(mCarBluetoothService);
+ allServices.add(mCarDiagnosticService);
+ allServices.add(mPerUserCarServiceHelper);
+ allServices.add(mCarStorageMonitoringService);
+ allServices.add(mCarConfigurationService);
+ allServices.add(mVmsSubscriberService);
+ allServices.add(mVmsPublisherService);
+
+ if (mUserManagerHelper.isHeadlessSystemUser()) {
+ mCarUserService = new CarUserService(serviceContext, mUserManagerHelper);
+ allServices.add(mCarUserService);
}
- mAllServices = allServices.toArray(new CarServiceBase[0]);
+
+ mAllServices = allServices.toArray(new CarServiceBase[allServices.size()]);
}
- public void init() {
+ @MainThread
+ void init() {
traceBegin("VehicleHal.init");
mHal.init();
traceEnd();
@@ -168,7 +188,7 @@
traceEnd();
}
- public void release() {
+ void release() {
// release done in opposite order from init
for (int i = mAllServices.length - 1; i >= 0; i--) {
mAllServices[i].release();
@@ -176,7 +196,7 @@
mHal.release();
}
- public void vehicleHalReconnected(IVehicle vehicle) {
+ void vehicleHalReconnected(IVehicle vehicle) {
mHal.vehicleHalReconnected(vehicle);
for (CarServiceBase service : mAllServices) {
service.vehicleHalReconnected();
@@ -191,6 +211,7 @@
}
synchronized (this) {
mICarServiceHelper = ICarServiceHelper.Stub.asInterface(helper);
+ mSystemInterface.setCarServiceHelper(mICarServiceHelper);
}
}
@@ -199,26 +220,23 @@
switch (serviceName) {
case Car.AUDIO_SERVICE:
return mCarAudioService;
- case Car.SENSOR_SERVICE:
- return mCarSensorService;
- case Car.INFO_SERVICE:
- return mCarInfoService;
case Car.APP_FOCUS_SERVICE:
return mAppFocusService;
case Car.PACKAGE_SERVICE:
return mCarPackageManagerService;
- case Car.CABIN_SERVICE:
- assertCabinPermission(mContext);
- return mCarCabinService;
case Car.DIAGNOSTIC_SERVICE:
assertAnyDiagnosticPermission(mContext);
return mCarDiagnosticService;
+ case Car.POWER_SERVICE:
+ assertPowerPermission(mContext);
+ return mCarPowerManagementService;
+ case Car.CABIN_SERVICE:
case Car.HVAC_SERVICE:
- assertHvacPermission(mContext);
- return mCarHvacService;
- case Car.RADIO_SERVICE:
- assertRadioPermission(mContext);
- return mCarRadioService;
+ case Car.INFO_SERVICE:
+ case Car.PROPERTY_SERVICE:
+ case Car.SENSOR_SERVICE:
+ case Car.VENDOR_EXTENSION_SERVICE:
+ return mCarPropertyService;
case Car.CAR_NAVIGATION_SERVICE:
assertNavigationManagerPermission(mContext);
IInstrumentClusterNavigation navService =
@@ -230,15 +248,9 @@
case Car.PROJECTION_SERVICE:
assertProjectionPermission(mContext);
return mCarProjectionService;
- case Car.VENDOR_EXTENSION_SERVICE:
- assertVendorExtensionPermission(mContext);
- return mCarVendorExtensionService;
case Car.VMS_SUBSCRIBER_SERVICE:
- FeatureUtil.assertFeature(FeatureConfiguration.ENABLE_VEHICLE_MAP_SERVICE);
- if (FeatureConfiguration.ENABLE_VEHICLE_MAP_SERVICE) {
- assertVmsSubscriberPermission(mContext);
- return mVmsSubscriberService;
- }
+ assertVmsSubscriberPermission(mContext);
+ return mVmsSubscriberService;
case Car.TEST_SERVICE: {
assertPermission(mContext, Car.PERMISSION_CAR_TEST_SERVICE);
synchronized (this) {
@@ -250,6 +262,16 @@
}
case Car.BLUETOOTH_SERVICE:
return mCarBluetoothService;
+ case Car.STORAGE_MONITORING_SERVICE:
+ assertPermission(mContext, Car.PERMISSION_STORAGE_MONITORING);
+ return mCarStorageMonitoringService;
+ case Car.CAR_DRIVING_STATE_SERVICE:
+ assertDrivingStatePermission(mContext);
+ return mCarDrivingStateService;
+ case Car.CAR_UX_RESTRICTION_SERVICE:
+ return mCarUXRestrictionsService;
+ case Car.CAR_CONFIGURATION_SERVICE:
+ return mCarConfigurationService;
default:
Log.w(CarLog.TAG_SERVICE, "getCarService for unknown service:" + serviceName);
return null;
@@ -278,10 +300,6 @@
assertPermission(context, Car.PERMISSION_MOCK_VEHICLE_HAL);
}
- public static void assertCabinPermission(Context context) {
- assertPermission(context, Car.PERMISSION_CAR_CABIN);
- }
-
public static void assertNavigationManagerPermission(Context context) {
assertPermission(context, Car.PERMISSION_CAR_NAVIGATION_MANAGER);
}
@@ -290,34 +308,28 @@
assertPermission(context, Car.PERMISSION_CAR_INSTRUMENT_CLUSTER_CONTROL);
}
- public static void assertHvacPermission(Context context) {
- assertPermission(context, Car.PERMISSION_CAR_HVAC);
- }
-
- private static void assertRadioPermission(Context context) {
- assertPermission(context, Car.PERMISSION_CAR_RADIO);
+ public static void assertPowerPermission(Context context) {
+ assertPermission(context, Car.PERMISSION_CAR_POWER);
}
public static void assertProjectionPermission(Context context) {
assertPermission(context, Car.PERMISSION_CAR_PROJECTION);
}
- public static void assertVendorExtensionPermission(Context context) {
- assertPermission(context, Car.PERMISSION_VENDOR_EXTENSION);
- }
-
public static void assertAnyDiagnosticPermission(Context context) {
assertAnyPermission(context,
Car.PERMISSION_CAR_DIAGNOSTIC_READ_ALL,
Car.PERMISSION_CAR_DIAGNOSTIC_CLEAR);
}
- @FutureFeature
+ public static void assertDrivingStatePermission(Context context) {
+ assertPermission(context, Car.PERMISSION_CAR_DRIVING_STATE);
+ }
+
public static void assertVmsPublisherPermission(Context context) {
assertPermission(context, Car.PERMISSION_VMS_PUBLISHER);
}
- @FutureFeature
public static void assertVmsSubscriberPermission(Context context) {
assertPermission(context, Car.PERMISSION_VMS_SUBSCRIBER);
}
@@ -328,6 +340,18 @@
}
}
+ /**
+ * Checks to see if the caller has a permission.
+ * @param context
+ * @param permission
+ *
+ * @return boolean TRUE if caller has the permission.
+ */
+ public static boolean hasPermission(Context context, String permission) {
+ return context.checkCallingOrSelfPermission(permission)
+ == PackageManager.PERMISSION_GRANTED;
+ }
+
public static void assertAnyPermission(Context context, String... permissions) {
for (String permission : permissions) {
if (context.checkCallingOrSelfPermission(permission) ==
@@ -338,29 +362,62 @@
throw new SecurityException("requires any of " + Arrays.toString(permissions));
}
- void dump(PrintWriter writer) {
- writer.println("*FutureConfig, DEFAULT:" + FeatureConfiguration.DEFAULT);
- //TODO dump all feature flags by reflection
- writer.println("*Dump all services*");
- for (CarServiceBase service : mAllServices) {
+ @Override
+ protected void dump(FileDescriptor fd, PrintWriter writer, String[] args) {
+ if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DUMP)
+ != PackageManager.PERMISSION_GRANTED) {
+ writer.println("Permission Denial: can't dump CarService from from pid="
+ + Binder.getCallingPid() + ", uid=" + Binder.getCallingUid()
+ + " without permission " + android.Manifest.permission.DUMP);
+ return;
+ }
+ if (args == null || args.length == 0) {
+ writer.println("*dump car service*");
+
+ writer.println("*FutureConfig, DEFAULT:" + FeatureConfiguration.DEFAULT);
+ writer.println("*Dump all services*");
+ for (CarServiceBase service : mAllServices) {
+ dumpService(service, writer);
+ }
+ if (mCarTestService != null) {
+ dumpService(mCarTestService, writer);
+ }
+ writer.println("*Dump Vehicle HAL*");
+ writer.println("Vehicle HAL Interface: " + mVehicleInterfaceName);
+ try {
+ // TODO dump all feature flags by creating a dumpable interface
+ mHal.dump(writer);
+ } catch (Exception e) {
+ writer.println("Failed dumping: " + mHal.getClass().getName());
+ e.printStackTrace(writer);
+ }
+ } else if (Build.IS_USERDEBUG || Build.IS_ENG) {
+ execShellCmd(args, writer);
+ } else {
+ writer.println("Commands not supported in " + Build.TYPE);
+ }
+ }
+
+ private void dumpService(CarServiceBase service, PrintWriter writer) {
+ try {
service.dump(writer);
+ } catch (Exception e) {
+ writer.println("Failed dumping: " + service.getClass().getName());
+ e.printStackTrace(writer);
}
- if (mCarTestService != null) {
- mCarTestService.dump(writer);
- }
- writer.println("*Dump Vehicle HAL*");
- mHal.dump(writer);
}
void execShellCmd(String[] args, PrintWriter writer) {
new CarShellCommand().exec(args, writer);
}
+ @MainThread
private static void traceBegin(String name) {
Slog.i(TAG, name);
mBootTiming.traceBegin(name);
}
+ @MainThread
private static void traceEnd() {
mBootTiming.traceEnd();
}
@@ -368,13 +425,19 @@
private class CarShellCommand {
private static final String COMMAND_HELP = "-h";
private static final String COMMAND_DAY_NIGHT_MODE = "day-night-mode";
- private static final String COMMAND_INJECT_EVENT = "inject-event";
+ private static final String COMMAND_INJECT_VHAL_EVENT = "inject-vhal-event";
+ private static final String COMMAND_ENABLE_UXR = "enable-uxr";
+ private static final String COMMAND_GARAGE_MODE = "garage-mode";
+ private static final String COMMAND_GET_DO_ACTIVITIES = "get-do-activities";
private static final String PARAM_DAY_MODE = "day";
private static final String PARAM_NIGHT_MODE = "night";
private static final String PARAM_SENSOR_MODE = "sensor";
- private static final String PARAM_ZONED_BOOLEAN = "zoned-boolean";
- private static final String PARAM_GLOBAL_INT = "global-integer";
+ private static final String PARAM_VEHICLE_PROPERTY_AREA_GLOBAL = "0";
+ private static final String PARAM_ON_MODE = "on";
+ private static final String PARAM_OFF_MODE = "off";
+ private static final String PARAM_QUERY_MODE = "query";
+
private void dumpHelp(PrintWriter pw) {
pw.println("Car service commands:");
@@ -382,8 +445,14 @@
pw.println("\t Print this help text.");
pw.println("\tday-night-mode [day|night|sensor]");
pw.println("\t Force into day/night mode or restore to auto.");
- pw.println("\tinject-event zoned-boolean propertyType zone [true|false]");
- pw.println("\t Inject a Boolean HAL Event. ");
+ pw.println("\tinject-vhal-event property [zone] data(can be comma separated list)");
+ pw.println("\t Inject a vehicle property for testing");
+ pw.println("\tdisable-uxr true|false");
+ pw.println("\t Disable UX restrictions and App blocking.");
+ pw.println("\tgarage-mode [on|off|query]");
+ pw.println("\t Force into garage mode or check status.");
+ pw.println("\tget-do-activities pkgname");
+ pw.println("\t Get Distraction Optimized activities in given package");
}
public void exec(String[] args, PrintWriter writer) {
@@ -392,37 +461,62 @@
case COMMAND_HELP:
dumpHelp(writer);
break;
- case COMMAND_DAY_NIGHT_MODE:
+ case COMMAND_DAY_NIGHT_MODE: {
String value = args.length < 1 ? "" : args[1];
forceDayNightMode(value, writer);
break;
- case COMMAND_INJECT_EVENT:
- String eventType;
- if (args.length > 1) {
- eventType = args[1].toLowerCase();
- switch (eventType) {
- case PARAM_ZONED_BOOLEAN:
- if (args.length < 5) {
- writer.println("Incorrect number of arguments.");
- dumpHelp(writer);
- break;
- }
- inject_zoned_boolean_event(args[2], args[3], args[4], writer);
- break;
-
- case PARAM_GLOBAL_INT:
- if (args.length < 4) {
- writer.println("Incorrect number of Arguments");
- dumpHelp(writer);
- break;
- }
- inject_global_integer_event(args[2], args[3], writer);
- break;
-
- default:
- writer.println("Unsupported event type");
- dumpHelp(writer);
- break;
+ }
+ case COMMAND_GARAGE_MODE: {
+ String value = args.length < 1 ? "" : args[1];
+ forceGarageMode(value, writer);
+ break;
+ }
+ case COMMAND_INJECT_VHAL_EVENT:
+ String zone = PARAM_VEHICLE_PROPERTY_AREA_GLOBAL;
+ String data;
+ if (args.length < 3) {
+ writer.println("Incorrect number of arguments.");
+ dumpHelp(writer);
+ break;
+ } else if (args.length > 3) {
+ // Zoned
+ zone = args[2];
+ data = args[3];
+ } else {
+ // Global
+ data = args[2];
+ }
+ injectVhalEvent(args[1], zone, data, writer);
+ break;
+ case COMMAND_ENABLE_UXR:
+ if (args.length < 2) {
+ writer.println("Incorrect number of arguments");
+ dumpHelp(writer);
+ break;
+ }
+ boolean enableBlocking = Boolean.valueOf(args[1]);
+ if (mCarPackageManagerService != null) {
+ mCarPackageManagerService.setEnableActivityBlocking(enableBlocking);
+ }
+ break;
+ case COMMAND_GET_DO_ACTIVITIES:
+ if (args.length < 2) {
+ writer.println("Incorrect number of arguments");
+ dumpHelp(writer);
+ break;
+ }
+ String pkgName = args[1].toLowerCase();
+ if (mCarPackageManagerService != null) {
+ String[] doActivities =
+ mCarPackageManagerService.getDistractionOptimizedActivities(
+ pkgName);
+ if (doActivities != null) {
+ writer.println("DO Activities for " + pkgName);
+ for (String a : doActivities) {
+ writer.println(a);
+ }
+ } else {
+ writer.println("No DO Activities for " + pkgName);
}
}
break;
@@ -465,55 +559,55 @@
writer.println("DayNightMode changed to: " + currentMode);
}
- /**
- * Inject a fake boolean HAL event to help testing.
- *
- * @param property - Vehicle Property
- * @param value - boolean value for the property
- * @param writer - Printwriter
- */
- private void inject_zoned_boolean_event(String property, String zone, String value,
- PrintWriter writer) {
- Log.d(CarLog.TAG_SERVICE, "Injecting Boolean event");
- boolean event;
- int propId;
- int zoneId;
- if (value.equalsIgnoreCase("true")) {
- event = true;
- } else {
- event = false;
+ private void forceGarageMode(String arg, PrintWriter writer) {
+ switch (arg) {
+ case PARAM_ON_MODE:
+ mGarageModeService.onPrepareShutdown(false);
+ break;
+ case PARAM_OFF_MODE:
+ mGarageModeService.onSleepEntry();
+ break;
+ case PARAM_QUERY_MODE:
+ // Nothing to do. Always query at the end anyway.
+ break;
+ default:
+ writer.println("Unknown value. Valid argument: " + PARAM_ON_MODE + "|"
+ + PARAM_OFF_MODE + "|" + PARAM_QUERY_MODE);
+ return;
}
- try {
- propId = Integer.decode(property);
- zoneId = Integer.decode(zone);
- } catch (NumberFormatException e) {
- writer.println("Invalid property Id or Zone Id. Prefix hex values with 0x");
- return;
- }
- mHal.injectBooleanEvent(propId, zoneId, event);
+ writer.println("Garage mode: " + mGarageModeService.isInGarageMode());
}
/**
- * Inject a fake Integer HAL event to help testing.
+ * Inject a fake VHAL event
*
- * @param property - Vehicle Property
- * @param value - Integer value to inject
- * @param writer - PrintWriter
+ * @param property the Vehicle property Id as defined in the HAL
+ * @param zone Zone that this event services
+ * @param value Data value of the event
+ * @param writer PrintWriter
*/
- private void inject_global_integer_event(String property, String value,
+ private void injectVhalEvent(String property, String zone, String value,
PrintWriter writer) {
- Log.d(CarLog.TAG_SERVICE, "Injecting integer event");
- int propId;
- int eventValue;
- try {
- propId = Integer.decode(property);
- eventValue = Integer.decode(value);
- } catch (NumberFormatException e) {
- writer.println("Invalid property Id or event value. Prefix hex values with 0x");
- return;
+ if (zone != null && (zone.equalsIgnoreCase(PARAM_VEHICLE_PROPERTY_AREA_GLOBAL))) {
+ if (!isPropertyAreaTypeGlobal(property)) {
+ writer.println("Property area type inconsistent with given zone");
+ return;
+ }
}
- mHal.injectIntegerEvent(propId, eventValue);
+ try {
+ mHal.injectVhalEvent(property, zone, value);
+ } catch (NumberFormatException e) {
+ writer.println("Invalid property Id zone Id or value" + e);
+ dumpHelp(writer);
+ }
}
+ // Check if the given property is global
+ private boolean isPropertyAreaTypeGlobal(String property) {
+ if (property == null) {
+ return false;
+ }
+ return (Integer.decode(property) & VehicleArea.MASK) == VehicleArea.GLOBAL;
+ }
}
}
diff --git a/service/src/com/android/car/JsonReaderImpl.java b/service/src/com/android/car/JsonReaderImpl.java
new file mode 100644
index 0000000..2ab7c32
--- /dev/null
+++ b/service/src/com/android/car/JsonReaderImpl.java
@@ -0,0 +1,65 @@
+/*
+ * 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;
+
+import android.annotation.Nullable;
+import android.annotation.RawRes;
+import android.content.Context;
+
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.io.Reader;
+
+/**
+ * An implementation of {@link com.android.car.CarConfigurationService.JsonReader} that will
+ * parse a JSON file on the system that is mapped to {@code R.raw.car_config}.
+ */
+public class JsonReaderImpl implements CarConfigurationService.JsonReader {
+ private static final int BUF_SIZE = 0x1000; // 2K chars (4K bytes)
+ private static final String JSON_FILE_ENCODING = "UTF-8";
+
+ /**
+ * Takes a resource file that is considered to be a JSON file and parses it into a String that
+ * is returned.
+ *
+ * @param resId The resource id pointing to the json file.
+ * @return A {@code String} representing the file contents, or {@code null} if
+ */
+ @Override
+ @Nullable
+ public String jsonFileToString(Context context, @RawRes int resId) {
+ InputStream is = context.getResources().openRawResource(resId);
+
+ // Note: this "try" will close the Reader, thus closing the associated InputStreamReader
+ // and InputStream.
+ try (Reader reader = new BufferedReader(new InputStreamReader(is, JSON_FILE_ENCODING))) {
+ char[] buffer = new char[BUF_SIZE];
+ StringBuilder stringBuilder = new StringBuilder();
+
+ int bufferedContent;
+ while ((bufferedContent = reader.read(buffer)) != -1) {
+ stringBuilder.append(buffer, /* offset= */ 0, bufferedContent);
+ }
+
+ return stringBuilder.toString();
+ } catch (IOException e) {
+ return null;
+ }
+ }
+}
diff --git a/service/src/com/android/car/OnShutdownReboot.java b/service/src/com/android/car/OnShutdownReboot.java
new file mode 100644
index 0000000..b68ff5b
--- /dev/null
+++ b/service/src/com/android/car/OnShutdownReboot.java
@@ -0,0 +1,69 @@
+/*
+ * 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.android.car;
+
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import java.util.concurrent.CopyOnWriteArrayList;
+import java.util.function.BiConsumer;
+
+/**
+ * This class allows one to register actions they want executed when the vehicle is being shutdown
+ * or rebooted.
+ *
+ * To use this class instantiate it as part of your long-lived service, and then add actions to it.
+ * Actions receive the Context and Intent that go with the shutdown/reboot action, which allows the
+ * action to differentiate the two cases, should it need to do so.
+ *
+ * The actions will run on the UI thread.
+ */
+class OnShutdownReboot {
+ private final Object mLock = new Object();
+
+ private final Context mContext;
+
+ private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ for (BiConsumer<Context, Intent> action : mActions) {
+ action.accept(context, intent);
+ }
+ }
+ };
+
+ private final CopyOnWriteArrayList<BiConsumer<Context, Intent>> mActions =
+ new CopyOnWriteArrayList<>();
+
+ OnShutdownReboot(Context context) {
+ mContext = context;
+ IntentFilter shutdownFilter = new IntentFilter(Intent.ACTION_SHUTDOWN);
+ IntentFilter rebootFilter = new IntentFilter(Intent.ACTION_REBOOT);
+ mContext.registerReceiver(mReceiver, shutdownFilter);
+ mContext.registerReceiver(mReceiver, rebootFilter);
+ }
+
+ OnShutdownReboot addAction(BiConsumer<Context, Intent> action) {
+ mActions.add(action);
+ return this;
+ }
+
+ void clearActions() {
+ mActions.clear();
+ }
+}
diff --git a/service/src/com/android/car/SlidingWindow.java b/service/src/com/android/car/SlidingWindow.java
new file mode 100644
index 0000000..634f2eb
--- /dev/null
+++ b/service/src/com/android/car/SlidingWindow.java
@@ -0,0 +1,64 @@
+/*
+ * 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.android.car;
+
+import java.util.ArrayDeque;
+import java.util.Iterator;
+import java.util.function.Predicate;
+import java.util.stream.Stream;
+
+/**
+ * This class keeps track of a limited fixed number of sample data points, correctly removing
+ * older samples as new ones are added, and it allows inspecting the samples, as well as
+ * easily answering N out of M questions.
+ */
+class SlidingWindow<T> implements Iterable<T> {
+ private final ArrayDeque<T> mElements;
+ private final int mMaxSize;
+
+ public SlidingWindow(int size) {
+ mMaxSize = size;
+ mElements = new ArrayDeque<>(mMaxSize);
+ }
+
+ public void add(T sample) {
+ if (mElements.size() == mMaxSize) {
+ mElements.removeFirst();
+ }
+ mElements.addLast(sample);
+ }
+
+ public void addAll(Iterable<T> elements) {
+ elements.forEach(this::add);
+ }
+
+ @Override
+ public Iterator<T> iterator() {
+ return mElements.iterator();
+ }
+
+ public Stream<T> stream() {
+ return mElements.stream();
+ }
+
+ public int size() {
+ return mElements.size();
+ }
+
+ public int count(Predicate<T> predicate) {
+ return (int)stream().filter(predicate).count();
+ }
+}
diff --git a/service/src/com/android/car/SparseArrayStream.java b/service/src/com/android/car/SparseArrayStream.java
new file mode 100644
index 0000000..c3e8fcd
--- /dev/null
+++ b/service/src/com/android/car/SparseArrayStream.java
@@ -0,0 +1,39 @@
+/*
+ * 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.android.car;
+
+import android.util.Pair;
+import android.util.SparseArray;
+import java.util.stream.IntStream;
+import java.util.stream.Stream;
+
+/**
+ * Helper class that provides Stream abstractions for android.util.SparseArray
+ */
+public class SparseArrayStream {
+ public static <E> IntStream keyStream(SparseArray<E> array) {
+ return IntStream.range(0, array.size()).map(array::keyAt);
+ }
+
+ public static <E> Stream<E> valueStream(SparseArray<E> array) {
+ return IntStream.range(0, array.size()).mapToObj(array::valueAt);
+ }
+
+ public static <E> Stream<Pair<Integer, E>> pairStream(SparseArray<E> array) {
+ return IntStream.range(0, array.size()).mapToObj(
+ i -> new Pair<>(array.keyAt(i), array.valueAt(i)));
+ }
+}
diff --git a/service/src/com/android/car/SystemActivityMonitoringService.java b/service/src/com/android/car/SystemActivityMonitoringService.java
index 2ff4e0e..2df9b00 100644
--- a/service/src/com/android/car/SystemActivityMonitoringService.java
+++ b/service/src/com/android/car/SystemActivityMonitoringService.java
@@ -85,10 +85,6 @@
void onActivityLaunch(TopTaskInfoContainer topTask);
}
- private static final boolean DBG = false;
-
- private static final int NUM_MAX_TASK_TO_FETCH = 10;
-
private final Context mContext;
private final IActivityManager mAm;
private final ProcessObserver mProcessObserver;
@@ -192,6 +188,57 @@
return false;
}
+ /**
+ * Attempts to restart a task.
+ *
+ * <p>Restarts a task by sending an empty intent with flag
+ * {@link Intent#FLAG_ACTIVITY_CLEAR_TASK} to its root activity. If the task does not exist,
+ * do nothing.
+ *
+ * @param taskId id of task to be restarted.
+ */
+ public void restartTask(int taskId) {
+ String rootActivityName = null;
+ int userId = 0;
+ try {
+ findRootActivityName:
+ for (StackInfo info : mAm.getAllStackInfos()) {
+ for (int i = 0; i < info.taskIds.length; i++) {
+ if (info.taskIds[i] == taskId) {
+ rootActivityName = info.taskNames[i];
+ userId = info.userId;
+ if (Log.isLoggable(CarLog.TAG_AM, Log.DEBUG)) {
+ Log.d(CarLog.TAG_AM, "Root activity is " + rootActivityName);
+ Log.d(CarLog.TAG_AM, "User id is " + userId);
+ }
+ // Break out of nested loop.
+ break findRootActivityName;
+ }
+ }
+ }
+ } catch (RemoteException e) {
+ Log.e(CarLog.TAG_AM, "Could not get stack info", e);
+ return;
+ }
+
+ if (rootActivityName == null) {
+ Log.e(CarLog.TAG_AM, "Could not find root activity with task id " + taskId);
+ return;
+ }
+
+ Intent rootActivityIntent = new Intent();
+ rootActivityIntent.setComponent(ComponentName.unflattenFromString(rootActivityName));
+ // Clear the task the root activity is running in and start it in a new task.
+ // Effectively restart root activity.
+ rootActivityIntent.addFlags(
+ Intent.FLAG_ACTIVITY_CLEAR_TASK | Intent.FLAG_ACTIVITY_NEW_TASK);
+
+ if (Log.isLoggable(CarLog.TAG_AM, Log.INFO)) {
+ Log.i(CarLog.TAG_AM, "restarting root activity with user id " + userId);
+ }
+ mContext.startActivityAsUser(rootActivityIntent, new UserHandle(userId));
+ }
+
public void registerActivityLaunchListener(ActivityLaunchListener listener) {
synchronized (this) {
mActivityLaunchListener = listener;
@@ -208,7 +255,12 @@
}
int focusedStackId = -1;
try {
- focusedStackId = mAm.getFocusedStackId();
+ // TODO(b/66955160): Someone on the Auto-team should probably re-work the code in the
+ // synchronized block below based on this new API.
+ final StackInfo focusedStackInfo = mAm.getFocusedStackInfo();
+ if (focusedStackInfo != null) {
+ focusedStackId = focusedStackInfo.stackId;
+ }
} catch (RemoteException e) {
Log.e(CarLog.TAG_AM, "cannot getFocusedStackId", e);
return;
@@ -233,7 +285,7 @@
(focusedStackId == stackId && focusedStackId != mFocusedStackId)) {
mTopTasks.put(stackId, newTopTaskInfo);
mTasksToDispatch.add(newTopTaskInfo);
- if (DBG) {
+ if (Log.isLoggable(CarLog.TAG_AM, Log.INFO)) {
Log.i(CarLog.TAG_AM, "New top task: " + newTopTaskInfo);
}
}
@@ -242,7 +294,7 @@
}
if (listener != null) {
for (TopTaskInfoContainer topTask : mTasksToDispatch) {
- if (DBG) {
+ if (Log.isLoggable(CarLog.TAG_AM, Log.INFO)) {
Log.i(CarLog.TAG_AM, "activity launched:" + topTask.toString());
}
listener.onActivityLaunch(topTask);
@@ -251,16 +303,9 @@
}
public StackInfo getFocusedStackForTopActivity(ComponentName activity) {
- int focusedStackId = -1;
- try {
- focusedStackId = mAm.getFocusedStackId();
- } catch (RemoteException e) {
- Log.e(CarLog.TAG_AM, "cannot getFocusedStackId", e);
- return null;
- }
StackInfo focusedStack;
try {
- focusedStack = mAm.getStackInfo(focusedStackId);
+ focusedStack = mAm.getFocusedStackInfo();
} catch (RemoteException e) {
Log.e(CarLog.TAG_AM, "cannot getFocusedStackId", e);
return null;
@@ -308,27 +353,14 @@
}
}
+ /**
+ * block the current task with the provided new activity.
+ */
private void handleBlockActivity(TopTaskInfoContainer currentTask, Intent newActivityIntent) {
- Log.i(CarLog.TAG_AM, String.format("stopping activity %s with taskid:%d",
- currentTask.topActivity, currentTask.taskId));
- // Put launcher in the activity stack, so that we have something safe to show after the
- // block activity finishes.
- Intent launcherIntent = new Intent();
- launcherIntent.setComponent(ComponentName.unflattenFromString(
- mContext.getString(R.string.defaultHomeActivity)));
- mContext.startActivity(launcherIntent);
-
- newActivityIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
-
mContext.startActivityAsUser(newActivityIntent,
new UserHandle(currentTask.stackInfo.userId));
- // now make stack with new activity focused.
+ // Now make stack with new activity focused.
findTaskAndGrantFocus(newActivityIntent.getComponent());
- try {
- mAm.removeTask(currentTask.taskId);
- } catch (RemoteException e) {
- Log.w(CarLog.TAG_AM, "cannot remove task:" + currentTask.taskId, e);
- }
}
private void findTaskAndGrantFocus(ComponentName activity) {
@@ -360,7 +392,7 @@
private class ProcessObserver extends IProcessObserver.Stub {
@Override
public void onForegroundActivitiesChanged(int pid, int uid, boolean foregroundActivities) {
- if (DBG) {
+ if (Log.isLoggable(CarLog.TAG_AM, Log.INFO)) {
Log.i(CarLog.TAG_AM,
String.format("onForegroundActivitiesChanged uid %d pid %d fg %b",
uid, pid, foregroundActivities));
@@ -377,7 +409,7 @@
private class TaskListener extends TaskStackListener {
@Override
public void onTaskStackChanged() {
- if (DBG) {
+ if (Log.isLoggable(CarLog.TAG_AM, Log.INFO)) {
Log.i(CarLog.TAG_AM, "onTaskStackChanged");
}
mHandler.requestUpdatingTask();
diff --git a/service/src/com/android/car/SystemInterface.java b/service/src/com/android/car/SystemInterface.java
deleted file mode 100644
index 6311d80..0000000
--- a/service/src/com/android/car/SystemInterface.java
+++ /dev/null
@@ -1,191 +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.content.Context;
-import android.hardware.display.DisplayManager;
-import android.os.PowerManager;
-import android.os.PowerManager.WakeLock;
-import android.os.SystemClock;
-import android.util.Log;
-import android.view.Display;
-
-/**
- * Interface to abstract all system interaction.
- */
-public abstract class SystemInterface {
- public abstract void setDisplayState(boolean on);
- public abstract void releaseAllWakeLocks();
- public abstract void shutdown();
- public abstract void enterDeepSleep(int wakeupTimeSec);
- public abstract void switchToPartialWakeLock();
- public abstract void switchToFullWakeLock();
- public abstract void startDisplayStateMonitoring(CarPowerManagementService service);
- public abstract void stopDisplayStateMonitoring();
- public abstract boolean isSystemSupportingDeepSleep();
- public abstract boolean isWakeupCausedByTimer();
-
-
- public static SystemInterface getDefault(Context context) {
- return new SystemInterfaceImpl(context);
- }
-
- private static class SystemInterfaceImpl extends SystemInterface {
- private final PowerManager mPowerManager;
- private final DisplayManager mDisplayManager;
- private final WakeLock mFullWakeLock;
- private final WakeLock mPartialWakeLock;
- private final DisplayStateListener mDisplayListener;
- private CarPowerManagementService mService;
- private boolean mDisplayStateSet;
-
- private SystemInterfaceImpl(Context context) {
- mPowerManager = (PowerManager) context.getSystemService(Context.POWER_SERVICE);
- mDisplayManager = (DisplayManager) context.getSystemService(Context.DISPLAY_SERVICE);
- mFullWakeLock = mPowerManager.newWakeLock(PowerManager.FULL_WAKE_LOCK,
- CarLog.TAG_POWER);
- mPartialWakeLock = mPowerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK,
- CarLog.TAG_POWER);
- mDisplayListener = new DisplayStateListener();
- }
-
- @Override
- public void startDisplayStateMonitoring(CarPowerManagementService service) {
- synchronized (this) {
- mService = service;
- mDisplayStateSet = isMainDisplayOn();
- }
- mDisplayManager.registerDisplayListener(mDisplayListener, service.getHandler());
- }
-
- @Override
- public void stopDisplayStateMonitoring() {
- mDisplayManager.unregisterDisplayListener(mDisplayListener);
- }
-
- @Override
- public void setDisplayState(boolean on) {
- synchronized (this) {
- mDisplayStateSet = on;
- }
- if (on) {
- switchToFullWakeLock();
- Log.i(CarLog.TAG_POWER, "on display");
- mPowerManager.wakeUp(SystemClock.uptimeMillis());
- } else {
- switchToPartialWakeLock();
- Log.i(CarLog.TAG_POWER, "off display");
- mPowerManager.goToSleep(SystemClock.uptimeMillis());
- }
- }
-
- private boolean isMainDisplayOn() {
- Display disp = mDisplayManager.getDisplay(Display.DEFAULT_DISPLAY);
- return disp.getState() == Display.STATE_ON;
- }
-
- @Override
- public void shutdown() {
- mPowerManager.shutdown(false /* no confirm*/, null, true /* true */);
- }
-
- @Override
- public void enterDeepSleep(int wakeupTimeSec) {
- //TODO set wake up time, bug: 32061842
- mPowerManager.goToSleep(SystemClock.uptimeMillis(),
- PowerManager.GO_TO_SLEEP_REASON_DEVICE_ADMIN,
- PowerManager.GO_TO_SLEEP_FLAG_NO_DOZE);
- }
-
- @Override
- public boolean isSystemSupportingDeepSleep() {
- //TODO should return by checking some kernel suspend control sysfs, bug: 32061842
- return false;
- }
-
- @Override
- public void switchToPartialWakeLock() {
- if (!mPartialWakeLock.isHeld()) {
- mPartialWakeLock.acquire();
- }
- if (mFullWakeLock.isHeld()) {
- mFullWakeLock.release();
- }
- }
-
- @Override
- public void switchToFullWakeLock() {
- if (!mFullWakeLock.isHeld()) {
- mFullWakeLock.acquire();
- }
- if (mPartialWakeLock.isHeld()) {
- mPartialWakeLock.release();
- }
- }
-
- @Override
- public void releaseAllWakeLocks() {
- if (mPartialWakeLock.isHeld()) {
- mPartialWakeLock.release();
- }
- if (mFullWakeLock.isHeld()) {
- mFullWakeLock.release();
- }
- }
-
- @Override
- public boolean isWakeupCausedByTimer() {
- //TODO bug: 32061842, check wake up reason and do necessary operation information should
- // come from kernel. it can be either power on or wake up for maintenance
- // power on will involve GPIO trigger from power controller
- // its own wakeup will involve timer expiration.
- return false;
- }
-
- private void handleMainDisplayChanged() {
- boolean isOn = isMainDisplayOn();
- CarPowerManagementService service;
- synchronized (this) {
- if (mDisplayStateSet == isOn) { // same as what is set
- return;
- }
- service = mService;
- }
- service.handleMainDisplayChanged(isOn);
- }
-
- private class DisplayStateListener implements DisplayManager.DisplayListener {
-
- @Override
- public void onDisplayAdded(int displayId) {
- //ignore
- }
-
- @Override
- public void onDisplayChanged(int displayId) {
- if (displayId == Display.DEFAULT_DISPLAY) {
- handleMainDisplayChanged();
- }
- }
-
- @Override
- public void onDisplayRemoved(int displayId) {
- //ignore
- }
- }
- }
-}
diff --git a/service/src/com/android/car/SystemStateControllerService.java b/service/src/com/android/car/SystemStateControllerService.java
index 63821c5..53d74a3 100644
--- a/service/src/com/android/car/SystemStateControllerService.java
+++ b/service/src/com/android/car/SystemStateControllerService.java
@@ -17,7 +17,6 @@
import android.content.Context;
import android.content.res.Resources;
-import android.util.Log;
import com.android.car.CarPowerManagementService.PowerEventProcessingHandler;
import com.android.car.CarPowerManagementService.PowerServiceEventListener;
@@ -50,14 +49,7 @@
@Override
public void onPowerOn(boolean displayOn) {
- if (displayOn) {
- Log.i(CarLog.TAG_SYS, "Media unmute");
- mCarAudioService.unMuteMedia();
- } else {
- Log.i(CarLog.TAG_SYS, "Media mute");
- mCarAudioService.muteMediaWithLock(mLockWhenMuting);
- //TODO store last context and resume or silence radio on display on. bug: 32096079
- }
+ // TODO may consider mute / unmute the system based on displayOn
}
@Override
diff --git a/service/src/com/android/car/UptimeTracker.java b/service/src/com/android/car/UptimeTracker.java
new file mode 100644
index 0000000..1709965
--- /dev/null
+++ b/service/src/com/android/car/UptimeTracker.java
@@ -0,0 +1,190 @@
+/*
+ * 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.android.car;
+
+import android.util.JsonReader;
+import android.util.JsonWriter;
+import android.util.Log;
+
+import com.android.car.systeminterface.SystemInterface;
+
+import com.android.car.systeminterface.TimeInterface;
+import com.android.internal.annotations.VisibleForTesting;
+
+import java.io.File;
+import java.io.FileReader;
+import java.io.FileWriter;
+import java.io.IOException;
+import java.util.Objects;
+import java.util.Optional;
+
+/**
+ * A class that can keep track of how long its instances are alive for.
+ *
+ * It can be used as a helper object to track the lifetime of system components, e.g.
+ *
+ * class InterestingService {
+ * private UptimeTracker mTracker;
+ *
+ * public void onCreate() {
+ * mTracker = new UptimeTracker(
+ * "/storage/emulated/0/Android/data/interestingservice.uptime", 1 hour);
+ * mTracker.onCreate();
+ * }
+ *
+ * public void onDestroy() {
+ * mTracker.onDestroy();
+ * }
+ * }
+ *
+ * Now it's possible to know how long InterestingService has been alive in the system by querying
+ * mTracker.getTotalUptime(). Because this data is stored to disk, the uptime is maintained across
+ * process and system reboot boundaries. It is possible to configure periodic snapshot points to
+ * ensure that crashes do not cause more than a certain amount of uptime to go untracked.
+ */
+public class UptimeTracker {
+ /**
+ * In order to prevent excessive wear-out of the storage, do not allow snapshots to happen
+ * more frequently than this value
+ */
+ public static final long MINIMUM_SNAPSHOT_INTERVAL_MS = 60 * 60 * 1000;
+
+ /**
+ * The default snapshot interval if none is given
+ */
+ private static long DEFAULT_SNAPSHOT_INTERVAL_MS = 5 * 60 * 60 * 1000; // 5 hours
+
+ private final Object mLock = new Object();
+
+ /**
+ * The file that uptime metrics are stored to
+ */
+ private File mUptimeFile;
+
+ /**
+ * The uptime value retrieved from mUptimeFile
+ */
+ private Optional<Long> mHistoricalUptime;
+
+ /**
+ * Last value of elapsedRealTime read from the system
+ */
+ private long mLastRealTimeSnapshot;
+
+ /**
+ * The source of real-time and scheduling
+ */
+ private TimeInterface mTimeInterface;
+
+ public UptimeTracker(File file) {
+ this(file, DEFAULT_SNAPSHOT_INTERVAL_MS);
+ }
+
+ public UptimeTracker(File file, long snapshotInterval) {
+ this(file, snapshotInterval, new TimeInterface.DefaultImpl());
+ }
+
+ UptimeTracker(File file, long snapshotInterval, SystemInterface systemInterface) {
+ this(file, snapshotInterval, systemInterface.getTimeInterface());
+ }
+
+ // This constructor allows one to replace the source of time-based truths with
+ // a mock version. This is mostly useful for testing purposes.
+ @VisibleForTesting
+ UptimeTracker(File file,
+ long snapshotInterval,
+ TimeInterface timeInterface) {
+ snapshotInterval = Math.max(snapshotInterval, MINIMUM_SNAPSHOT_INTERVAL_MS);
+ mUptimeFile = Objects.requireNonNull(file);
+ mTimeInterface = timeInterface;
+ mLastRealTimeSnapshot = mTimeInterface.getUptime(TimeInterface.EXCLUDE_DEEP_SLEEP_TIME);
+ mHistoricalUptime = Optional.empty();
+
+ mTimeInterface.scheduleAction(this::flushSnapshot, snapshotInterval);
+ }
+
+ void onDestroy() {
+ synchronized (mLock) {
+ if (mTimeInterface != null) {
+ mTimeInterface.cancelAllActions();
+ }
+ flushSnapshot();
+ mTimeInterface = null;
+ mUptimeFile = null;
+ }
+ }
+
+ /**
+ * Return the total amount of uptime that has been observed, in milliseconds.
+ *
+ * This is the sum of the uptime stored on disk + the uptime seen since the last snapshot.
+ */
+ long getTotalUptime() {
+ synchronized (mLock) {
+ if (mTimeInterface == null) {
+ return 0;
+ }
+ return getHistoricalUptimeLocked() + (
+ mTimeInterface.getUptime(TimeInterface.EXCLUDE_DEEP_SLEEP_TIME)
+ - mLastRealTimeSnapshot);
+ }
+ }
+
+ private long getHistoricalUptimeLocked() {
+ if (!mHistoricalUptime.isPresent() && mUptimeFile != null && mUptimeFile.exists()) {
+ try {
+ JsonReader reader = new JsonReader(new FileReader(mUptimeFile));
+ reader.beginObject();
+ if (!reader.nextName().equals("uptime")) {
+ throw new IllegalArgumentException(
+ mUptimeFile + " is not in a valid format");
+ } else {
+ mHistoricalUptime = Optional.of(reader.nextLong());
+ }
+ reader.endObject();
+ reader.close();
+ } catch (IllegalArgumentException | IOException e) {
+ Log.w(CarLog.TAG_SERVICE, "unable to read historical uptime data", e);
+ mHistoricalUptime = Optional.empty();
+ }
+ }
+ return mHistoricalUptime.orElse(0L);
+ }
+
+ private void flushSnapshot() {
+ synchronized (mLock) {
+ if (mUptimeFile == null) {
+ return;
+ }
+ try {
+ long newUptime = getTotalUptime();
+ mHistoricalUptime = Optional.of(newUptime);
+ mLastRealTimeSnapshot = mTimeInterface.getUptime(
+ TimeInterface.EXCLUDE_DEEP_SLEEP_TIME);
+
+ JsonWriter writer = new JsonWriter(new FileWriter(mUptimeFile));
+ writer.beginObject();
+ writer.name("uptime");
+ writer.value(newUptime);
+ writer.endObject();
+ writer.close();
+ } catch (IOException e) {
+ Log.w(CarLog.TAG_SERVICE, "unable to write historical uptime data", e);
+ }
+ }
+ }
+}
diff --git a/service/src/com/android/car/Utils.java b/service/src/com/android/car/Utils.java
new file mode 100644
index 0000000..78f5a8e
--- /dev/null
+++ b/service/src/com/android/car/Utils.java
@@ -0,0 +1,78 @@
+package com.android.car;
+
+import android.bluetooth.BluetoothDevice;
+import android.bluetooth.BluetoothProfile;
+
+/**
+ * Some potentially useful static methods.
+ */
+public class Utils {
+ static final Boolean DBG = false;
+
+ static String getDeviceDebugInfo(BluetoothDevice device) {
+ return "(name = " + device.getName() + ", addr = " + device.getAddress() + ")";
+ }
+
+ static String getProfileName(int profile) {
+ switch(profile) {
+ case BluetoothProfile.A2DP_SINK:
+ return "A2DP_SINK";
+ case BluetoothProfile.HEADSET_CLIENT:
+ return "HFP";
+ case BluetoothProfile.PBAP_CLIENT:
+ return "PBAP";
+ case BluetoothProfile.MAP_CLIENT:
+ return "MAP";
+ case BluetoothProfile.AVRCP_CONTROLLER:
+ return "AVRCP";
+ case BluetoothProfile.PAN:
+ return "PAN";
+ default:
+ return profile + "";
+
+ }
+ }
+
+ /**
+ * An utility class to dump transition events across different car service components.
+ * The output will be of the form
+ * <p>
+ * "Time <svc name>: [optional context information] changed from <from state> to <to state>"
+ * This can be used in conjunction with the dump() method to dump this information through
+ * adb shell dumpsys activity service com.android.car
+ * <p>
+ * A specific service in CarService can choose to use a circular buffer of N records to keep
+ * track of the last N transitions.
+ *
+ */
+ public static class TransitionLog {
+ private String mServiceName; // name of the service or tag
+ private int mFromState; // old state
+ private int mToState; // new state
+ private long mTimestampMs; // System.currentTimeMillis()
+ private String mExtra; // Additional information as a String
+
+ public TransitionLog(String name, int fromState, int toState, long timestamp,
+ String extra) {
+ this(name, fromState, toState, timestamp);
+ mExtra = extra;
+ }
+
+ public TransitionLog(String name, int fromState, int toState, long timeStamp) {
+ mServiceName = name;
+ mFromState = fromState;
+ mToState = toState;
+ mTimestampMs = timeStamp;
+ }
+
+ private CharSequence timeToLog(long timestamp) {
+ return android.text.format.DateFormat.format("MM-dd HH:mm:ss", timestamp);
+ }
+
+ @Override
+ public String toString() {
+ return timeToLog(mTimestampMs) + " " + mServiceName + ": " + (mExtra != null ? mExtra
+ : "") + " changed from " + mFromState + " to " + mToState;
+ }
+ }
+}
diff --git a/service/src/com/android/car/VmsLayersAvailability.java b/service/src/com/android/car/VmsLayersAvailability.java
index 93b917c..200b347 100644
--- a/service/src/com/android/car/VmsLayersAvailability.java
+++ b/service/src/com/android/car/VmsLayersAvailability.java
@@ -16,8 +16,8 @@
package com.android.car;
-import android.car.annotation.FutureFeature;
import android.car.vms.VmsAssociatedLayer;
+import android.car.vms.VmsAvailableLayers;
import android.car.vms.VmsLayer;
import android.car.vms.VmsLayerDependency;
import android.car.vms.VmsLayersOffering;
@@ -40,9 +40,10 @@
* Each VMS publisher sets its layers offering which are a list of layers the publisher claims
* it might publish. VmsLayersAvailability calculates from all the offering what are the
* available layers.
+ *
+ * @hide
*/
-@FutureFeature
public class VmsLayersAvailability {
private static final boolean DBG = true;
@@ -58,6 +59,8 @@
private Set<VmsAssociatedLayer> mUnavailableAssociatedLayers = Collections.EMPTY_SET;
@GuardedBy("mLock")
private Map<VmsLayer, Set<Integer>> mPotentialLayersAndPublishers = new HashMap<>();
+ @GuardedBy("mLock")
+ private int mSeq = 0;
/**
* Setting the current layers offerings as reported by publishers.
@@ -96,19 +99,9 @@
/**
* Returns a collection of all the layers which may be published.
*/
- public Set<VmsAssociatedLayer> getAvailableLayers() {
+ public VmsAvailableLayers getAvailableLayers() {
synchronized (mLock) {
- return mAvailableAssociatedLayers;
- }
- }
-
- /**
- * Returns a collection of all the layers which publishers could have published if the
- * dependencies were satisfied.
- */
- public Set<VmsAssociatedLayer> getUnavailableLayers() {
- synchronized (mLock) {
- return mUnavailableAssociatedLayers;
+ return new VmsAvailableLayers(mAvailableAssociatedLayers, mSeq);
}
}
@@ -118,6 +111,10 @@
mPotentialLayersAndPublishers.clear();
mAvailableAssociatedLayers = Collections.EMPTY_SET;
mUnavailableAssociatedLayers = Collections.EMPTY_SET;
+ if (mSeq + 1 < mSeq) {
+ throw new IllegalStateException("Sequence is about to loop");
+ }
+ mSeq += 1;
}
}
@@ -147,6 +144,7 @@
}
}
+ @GuardedBy("mLock")
private void addLayerToAvailabilityCalculationLocked(VmsLayer layer,
Set<VmsLayer> currentAvailableLayers,
Set<VmsLayer> cyclicAvoidanceSet) {
diff --git a/service/src/com/android/car/VmsPublisherService.java b/service/src/com/android/car/VmsPublisherService.java
index 8a293e5..a240e17 100644
--- a/service/src/com/android/car/VmsPublisherService.java
+++ b/service/src/com/android/car/VmsPublisherService.java
@@ -16,69 +16,102 @@
package com.android.car;
-import android.car.annotation.FutureFeature;
-import android.car.vms.IVmsSubscriberClient;
import android.car.vms.IVmsPublisherClient;
import android.car.vms.IVmsPublisherService;
+import android.car.vms.IVmsSubscriberClient;
import android.car.vms.VmsLayer;
import android.car.vms.VmsLayersOffering;
import android.car.vms.VmsSubscriptionState;
+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.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.os.Binder;
+import android.os.Handler;
import android.os.IBinder;
+import android.os.Message;
import android.os.RemoteException;
import android.os.UserHandle;
import android.text.TextUtils;
+import android.util.ArrayMap;
+import android.util.ArraySet;
import android.util.Log;
+
import com.android.car.hal.VmsHalService;
-import com.android.internal.annotations.GuardedBy;
+import com.android.car.hal.VmsHalService.VmsHalPublisherListener;
+
import java.io.PrintWriter;
-import java.lang.ref.WeakReference;
-import java.util.ArrayList;
import java.util.Arrays;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.List;
import java.util.Map;
import java.util.Set;
/**
- * + Receives HAL updates by implementing VmsHalService.VmsHalListener.
- * + Binds to publishers and configures them to use this service.
- * + Notifies publishers of subscription changes.
+ * Receives HAL updates by implementing VmsHalService.VmsHalListener.
+ * Binds to publishers and configures them to use this service.
+ * Notifies publishers of subscription changes.
*/
-@FutureFeature
-public class VmsPublisherService extends IVmsPublisherService.Stub
- implements CarServiceBase, VmsHalService.VmsHalPublisherListener {
+public class VmsPublisherService extends IVmsPublisherService.Stub implements CarServiceBase {
private static final boolean DBG = true;
private static final String TAG = "VmsPublisherService";
+ private static final int MSG_HAL_SUBSCRIPTION_CHANGED = 1;
+
private final Context mContext;
private final VmsHalService mHal;
- private final VmsPublisherManager mPublisherManager;
- private Set<String> mSafePermissions;
+ private final Map<String, PublisherConnection> mPublisherConnectionMap = new ArrayMap<>();
+ private final Map<String, IVmsPublisherClient> mPublisherMap = new ArrayMap<>();
+ private final Set<String> mSafePermissions;
+ private final Handler mHandler = new EventHandler();
+ private final VmsHalPublisherListener mHalPublisherListener;
+
+ private BroadcastReceiver mBootCompleteReceiver;
public VmsPublisherService(Context context, VmsHalService hal) {
mContext = context;
mHal = hal;
- mPublisherManager = new VmsPublisherManager(this);
+
+ mHalPublisherListener = subscriptionState -> mHandler.sendMessage(
+ mHandler.obtainMessage(MSG_HAL_SUBSCRIPTION_CHANGED, subscriptionState));
+
+ // Load permissions that can be granted to publishers.
+ mSafePermissions = new ArraySet<>(
+ Arrays.asList(mContext.getResources().getStringArray(R.array.vmsSafePermissions)));
}
// Implements CarServiceBase interface.
@Override
public void init() {
- mHal.addPublisherListener(this);
- // Load permissions that can be granted to publishers.
- mSafePermissions = new HashSet<>(
- Arrays.asList(mContext.getResources().getStringArray(R.array.vmsSafePermissions)));
- // Launch publishers.
+ mHal.addPublisherListener(mHalPublisherListener);
+
+ if (isTestEnvironment()) {
+ Log.d(TAG, "Running under test environment");
+ bindToAllPublishers();
+ } else {
+ mBootCompleteReceiver = new BroadcastReceiver() {
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ if (Intent.ACTION_LOCKED_BOOT_COMPLETED.equals(intent.getAction())) {
+ onLockedBootCompleted();
+ } else {
+ Log.e(TAG, "Unexpected action received: " + intent);
+ }
+ }
+ };
+
+ mContext.registerReceiver(mBootCompleteReceiver,
+ new IntentFilter(Intent.ACTION_LOCKED_BOOT_COMPLETED));
+ }
+ }
+
+ private void bindToAllPublishers() {
String[] publisherNames = mContext.getResources().getStringArray(
R.array.vmsPublisherClients);
+ if (DBG) Log.d(TAG, "Publishers found: " + publisherNames.length);
+
for (String publisherName : publisherNames) {
if (TextUtils.isEmpty(publisherName)) {
Log.e(TAG, "empty publisher name");
@@ -87,27 +120,48 @@
ComponentName name = ComponentName.unflattenFromString(publisherName);
if (name == null) {
Log.e(TAG, "invalid publisher name: " + publisherName);
+ continue;
}
- mPublisherManager.bind(name);
+
+ if (!mContext.getPackageManager().isPackageAvailable(name.getPackageName())) {
+ Log.w(TAG, "VMS publisher not installed: " + publisherName);
+ continue;
+ }
+
+ bind(name);
}
}
@Override
public void release() {
- mPublisherManager.release();
- mHal.removePublisherListener(this);
+ if (mBootCompleteReceiver != null) {
+ mContext.unregisterReceiver(mBootCompleteReceiver);
+ mBootCompleteReceiver = null;
+ }
+ mHal.removePublisherListener(mHalPublisherListener);
+
+ for (PublisherConnection connection : mPublisherConnectionMap.values()) {
+ mContext.unbindService(connection);
+ }
+ mPublisherConnectionMap.clear();
+ mPublisherMap.clear();
}
@Override
public void dump(PrintWriter writer) {
+ writer.println("*" + getClass().getSimpleName() + "*");
+ writer.println("mSafePermissions: " + mSafePermissions);
+ writer.println("mPublisherMap:" + mPublisherMap);
+ writer.println("mPublisherConnectionMap:" + mPublisherConnectionMap);
}
+ /* Called in arbitrary binder thread */
@Override
public void setLayersOffering(IBinder token, VmsLayersOffering offering) {
mHal.setPublisherLayersOffering(token, offering);
}
- // Implements IVmsPublisherService interface.
+ /* Called in arbitrary binder thread */
@Override
public void publish(IBinder token, VmsLayer layer, int publisherId, byte[] payload) {
if (DBG) {
@@ -139,27 +193,33 @@
}
}
+ /* Called in arbitrary binder thread */
@Override
public VmsSubscriptionState getSubscriptions() {
ICarImpl.assertVmsPublisherPermission(mContext);
return mHal.getSubscriptionState();
}
+ /* Called in arbitrary binder thread */
@Override
public int getPublisherId(byte[] publisherInfo) {
ICarImpl.assertVmsPublisherPermission(mContext);
return mHal.getPublisherId(publisherInfo);
}
- // Implements VmsHalListener interface
+ private void onLockedBootCompleted() {
+ if (DBG) Log.i(TAG, "onLockedBootCompleted");
+
+ bindToAllPublishers();
+ }
+
/**
* This method is only invoked by VmsHalService.notifyPublishers which is synchronized.
* Therefore this method only sees a non-decreasing sequence.
*/
- @Override
- public void onChange(VmsSubscriptionState subscriptionState) {
+ private void handleHalSubscriptionChanged(VmsSubscriptionState subscriptionState) {
// Send the message to application listeners.
- for (IVmsPublisherClient client : mPublisherManager.getClients()) {
+ for (IVmsPublisherClient client : mPublisherMap.values()) {
try {
client.onVmsSubscriptionChange(subscriptionState);
} catch (RemoteException ex) {
@@ -169,168 +229,154 @@
}
/**
- * Keeps track of publishers that are using this service.
+ * Tries to bind to a publisher.
+ *
+ * @param name publisher component name (e.g. android.car.vms.logger/.LoggingService).
*/
- private static class VmsPublisherManager {
- /**
- * Allows to modify mPublisherMap and mPublisherConnectionMap as a single unit.
- */
- private final Object mLock = new Object();
- @GuardedBy("mLock")
- private final Map<String, PublisherConnection> mPublisherConnectionMap = new HashMap<>();
- @GuardedBy("mLock")
- private final Map<String, IVmsPublisherClient> mPublisherMap = new HashMap<>();
- private final WeakReference<VmsPublisherService> mPublisherService;
-
- public VmsPublisherManager(VmsPublisherService publisherService) {
- mPublisherService = new WeakReference<>(publisherService);
+ private void bind(ComponentName name) {
+ String publisherName = name.flattenToString();
+ if (DBG) {
+ Log.d(TAG, "binding to: " + publisherName);
}
- /**
- * Tries to bind to a publisher.
- *
- * @param name publisher component name (e.g. android.car.vms.logger/.LoggingService).
- */
- public void bind(ComponentName name) {
- VmsPublisherService publisherService = mPublisherService.get();
- if (publisherService == null) return;
- String publisherName = name.flattenToString();
- if (DBG) {
- Log.d(TAG, "binding to: " + publisherName);
- }
- synchronized (mLock) {
- if (mPublisherConnectionMap.containsKey(publisherName)) {
- // Already registered, nothing to do.
- return;
- }
- grantPermissions(name);
- Intent intent = new Intent();
- intent.setComponent(name);
- PublisherConnection connection = new PublisherConnection();
- if (publisherService.mContext.bindServiceAsUser(intent, connection,
- Context.BIND_AUTO_CREATE, UserHandle.SYSTEM)) {
- mPublisherConnectionMap.put(publisherName, connection);
- } else {
- Log.e(TAG, "unable to bind to: " + publisherName);
- }
- }
+ if (mPublisherConnectionMap.containsKey(publisherName)) {
+ // Already registered, nothing to do.
+ return;
+ }
+ grantPermissions(name);
+ Intent intent = new Intent();
+ intent.setComponent(name);
+ PublisherConnection connection = new PublisherConnection(name);
+ if (mContext.bindServiceAsUser(intent, connection,
+ Context.BIND_AUTO_CREATE, UserHandle.SYSTEM)) {
+ mPublisherConnectionMap.put(publisherName, connection);
+ } else {
+ Log.e(TAG, "unable to bind to: " + publisherName);
+ }
+ }
+
+ /**
+ * Removes the publisher and associated connection.
+ *
+ * @param name publisher component name (e.g. android.car.vms.Logger).
+ */
+ private void unbind(ComponentName name) {
+ String publisherName = name.flattenToString();
+ if (DBG) {
+ Log.d(TAG, "unbinding from: " + publisherName);
}
- /**
- * Removes the publisher and associated connection.
- *
- * @param name publisher component name (e.g. android.car.vms.Logger).
- */
- public void unbind(ComponentName name) {
- VmsPublisherService publisherService = mPublisherService.get();
- if (publisherService == null) return;
- String publisherName = name.flattenToString();
- if (DBG) {
- Log.d(TAG, "unbinding from: " + publisherName);
- }
- synchronized (mLock) {
- boolean found = mPublisherMap.remove(publisherName) != null;
- if (found) {
- PublisherConnection connection = mPublisherConnectionMap.get(publisherName);
- publisherService.mContext.unbindService(connection);
- mPublisherConnectionMap.remove(publisherName);
- } else {
- Log.e(TAG, "unbind: unknown publisher." + publisherName);
- }
- }
+ boolean found = mPublisherMap.remove(publisherName) != null;
+ if (found) {
+ PublisherConnection connection = mPublisherConnectionMap.get(publisherName);
+ mContext.unbindService(connection);
+ mPublisherConnectionMap.remove(publisherName);
+ } else {
+ Log.e(TAG, "unbind: unknown publisher." + publisherName);
}
+ }
- /**
- * Returns the list of publishers currently registered.
- *
- * @return list of publishers.
- */
- public List<IVmsPublisherClient> getClients() {
- synchronized (mLock) {
- return new ArrayList<>(mPublisherMap.values());
- }
+ private void grantPermissions(ComponentName component) {
+ final PackageManager packageManager = mContext.getPackageManager();
+ final String packageName = component.getPackageName();
+ PackageInfo packageInfo;
+ try {
+ packageInfo = packageManager.getPackageInfo(packageName,
+ PackageManager.GET_PERMISSIONS);
+ } catch (PackageManager.NameNotFoundException e) {
+ Log.e(TAG, "Error getting package info for " + packageName, e);
+ return;
}
-
- public void release() {
- VmsPublisherService publisherService = mPublisherService.get();
- if (publisherService == null) return;
- for (PublisherConnection connection : mPublisherConnectionMap.values()) {
- publisherService.mContext.unbindService(connection);
+ if (packageInfo.requestedPermissions == null) return;
+ for (String permission : packageInfo.requestedPermissions) {
+ if (!mSafePermissions.contains(permission)) {
+ continue;
}
- mPublisherConnectionMap.clear();
- mPublisherMap.clear();
- }
-
- private void grantPermissions(ComponentName component) {
- VmsPublisherService publisherService = mPublisherService.get();
- if (publisherService == null) return;
- final PackageManager packageManager = publisherService.mContext.getPackageManager();
- final String packageName = component.getPackageName();
- PackageInfo packageInfo;
+ if (packageManager.checkPermission(permission, packageName)
+ == PackageManager.PERMISSION_GRANTED) {
+ continue;
+ }
try {
- packageInfo = packageManager.getPackageInfo(packageName,
- PackageManager.GET_PERMISSIONS);
- } catch (PackageManager.NameNotFoundException e) {
- Log.e(TAG, "Error getting package info for " + packageName, e);
- return;
+ packageManager.grantRuntimePermission(packageName, permission,
+ UserHandle.SYSTEM);
+ Log.d(TAG, "Permission " + permission + " granted to " + packageName);
+ } catch (SecurityException | IllegalArgumentException e) {
+ Log.e(TAG, "Error while trying to grant " + permission + " to " + packageName,
+ e);
}
- if (packageInfo.requestedPermissions == null) return;
- for (String permission : packageInfo.requestedPermissions) {
- if (!publisherService.mSafePermissions.contains(permission)) {
- continue;
- }
- if (packageManager.checkPermission(permission, packageName)
- == PackageManager.PERMISSION_GRANTED) {
- continue;
- }
- try {
- packageManager.grantRuntimePermission(packageName, permission,
- UserHandle.SYSTEM);
- Log.d(TAG, "Permission " + permission + " granted to " + packageName);
- } catch (SecurityException | IllegalArgumentException e) {
- Log.e(TAG, "Error while trying to grant " + permission + " to " + packageName,
- e);
- }
+ }
+ }
+
+ 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());
+ }
+
+ class PublisherConnection implements ServiceConnection {
+ private final IBinder mToken = new Binder();
+ private final ComponentName mName;
+
+ PublisherConnection(ComponentName name) {
+ mName = name;
+ }
+
+ private final Runnable mBindRunnable = new Runnable() {
+ @Override
+ public void run() {
+ Log.d(TAG, "delayed binding for: " + mName);
+ bind(mName);
+ }
+ };
+
+ /**
+ * Once the service binds to a publisher service, the publisher binder is added to
+ * mPublisherMap
+ * and the publisher is configured to use this service.
+ */
+ @Override
+ public void onServiceConnected(ComponentName name, IBinder binder) {
+ if (DBG) {
+ Log.d(TAG, "onServiceConnected, name: " + name + ", binder: " + binder);
+ }
+ IVmsPublisherClient service = IVmsPublisherClient.Stub.asInterface(binder);
+ mPublisherMap.put(name.flattenToString(), service);
+ try {
+ service.setVmsPublisherService(mToken, VmsPublisherService.this);
+ } catch (RemoteException e) {
+ Log.e(TAG, "unable to configure publisher: " + name, e);
}
}
- class PublisherConnection implements ServiceConnection {
+ /**
+ * Tries to rebind to the publisher service.
+ */
+ @Override
+ public void onServiceDisconnected(ComponentName name) {
+ String publisherName = name.flattenToString();
+ Log.d(TAG, "onServiceDisconnected, name: " + publisherName);
- private final IBinder mToken = new Binder();
-
- /**
- * Once the service binds to a publisher service, the publisher binder is added to
- * mPublisherMap
- * and the publisher is configured to use this service.
- */
- @Override
- public void onServiceConnected(ComponentName name, IBinder binder) {
- VmsPublisherService publisherService = mPublisherService.get();
- if (publisherService == null) return;
- if (DBG) {
- Log.d(TAG, "onServiceConnected, name: " + name + ", binder: " + binder);
- }
- IVmsPublisherClient service = IVmsPublisherClient.Stub.asInterface(binder);
- synchronized (mLock) {
- mPublisherMap.put(name.flattenToString(), service);
- }
- try {
- service.setVmsPublisherService(mToken, publisherService);
- } catch (RemoteException e) {
- Log.e(TAG, "unable to configure publisher: " + name);
- }
+ int millisecondsToWait = mContext.getResources().getInteger(
+ com.android.car.R.integer.millisecondsBeforeRebindToVmsPublisher);
+ if (!mName.flattenToString().equals(name.flattenToString())) {
+ throw new IllegalArgumentException(
+ "Mismatch on publisherConnection. Expected: " + mName + " Got: " + name);
}
+ mHandler.postDelayed(mBindRunnable, millisecondsToWait);
- /**
- * Tries to rebind to the publisher service.
- */
- @Override
- public void onServiceDisconnected(ComponentName name) {
- String publisherName = name.flattenToString();
- Log.d(TAG, "onServiceDisconnected, name: " + publisherName);
- VmsPublisherManager.this.unbind(name);
- VmsPublisherManager.this.bind(name);
+ unbind(name);
+ }
+ }
+
+ private class EventHandler extends Handler {
+ @Override
+ public void handleMessage(Message msg) {
+ switch (msg.what) {
+ case MSG_HAL_SUBSCRIPTION_CHANGED:
+ handleHalSubscriptionChanged((VmsSubscriptionState) msg.obj);
+ return;
}
+ super.handleMessage(msg);
}
}
}
diff --git a/service/src/com/android/car/VmsPublishersInfo.java b/service/src/com/android/car/VmsPublishersInfo.java
index 04ee82f..e8baf58 100644
--- a/service/src/com/android/car/VmsPublishersInfo.java
+++ b/service/src/com/android/car/VmsPublishersInfo.java
@@ -16,8 +16,6 @@
package com.android.car;
-
-import android.car.annotation.FutureFeature;
import java.util.HashMap;
import java.util.Map;
import java.util.List;
@@ -26,7 +24,6 @@
import com.android.internal.annotations.GuardedBy;
import android.util.Log;
-@FutureFeature
public class VmsPublishersInfo {
private static final String TAG = "VmsPublishersInfo";
private static final boolean DBG = true;
@@ -85,6 +82,7 @@
}
}
+ @GuardedBy("mLock")
private void maybeAddPublisherInfoLocked(InfoWrapper wrappedPublisherInfo) {
if (!mPublishersIds.containsKey(wrappedPublisherInfo)) {
// Assign ID to the info
diff --git a/service/src/com/android/car/VmsRouting.java b/service/src/com/android/car/VmsRouting.java
index 2e66781..fa29a27 100644
--- a/service/src/com/android/car/VmsRouting.java
+++ b/service/src/com/android/car/VmsRouting.java
@@ -16,7 +16,6 @@
package com.android.car;
-import android.car.annotation.FutureFeature;
import android.car.vms.IVmsSubscriberClient;
import android.car.vms.VmsAssociatedLayer;
import android.car.vms.VmsLayer;
@@ -39,7 +38,7 @@
* + Subscriptions to all data messages.
* + HAL subscriptions to layer + version.
*/
-@FutureFeature
+
public class VmsRouting {
private final Object mLock = new Object();
// A map of Layer + Version to subscribers.
diff --git a/service/src/com/android/car/VmsSubscriberService.java b/service/src/com/android/car/VmsSubscriberService.java
index 94f0844..c4c507e 100644
--- a/service/src/com/android/car/VmsSubscriberService.java
+++ b/service/src/com/android/car/VmsSubscriberService.java
@@ -17,10 +17,9 @@
package com.android.car;
import android.car.Car;
-import android.car.annotation.FutureFeature;
import android.car.vms.IVmsSubscriberClient;
import android.car.vms.IVmsSubscriberService;
-import android.car.vms.VmsAssociatedLayer;
+import android.car.vms.VmsAvailableLayers;
import android.car.vms.VmsLayer;
import android.content.Context;
import android.os.IBinder;
@@ -32,7 +31,6 @@
import java.io.PrintWriter;
import java.util.ArrayList;
-import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
@@ -43,7 +41,6 @@
* + Receives HAL updates by implementing VmsHalService.VmsHalListener.
* + Offers subscriber/publisher services by implementing IVmsService.Stub.
*/
-@FutureFeature
public class VmsSubscriberService extends IVmsSubscriberService.Stub
implements CarServiceBase, VmsHalService.VmsHalSubscriberListener {
private static final boolean DBG = true;
@@ -125,7 +122,7 @@
* subscriber.
*/
public void add(IVmsSubscriberClient subscriber) {
- ICarImpl.assertPermission(mContext, PERMISSION);
+ ICarImpl.assertVmsSubscriberPermission(mContext);
if (subscriber == null) {
Log.e(TAG, "register: subscriber is null.");
throw new IllegalArgumentException("subscriber cannot be null.");
@@ -221,6 +218,7 @@
// Implements IVmsService interface.
@Override
public void addVmsSubscriberToNotifications(IVmsSubscriberClient subscriber) {
+ ICarImpl.assertVmsSubscriberPermission(mContext);
synchronized (mSubscriberServiceLock) {
// Add the subscriber so it can subscribe.
mSubscribersManager.add(subscriber);
@@ -229,6 +227,7 @@
@Override
public void removeVmsSubscriberToNotifications(IVmsSubscriberClient subscriber) {
+ ICarImpl.assertVmsSubscriberPermission(mContext);
synchronized (mSubscriberServiceLock) {
if (mHal.containsSubscriber(subscriber)) {
throw new IllegalArgumentException("Subscriber has active subscriptions.");
@@ -239,6 +238,7 @@
@Override
public void addVmsSubscriber(IVmsSubscriberClient subscriber, VmsLayer layer) {
+ ICarImpl.assertVmsSubscriberPermission(mContext);
synchronized (mSubscriberServiceLock) {
// Add the subscriber so it can subscribe.
mSubscribersManager.add(subscriber);
@@ -250,6 +250,7 @@
@Override
public void removeVmsSubscriber(IVmsSubscriberClient subscriber, VmsLayer layer) {
+ ICarImpl.assertVmsSubscriberPermission(mContext);
synchronized (mSubscriberServiceLock) {
// Remove the subscription.
mHal.removeSubscription(subscriber, layer);
@@ -258,8 +259,9 @@
@Override
public void addVmsSubscriberToPublisher(IVmsSubscriberClient subscriber,
- VmsLayer layer,
- int publisherId) {
+ VmsLayer layer,
+ int publisherId) {
+ ICarImpl.assertVmsSubscriberPermission(mContext);
synchronized (mSubscriberServiceLock) {
// Add the subscriber so it can subscribe.
mSubscribersManager.add(subscriber);
@@ -271,8 +273,9 @@
@Override
public void removeVmsSubscriberToPublisher(IVmsSubscriberClient subscriber,
- VmsLayer layer,
- int publisherId) {
+ VmsLayer layer,
+ int publisherId) {
+ ICarImpl.assertVmsSubscriberPermission(mContext);
synchronized (mSubscriberServiceLock) {
// Remove the subscription.
mHal.removeSubscription(subscriber, layer, publisherId);
@@ -281,6 +284,7 @@
@Override
public void addVmsSubscriberPassive(IVmsSubscriberClient subscriber) {
+ ICarImpl.assertVmsSubscriberPermission(mContext);
synchronized (mSubscriberServiceLock) {
mSubscribersManager.add(subscriber);
mHal.addSubscription(subscriber);
@@ -289,6 +293,7 @@
@Override
public void removeVmsSubscriberPassive(IVmsSubscriberClient subscriber) {
+ ICarImpl.assertVmsSubscriberPermission(mContext);
synchronized (mSubscriberServiceLock) {
// Remove the subscription.
mHal.removeSubscription(subscriber);
@@ -297,15 +302,16 @@
@Override
public byte[] getPublisherInfo(int publisherId) {
+ ICarImpl.assertVmsSubscriberPermission(mContext);
synchronized (mSubscriberServiceLock) {
return mHal.getPublisherInfo(publisherId);
}
}
@Override
- public List<VmsLayer> getAvailableLayers() {
- //TODO(asafro): return the list of available layers once logic is implemented.
- return Collections.emptyList();
+ public VmsAvailableLayers getAvailableLayers() {
+ return mHal.getAvailableLayers();
+
}
// Implements VmsHalSubscriberListener interface
@@ -330,15 +336,13 @@
}
@Override
- public void onLayersAvaiabilityChange(List<VmsAssociatedLayer> availableLayers) {
+ public void onLayersAvaiabilityChange(VmsAvailableLayers availableLayers) {
if (DBG) {
Log.d(TAG, "Publishing layers availability change: " + availableLayers);
}
Set<IVmsSubscriberClient> subscribers;
- synchronized (mSubscriberServiceLock) {
- subscribers = new HashSet<>(mSubscribersManager.getListeners());
- }
+ subscribers = new HashSet<>(mSubscribersManager.getListeners());
for (IVmsSubscriberClient subscriber : subscribers) {
try {
diff --git a/service/src/com/android/car/VolumeUtils.java b/service/src/com/android/car/VolumeUtils.java
deleted file mode 100644
index 265615b..0000000
--- a/service/src/com/android/car/VolumeUtils.java
+++ /dev/null
@@ -1,242 +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.car.settings.CarSettings;
-import android.hardware.automotive.vehicle.V2_0.VehicleAudioContextFlag;
-import android.media.AudioAttributes;
-import android.media.AudioManager;
-import android.util.Log;
-import android.util.SparseArray;
-
-import java.util.Arrays;
-
-public class VolumeUtils {
- private static final String TAG = "VolumeUtils";
-
- public static final int[] LOGICAL_STREAMS = {
- AudioManager.STREAM_VOICE_CALL,
- AudioManager.STREAM_SYSTEM,
- AudioManager.STREAM_RING,
- AudioManager.STREAM_MUSIC,
- AudioManager.STREAM_ALARM,
- AudioManager.STREAM_NOTIFICATION,
- AudioManager.STREAM_DTMF,
- };
-
- public static final int[] CAR_AUDIO_CONTEXT = {
- VehicleAudioContextFlag.MUSIC_FLAG,
- VehicleAudioContextFlag.NAVIGATION_FLAG,
- VehicleAudioContextFlag.VOICE_COMMAND_FLAG,
- VehicleAudioContextFlag.CALL_FLAG,
- VehicleAudioContextFlag.RINGTONE_FLAG,
- VehicleAudioContextFlag.ALARM_FLAG,
- VehicleAudioContextFlag.NOTIFICATION_FLAG,
- VehicleAudioContextFlag.UNKNOWN_FLAG,
- VehicleAudioContextFlag.SAFETY_ALERT_FLAG,
- VehicleAudioContextFlag.CD_ROM_FLAG,
- VehicleAudioContextFlag.AUX_AUDIO_FLAG,
- VehicleAudioContextFlag.SYSTEM_SOUND_FLAG,
- VehicleAudioContextFlag.RADIO_FLAG
- };
-
- public static final SparseArray<String> CAR_AUDIO_CONTEXT_SETTINGS = new SparseArray<>();
- static {
- CAR_AUDIO_CONTEXT_SETTINGS.put(VehicleAudioContextFlag.UNKNOWN_FLAG,
- CarSettings.Global.KEY_VOLUME_MUSIC);
- CAR_AUDIO_CONTEXT_SETTINGS.put(VehicleAudioContextFlag.MUSIC_FLAG,
- CarSettings.Global.KEY_VOLUME_MUSIC);
- CAR_AUDIO_CONTEXT_SETTINGS.put(
- VehicleAudioContextFlag.NAVIGATION_FLAG,
- CarSettings.Global.KEY_VOLUME_NAVIGATION);
- CAR_AUDIO_CONTEXT_SETTINGS.put(
- VehicleAudioContextFlag.VOICE_COMMAND_FLAG,
- CarSettings.Global.KEY_VOLUME_VOICE_COMMAND);
- CAR_AUDIO_CONTEXT_SETTINGS.put(VehicleAudioContextFlag.CALL_FLAG,
- CarSettings.Global.KEY_VOLUME_CALL);
- CAR_AUDIO_CONTEXT_SETTINGS.put(VehicleAudioContextFlag.RINGTONE_FLAG,
- CarSettings.Global.KEY_VOLUME_RINGTONE);
- CAR_AUDIO_CONTEXT_SETTINGS.put(VehicleAudioContextFlag.ALARM_FLAG,
- CarSettings.Global.KEY_VOLUME_ALARM);
- CAR_AUDIO_CONTEXT_SETTINGS.put(
- VehicleAudioContextFlag.NOTIFICATION_FLAG,
- CarSettings.Global.KEY_VOLUME_NOTIFICATION);
- CAR_AUDIO_CONTEXT_SETTINGS.put(
- VehicleAudioContextFlag.SAFETY_ALERT_FLAG,
- CarSettings.Global.KEY_VOLUME_SAFETY_ALERT);
- CAR_AUDIO_CONTEXT_SETTINGS.put(VehicleAudioContextFlag.CD_ROM_FLAG,
- CarSettings.Global.KEY_VOLUME_CD_ROM);
- CAR_AUDIO_CONTEXT_SETTINGS.put(VehicleAudioContextFlag.AUX_AUDIO_FLAG,
- CarSettings.Global.KEY_VOLUME_AUX);
- CAR_AUDIO_CONTEXT_SETTINGS.put(
- VehicleAudioContextFlag.SYSTEM_SOUND_FLAG,
- CarSettings.Global.KEY_VOLUME_SYSTEM_SOUND);
- CAR_AUDIO_CONTEXT_SETTINGS.put(VehicleAudioContextFlag.RADIO_FLAG,
- CarSettings.Global.KEY_VOLUME_RADIO);
- }
-
- public static String streamToName(int stream) {
- switch (stream) {
- case AudioManager.STREAM_ALARM: return "Alarm";
- case AudioManager.STREAM_MUSIC: return "Music";
- case AudioManager.STREAM_NOTIFICATION: return "Notification";
- case AudioManager.STREAM_RING: return "Ring";
- case AudioManager.STREAM_VOICE_CALL: return "Call";
- case AudioManager.STREAM_SYSTEM: return "System";
- case AudioManager.STREAM_DTMF: return "DTMF";
- default: return "Unknown";
- }
- }
-
- public static int androidStreamToCarContext(int logicalAndroidStream) {
- switch (logicalAndroidStream) {
- case AudioManager.STREAM_VOICE_CALL:
- return VehicleAudioContextFlag.CALL_FLAG;
- case AudioManager.STREAM_SYSTEM:
- return VehicleAudioContextFlag.SYSTEM_SOUND_FLAG;
- case AudioManager.STREAM_RING:
- return VehicleAudioContextFlag.RINGTONE_FLAG;
- case AudioManager.STREAM_MUSIC:
- return VehicleAudioContextFlag.MUSIC_FLAG;
- case AudioManager.STREAM_ALARM:
- return VehicleAudioContextFlag.ALARM_FLAG;
- case AudioManager.STREAM_NOTIFICATION:
- return VehicleAudioContextFlag.NOTIFICATION_FLAG;
- case AudioManager.STREAM_DTMF:
- return VehicleAudioContextFlag.SYSTEM_SOUND_FLAG;
- default:
- return VehicleAudioContextFlag.UNKNOWN_FLAG;
- }
- }
-
- public static int carContextToAndroidStream(int carContext) {
- switch (carContext) {
- case VehicleAudioContextFlag.CALL_FLAG:
- return AudioManager.STREAM_VOICE_CALL;
- case VehicleAudioContextFlag.RINGTONE_FLAG:
- return AudioManager.STREAM_RING;
- case VehicleAudioContextFlag.SYSTEM_SOUND_FLAG:
- return AudioManager.STREAM_SYSTEM;
- case VehicleAudioContextFlag.NOTIFICATION_FLAG:
- return AudioManager.STREAM_NOTIFICATION;
- case VehicleAudioContextFlag.MUSIC_FLAG:
- return AudioManager.STREAM_MUSIC;
- case VehicleAudioContextFlag.ALARM_FLAG:
- return AudioManager.STREAM_ALARM;
- default:
- return AudioManager.STREAM_MUSIC;
- }
- }
-
- public static int androidStreamToCarUsage(int logicalAndroidStream) {
- return CarAudioAttributesUtil.getCarUsageFromAudioAttributes(
- new AudioAttributes.Builder()
- .setLegacyStreamType(logicalAndroidStream).build());
- }
-
- private final SparseArray<Float[]> mStreamAmplLookup = new SparseArray<>(7);
-
- private static final float LN_10 = 2.302585093f;
- // From cs/#android/frameworks/av/media/libmedia/AudioSystem.cpp
- private static final float DB_PER_STEP = -.5f;
-
- private final AudioManager mAudioManager;
-
- public VolumeUtils(AudioManager audioManager) {
- mAudioManager = audioManager;
- for(int i : LOGICAL_STREAMS) {
- initStreamLookup(i);
- }
- }
-
- private void initStreamLookup(int streamType) {
- int maxIndex = mAudioManager.getStreamMaxVolume(streamType);
- Float[] amplList = new Float[maxIndex + 1];
-
- for (int i = 0; i <= maxIndex; i++) {
- amplList[i] = volIndexToAmpl(i, maxIndex);
- }
- Log.d(TAG, streamToName(streamType) + ": " + Arrays.toString(amplList));
- mStreamAmplLookup.put(streamType, amplList);
- }
-
-
- public static int closestIndex(float desired, Float[] list) {
- float min = Float.MAX_VALUE;
- int closestIndex = 0;
-
- for (int i = 0; i < list.length; i++) {
- float diff = Math.abs(list[i] - desired);
- if (diff < min) {
- min = diff;
- closestIndex = i;
- }
- }
- return closestIndex;
- }
-
- public void adjustStreamVol(int stream, int desired, int actual, int maxIndex) {
- float gain = getTrackGain(desired, actual, maxIndex);
- int index = closestIndex(gain, mStreamAmplLookup.get(stream));
- if (index == mAudioManager.getStreamVolume(stream)) {
- return;
- } else {
- mAudioManager.setStreamVolume(stream, index, 0 /*don't show UI*/);
- }
- }
-
- /**
- * Returns the gain which, when applied to an a stream with volume
- * actualVolIndex, will make the output volume equivalent to a stream with a gain of
- * 1.0 playing on a stream with volume desiredVolIndex.
- *
- * Computing this is non-trivial because the gain is applied on a linear scale while the volume
- * indices map to a log (dB) scale.
- *
- * The computation is copied from cs/#android/frameworks/av/media/libmedia/AudioSystem.cpp
- */
- float getTrackGain(int desiredVolIndex, int actualVolIndex, int maxIndex) {
- if (desiredVolIndex == actualVolIndex) {
- return 1.0f;
- }
- return volIndexToAmpl(desiredVolIndex, maxIndex)
- / volIndexToAmpl(actualVolIndex, maxIndex);
- }
-
- /**
- * Returns the amplitude corresponding to volIndex. Guaranteed to return a non-negative value.
- */
- private float volIndexToAmpl(int volIndex, int maxIndex) {
- // Normalize volIndex to be in the range [0, 100].
- int volume = (int) ((float) volIndex / maxIndex * 100.0f);
- return logToLinear(volumeToDecibels(volume));
- }
-
- /**
- * volume is in the range [0, 100].
- */
- private static float volumeToDecibels(int volume) {
- return (100 - volume) * DB_PER_STEP;
- }
-
- /**
- * Corresponds to the function linearToLog in AudioSystem.cpp.
- */
- private static float logToLinear(float decibels) {
- return decibels < 0.0f ? (float) Math.exp(decibels * LN_10 / 20.0f) : 1.0f;
- }
-}
diff --git a/service/src/com/android/car/cluster/InstrumentClusterService.java b/service/src/com/android/car/cluster/InstrumentClusterService.java
index eef177c..ab3ea62 100644
--- a/service/src/com/android/car/cluster/InstrumentClusterService.java
+++ b/service/src/com/android/car/cluster/InstrumentClusterService.java
@@ -36,8 +36,10 @@
import android.content.pm.ResolveInfo;
import android.os.Binder;
import android.os.Bundle;
+import android.os.Handler;
import android.os.IBinder;
import android.os.IBinder.DeathRecipient;
+import android.os.Message;
import android.os.Process;
import android.os.RemoteException;
import android.text.TextUtils;
@@ -92,6 +94,10 @@
@GuardedBy("mSync")
private final HashMap<IBinder, ManagerCallbackInfo> mManagerCallbacks = new HashMap<>();
+ // If renderer service crashed / stopped and this class fails to rebind with it immediately,
+ // we should wait some time before next attempt. This may happen during APK update for example.
+ private DeferredRebinder mDeferredRebinder;
+
private boolean mRendererBound = false;
private final ServiceConnection mRendererServiceConnection = new ServiceConnection() {
@@ -114,11 +120,16 @@
@Override
public void onServiceDisconnected(ComponentName name) {
Log.d(TAG, "onServiceDisconnected, name: " + name);
+ mRendererBound = false;
+
synchronized (mSync) {
mRendererService = null;
}
- // Try to rebind with instrument cluster.
- mRendererBound = bindInstrumentClusterRendererService();
+
+ if (mDeferredRebinder == null) {
+ mDeferredRebinder = new DeferredRebinder();
+ }
+ mDeferredRebinder.rebind();
}
};
@@ -225,7 +236,8 @@
InstrumentClusterRenderingService.EXTRA_KEY_CALLBACK_SERVICE,
mClusterCallback);
intent.putExtras(extras);
- return mContext.bindService(intent, mRendererServiceConnection, Context.BIND_AUTO_CREATE);
+ return mContext.bindService(intent, mRendererServiceConnection,
+ Context.BIND_AUTO_CREATE | Context.BIND_IMPORTANT);
}
@Nullable
@@ -458,6 +470,7 @@
}
}
+ @GuardedBy("mSync")
private ClusterActivityInfo getOrCreateActivityInfoLocked(String category) {
return mActivityInfoByCategory.computeIfAbsent(category, k -> new ClusterActivityInfo());
}
@@ -520,4 +533,36 @@
this.deathRecipient = deathRecipient;
}
}
+
+ private class DeferredRebinder extends Handler {
+ private static final long NEXT_REBIND_ATTEMPT_DELAY_MS = 1000L;
+ private static final int NUMBER_OF_ATTEMPTS = 10;
+
+ public void rebind() {
+ mRendererBound = bindInstrumentClusterRendererService();
+
+ if (!mRendererBound) {
+ removeMessages(0);
+ sendMessageDelayed(obtainMessage(0, NUMBER_OF_ATTEMPTS, 0),
+ NEXT_REBIND_ATTEMPT_DELAY_MS);
+ }
+ }
+
+ @Override
+ public void handleMessage(Message msg) {
+ mRendererBound = bindInstrumentClusterRendererService();
+
+ if (mRendererBound) {
+ Log.w(TAG, "Failed to bound to render service, next attempt in "
+ + NEXT_REBIND_ATTEMPT_DELAY_MS + "ms.");
+
+ int attempts = msg.arg1;
+ if (--attempts >= 0) {
+ sendMessageDelayed(obtainMessage(0, attempts, 0), NEXT_REBIND_ATTEMPT_DELAY_MS);
+ } else {
+ Log.wtf(TAG, "Failed to rebind with cluster rendering service");
+ }
+ }
+ }
+ }
}
diff --git a/service/src/com/android/car/hal/AudioHalService.java b/service/src/com/android/car/hal/AudioHalService.java
deleted file mode 100644
index 879bb6c..0000000
--- a/service/src/com/android/car/hal/AudioHalService.java
+++ /dev/null
@@ -1,754 +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.hal;
-
-import static android.hardware.automotive.vehicle.V2_0.VehicleProperty.AUDIO_EXT_ROUTING_HINT;
-import static android.hardware.automotive.vehicle.V2_0.VehicleProperty.AUDIO_FOCUS;
-import static android.hardware.automotive.vehicle.V2_0.VehicleProperty.AUDIO_HW_VARIANT;
-import static android.hardware.automotive.vehicle.V2_0.VehicleProperty.AUDIO_PARAMETERS;
-import static android.hardware.automotive.vehicle.V2_0.VehicleProperty.AUDIO_ROUTING_POLICY;
-import static android.hardware.automotive.vehicle.V2_0.VehicleProperty.AUDIO_STREAM_STATE;
-import static android.hardware.automotive.vehicle.V2_0.VehicleProperty.AUDIO_VOLUME;
-import static android.hardware.automotive.vehicle.V2_0.VehicleProperty.AUDIO_VOLUME_LIMIT;
-import static com.android.car.CarServiceUtils.toIntArray;
-
-import android.annotation.Nullable;
-import android.car.VehicleZoneUtil;
-import android.car.media.CarAudioManager;
-import android.car.media.CarAudioManager.OnParameterChangeListener;
-import android.hardware.automotive.vehicle.V2_0.SubscribeFlags;
-import android.hardware.automotive.vehicle.V2_0.VehicleAudioContextFlag;
-import android.hardware.automotive.vehicle.V2_0.VehicleAudioExtFocusFlag;
-import android.hardware.automotive.vehicle.V2_0.VehicleAudioFocusIndex;
-import android.hardware.automotive.vehicle.V2_0.VehicleAudioFocusRequest;
-import android.hardware.automotive.vehicle.V2_0.VehicleAudioFocusState;
-import android.hardware.automotive.vehicle.V2_0.VehicleAudioHwVariantConfigFlag;
-import android.hardware.automotive.vehicle.V2_0.VehicleAudioRoutingPolicyIndex;
-import android.hardware.automotive.vehicle.V2_0.VehicleAudioVolumeCapabilityFlag;
-import android.hardware.automotive.vehicle.V2_0.VehicleAudioVolumeIndex;
-import android.hardware.automotive.vehicle.V2_0.VehicleAudioVolumeLimitIndex;
-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.text.TextUtils;
-import android.util.Log;
-
-import com.android.car.AudioRoutingPolicy;
-import com.android.car.CarAudioAttributesUtil;
-import com.android.car.CarLog;
-
-import java.io.PrintWriter;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Collection;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-
-public class AudioHalService extends HalServiceBase {
- public static final int VEHICLE_AUDIO_FOCUS_REQUEST_INVALID = -1;
- public static final int VEHICLE_AUDIO_FOCUS_REQUEST_GAIN =
- VehicleAudioFocusRequest.REQUEST_GAIN;
- public static final int VEHICLE_AUDIO_FOCUS_REQUEST_GAIN_TRANSIENT =
- VehicleAudioFocusRequest.REQUEST_GAIN_TRANSIENT;
- public static final int VEHICLE_AUDIO_FOCUS_REQUEST_GAIN_TRANSIENT_MAY_DUCK =
- VehicleAudioFocusRequest.REQUEST_GAIN_TRANSIENT_MAY_DUCK;
- public static final int VEHICLE_AUDIO_FOCUS_REQUEST_GAIN_TRANSIENT_NO_DUCK =
- VehicleAudioFocusRequest.REQUEST_GAIN_TRANSIENT_NO_DUCK;
- public static final int VEHICLE_AUDIO_FOCUS_REQUEST_RELEASE =
- VehicleAudioFocusRequest.REQUEST_RELEASE;
-
- public static final int VEHICLE_AUDIO_FOCUS_STATE_INVALID = -1;
- public static final int VEHICLE_AUDIO_FOCUS_STATE_GAIN =
- VehicleAudioFocusState.STATE_GAIN;
- public static final int VEHICLE_AUDIO_FOCUS_STATE_GAIN_TRANSIENT =
- VehicleAudioFocusState.STATE_GAIN_TRANSIENT;
- public static final int VEHICLE_AUDIO_FOCUS_STATE_LOSS_TRANSIENT_CAN_DUCK =
- VehicleAudioFocusState.STATE_LOSS_TRANSIENT_CAN_DUCK;
- public static final int VEHICLE_AUDIO_FOCUS_STATE_LOSS_TRANSIENT =
- VehicleAudioFocusState.STATE_LOSS_TRANSIENT;
- public static final int VEHICLE_AUDIO_FOCUS_STATE_LOSS =
- VehicleAudioFocusState.STATE_LOSS;
- public static final int VEHICLE_AUDIO_FOCUS_STATE_LOSS_TRANSIENT_EXLCUSIVE =
- VehicleAudioFocusState.STATE_LOSS_TRANSIENT_EXLCUSIVE;
-
- public static final int VEHICLE_AUDIO_STREAM_STATE_STOPPED = 0;
- public static final int VEHICLE_AUDIO_STREAM_STATE_STARTED = 1;
-
- public static final int VEHICLE_AUDIO_EXT_FOCUS_NONE_FLAG =
- VehicleAudioExtFocusFlag.NONE_FLAG;
- public static final int VEHICLE_AUDIO_EXT_FOCUS_CAR_PERMANENT_FLAG =
- VehicleAudioExtFocusFlag.PERMANENT_FLAG;
- public static final int VEHICLE_AUDIO_EXT_FOCUS_CAR_TRANSIENT_FLAG =
- VehicleAudioExtFocusFlag.TRANSIENT_FLAG;
- public static final int VEHICLE_AUDIO_EXT_FOCUS_CAR_PLAY_ONLY_FLAG =
- VehicleAudioExtFocusFlag.PLAY_ONLY_FLAG;
- public static final int VEHICLE_AUDIO_EXT_FOCUS_CAR_MUTE_MEDIA_FLAG =
- VehicleAudioExtFocusFlag.MUTE_MEDIA_FLAG;
-
- public static final int STREAM_NUM_DEFAULT = 0;
-
- public static final int FOCUS_STATE_ARRAY_INDEX_STATE =
- VehicleAudioFocusIndex.FOCUS;
- public static final int FOCUS_STATE_ARRAY_INDEX_STREAMS =
- VehicleAudioFocusIndex.STREAMS;
- public static final int FOCUS_STATE_ARRAY_INDEX_EXTERNAL_FOCUS =
- VehicleAudioFocusIndex.EXTERNAL_FOCUS_STATE;
-
- public static final int AUDIO_CONTEXT_MUSIC_FLAG =
- VehicleAudioContextFlag.MUSIC_FLAG;
- public static final int AUDIO_CONTEXT_NAVIGATION_FLAG =
- VehicleAudioContextFlag.NAVIGATION_FLAG;
- public static final int AUDIO_CONTEXT_VOICE_COMMAND_FLAG =
- VehicleAudioContextFlag.VOICE_COMMAND_FLAG;
- public static final int AUDIO_CONTEXT_CALL_FLAG =
- VehicleAudioContextFlag.CALL_FLAG;
- public static final int AUDIO_CONTEXT_ALARM_FLAG =
- VehicleAudioContextFlag.ALARM_FLAG;
- public static final int AUDIO_CONTEXT_NOTIFICATION_FLAG =
- VehicleAudioContextFlag.NOTIFICATION_FLAG;
- public static final int AUDIO_CONTEXT_UNKNOWN_FLAG =
- VehicleAudioContextFlag.UNKNOWN_FLAG;
- public static final int AUDIO_CONTEXT_SAFETY_ALERT_FLAG =
- VehicleAudioContextFlag.SAFETY_ALERT_FLAG;
- public static final int AUDIO_CONTEXT_RADIO_FLAG =
- VehicleAudioContextFlag.RADIO_FLAG;
- public static final int AUDIO_CONTEXT_CD_ROM_FLAG =
- VehicleAudioContextFlag.CD_ROM_FLAG;
- public static final int AUDIO_CONTEXT_AUX_AUDIO_FLAG =
- VehicleAudioContextFlag.AUX_AUDIO_FLAG;
- public static final int AUDIO_CONTEXT_SYSTEM_SOUND_FLAG =
- VehicleAudioContextFlag.SYSTEM_SOUND_FLAG;
- public static final int AUDIO_CONTEXT_EXT_SOURCE_FLAG =
- VehicleAudioContextFlag.EXT_SOURCE_FLAG;
- public static final int AUDIO_CONTEXT_RINGTONE_FLAG =
- VehicleAudioContextFlag.RINGTONE_FLAG;
-
- public interface AudioHalFocusListener {
- /**
- * Audio focus change from car.
- * @param focusState
- * @param streams
- * @param externalFocus Flags of active external audio focus.
- * 0 means no external audio focus.
- */
- void onFocusChange(int focusState, int streams, int externalFocus);
- /**
- * Stream state change (start / stop) from android
- * @param streamNumber stream number like 0, 1, ...
- * @param streamActive Whether the stream is active or not.
- */
- void onStreamStatusChange(int streamNumber, boolean streamActive);
- }
-
- public interface AudioHalVolumeListener {
- /**
- * Audio volume change from car.
- * @param streamNumber
- * @param volume
- * @param volumeState
- */
- void onVolumeChange(int streamNumber, int volume, int volumeState);
- /**
- * Volume limit change from car.
- * @param streamNumber
- * @param volume
- */
- void onVolumeLimitChange(int streamNumber, int volume);
- }
-
- private static final boolean DBG = false;
-
- private final VehicleHal mVehicleHal;
- private AudioHalFocusListener mFocusListener;
- private AudioHalVolumeListener mVolumeListener;
- private int mVariant;
-
- private final HashMap<Integer, VehiclePropConfig> mProperties = new HashMap<>();
-
- private OnParameterChangeListener mOnParameterChangeListener;
-
- public AudioHalService(VehicleHal vehicleHal) {
- mVehicleHal = vehicleHal;
- }
-
- public synchronized void setFocusListener(AudioHalFocusListener focusListener) {
- mFocusListener = focusListener;
- }
-
- public synchronized void setVolumeListener(AudioHalVolumeListener volumeListener) {
- mVolumeListener = volumeListener;
- }
-
- public void setAudioRoutingPolicy(AudioRoutingPolicy policy) {
- if (!mVehicleHal.isPropertySupported(VehicleProperty.AUDIO_ROUTING_POLICY)) {
- Log.w(CarLog.TAG_AUDIO,
- "Vehicle HAL did not implement VehicleProperty.AUDIO_ROUTING_POLICY");
- return;
- }
- int[] policyToSet = new int[2];
- for (int i = 0; i < policy.getPhysicalStreamsCount(); i++) {
- policyToSet[VehicleAudioRoutingPolicyIndex.STREAM] = i;
- int contexts = 0;
- for (int logicalStream : policy.getLogicalStreamsForPhysicalStream(i)) {
- contexts |= logicalStreamToHalContextType(logicalStream);
- }
- policyToSet[VehicleAudioRoutingPolicyIndex.CONTEXTS] = contexts;
- try {
- mVehicleHal.set(AUDIO_ROUTING_POLICY).to(policyToSet);
- } catch (PropertyTimeoutException e) {
- Log.e(CarLog.TAG_AUDIO, "Cannot write to VehicleProperty.AUDIO_ROUTING_POLICY", e);
- }
- }
- }
-
- /**
- * Returns the volume limits of a stream. Returns null if max value wasn't defined for
- * AUDIO_VOLUME property.
- */
- @Nullable
- public synchronized Integer getStreamMaxVolume(int stream) {
- VehiclePropConfig config = mProperties.get(VehicleProperty.AUDIO_VOLUME);
- if (config == null) {
- throw new IllegalStateException("VehicleProperty.AUDIO_VOLUME not supported");
- }
- int supportedContext = getSupportedAudioVolumeContexts();
-
- int MAX_VALUES_FIRST_ELEMENT_INDEX = 4;
- ArrayList<Integer> maxValues = new ArrayList<>();
- for (int i = MAX_VALUES_FIRST_ELEMENT_INDEX; i < config.configArray.size(); i++) {
- maxValues.add(config.configArray.get(i));
- }
-
- Integer result = null;
- if (supportedContext != 0) {
- int index = VehicleZoneUtil.zoneToIndex(supportedContext, stream);
- if (index < maxValues.size()) {
- result = maxValues.get(index);
- }
- } else {
- if (stream < maxValues.size()) {
- result = maxValues.get(stream);
- }
- }
-
- if (result == null) {
- Log.e(CarLog.TAG_AUDIO, "No min/max volume found in vehicle" +
- " prop config for stream: " + stream);
- }
-
- return result;
- }
-
- /**
- * Convert car audio manager stream type (usage) into audio context type.
- */
- public static int logicalStreamToHalContextType(int logicalStream) {
- return logicalStreamWithExtTypeToHalContextType(logicalStream, null);
- }
-
- public static int logicalStreamWithExtTypeToHalContextType(int logicalStream, String extType) {
- switch (logicalStream) {
- case CarAudioManager.CAR_AUDIO_USAGE_RADIO:
- return VehicleAudioContextFlag.RADIO_FLAG;
- case CarAudioManager.CAR_AUDIO_USAGE_VOICE_CALL:
- return VehicleAudioContextFlag.CALL_FLAG;
- case CarAudioManager.CAR_AUDIO_USAGE_RINGTONE:
- return VehicleAudioContextFlag.RINGTONE_FLAG;
- case CarAudioManager.CAR_AUDIO_USAGE_MUSIC:
- return VehicleAudioContextFlag.MUSIC_FLAG;
- case CarAudioManager.CAR_AUDIO_USAGE_NAVIGATION_GUIDANCE:
- return VehicleAudioContextFlag.NAVIGATION_FLAG;
- case CarAudioManager.CAR_AUDIO_USAGE_VOICE_COMMAND:
- return VehicleAudioContextFlag.VOICE_COMMAND_FLAG;
- case CarAudioManager.CAR_AUDIO_USAGE_ALARM:
- return VehicleAudioContextFlag.ALARM_FLAG;
- case CarAudioManager.CAR_AUDIO_USAGE_NOTIFICATION:
- return VehicleAudioContextFlag.NOTIFICATION_FLAG;
- case CarAudioManager.CAR_AUDIO_USAGE_SYSTEM_SAFETY_ALERT:
- return VehicleAudioContextFlag.SAFETY_ALERT_FLAG;
- case CarAudioManager.CAR_AUDIO_USAGE_SYSTEM_SOUND:
- return VehicleAudioContextFlag.SYSTEM_SOUND_FLAG;
- case CarAudioManager.CAR_AUDIO_USAGE_DEFAULT:
- return VehicleAudioContextFlag.UNKNOWN_FLAG;
- case CarAudioManager.CAR_AUDIO_USAGE_EXTERNAL_AUDIO_SOURCE:
- if (extType != null) {
- switch (extType) {
- case CarAudioManager.CAR_EXTERNAL_SOURCE_TYPE_CD_DVD:
- return VehicleAudioContextFlag.CD_ROM_FLAG;
- case CarAudioManager.CAR_EXTERNAL_SOURCE_TYPE_AUX_IN0:
- case CarAudioManager.CAR_EXTERNAL_SOURCE_TYPE_AUX_IN1:
- return VehicleAudioContextFlag.AUX_AUDIO_FLAG;
- default:
- if (extType.startsWith("RADIO_")) {
- return VehicleAudioContextFlag.RADIO_FLAG;
- } else {
- return VehicleAudioContextFlag.EXT_SOURCE_FLAG;
- }
- }
- } else { // no external source specified. fall back to radio
- return VehicleAudioContextFlag.RADIO_FLAG;
- }
- case CarAudioAttributesUtil.CAR_AUDIO_USAGE_CARSERVICE_BOTTOM:
- case CarAudioAttributesUtil.CAR_AUDIO_USAGE_CARSERVICE_CAR_PROXY:
- case CarAudioAttributesUtil.CAR_AUDIO_USAGE_CARSERVICE_MEDIA_MUTE:
- // internal tag not associated with any stream
- return 0;
- default:
- Log.w(CarLog.TAG_AUDIO, "Unknown logical stream:" + logicalStream);
- return 0;
- }
- }
-
- /**
- * Converts car audio context type to car stream usage.
- */
- public static int carContextToCarUsage(int carContext) {
- switch (carContext) {
- case VehicleAudioContextFlag.MUSIC_FLAG:
- return CarAudioManager.CAR_AUDIO_USAGE_MUSIC;
- case VehicleAudioContextFlag.NAVIGATION_FLAG:
- return CarAudioManager.CAR_AUDIO_USAGE_NAVIGATION_GUIDANCE;
- case VehicleAudioContextFlag.ALARM_FLAG:
- return CarAudioManager.CAR_AUDIO_USAGE_ALARM;
- case VehicleAudioContextFlag.VOICE_COMMAND_FLAG:
- return CarAudioManager.CAR_AUDIO_USAGE_VOICE_COMMAND;
- case VehicleAudioContextFlag.AUX_AUDIO_FLAG:
- return CarAudioManager.CAR_AUDIO_USAGE_EXTERNAL_AUDIO_SOURCE;
- case VehicleAudioContextFlag.CALL_FLAG:
- return CarAudioManager.CAR_AUDIO_USAGE_VOICE_CALL;
- case VehicleAudioContextFlag.RINGTONE_FLAG:
- return CarAudioManager.CAR_AUDIO_USAGE_RINGTONE;
- case VehicleAudioContextFlag.CD_ROM_FLAG:
- return CarAudioManager.CAR_AUDIO_USAGE_EXTERNAL_AUDIO_SOURCE;
- case VehicleAudioContextFlag.NOTIFICATION_FLAG:
- return CarAudioManager.CAR_AUDIO_USAGE_NOTIFICATION;
- case VehicleAudioContextFlag.RADIO_FLAG:
- return CarAudioManager.CAR_AUDIO_USAGE_RADIO;
- case VehicleAudioContextFlag.SAFETY_ALERT_FLAG:
- return CarAudioManager.CAR_AUDIO_USAGE_SYSTEM_SAFETY_ALERT;
- case VehicleAudioContextFlag.SYSTEM_SOUND_FLAG:
- return CarAudioManager.CAR_AUDIO_USAGE_SYSTEM_SOUND;
- case VehicleAudioContextFlag.UNKNOWN_FLAG:
- return CarAudioManager.CAR_AUDIO_USAGE_DEFAULT;
- case VehicleAudioContextFlag.EXT_SOURCE_FLAG:
- return CarAudioManager.CAR_AUDIO_USAGE_EXTERNAL_AUDIO_SOURCE;
- default:
- Log.w(CarLog.TAG_AUDIO, "Unknown car context:" + carContext);
- return 0;
- }
- }
-
- public void requestAudioFocusChange(int request, int streams, int audioContexts) {
- requestAudioFocusChange(request, streams, VEHICLE_AUDIO_EXT_FOCUS_NONE_FLAG, audioContexts);
- }
-
- public void requestAudioFocusChange(int request, int streams, int extFocus, int audioContexts) {
- int[] payload = { request, streams, extFocus, audioContexts };
- try {
- mVehicleHal.set(AUDIO_FOCUS).to(payload);
- } catch (PropertyTimeoutException e) {
- Log.e(CarLog.TAG_AUDIO, "Cannot write to VehicleProperty.AUDIO_FOCUS", e);
- // focus timeout will reset it anyway
- }
- }
-
- public void setStreamVolume(int streamType, int index) {
- int[] payload = {streamType, index, 0};
- try {
- mVehicleHal.set(VehicleProperty.AUDIO_VOLUME).to(payload);
- } catch (PropertyTimeoutException e) {
- Log.e(CarLog.TAG_AUDIO, "Cannot write to VehicleProperty.AUDIO_VOLUME", e);
- //TODO should reset volume, bug: 32096870
- }
- }
-
- public int getStreamVolume(int stream) {
- int[] volume = {stream, 0, 0};
- VehiclePropValue requestedStreamVolume = new VehiclePropValue();
- requestedStreamVolume.prop = VehicleProperty.AUDIO_VOLUME;
- requestedStreamVolume.value.int32Values.addAll(Arrays.asList(stream, 0 , 0));
- VehiclePropValue propValue;
- try {
- propValue = mVehicleHal.get(requestedStreamVolume);
- } catch (PropertyTimeoutException e) {
- Log.e(CarLog.TAG_AUDIO, "VehicleProperty.AUDIO_VOLUME not ready", e);
- return 0;
- }
-
- if (propValue.value.int32Values.size() != 3) {
- Log.e(CarLog.TAG_AUDIO, "returned value not valid");
- throw new IllegalStateException("Invalid preset returned from service: "
- + Arrays.toString(propValue.value.int32Values.toArray()));
- }
-
- int retStreamNum = propValue.value.int32Values.get(0);
- int retVolume = propValue.value.int32Values.get(1);
- int retVolumeState = propValue.value.int32Values.get(2);
-
- if (retStreamNum != stream) {
- Log.e(CarLog.TAG_AUDIO, "Stream number is not the same: "
- + stream + " vs " + retStreamNum);
- throw new IllegalStateException("Stream number is not the same");
- }
- return retVolume;
- }
-
- public synchronized int getHwVariant() {
- return mVariant;
- }
-
- public synchronized boolean isRadioExternal() {
- VehiclePropConfig config = mProperties.get(VehicleProperty.AUDIO_HW_VARIANT);
- if (config == null) {
- return true;
- }
- return (config.configArray.get(0)
- & VehicleAudioHwVariantConfigFlag.INTERNAL_RADIO_FLAG) == 0;
- }
-
- public synchronized boolean isFocusSupported() {
- return isPropertySupportedLocked(AUDIO_FOCUS);
- }
-
- public synchronized boolean isAudioVolumeSupported() {
- return isPropertySupportedLocked(VehicleProperty.AUDIO_VOLUME);
- }
-
- public synchronized int getSupportedAudioVolumeContexts() {
- if (!isPropertySupportedLocked(VehicleProperty.AUDIO_VOLUME)) {
- throw new IllegalStateException("VehicleProperty.AUDIO_VOLUME not supported");
- }
- VehiclePropConfig config = mProperties.get(VehicleProperty.AUDIO_VOLUME);
- return config.configArray.get(0);
- }
-
- /**
- * Whether external audio module can memorize logical audio volumes or not.
- * @return
- */
- public synchronized boolean isExternalAudioVolumePersistent() {
- if (!isPropertySupportedLocked(VehicleProperty.AUDIO_VOLUME)) {
- throw new IllegalStateException("VehicleProperty.AUDIO_VOLUME not supported");
- }
- VehiclePropConfig config = mProperties.get(VehicleProperty.AUDIO_VOLUME);
- if (config.configArray.get(0) == 0) { // physical streams only
- return false;
- }
- if ((config.configArray.get(1)
- & VehicleAudioVolumeCapabilityFlag.PERSISTENT_STORAGE) != 0) {
- return true;
- }
- return false;
- }
-
- public synchronized boolean isAudioVolumeLimitSupported() {
- return isPropertySupportedLocked(AUDIO_VOLUME_LIMIT);
- }
-
- public synchronized boolean isAudioVolumeMasterOnly() {
- if (!isPropertySupportedLocked(VehicleProperty.AUDIO_VOLUME)) {
- throw new IllegalStateException("VehicleProperty.AUDIO_VOLUME not supported");
- }
- VehiclePropConfig config = mProperties.get(
- AUDIO_VOLUME);
- if ((config.configArray.get(1) &
- VehicleAudioVolumeCapabilityFlag.MASTER_VOLUME_ONLY)
- != 0) {
- return true;
- }
- return false;
- }
-
- /**
- * Get the current audio focus state.
- * @return 0: focusState, 1: streams, 2: externalFocus
- */
- public int[] getCurrentFocusState() {
- if (!isFocusSupported()) {
- return new int[] { VEHICLE_AUDIO_FOCUS_STATE_GAIN, 0xffffffff, 0};
- }
- try {
- VehiclePropValue propValue = mVehicleHal.get(VehicleProperty.AUDIO_FOCUS);
- return toIntArray(propValue.value.int32Values);
- } catch (PropertyTimeoutException e) {
- Log.e(CarLog.TAG_AUDIO, "VehicleProperty.AUDIO_FOCUS not ready", e);
- return new int[] { VEHICLE_AUDIO_FOCUS_STATE_LOSS, 0x0, 0};
- }
- }
-
- public static class ExtRoutingSourceInfo {
- /** Represents an external route which will not disable any physical stream in android side.
- */
- public static final int NO_DISABLED_PHYSICAL_STREAM = -1;
-
- /** Bit position of this source in vhal */
- public final int bitPosition;
- /**
- * Physical stream replaced by this routing. will be {@link #NO_DISABLED_PHYSICAL_STREAM}
- * if no physical stream for android is replaced by this routing.
- */
- public final int physicalStreamNumber;
-
- public ExtRoutingSourceInfo(int bitPosition, int physycalStreamNumber) {
- this.bitPosition = bitPosition;
- this.physicalStreamNumber = physycalStreamNumber;
- }
-
- @Override
- public String toString() {
- return "[bitPosition=" + bitPosition + ", physicalStreamNumber="
- + physicalStreamNumber + "]";
- }
- }
-
- /**
- * Get external audio routing types from AUDIO_EXT_ROUTING_HINT property.
- *
- * @return null if AUDIO_EXT_ROUTING_HINT is not supported.
- */
- public Map<String, ExtRoutingSourceInfo> getExternalAudioRoutingTypes() {
- VehiclePropConfig config;
- synchronized (this) {
- if (!isPropertySupportedLocked(AUDIO_EXT_ROUTING_HINT)) {
- if (DBG) {
- Log.i(CarLog.TAG_AUDIO, "AUDIO_EXT_ROUTING_HINT is not supported");
- }
- return null;
- }
- config = mProperties.get(AUDIO_EXT_ROUTING_HINT);
- }
- if (TextUtils.isEmpty(config.configString)) {
- Log.w(CarLog.TAG_AUDIO, "AUDIO_EXT_ROUTING_HINT with empty config string");
- return null;
- }
- Map<String, ExtRoutingSourceInfo> routingTypes = new HashMap<>();
- String configString = config.configString;
- if (DBG) {
- Log.i(CarLog.TAG_AUDIO, "AUDIO_EXT_ROUTING_HINT config string:" + configString);
- }
- String[] routes = configString.split(",");
- for (String routeString : routes) {
- String[] tokens = routeString.split(":");
- int bitPosition = 0;
- String name = null;
- int physicalStreamNumber = ExtRoutingSourceInfo.NO_DISABLED_PHYSICAL_STREAM;
- if (tokens.length == 2) {
- bitPosition = Integer.parseInt(tokens[0]);
- name = tokens[1];
- } else if (tokens.length == 3) {
- bitPosition = Integer.parseInt(tokens[0]);
- name = tokens[1];
- physicalStreamNumber = Integer.parseInt(tokens[2]);
- } else {
- Log.w(CarLog.TAG_AUDIO, "AUDIO_EXT_ROUTING_HINT has wrong entry:" +
- routeString);
- continue;
- }
- routingTypes.put(name, new ExtRoutingSourceInfo(bitPosition, physicalStreamNumber));
- }
- return routingTypes;
- }
-
- public void setExternalRoutingSource(int[] externalRoutings) {
- try {
- mVehicleHal.set(AUDIO_EXT_ROUTING_HINT).to(externalRoutings);
- } catch (PropertyTimeoutException e) {
- Log.e(CarLog.TAG_AUDIO, "Cannot write to VehicleProperty.AUDIO_EXT_ROUTING_HINT", e);
- }
- }
-
- private boolean isPropertySupportedLocked(int property) {
- VehiclePropConfig config = mProperties.get(property);
- return config != null;
- }
-
- @Override
- public synchronized void init() {
- for (VehiclePropConfig config : mProperties.values()) {
- if (VehicleHal.isPropertySubscribable(config)) {
- int subsribeFlag = SubscribeFlags.HAL_EVENT;
- if (AUDIO_STREAM_STATE == config.prop) {
- subsribeFlag |= SubscribeFlags.SET_CALL;
- }
- mVehicleHal.subscribeProperty(this, config.prop, 0, subsribeFlag);
- }
- }
- try {
- mVariant = mVehicleHal.get(int.class, AUDIO_HW_VARIANT);
- } catch (IllegalArgumentException e) {
- // no variant. Set to default, 0.
- mVariant = 0;
- } catch (PropertyTimeoutException e) {
- Log.e(CarLog.TAG_AUDIO, "VehicleProperty.AUDIO_HW_VARIANT not ready", e);
- mVariant = 0;
- }
- }
-
- @Override
- public synchronized void release() {
- for (VehiclePropConfig config : mProperties.values()) {
- if (VehicleHal.isPropertySubscribable(config)) {
- mVehicleHal.unsubscribeProperty(this, config.prop);
- }
- }
- mProperties.clear();
- }
-
- @Override
- public synchronized Collection<VehiclePropConfig> takeSupportedProperties(
- Collection<VehiclePropConfig> allProperties) {
- for (VehiclePropConfig p : allProperties) {
- switch (p.prop) {
- case VehicleProperty.AUDIO_FOCUS:
- case VehicleProperty.AUDIO_VOLUME:
- case VehicleProperty.AUDIO_VOLUME_LIMIT:
- case VehicleProperty.AUDIO_HW_VARIANT:
- case VehicleProperty.AUDIO_EXT_ROUTING_HINT:
- case VehicleProperty.AUDIO_PARAMETERS:
- case VehicleProperty.AUDIO_STREAM_STATE:
- mProperties.put(p.prop, p);
- break;
- }
- }
- return new ArrayList<>(mProperties.values());
- }
-
- @Override
- public void handleHalEvents(List<VehiclePropValue> values) {
- AudioHalFocusListener focusListener;
- AudioHalVolumeListener volumeListener;
- OnParameterChangeListener parameterListener;
- synchronized (this) {
- focusListener = mFocusListener;
- volumeListener = mVolumeListener;
- parameterListener = mOnParameterChangeListener;
- }
- dispatchEventToListener(focusListener, volumeListener, parameterListener, values);
- }
-
- public String[] getAudioParameterKeys() {
- VehiclePropConfig config;
- synchronized (this) {
- if (!isPropertySupportedLocked(AUDIO_PARAMETERS)) {
- if (DBG) {
- Log.i(CarLog.TAG_AUDIO, "AUDIO_PARAMETERS is not supported");
- }
- return null;
- }
- config = mProperties.get(AUDIO_PARAMETERS);
- }
- return config.configString.split(";");
- }
-
- public void setAudioParameters(String parameters) {
- synchronized (this) {
- if (!isPropertySupportedLocked(AUDIO_PARAMETERS)) {
- throw new IllegalStateException("VehicleProperty.AUDIO_PARAMETERS not supported");
- }
- }
- VehiclePropValue value = new VehiclePropValue();
- value.prop = AUDIO_PARAMETERS;
- value.value.stringValue = parameters;
- try {
- mVehicleHal.set(value);
- } catch (PropertyTimeoutException e) {
- Log.e(CarLog.TAG_AUDIO, "Cannot write to VehicleProperty.AUDIO_EXT_ROUTING_HINT", e);
- }
- }
-
- public String getAudioParameters(String keys) {
- synchronized (this) {
- if (!isPropertySupportedLocked(AUDIO_PARAMETERS)) {
- throw new IllegalStateException("VehicleProperty.AUDIO_PARAMETERS not supported");
- }
- }
- try {
- VehiclePropValue requested = new VehiclePropValue();
- requested.prop = AUDIO_PARAMETERS;
- requested.value.stringValue = keys;
- VehiclePropValue propValue = mVehicleHal.get(requested);
- return propValue.value.stringValue;
- } catch (PropertyTimeoutException e) {
- Log.e(CarLog.TAG_AUDIO, "VehicleProperty.AUDIO_PARAMETERS not ready", e);
- return new String("");
- }
- }
-
- public synchronized void setOnParameterChangeListener(OnParameterChangeListener listener) {
- mOnParameterChangeListener = listener;
- }
-
- private void dispatchEventToListener(AudioHalFocusListener focusListener,
- AudioHalVolumeListener volumeListener,
- OnParameterChangeListener parameterListener,
- List<VehiclePropValue> values) {
- for (VehiclePropValue v : values) {
- switch (v.prop) {
- case VehicleProperty.AUDIO_FOCUS: {
- ArrayList<Integer> vec = v.value.int32Values;
- int focusState = vec.get(VehicleAudioFocusIndex.FOCUS);
- int streams = vec.get(VehicleAudioFocusIndex.STREAMS);
- int externalFocus = vec.get(VehicleAudioFocusIndex.EXTERNAL_FOCUS_STATE);
- if (focusListener != null) {
- focusListener.onFocusChange(focusState, streams, externalFocus);
- }
- } break;
- case VehicleProperty.AUDIO_STREAM_STATE: {
- ArrayList<Integer> vec = v.value.int32Values;
- boolean streamStarted = vec.get(0) == VEHICLE_AUDIO_STREAM_STATE_STARTED;
- int streamNum = vec.get(1);
- if (focusListener != null) {
- focusListener.onStreamStatusChange(streamNum, streamStarted);
- }
- } break;
- case AUDIO_VOLUME: {
- ArrayList<Integer> vec = v.value.int32Values;
- int streamNum = vec.get(VehicleAudioVolumeIndex.STREAM);
- int volume = vec.get(VehicleAudioVolumeIndex.VOLUME);
- int volumeState = vec.get(VehicleAudioVolumeIndex.STATE);
- if (volumeListener != null) {
- volumeListener.onVolumeChange(streamNum, volume, volumeState);
- }
- } break;
- case AUDIO_VOLUME_LIMIT: {
- ArrayList<Integer> vec = v.value.int32Values;
- int stream = vec.get(VehicleAudioVolumeLimitIndex.STREAM);
- int maxVolume = vec.get(VehicleAudioVolumeLimitIndex.MAX_VOLUME);
- if (volumeListener != null) {
- volumeListener.onVolumeLimitChange(stream, maxVolume);
- }
- } break;
- case AUDIO_PARAMETERS: {
- String params = v.value.stringValue;
- if (parameterListener != null) {
- parameterListener.onParameterChange(params);
- }
- }
- }
- }
- values.clear();
- }
-
- @Override
- public void dump(PrintWriter writer) {
- writer.println("*Audio HAL*");
- writer.println(" audio H/W variant:" + mVariant);
- writer.println(" Supported properties");
- VehicleHal.dumpProperties(writer, mProperties.values());
- }
-
-}
diff --git a/service/src/com/android/car/hal/CabinHalService.java b/service/src/com/android/car/hal/CabinHalService.java
deleted file mode 100644
index cfdf07e..0000000
--- a/service/src/com/android/car/hal/CabinHalService.java
+++ /dev/null
@@ -1,165 +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.hal;
-
-import android.car.hardware.cabin.CarCabinManager;
-import android.hardware.automotive.vehicle.V2_0.VehicleProperty;
-
-public class CabinHalService extends PropertyHalServiceBase {
- private static final boolean DBG = false;
- private static final String TAG = "CAR.CABIN.HAL";
-
- private final ManagerToHalPropIdMap mMgrHalPropIdMap = ManagerToHalPropIdMap.create(
- CarCabinManager.ID_DOOR_POS,
- VehicleProperty.DOOR_POS,
-
- CarCabinManager.ID_DOOR_MOVE,
- VehicleProperty.DOOR_MOVE,
-
- CarCabinManager.ID_DOOR_LOCK,
- VehicleProperty.DOOR_LOCK,
-
- CarCabinManager.ID_MIRROR_Z_POS,
- VehicleProperty.MIRROR_Z_POS,
-
- CarCabinManager.ID_MIRROR_Z_MOVE,
- VehicleProperty.MIRROR_Z_MOVE,
-
- CarCabinManager.ID_MIRROR_Y_POS,
- VehicleProperty.MIRROR_Y_POS,
-
- CarCabinManager.ID_MIRROR_Y_MOVE,
- VehicleProperty.MIRROR_Y_MOVE,
-
- CarCabinManager.ID_MIRROR_LOCK,
- VehicleProperty.MIRROR_LOCK,
-
- CarCabinManager.ID_MIRROR_FOLD,
- VehicleProperty.MIRROR_FOLD,
-
- CarCabinManager.ID_SEAT_MEMORY_SELECT,
- VehicleProperty.SEAT_MEMORY_SELECT,
-
- CarCabinManager.ID_SEAT_MEMORY_SET,
- VehicleProperty.SEAT_MEMORY_SET,
-
- CarCabinManager.ID_SEAT_BELT_BUCKLED,
- VehicleProperty.SEAT_BELT_BUCKLED,
-
- CarCabinManager.ID_SEAT_BELT_HEIGHT_POS,
- VehicleProperty.SEAT_BELT_HEIGHT_POS,
-
- CarCabinManager.ID_SEAT_BELT_HEIGHT_MOVE,
- VehicleProperty.SEAT_BELT_HEIGHT_MOVE,
-
- CarCabinManager.ID_SEAT_FORE_AFT_POS,
- VehicleProperty.SEAT_FORE_AFT_POS,
-
- CarCabinManager.ID_SEAT_FORE_AFT_MOVE,
- VehicleProperty.SEAT_FORE_AFT_MOVE,
-
- CarCabinManager.ID_SEAT_BACKREST_ANGLE_1_POS,
- VehicleProperty.SEAT_BACKREST_ANGLE_1_POS,
-
- CarCabinManager.ID_SEAT_BACKREST_ANGLE_1_MOVE,
- VehicleProperty.SEAT_BACKREST_ANGLE_1_MOVE,
-
- CarCabinManager.ID_SEAT_BACKREST_ANGLE_2_POS,
- VehicleProperty.SEAT_BACKREST_ANGLE_2_POS,
-
- CarCabinManager.ID_SEAT_BACKREST_ANGLE_2_MOVE,
- VehicleProperty.SEAT_BACKREST_ANGLE_2_MOVE,
-
- CarCabinManager.ID_SEAT_HEIGHT_POS,
- VehicleProperty.SEAT_HEIGHT_POS,
-
- CarCabinManager.ID_SEAT_HEIGHT_MOVE,
- VehicleProperty.SEAT_HEIGHT_MOVE,
-
- CarCabinManager.ID_SEAT_DEPTH_POS,
- VehicleProperty.SEAT_DEPTH_POS,
-
- CarCabinManager.ID_SEAT_DEPTH_MOVE,
- VehicleProperty.SEAT_DEPTH_MOVE,
-
- CarCabinManager.ID_SEAT_TILT_POS,
- VehicleProperty.SEAT_TILT_POS,
-
- CarCabinManager.ID_SEAT_TILT_MOVE,
- VehicleProperty.SEAT_TILT_MOVE,
-
- CarCabinManager.ID_SEAT_LUMBAR_FORE_AFT_POS,
- VehicleProperty.SEAT_LUMBAR_FORE_AFT_POS,
-
- CarCabinManager.ID_SEAT_LUMBAR_FORE_AFT_MOVE,
- VehicleProperty.SEAT_LUMBAR_FORE_AFT_MOVE,
-
- CarCabinManager.ID_SEAT_LUMBAR_SIDE_SUPPORT_POS,
- VehicleProperty.SEAT_LUMBAR_SIDE_SUPPORT_POS,
-
- CarCabinManager.ID_SEAT_LUMBAR_SIDE_SUPPORT_MOVE,
- VehicleProperty.SEAT_LUMBAR_SIDE_SUPPORT_MOVE,
-
- CarCabinManager.ID_SEAT_HEADREST_HEIGHT_POS,
- VehicleProperty.SEAT_HEADREST_HEIGHT_POS,
-
- CarCabinManager.ID_SEAT_HEADREST_HEIGHT_MOVE,
- VehicleProperty.SEAT_HEADREST_HEIGHT_MOVE,
-
- CarCabinManager.ID_SEAT_HEADREST_ANGLE_POS,
- VehicleProperty.SEAT_HEADREST_ANGLE_POS,
-
- CarCabinManager.ID_SEAT_HEADREST_ANGLE_MOVE,
- VehicleProperty.SEAT_HEADREST_ANGLE_MOVE,
-
- CarCabinManager.ID_SEAT_HEADREST_FORE_AFT_POS,
- VehicleProperty.SEAT_HEADREST_FORE_AFT_POS,
-
- CarCabinManager.ID_SEAT_HEADREST_FORE_AFT_MOVE,
- VehicleProperty.SEAT_HEADREST_FORE_AFT_MOVE,
-
- CarCabinManager.ID_WINDOW_POS,
- VehicleProperty.WINDOW_POS,
-
- CarCabinManager.ID_WINDOW_MOVE,
- VehicleProperty.WINDOW_MOVE,
-
- CarCabinManager.ID_WINDOW_VENT_POS,
- VehicleProperty.WINDOW_VENT_POS,
-
- CarCabinManager.ID_WINDOW_VENT_MOVE,
- VehicleProperty.WINDOW_VENT_MOVE,
-
- CarCabinManager.ID_WINDOW_LOCK,
- VehicleProperty.WINDOW_LOCK
- );
-
- public CabinHalService(VehicleHal vehicleHal) {
- super(vehicleHal, TAG, DBG);
- }
-
- // Convert the Cabin public API property ID to HAL property ID
- @Override
- protected int managerToHalPropId(int propId) {
- return mMgrHalPropIdMap.getHalPropId(propId);
- }
-
- // Convert he HAL specific property ID to Cabin public API
- @Override
- protected int halToManagerPropId(int halPropId) {
- return mMgrHalPropIdMap.getManagerPropId(halPropId);
- }
-}
diff --git a/service/src/com/android/car/hal/CarPropertyUtils.java b/service/src/com/android/car/hal/CarPropertyUtils.java
index 6229511..d9151e2 100644
--- a/service/src/com/android/car/hal/CarPropertyUtils.java
+++ b/service/src/com/android/car/hal/CarPropertyUtils.java
@@ -16,10 +16,10 @@
package com.android.car.hal;
import static com.android.car.CarServiceUtils.toByteArray;
+
import static java.lang.Integer.toHexString;
import android.car.VehicleAreaType;
-import android.car.VehicleZoneUtil;
import android.car.hardware.CarPropertyConfig;
import android.car.hardware.CarPropertyValue;
import android.hardware.automotive.vehicle.V2_0.VehicleArea;
@@ -44,20 +44,33 @@
VehiclePropValue halValue, int propertyId) {
Class<?> clazz = getJavaClass(halValue.prop & VehiclePropertyType.MASK);
int areaId = halValue.areaId;
+ int status = halValue.status;
+ long timestamp = halValue.timestamp;
VehiclePropValue.RawValue v = halValue.value;
if (Boolean.class == clazz) {
- return new CarPropertyValue<>(propertyId, areaId, v.int32Values.get(0) == 1);
+ return new CarPropertyValue<>(propertyId, areaId, status, timestamp,
+ v.int32Values.get(0) == 1);
+ } else if (Boolean[].class == clazz) {
+ Boolean[] values = new Boolean[v.int32Values.size()];
+ for (int i = 0; i < values.length; i++) {
+ values[i] = v.int32Values.get(i) == 1;
+ }
+ return new CarPropertyValue<>(propertyId, areaId, status, timestamp, values);
} else if (String.class == clazz) {
- return new CarPropertyValue<>(propertyId, areaId, v.stringValue);
- } else if (Long.class == clazz) {
- return new CarPropertyValue<>(propertyId, areaId, v.int64Values.get(0));
+ return new CarPropertyValue<>(propertyId, areaId, status, timestamp, v.stringValue);
} else if (byte[].class == clazz) {
byte[] halData = toByteArray(v.bytes);
- return new CarPropertyValue<>(propertyId, areaId, halData);
+ return new CarPropertyValue<>(propertyId, areaId, status, timestamp, halData);
+ } else if (Long[].class == clazz) {
+ Long[] values = new Long[v.int64Values.size()];
+ for (int i = 0; i < values.length; i++) {
+ values[i] = v.int64Values.get(i);
+ }
+ return new CarPropertyValue<>(propertyId, areaId, status, timestamp, values);
} else /* All list properties */ {
Object[] values = getRawValueList(clazz, v).toArray();
- return new CarPropertyValue<>(propertyId, areaId,
+ return new CarPropertyValue<>(propertyId, areaId, status, timestamp,
values.length == 1 ? values[0] : values);
}
}
@@ -72,15 +85,23 @@
Object o = carProp.getValue();
if (o instanceof Boolean) {
- v.int32Values.add(((Boolean )o) ? 1 : 0);
+ v.int32Values.add(((Boolean) o) ? 1 : 0);
+ } else if (o instanceof Boolean[]) {
+ for (Boolean b : (Boolean[]) o) {
+ v.int32Values.add(((Boolean) o) ? 1 : 0);
+ }
} else if (o instanceof Integer) {
v.int32Values.add((Integer) o);
- } else if (o instanceof Float) {
- v.floatValues.add((Float) o);
} else if (o instanceof Integer[]) {
Collections.addAll(v.int32Values, (Integer[]) o);
+ } else if (o instanceof Float) {
+ v.floatValues.add((Float) o);
} else if (o instanceof Float[]) {
Collections.addAll(v.floatValues, (Float[]) o);
+ } else if (o instanceof Long) {
+ v.int64Values.add((Long) o);
+ } else if (o instanceof Long[]) {
+ Collections.addAll(v.int64Values, (Long[]) o);
} else if (o instanceof String) {
v.stringValue = (String) o;
} else if (o instanceof byte[]) {
@@ -98,19 +119,34 @@
* Converts {@link VehiclePropConfig} to {@link CarPropertyConfig}.
*/
static CarPropertyConfig<?> toCarPropertyConfig(VehiclePropConfig p, int propertyId) {
- int[] areas = VehicleZoneUtil.listAllZones(p.supportedAreas);
-
int areaType = getVehicleAreaType(p.prop & VehicleArea.MASK);
+ // Create list of areaIds for this property
+ int[] areas = new int[p.areaConfigs.size()];
+ for (int i=0; i<p.areaConfigs.size(); i++) {
+ areas[i] = p.areaConfigs.get(i).areaId;
+ }
Class<?> clazz = getJavaClass(p.prop & VehiclePropertyType.MASK);
if (p.areaConfigs.isEmpty()) {
return CarPropertyConfig
.newBuilder(clazz, propertyId, areaType, /* capacity */ 1)
.addAreas(areas)
+ .setAccess(p.access)
+ .setChangeMode(p.changeMode)
+ .setConfigArray(p.configArray)
+ .setConfigString(p.configString)
+ .setMaxSampleRate(p.maxSampleRate)
+ .setMinSampleRate(p.minSampleRate)
.build();
} else {
CarPropertyConfig.Builder builder = CarPropertyConfig
- .newBuilder(clazz, propertyId, areaType, /* capacity */ p.areaConfigs.size());
+ .newBuilder(clazz, propertyId, areaType, /* capacity */ p.areaConfigs.size())
+ .setAccess(p.access)
+ .setChangeMode(p.changeMode)
+ .setConfigArray(p.configArray)
+ .setConfigString(p.configString)
+ .setMaxSampleRate(p.maxSampleRate)
+ .setMinSampleRate(p.minSampleRate);
for (VehicleAreaConfig area : p.areaConfigs) {
if (classMatched(Integer.class, clazz)) {
@@ -119,10 +155,20 @@
builder.addAreaConfig(area.areaId, area.minFloatValue, area.maxFloatValue);
} else if (classMatched(Long.class, clazz)) {
builder.addAreaConfig(area.areaId, area.minInt64Value, area.maxInt64Value);
+ } else if (classMatched(Boolean.class, clazz) ||
+ classMatched(Float[].class, clazz) ||
+ classMatched(Integer[].class, clazz) ||
+ classMatched(Long[].class, clazz) ||
+ classMatched(String.class, clazz) ||
+ classMatched(byte[].class, clazz) ||
+ classMatched(Object.class, clazz)) {
+ // These property types do not have min/max values
+ builder.addArea(area.areaId);
} else {
throw new IllegalArgumentException("Unexpected type: " + clazz);
}
}
+
return builder.build();
}
}
@@ -130,9 +176,7 @@
private static @VehicleAreaType.VehicleAreaTypeValue int getVehicleAreaType(int halArea) {
switch (halArea) {
case VehicleArea.GLOBAL:
- return VehicleAreaType.VEHICLE_AREA_TYPE_NONE;
- case VehicleArea.ZONE:
- return VehicleAreaType.VEHICLE_AREA_TYPE_ZONE;
+ return VehicleAreaType.VEHICLE_AREA_TYPE_GLOBAL;
case VehicleArea.SEAT:
return VehicleAreaType.VEHICLE_AREA_TYPE_SEAT;
case VehicleArea.DOOR:
@@ -141,6 +185,8 @@
return VehicleAreaType.VEHICLE_AREA_TYPE_WINDOW;
case VehicleArea.MIRROR:
return VehicleAreaType.VEHICLE_AREA_TYPE_MIRROR;
+ case VehicleArea.WHEEL:
+ return VehicleAreaType.VEHICLE_AREA_TYPE_WHEEL;
default:
throw new RuntimeException("Unsupported area type " + halArea);
}
@@ -154,15 +200,19 @@
return Float.class;
case VehiclePropertyType.INT32:
return Integer.class;
- case VehiclePropertyType.INT32_VEC:
- return Integer[].class;
+ case VehiclePropertyType.INT64:
+ return Long.class;
case VehiclePropertyType.FLOAT_VEC:
return Float[].class;
+ case VehiclePropertyType.INT32_VEC:
+ return Integer[].class;
+ case VehiclePropertyType.INT64_VEC:
+ return Long[].class;
case VehiclePropertyType.STRING:
return String.class;
case VehiclePropertyType.BYTES:
return byte[].class;
- case VehiclePropertyType.COMPLEX:
+ case VehiclePropertyType.MIXED:
return Object.class;
default:
throw new IllegalArgumentException("Unexpected type: " + toHexString(halType));
@@ -170,10 +220,12 @@
}
private static List getRawValueList(Class<?> clazz, VehiclePropValue.RawValue value) {
- if (classMatched(Float.class, clazz)) {
+ if (classMatched(Float.class, clazz) || classMatched(Float[].class, clazz)) {
return value.floatValues;
- } else if (classMatched(Integer.class, clazz)) {
+ } else if (classMatched(Integer.class, clazz) || classMatched(Integer[].class, clazz)) {
return value.int32Values;
+ } else if (classMatched(Long.class, clazz) || classMatched(Long[].class, clazz)) {
+ return value.int64Values;
} else {
throw new IllegalArgumentException("Unexpected type: " + clazz);
}
diff --git a/service/src/com/android/car/hal/DiagnosticHalService.java b/service/src/com/android/car/hal/DiagnosticHalService.java
index 4ff0ada..c876035 100644
--- a/service/src/com/android/car/hal/DiagnosticHalService.java
+++ b/service/src/com/android/car/hal/DiagnosticHalService.java
@@ -20,17 +20,19 @@
import android.car.diagnostic.CarDiagnosticEvent;
import android.car.diagnostic.CarDiagnosticManager;
import android.car.hardware.CarSensorManager;
-import android.hardware.automotive.vehicle.V2_0.VehiclePropConfig;
-import android.hardware.automotive.vehicle.V2_0.VehiclePropValue;
-import android.hardware.automotive.vehicle.V2_0.VehiclePropertyChangeMode;
import android.hardware.automotive.vehicle.V2_0.DiagnosticFloatSensorIndex;
import android.hardware.automotive.vehicle.V2_0.DiagnosticIntegerSensorIndex;
+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.hardware.automotive.vehicle.V2_0.VehiclePropertyChangeMode;
import android.util.Log;
import android.util.SparseArray;
+
import com.android.car.CarLog;
import com.android.car.CarServiceUtils;
import com.android.car.vehiclehal.VehiclePropValueBuilder;
+
import java.io.PrintWriter;
import java.util.BitSet;
import java.util.LinkedList;
@@ -42,6 +44,8 @@
* higher-level semantic information
*/
public class DiagnosticHalService extends SensorHalServiceBase {
+ static final int OBD2_SELECTIVE_FRAME_CLEAR = 1;
+
public static class DiagnosticCapabilities {
private final CopyOnWriteArraySet<Integer> mProperties = new CopyOnWriteArraySet<>();
@@ -69,6 +73,10 @@
return isSupported(VehicleProperty.OBD2_FREEZE_FRAME_CLEAR);
}
+ public boolean isSelectiveClearFreezeFramesSupported() {
+ return isSupported(OBD2_SELECTIVE_FRAME_CLEAR);
+ }
+
void clear() {
mProperties.clear();
}
@@ -102,6 +110,17 @@
return propConfig.prop;
case VehicleProperty.OBD2_FREEZE_FRAME_CLEAR:
mDiagnosticCapabilities.setSupported(propConfig.prop);
+ Log.i(CarLog.TAG_DIAGNOSTIC, String.format(
+ "configArray for OBD2_FREEZE_FRAME_CLEAR is %s", propConfig.configArray));
+ if (propConfig.configArray.size() < 1) {
+ Log.e(CarLog.TAG_DIAGNOSTIC, String.format(
+ "property 0x%x does not specify whether it supports selective " +
+ "clearing of freeze frames. assuming it does not.", propConfig.prop));
+ } else {
+ if (propConfig.configArray.get(0) == 1) {
+ mDiagnosticCapabilities.setSupported(OBD2_SELECTIVE_FRAME_CLEAR);
+ }
+ }
return propConfig.prop;
default:
return SENSOR_TYPE_INVALID;
@@ -235,7 +254,6 @@
//TODO(egranata): tweak this for diagnostics
switch (prop.changeMode) {
case VehiclePropertyChangeMode.ON_CHANGE:
- case VehiclePropertyChangeMode.ON_SET:
return 0;
}
float rate = 1.0f;
diff --git a/service/src/com/android/car/hal/HvacHalService.java b/service/src/com/android/car/hal/HvacHalService.java
deleted file mode 100644
index 77ab1be..0000000
--- a/service/src/com/android/car/hal/HvacHalService.java
+++ /dev/null
@@ -1,83 +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.hal;
-
-import android.car.hardware.hvac.CarHvacManager;
-import android.hardware.automotive.vehicle.V2_0.VehicleProperty;
-
-public class HvacHalService extends PropertyHalServiceBase {
- private static final boolean DBG = false;
- private static final String TAG = "HvacHalService";
-
- private final ManagerToHalPropIdMap mMgrHalPropIdMap = ManagerToHalPropIdMap.create(
- CarHvacManager.ID_MIRROR_DEFROSTER_ON, VehicleProperty.HVAC_SIDE_MIRROR_HEAT,
-
- CarHvacManager.ID_STEERING_WHEEL_TEMP, VehicleProperty.HVAC_STEERING_WHEEL_TEMP,
-
- CarHvacManager.ID_OUTSIDE_AIR_TEMP, VehicleProperty.ENV_OUTSIDE_TEMPERATURE,
-
- CarHvacManager.ID_TEMPERATURE_UNITS, VehicleProperty.HVAC_TEMPERATURE_UNITS,
-
- CarHvacManager.ID_ZONED_TEMP_SETPOINT, VehicleProperty.HVAC_TEMPERATURE_SET,
-
- CarHvacManager.ID_ZONED_TEMP_ACTUAL, VehicleProperty.HVAC_TEMPERATURE_CURRENT,
-
- CarHvacManager.ID_ZONED_FAN_SPEED_SETPOINT, VehicleProperty.HVAC_FAN_SPEED,
-
- CarHvacManager.ID_ZONED_FAN_SPEED_RPM, VehicleProperty.HVAC_ACTUAL_FAN_SPEED_RPM,
-
- CarHvacManager.ID_ZONED_FAN_POSITION_AVAILABLE,
- VehicleProperty.HVAC_FAN_DIRECTION_AVAILABLE,
-
- CarHvacManager.ID_ZONED_FAN_POSITION, VehicleProperty.HVAC_FAN_DIRECTION,
-
- CarHvacManager.ID_ZONED_SEAT_TEMP, VehicleProperty.HVAC_SEAT_TEMPERATURE,
-
- CarHvacManager.ID_ZONED_AC_ON, VehicleProperty.HVAC_AC_ON,
-
- CarHvacManager.ID_ZONED_AUTOMATIC_MODE_ON, VehicleProperty.HVAC_AUTO_ON,
-
- CarHvacManager.ID_ZONED_AIR_RECIRCULATION_ON,VehicleProperty.HVAC_RECIRC_ON,
-
- CarHvacManager.ID_ZONED_MAX_AC_ON, VehicleProperty.HVAC_MAX_AC_ON,
-
- CarHvacManager.ID_ZONED_DUAL_ZONE_ON, VehicleProperty.HVAC_DUAL_ON,
-
- CarHvacManager.ID_ZONED_MAX_DEFROST_ON, VehicleProperty.HVAC_MAX_DEFROST_ON,
-
- CarHvacManager.ID_ZONED_HVAC_POWER_ON, VehicleProperty.HVAC_POWER_ON,
-
- CarHvacManager.ID_ZONED_HVAC_AUTO_RECIRC_ON, VehicleProperty.HVAC_AUTO_RECIRC_ON,
-
- CarHvacManager.ID_WINDOW_DEFROSTER_ON, VehicleProperty.HVAC_DEFROSTER
- );
-
- public HvacHalService(VehicleHal vehicleHal) {
- super(vehicleHal, TAG, DBG);
- }
-
- // Convert the HVAC public API property ID to HAL property ID
- @Override
- protected int managerToHalPropId(int hvacPropId) {
- return mMgrHalPropIdMap.getHalPropId(hvacPropId);
- }
-
- // Convert he HAL specific property ID to HVAC public API
- @Override
- protected int halToManagerPropId(int halPropId) {
- return mMgrHalPropIdMap.getManagerPropId(halPropId);
- }
-}
diff --git a/service/src/com/android/car/hal/InfoHalService.java b/service/src/com/android/car/hal/InfoHalService.java
deleted file mode 100644
index 26d1943..0000000
--- a/service/src/com/android/car/hal/InfoHalService.java
+++ /dev/null
@@ -1,104 +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.hal;
-
-import android.car.CarInfoManager;
-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.util.Log;
-
-import com.android.car.CarLog;
-
-import java.io.PrintWriter;
-import java.util.Collection;
-import java.util.LinkedList;
-import java.util.List;
-
-public class InfoHalService extends HalServiceBase {
-
- private final VehicleHal mHal;
- private Bundle mBasicInfo = new Bundle();
-
- public InfoHalService(VehicleHal hal) {
- mHal = hal;
- }
-
- @Override
- public void init() {
- //nothing to do
- }
-
- @Override
- public synchronized void release() {
- mBasicInfo = new Bundle();
- }
-
- @Override
- public synchronized Collection<VehiclePropConfig> takeSupportedProperties(
- Collection<VehiclePropConfig> allProperties) {
- List<VehiclePropConfig> supported = new LinkedList<>();
- for (VehiclePropConfig p: allProperties) {
- switch (p.prop) {
- case VehicleProperty.INFO_MAKE:
- readPropertyToBundle(p.prop, CarInfoManager.BASIC_INFO_KEY_MANUFACTURER);
- break;
- case VehicleProperty.INFO_MODEL:
- readPropertyToBundle(p.prop, CarInfoManager.BASIC_INFO_KEY_MODEL);
- break;
- case VehicleProperty.INFO_MODEL_YEAR:
- readPropertyToBundle(p.prop, CarInfoManager.BASIC_INFO_KEY_MODEL_YEAR);
- break;
- default: // not supported
- break;
- }
- }
- return supported;
- }
-
- private void readPropertyToBundle(int prop, String key) {
- String value = "";
- try {
- value = mHal.get(String.class, prop);
- } catch (PropertyTimeoutException e) {
- Log.e(CarLog.TAG_INFO, "Unable to read property", e);
- }
- mBasicInfo.putString(key, value);
- }
-
- @Override
- public void handleHalEvents(List<VehiclePropValue> values) {
- for (VehiclePropValue v : values) {
- logUnexpectedEvent(v.prop);
- }
- }
-
- @Override
- public void dump(PrintWriter writer) {
- writer.println("*InfoHal*");
- writer.println("**BasicInfo:" + mBasicInfo);
- }
-
- public synchronized Bundle getBasicInfo() {
- return mBasicInfo;
- }
-
- private void logUnexpectedEvent(int property) {
- Log.w(CarLog.TAG_INFO, "unexpected HAL event for property 0x" +
- Integer.toHexString(property));
- }
-}
diff --git a/service/src/com/android/car/hal/PowerHalService.java b/service/src/com/android/car/hal/PowerHalService.java
index dab28c8..504fbf2 100644
--- a/service/src/com/android/car/hal/PowerHalService.java
+++ b/service/src/com/android/car/hal/PowerHalService.java
@@ -15,14 +15,18 @@
*/
package com.android.car.hal;
-import static android.hardware.automotive.vehicle.V2_0.VehicleProperty.AP_POWER_STATE;
+
+import static android.hardware.automotive.vehicle.V2_0.VehicleProperty.AP_POWER_BOOTUP_REASON;
+import static android.hardware.automotive.vehicle.V2_0.VehicleProperty.AP_POWER_STATE_REPORT;
+import static android.hardware.automotive.vehicle.V2_0.VehicleProperty.AP_POWER_STATE_REQ;
import static android.hardware.automotive.vehicle.V2_0.VehicleProperty.DISPLAY_BRIGHTNESS;
import android.annotation.Nullable;
-import android.hardware.automotive.vehicle.V2_0.VehicleApPowerSetState;
-import android.hardware.automotive.vehicle.V2_0.VehicleApPowerState;
+import android.hardware.automotive.vehicle.V2_0.VehicleApPowerBootupReason;
import android.hardware.automotive.vehicle.V2_0.VehicleApPowerStateConfigFlag;
-import android.hardware.automotive.vehicle.V2_0.VehicleApPowerStateIndex;
+import android.hardware.automotive.vehicle.V2_0.VehicleApPowerStateReport;
+import android.hardware.automotive.vehicle.V2_0.VehicleApPowerStateReq;
+import android.hardware.automotive.vehicle.V2_0.VehicleApPowerStateReqIndex;
import android.hardware.automotive.vehicle.V2_0.VehicleApPowerStateShutdownParam;
import android.hardware.automotive.vehicle.V2_0.VehiclePropConfig;
import android.hardware.automotive.vehicle.V2_0.VehiclePropValue;
@@ -39,35 +43,43 @@
import java.util.List;
public class PowerHalService extends HalServiceBase {
+ // AP Power State constants set by HAL implementation
+ public static final int STATE_OFF = VehicleApPowerStateReq.OFF;
+ public static final int STATE_DEEP_SLEEP = VehicleApPowerStateReq.DEEP_SLEEP;
+ public static final int STATE_ON_DISP_OFF = VehicleApPowerStateReq.ON_DISP_OFF;
+ public static final int STATE_ON_FULL = VehicleApPowerStateReq.ON_FULL;
+ public static final int STATE_SHUTDOWN_PREPARE = VehicleApPowerStateReq.SHUTDOWN_PREPARE;
- public static final int STATE_OFF = VehicleApPowerState.OFF;
- public static final int STATE_DEEP_SLEEP = VehicleApPowerState.DEEP_SLEEP;
- public static final int STATE_ON_DISP_OFF = VehicleApPowerState.ON_DISP_OFF;
- public static final int STATE_ON_FULL = VehicleApPowerState.ON_FULL;
- public static final int STATE_SHUTDOWN_PREPARE = VehicleApPowerState.SHUTDOWN_PREPARE;
+ // Boot reason set by VMCU
+ public static final int BOOT_REASON_USER_POWER_ON = VehicleApPowerBootupReason.USER_POWER_ON;
+ public static final int BOOT_REASON_USER_UNLOCK = VehicleApPowerBootupReason.USER_UNLOCK;
+ public static final int BOOT_REASON_TIMER = VehicleApPowerBootupReason.TIMER;
+
+ // Set display brightness from 0-100%
+ public static final int MAX_BRIGHTNESS = 100;
@VisibleForTesting
- public static final int SET_BOOT_COMPLETE = VehicleApPowerSetState.BOOT_COMPLETE;
+ public static final int SET_BOOT_COMPLETE = VehicleApPowerStateReport.BOOT_COMPLETE;
@VisibleForTesting
- public static final int SET_DEEP_SLEEP_ENTRY = VehicleApPowerSetState.DEEP_SLEEP_ENTRY;
+ public static final int SET_DEEP_SLEEP_ENTRY = VehicleApPowerStateReport.DEEP_SLEEP_ENTRY;
@VisibleForTesting
- public static final int SET_DEEP_SLEEP_EXIT = VehicleApPowerSetState.DEEP_SLEEP_EXIT;
+ public static final int SET_DEEP_SLEEP_EXIT = VehicleApPowerStateReport.DEEP_SLEEP_EXIT;
@VisibleForTesting
- public static final int SET_SHUTDOWN_POSTPONE = VehicleApPowerSetState.SHUTDOWN_POSTPONE;
+ public static final int SET_SHUTDOWN_POSTPONE = VehicleApPowerStateReport.SHUTDOWN_POSTPONE;
@VisibleForTesting
- public static final int SET_SHUTDOWN_START = VehicleApPowerSetState.SHUTDOWN_START;
+ public static final int SET_SHUTDOWN_START = VehicleApPowerStateReport.SHUTDOWN_START;
@VisibleForTesting
- public static final int SET_DISPLAY_ON = VehicleApPowerSetState.DISPLAY_ON;
+ public static final int SET_DISPLAY_ON = VehicleApPowerStateReport.DISPLAY_ON;
@VisibleForTesting
- public static final int SET_DISPLAY_OFF =
- VehicleApPowerSetState.DISPLAY_OFF;
+ public static final int SET_DISPLAY_OFF = VehicleApPowerStateReport.DISPLAY_OFF;
@VisibleForTesting
- public static final int FLAG_SHUTDOWN_PARAM_CAN_SLEEP =
- VehicleApPowerStateShutdownParam.CAN_SLEEP;
+ public static final int SHUTDOWN_CAN_SLEEP = VehicleApPowerStateShutdownParam.CAN_SLEEP;
@VisibleForTesting
- public static final int FLAG_SHUTDOWN_IMMEDIATELY =
+ public static final int SHUTDOWN_IMMEDIATELY =
VehicleApPowerStateShutdownParam.SHUTDOWN_IMMEDIATELY;
+ @VisibleForTesting
+ public static final int SHUTDOWN_ONLY = VehicleApPowerStateShutdownParam.SHUTDOWN_ONLY;
public interface PowerEventListener {
/**
@@ -80,6 +92,11 @@
* @param brightness in percentile. 100% full.
*/
void onDisplayBrightnessChange(int brightness);
+ /**
+ * Received boot reason.
+ * @param boot reason.
+ */
+ void onBootReasonReceived(int bootReason);
}
public static final class PowerState {
@@ -104,7 +121,7 @@
if (mState != STATE_SHUTDOWN_PREPARE) {
throw new IllegalStateException("wrong state");
}
- return (mParam & VehicleApPowerStateShutdownParam.CAN_SLEEP) != 0;
+ return (mParam == VehicleApPowerStateShutdownParam.CAN_SLEEP);
}
/**
@@ -117,7 +134,7 @@
if (mState != STATE_SHUTDOWN_PREPARE) {
throw new IllegalStateException("wrong state");
}
- return (mParam & VehicleApPowerStateShutdownParam.SHUTDOWN_IMMEDIATELY) == 0;
+ return (mParam != VehicleApPowerStateShutdownParam.SHUTDOWN_IMMEDIATELY);
}
@Override
@@ -165,46 +182,64 @@
public void sendBootComplete() {
Log.i(CarLog.TAG_POWER, "send boot complete");
- setPowerState(VehicleApPowerSetState.BOOT_COMPLETE, 0);
+ setPowerState(VehicleApPowerStateReport.BOOT_COMPLETE, 0);
}
public void sendSleepEntry() {
Log.i(CarLog.TAG_POWER, "send sleep entry");
- setPowerState(VehicleApPowerSetState.DEEP_SLEEP_ENTRY, 0);
+ setPowerState(VehicleApPowerStateReport.DEEP_SLEEP_ENTRY, 0);
}
public void sendSleepExit() {
Log.i(CarLog.TAG_POWER, "send sleep exit");
- setPowerState(VehicleApPowerSetState.DEEP_SLEEP_EXIT, 0);
+ setPowerState(VehicleApPowerStateReport.DEEP_SLEEP_EXIT, 0);
}
public void sendShutdownPostpone(int postponeTimeMs) {
Log.i(CarLog.TAG_POWER, "send shutdown postpone, time:" + postponeTimeMs);
- setPowerState(VehicleApPowerSetState.SHUTDOWN_POSTPONE,
- postponeTimeMs);
+ setPowerState(VehicleApPowerStateReport.SHUTDOWN_POSTPONE, postponeTimeMs);
}
public void sendShutdownStart(int wakeupTimeSec) {
Log.i(CarLog.TAG_POWER, "send shutdown start");
- setPowerState(VehicleApPowerSetState.SHUTDOWN_START, 0);
+ setPowerState(VehicleApPowerStateReport.SHUTDOWN_START, wakeupTimeSec);
+ }
+
+ /**
+ * Sets the display brightness for the vehicle.
+ * @param brightness value from 0 to 100.
+ */
+ public void sendDisplayBrightness(int brightness) {
+ if (brightness < 0) {
+ brightness = 0;
+ } else if (brightness > 100) {
+ brightness = 100;
+ }
+ try {
+ mHal.set(VehicleProperty.DISPLAY_BRIGHTNESS, 0).to(brightness);
+ Log.i(CarLog.TAG_POWER, "send display brightness = " + brightness);
+ } catch (PropertyTimeoutException e) {
+ Log.e(CarLog.TAG_POWER, "cannot set DISPLAY_BRIGHTNESS", e);
+ }
}
public void sendDisplayOn() {
Log.i(CarLog.TAG_POWER, "send display on");
- setPowerState(VehicleApPowerSetState.DISPLAY_ON, 0);
+ setPowerState(VehicleApPowerStateReport.DISPLAY_ON, 0);
}
public void sendDisplayOff() {
Log.i(CarLog.TAG_POWER, "send display off");
- setPowerState(VehicleApPowerSetState.DISPLAY_OFF, 0);
+ setPowerState(VehicleApPowerStateReport.DISPLAY_OFF, 0);
}
private void setPowerState(int state, int additionalParam) {
int[] values = { state, additionalParam };
try {
- mHal.set(VehicleProperty.AP_POWER_STATE).to(values);
+ mHal.set(VehicleProperty.AP_POWER_STATE_REPORT, 0).to(values);
+ Log.i(CarLog.TAG_POWER, "setPowerState=" + state + " param=" + additionalParam);
} catch (PropertyTimeoutException e) {
- Log.e(CarLog.TAG_POWER, "cannot set to AP_POWER_STATE", e);
+ Log.e(CarLog.TAG_POWER, "cannot set to AP_POWER_STATE_REPORT", e);
}
}
@@ -212,37 +247,36 @@
public PowerState getCurrentPowerState() {
int[] state;
try {
- state = mHal.get(int[].class, VehicleProperty.AP_POWER_STATE);
+ state = mHal.get(int[].class, VehicleProperty.AP_POWER_STATE_REQ);
} catch (PropertyTimeoutException e) {
- Log.e(CarLog.TAG_POWER, "Cannot get AP_POWER_STATE", e);
+ Log.e(CarLog.TAG_POWER, "Cannot get AP_POWER_STATE_REQ", e);
return null;
}
- return new PowerState(state[VehicleApPowerStateIndex.STATE],
- state[VehicleApPowerStateIndex.ADDITIONAL]);
+ return new PowerState(state[VehicleApPowerStateReqIndex.STATE],
+ state[VehicleApPowerStateReqIndex.ADDITIONAL]);
}
public synchronized boolean isPowerStateSupported() {
- VehiclePropConfig config = mProperties.get(VehicleProperty.AP_POWER_STATE);
+ VehiclePropConfig config = mProperties.get(VehicleProperty.AP_POWER_STATE_REQ);
return config != null;
}
- public synchronized boolean isDeepSleepAllowed() {
- VehiclePropConfig config = mProperties.get(VehicleProperty.AP_POWER_STATE);
+ private synchronized boolean isConfigFlagSet(int flag) {
+ VehiclePropConfig config = mProperties.get(VehicleProperty.AP_POWER_STATE_REQ);
if (config == null) {
return false;
+ } else if (config.configArray.size() < 1) {
+ return false;
}
- return (config.configArray.get(0)
- & VehicleApPowerStateConfigFlag.ENABLE_DEEP_SLEEP_FLAG) != 0;
+ return (config.configArray.get(0) & flag) != 0;
}
- public synchronized boolean isTimedWakeupAllowed() {
- VehiclePropConfig config = mProperties.get(
- AP_POWER_STATE);
- if (config == null) {
- return false;
- }
- return (config.configArray.get(0)
- & VehicleApPowerStateConfigFlag.CONFIG_SUPPORT_TIMER_POWER_ON_FLAG) != 0;
+ public boolean isDeepSleepAllowed() {
+ return isConfigFlagSet(VehicleApPowerStateConfigFlag.ENABLE_DEEP_SLEEP_FLAG);
+ }
+
+ public boolean isTimedWakeupAllowed() {
+ return isConfigFlagSet(VehicleApPowerStateConfigFlag.CONFIG_SUPPORT_TIMER_POWER_ON_FLAG);
}
@Override
@@ -274,7 +308,9 @@
Collection<VehiclePropConfig> allProperties) {
for (VehiclePropConfig config : allProperties) {
switch (config.prop) {
- case AP_POWER_STATE:
+ case AP_POWER_BOOTUP_REASON:
+ case AP_POWER_STATE_REQ:
+ case AP_POWER_STATE_REPORT:
case DISPLAY_BRIGHTNESS:
mProperties.put(config.prop, config);
break;
@@ -302,18 +338,36 @@
private void dispatchEvents(List<VehiclePropValue> values, PowerEventListener listener) {
for (VehiclePropValue v : values) {
switch (v.prop) {
- case AP_POWER_STATE:
- int state = v.value.int32Values.get(VehicleApPowerStateIndex.STATE);
- int param = v.value.int32Values.get(VehicleApPowerStateIndex.ADDITIONAL);
+ case AP_POWER_BOOTUP_REASON:
+ int reason = v.value.int32Values.get(0);
+ Log.i(CarLog.TAG_POWER, "Received AP_POWER_BOOTUP_REASON=" + reason);
+ listener.onBootReasonReceived(reason);
+ break;
+ case AP_POWER_STATE_REQ:
+ int state = v.value.int32Values.get(VehicleApPowerStateReqIndex.STATE);
+ int param = v.value.int32Values.get(VehicleApPowerStateReqIndex.ADDITIONAL);
+ Log.i(CarLog.TAG_POWER, "Received AP_POWER_STATE_REQ=" + state
+ + " param=" + param);
listener.onApPowerStateChange(new PowerState(state, param));
break;
case DISPLAY_BRIGHTNESS:
+ {
int maxBrightness;
synchronized (this) {
maxBrightness = mMaxDisplayBrightness;
}
- listener.onDisplayBrightnessChange(
- (v.value.int32Values.get(0) * 100) / maxBrightness);
+ int brightness = v.value.int32Values.get(0) * MAX_BRIGHTNESS / maxBrightness;
+ if (brightness < 0) {
+ Log.e(CarLog.TAG_POWER, "invalid brightness: " + brightness + ", set to 0");
+ brightness = 0;
+ } else if (brightness > MAX_BRIGHTNESS) {
+ Log.e(CarLog.TAG_POWER, "invalid brightness: " + brightness + ", set to "
+ + MAX_BRIGHTNESS);
+ brightness = MAX_BRIGHTNESS;
+ }
+ Log.i(CarLog.TAG_POWER, "Received DISPLAY_BRIGHTNESS=" + brightness);
+ listener.onDisplayBrightnessChange(brightness);
+ }
break;
}
}
diff --git a/service/src/com/android/car/hal/PropertyHalService.java b/service/src/com/android/car/hal/PropertyHalService.java
new file mode 100644
index 0000000..ad81507
--- /dev/null
+++ b/service/src/com/android/car/hal/PropertyHalService.java
@@ -0,0 +1,342 @@
+/*
+ * 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.hal;
+
+import static com.android.car.hal.CarPropertyUtils.toCarPropertyValue;
+import static com.android.car.hal.CarPropertyUtils.toVehiclePropValue;
+
+import static java.lang.Integer.toHexString;
+
+import android.annotation.Nullable;
+import android.car.hardware.CarPropertyConfig;
+import android.car.hardware.CarPropertyValue;
+import android.car.hardware.property.CarPropertyEvent;
+import android.hardware.automotive.vehicle.V2_0.VehiclePropConfig;
+import android.hardware.automotive.vehicle.V2_0.VehiclePropValue;
+import android.util.Log;
+import android.util.SparseArray;
+
+import com.android.car.CarLog;
+import com.android.internal.annotations.GuardedBy;
+
+import java.io.PrintWriter;
+import java.util.Collection;
+import java.util.HashSet;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.concurrent.ConcurrentHashMap;
+
+/**
+ * Common interface for HAL services that send Vehicle Properties back and forth via ICarProperty.
+ * Services that communicate by passing vehicle properties back and forth via ICarProperty should
+ * extend this class.
+ */
+public class PropertyHalService extends HalServiceBase {
+ private final boolean mDbg = true;
+ private final LinkedList<CarPropertyEvent> mEventsToDispatch = new LinkedList<>();
+ private final Map<Integer, CarPropertyConfig<?>> mProps =
+ new ConcurrentHashMap<>();
+ private final SparseArray<Float> mRates = new SparseArray<Float>();
+ private static final String TAG = "PropertyHalService";
+ private final VehicleHal mVehicleHal;
+ private final PropertyHalServiceIds mPropIds;
+
+ @GuardedBy("mLock")
+ private PropertyHalListener mListener;
+
+ private Set<Integer> mSubscribedPropIds;
+
+ private final Object mLock = new Object();
+
+ /**
+ * Converts manager property ID to Vehicle HAL property ID.
+ * If property is not supported, it will return {@link #NOT_SUPPORTED_PROPERTY}.
+ */
+ private int managerToHalPropId(int propId) {
+ if (mProps.containsKey(propId)) {
+ return propId;
+ } else {
+ return NOT_SUPPORTED_PROPERTY;
+ }
+ }
+
+ /**
+ * Converts Vehicle HAL property ID to manager property ID.
+ * If property is not supported, it will return {@link #NOT_SUPPORTED_PROPERTY}.
+ */
+ private int halToManagerPropId(int halPropId) {
+ if (mProps.containsKey(halPropId)) {
+ return halPropId;
+ } else {
+ return NOT_SUPPORTED_PROPERTY;
+ }
+ }
+
+ /**
+ * PropertyHalListener used to send events to CarPropertyService
+ */
+ public interface PropertyHalListener {
+ /**
+ * This event is sent whenever the property value is updated
+ * @param event
+ */
+ void onPropertyChange(List<CarPropertyEvent> events);
+ /**
+ * This event is sent when the set property call fails
+ * @param property
+ * @param area
+ */
+ void onPropertySetError(int property, int area);
+ }
+
+ public PropertyHalService(VehicleHal vehicleHal) {
+ mPropIds = new PropertyHalServiceIds();
+ mSubscribedPropIds = new HashSet<Integer>();
+ mVehicleHal = vehicleHal;
+ if (mDbg) {
+ Log.d(TAG, "started PropertyHalService");
+ }
+ }
+
+ /**
+ * Set the listener for the HAL service
+ * @param listener
+ */
+ public void setListener(PropertyHalListener listener) {
+ synchronized (mLock) {
+ mListener = listener;
+ }
+ }
+
+ /**
+ *
+ * @return List<CarPropertyConfig> List of configs available.
+ */
+ public Map<Integer, CarPropertyConfig<?>> getPropertyList() {
+ if (mDbg) {
+ Log.d(TAG, "getPropertyList");
+ }
+ return mProps;
+ }
+
+ /**
+ * Returns property or null if property is not ready yet.
+ * @param mgrPropId
+ * @param areaId
+ */
+ @Nullable
+ public CarPropertyValue getProperty(int mgrPropId, int areaId) {
+ int halPropId = managerToHalPropId(mgrPropId);
+ if (halPropId == NOT_SUPPORTED_PROPERTY) {
+ throw new IllegalArgumentException("Invalid property Id : 0x" + toHexString(mgrPropId));
+ }
+
+ VehiclePropValue value = null;
+ try {
+ value = mVehicleHal.get(halPropId, areaId);
+ } catch (PropertyTimeoutException e) {
+ Log.e(CarLog.TAG_PROPERTY, "get, property not ready 0x" + toHexString(halPropId), e);
+ }
+
+ return value == null ? null : toCarPropertyValue(value, mgrPropId);
+ }
+
+ /**
+ * Returns sample rate for the property
+ * @param propId
+ */
+ public float getSampleRate(int propId) {
+ return mVehicleHal.getSampleRate(propId);
+ }
+
+ /**
+ * Get the read permission string for the property.
+ * @param propId
+ */
+ @Nullable
+ public String getReadPermission(int propId) {
+ return mPropIds.getReadPermission(propId);
+ }
+
+ /**
+ * Get the write permission string for the property.
+ * @param propId
+ */
+ @Nullable
+ public String getWritePermission(int propId) {
+ return mPropIds.getWritePermission(propId);
+ }
+
+ /**
+ * Set the property value.
+ * @param prop
+ */
+ public void setProperty(CarPropertyValue prop) {
+ int halPropId = managerToHalPropId(prop.getPropertyId());
+ if (halPropId == NOT_SUPPORTED_PROPERTY) {
+ throw new IllegalArgumentException("Invalid property Id : 0x"
+ + toHexString(prop.getPropertyId()));
+ }
+ VehiclePropValue halProp = toVehiclePropValue(prop, halPropId);
+ try {
+ mVehicleHal.set(halProp);
+ } catch (PropertyTimeoutException e) {
+ Log.e(CarLog.TAG_PROPERTY, "set, property not ready 0x" + toHexString(halPropId), e);
+ throw new RuntimeException(e);
+ }
+ }
+
+ /**
+ * Subscribe to this property at the specified update rate.
+ * @param propId
+ * @param rate
+ */
+ public void subscribeProperty(int propId, float rate) {
+ if (mDbg) {
+ Log.d(TAG, "subscribeProperty propId=0x" + toHexString(propId) + ", rate=" + rate);
+ }
+ int halPropId = managerToHalPropId(propId);
+ if (halPropId == NOT_SUPPORTED_PROPERTY) {
+ throw new IllegalArgumentException("Invalid property Id : 0x"
+ + toHexString(propId));
+ }
+ // Validate the min/max rate
+ CarPropertyConfig cfg = mProps.get(propId);
+ if (rate > cfg.getMaxSampleRate()) {
+ rate = cfg.getMaxSampleRate();
+ } else if (rate < cfg.getMinSampleRate()) {
+ rate = cfg.getMinSampleRate();
+ }
+ synchronized (mSubscribedPropIds) {
+ mSubscribedPropIds.add(halPropId);
+ }
+ mVehicleHal.subscribeProperty(this, halPropId, rate);
+ }
+
+ /**
+ * Unsubscribe the property and turn off update events for it.
+ * @param propId
+ */
+ public void unsubscribeProperty(int propId) {
+ if (mDbg) {
+ Log.d(TAG, "unsubscribeProperty propId=0x" + toHexString(propId));
+ }
+ int halPropId = managerToHalPropId(propId);
+ if (halPropId == NOT_SUPPORTED_PROPERTY) {
+ throw new IllegalArgumentException("Invalid property Id : 0x"
+ + toHexString(propId));
+ }
+ synchronized (mSubscribedPropIds) {
+ if (mSubscribedPropIds.contains(halPropId)) {
+ mSubscribedPropIds.remove(halPropId);
+ mVehicleHal.unsubscribeProperty(this, halPropId);
+ }
+ }
+ }
+
+ @Override
+ public void init() {
+ if (mDbg) {
+ Log.d(TAG, "init()");
+ }
+ }
+
+ @Override
+ public void release() {
+ if (mDbg) {
+ Log.d(TAG, "release()");
+ }
+ synchronized (mSubscribedPropIds) {
+ for (Integer prop : mSubscribedPropIds) {
+ mVehicleHal.unsubscribeProperty(this, prop);
+ }
+ mSubscribedPropIds.clear();
+ }
+ mProps.clear();
+
+ synchronized (mLock) {
+ mListener = null;
+ }
+ }
+
+ @Override
+ public Collection<VehiclePropConfig> takeSupportedProperties(
+ Collection<VehiclePropConfig> allProperties) {
+ List<VehiclePropConfig> taken = new LinkedList<>();
+
+ for (VehiclePropConfig p : allProperties) {
+ if (mPropIds.isSupportedProperty(p.prop)) {
+ CarPropertyConfig config = CarPropertyUtils.toCarPropertyConfig(p, p.prop);
+ taken.add(p);
+ mProps.put(p.prop, config);
+ if (mDbg) {
+ Log.d(TAG, "takeSupportedProperties: " + toHexString(p.prop));
+ }
+ }
+ }
+ if (mDbg) {
+ Log.d(TAG, "takeSupportedProperties() took " + taken.size() + " properties");
+ }
+ return taken;
+ }
+
+ @Override
+ public void handleHalEvents(List<VehiclePropValue> values) {
+ PropertyHalListener listener;
+ synchronized (mLock) {
+ listener = mListener;
+ }
+ if (listener != null) {
+ for (VehiclePropValue v : values) {
+ int mgrPropId = halToManagerPropId(v.prop);
+ if (mgrPropId == NOT_SUPPORTED_PROPERTY) {
+ Log.e(TAG, "Property is not supported: 0x" + toHexString(v.prop));
+ continue;
+ }
+ CarPropertyValue<?> propVal = toCarPropertyValue(v, mgrPropId);
+ CarPropertyEvent event = new CarPropertyEvent(
+ CarPropertyEvent.PROPERTY_EVENT_PROPERTY_CHANGE, propVal);
+ if (event != null) {
+ mEventsToDispatch.add(event);
+ }
+ }
+ listener.onPropertyChange(mEventsToDispatch);
+ mEventsToDispatch.clear();
+ }
+ }
+
+ @Override
+ public void handlePropertySetError(int property, int area) {
+ PropertyHalListener listener;
+ synchronized (mLock) {
+ listener = mListener;
+ }
+ if (listener != null) {
+ listener.onPropertySetError(property, area);
+ }
+ }
+
+ @Override
+ public void dump(PrintWriter writer) {
+ writer.println(TAG);
+ writer.println(" Properties available:");
+ for (CarPropertyConfig prop : mProps.values()) {
+ writer.println(" " + prop.toString());
+ }
+ }
+}
diff --git a/service/src/com/android/car/hal/PropertyHalServiceBase.java b/service/src/com/android/car/hal/PropertyHalServiceBase.java
deleted file mode 100644
index 07b722c..0000000
--- a/service/src/com/android/car/hal/PropertyHalServiceBase.java
+++ /dev/null
@@ -1,229 +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.hal;
-
-import static com.android.car.hal.CarPropertyUtils.toCarPropertyValue;
-import static com.android.car.hal.CarPropertyUtils.toVehiclePropValue;
-import static java.lang.Integer.toHexString;
-
-import android.annotation.Nullable;
-import android.car.hardware.CarPropertyConfig;
-import android.car.hardware.CarPropertyValue;
-import android.car.hardware.property.CarPropertyEvent;
-import android.hardware.automotive.vehicle.V2_0.VehiclePropConfig;
-import android.hardware.automotive.vehicle.V2_0.VehiclePropValue;
-import android.util.Log;
-
-import com.android.car.CarLog;
-import com.android.internal.annotations.GuardedBy;
-
-import java.io.PrintWriter;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.LinkedList;
-import java.util.List;
-import java.util.concurrent.ConcurrentHashMap;
-
-/**
- * Common interface for HAL services that send Vehicle Properties back and forth via ICarProperty.
- * Services that communicate by passing vehicle properties back and forth via ICarProperty should
- * extend this class.
- */
-public abstract class PropertyHalServiceBase extends HalServiceBase {
- private final boolean mDbg;
- private final ConcurrentHashMap<Integer, CarPropertyConfig<?>> mProps =
- new ConcurrentHashMap<>();
- private final String mTag;
- private final VehicleHal mVehicleHal;
-
- @GuardedBy("mLock")
- private PropertyHalListener mListener;
- private final Object mLock = new Object();
-
- public interface PropertyHalListener {
- void onPropertyChange(CarPropertyEvent event);
- void onPropertySetError(int property, int area);
- }
-
- protected PropertyHalServiceBase(VehicleHal vehicleHal, String tag, boolean dbg) {
- mVehicleHal = vehicleHal;
- mTag = "PropertyHalServiceBase." + tag;
- mDbg = dbg;
-
- if (mDbg) {
- Log.d(mTag, "started PropertyHalServiceBase!");
- }
- }
-
- public void setListener(PropertyHalListener listener) {
- synchronized (mLock) {
- mListener = listener;
- }
- }
-
- public List<CarPropertyConfig> getPropertyList() {
- return new ArrayList<>(mProps.values());
- }
-
- /**
- * Returns property or null if property is not ready yet.
- */
- @Nullable
- public CarPropertyValue getProperty(int mgrPropId, int areaId) {
- int halPropId = managerToHalPropId(mgrPropId);
- if (halPropId == NOT_SUPPORTED_PROPERTY) {
- throw new IllegalArgumentException("Invalid property Id : 0x" + toHexString(mgrPropId));
- }
-
- VehiclePropValue value = null;
- try {
- value = mVehicleHal.get(halPropId, areaId);
- } catch (PropertyTimeoutException e) {
- Log.e(CarLog.TAG_PROPERTY, "get, property not ready 0x" + toHexString(halPropId), e);
- }
-
- return value == null ? null : toCarPropertyValue(value, mgrPropId);
- }
-
- public void setProperty(CarPropertyValue prop) {
- int halPropId = managerToHalPropId(prop.getPropertyId());
- if (halPropId == NOT_SUPPORTED_PROPERTY) {
- throw new IllegalArgumentException("Invalid property Id : 0x"
- + toHexString(prop.getPropertyId()));
- }
- VehiclePropValue halProp = toVehiclePropValue(prop, halPropId);
- try {
- mVehicleHal.set(halProp);
- } catch (PropertyTimeoutException e) {
- Log.e(CarLog.TAG_PROPERTY, "set, property not ready 0x" + toHexString(halPropId), e);
- throw new RuntimeException(e);
- }
- }
-
- @Override
- public void init() {
- if (mDbg) {
- Log.d(mTag, "init()");
- }
- // Subscribe to each of the properties
- for (Integer prop : mProps.keySet()) {
- mVehicleHal.subscribeProperty(this, prop);
- }
- }
-
- @Override
- public void release() {
- if (mDbg) {
- Log.d(mTag, "release()");
- }
-
- for (Integer prop : mProps.keySet()) {
- mVehicleHal.unsubscribeProperty(this, prop);
- }
-
- // Clear the property list
- mProps.clear();
-
- synchronized (mLock) {
- mListener = null;
- }
- }
-
- @Override
- public Collection<VehiclePropConfig> takeSupportedProperties(
- Collection<VehiclePropConfig> allProperties) {
- List<VehiclePropConfig> taken = new LinkedList<>();
-
- for (VehiclePropConfig p : allProperties) {
- int mgrPropId = halToManagerPropId(p.prop);
-
- if (mgrPropId == NOT_SUPPORTED_PROPERTY) {
- continue; // The property is not handled by this HAL.
- }
-
- CarPropertyConfig config = CarPropertyUtils.toCarPropertyConfig(p, mgrPropId);
-
- taken.add(p);
- mProps.put(p.prop, config);
-
- if (mDbg) {
- Log.d(mTag, "takeSupportedProperties: " + toHexString(p.prop));
- }
- }
- return taken;
- }
-
- @Override
- public void handleHalEvents(List<VehiclePropValue> values) {
- PropertyHalListener listener;
- synchronized (mLock) {
- listener = mListener;
- }
- if (listener != null) {
- for (VehiclePropValue v : values) {
- int prop = v.prop;
- int mgrPropId = halToManagerPropId(prop);
-
- if (mgrPropId == NOT_SUPPORTED_PROPERTY) {
- Log.e(mTag, "Property is not supported: 0x" + toHexString(prop));
- continue;
- }
-
- CarPropertyEvent event;
- CarPropertyValue<?> propVal = toCarPropertyValue(v, mgrPropId);
- event = new CarPropertyEvent(CarPropertyEvent.PROPERTY_EVENT_PROPERTY_CHANGE,
- propVal);
-
- listener.onPropertyChange(event);
- if (mDbg) {
- Log.d(mTag, "handleHalEvents event: " + event);
- }
- }
- }
- }
-
- @Override
- public void handlePropertySetError(int property, int area) {
- PropertyHalListener listener;
- synchronized (mLock) {
- listener = mListener;
- }
- if (listener != null) {
- listener.onPropertySetError(property, area);
- }
- }
-
- @Override
- public void dump(PrintWriter writer) {
- writer.println(mTag);
- writer.println(" Properties available:");
- for (CarPropertyConfig prop : mProps.values()) {
- writer.println(" " + prop.toString());
- }
- }
-
- /**
- * Converts manager property ID to Vehicle HAL property ID.
- * If property is not supported, it will return {@link #NOT_SUPPORTED_PROPERTY}.
- */
- abstract protected int managerToHalPropId(int managerPropId);
-
- /**
- * Converts Vehicle HAL property ID to manager property ID.
- * If property is not supported, it will return {@link #NOT_SUPPORTED_PROPERTY}.
- */
- abstract protected int halToManagerPropId(int halPropId);
-}
diff --git a/service/src/com/android/car/hal/PropertyHalServiceIds.java b/service/src/com/android/car/hal/PropertyHalServiceIds.java
new file mode 100644
index 0000000..651afea
--- /dev/null
+++ b/service/src/com/android/car/hal/PropertyHalServiceIds.java
@@ -0,0 +1,416 @@
+/*
+ * 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.hal;
+
+import android.annotation.Nullable;
+import android.car.Car;
+import android.hardware.automotive.vehicle.V2_0.VehicleProperty;
+import android.hardware.automotive.vehicle.V2_0.VehiclePropertyGroup;
+import android.util.Pair;
+import android.util.SparseArray;
+
+/**
+ * Helper class to define which property IDs are used by PropertyHalService. This class binds the
+ * read and write permissions to the property ID.
+ */
+public class PropertyHalServiceIds {
+ // Index (key is propertyId, and the value is readPermission, writePermission
+ private final SparseArray<Pair<String, String>> mProps;
+
+ public PropertyHalServiceIds() {
+ mProps = new SparseArray<>();
+
+ // Add propertyId and read/write permissions
+ // Cabin Properties
+ mProps.put(VehicleProperty.DOOR_POS, new Pair<>(
+ Car.PERMISSION_CONTROL_CAR_DOORS,
+ Car.PERMISSION_CONTROL_CAR_DOORS));
+ mProps.put(VehicleProperty.DOOR_MOVE, new Pair<>(
+ Car.PERMISSION_CONTROL_CAR_DOORS,
+ Car.PERMISSION_CONTROL_CAR_DOORS));
+ mProps.put(VehicleProperty.DOOR_LOCK, new Pair<>(
+ Car.PERMISSION_CONTROL_CAR_DOORS,
+ Car.PERMISSION_CONTROL_CAR_DOORS));
+ mProps.put(VehicleProperty.MIRROR_Z_POS, new Pair<>(
+ Car.PERMISSION_CONTROL_CAR_MIRRORS,
+ Car.PERMISSION_CONTROL_CAR_MIRRORS));
+ mProps.put(VehicleProperty.MIRROR_Z_MOVE, new Pair<>(
+ Car.PERMISSION_CONTROL_CAR_MIRRORS,
+ Car.PERMISSION_CONTROL_CAR_MIRRORS));
+ mProps.put(VehicleProperty.MIRROR_Y_POS, new Pair<>(
+ Car.PERMISSION_CONTROL_CAR_MIRRORS,
+ Car.PERMISSION_CONTROL_CAR_MIRRORS));
+ mProps.put(VehicleProperty.MIRROR_Y_MOVE, new Pair<>(
+ Car.PERMISSION_CONTROL_CAR_MIRRORS,
+ Car.PERMISSION_CONTROL_CAR_MIRRORS));
+ mProps.put(VehicleProperty.MIRROR_LOCK, new Pair<>(
+ Car.PERMISSION_CONTROL_CAR_MIRRORS,
+ Car.PERMISSION_CONTROL_CAR_MIRRORS));
+ mProps.put(VehicleProperty.MIRROR_FOLD, new Pair<>(
+ Car.PERMISSION_CONTROL_CAR_MIRRORS,
+ Car.PERMISSION_CONTROL_CAR_MIRRORS));
+ mProps.put(VehicleProperty.SEAT_MEMORY_SELECT, new Pair<>(
+ Car.PERMISSION_CONTROL_CAR_SEATS,
+ Car.PERMISSION_CONTROL_CAR_SEATS));
+ mProps.put(VehicleProperty.SEAT_MEMORY_SET, new Pair<>(
+ Car.PERMISSION_CONTROL_CAR_SEATS,
+ Car.PERMISSION_CONTROL_CAR_SEATS));
+ mProps.put(VehicleProperty.SEAT_BELT_BUCKLED, new Pair<>(
+ Car.PERMISSION_CONTROL_CAR_SEATS,
+ Car.PERMISSION_CONTROL_CAR_SEATS));
+ mProps.put(VehicleProperty.SEAT_BELT_HEIGHT_POS, new Pair<>(
+ Car.PERMISSION_CONTROL_CAR_SEATS,
+ Car.PERMISSION_CONTROL_CAR_SEATS));
+ mProps.put(VehicleProperty.SEAT_BELT_HEIGHT_MOVE, new Pair<>(
+ Car.PERMISSION_CONTROL_CAR_SEATS,
+ Car.PERMISSION_CONTROL_CAR_SEATS));
+ mProps.put(VehicleProperty.SEAT_FORE_AFT_POS, new Pair<>(
+ Car.PERMISSION_CONTROL_CAR_SEATS,
+ Car.PERMISSION_CONTROL_CAR_SEATS));
+ mProps.put(VehicleProperty.SEAT_FORE_AFT_MOVE, new Pair<>(
+ Car.PERMISSION_CONTROL_CAR_SEATS,
+ Car.PERMISSION_CONTROL_CAR_SEATS));
+ mProps.put(VehicleProperty.SEAT_BACKREST_ANGLE_1_POS, new Pair<>(
+ Car.PERMISSION_CONTROL_CAR_SEATS,
+ Car.PERMISSION_CONTROL_CAR_SEATS));
+ mProps.put(VehicleProperty.SEAT_BACKREST_ANGLE_1_MOVE, new Pair<>(
+ Car.PERMISSION_CONTROL_CAR_SEATS,
+ Car.PERMISSION_CONTROL_CAR_SEATS));
+ mProps.put(VehicleProperty.SEAT_BACKREST_ANGLE_2_POS, new Pair<>(
+ Car.PERMISSION_CONTROL_CAR_SEATS,
+ Car.PERMISSION_CONTROL_CAR_SEATS));
+ mProps.put(VehicleProperty.SEAT_BACKREST_ANGLE_2_MOVE, new Pair<>(
+ Car.PERMISSION_CONTROL_CAR_SEATS,
+ Car.PERMISSION_CONTROL_CAR_SEATS));
+ mProps.put(VehicleProperty.SEAT_HEIGHT_POS, new Pair<>(
+ Car.PERMISSION_CONTROL_CAR_SEATS,
+ Car.PERMISSION_CONTROL_CAR_SEATS));
+ mProps.put(VehicleProperty.SEAT_HEIGHT_MOVE, new Pair<>(
+ Car.PERMISSION_CONTROL_CAR_SEATS,
+ Car.PERMISSION_CONTROL_CAR_SEATS));
+ mProps.put(VehicleProperty.SEAT_DEPTH_POS, new Pair<>(
+ Car.PERMISSION_CONTROL_CAR_SEATS,
+ Car.PERMISSION_CONTROL_CAR_SEATS));
+ mProps.put(VehicleProperty.SEAT_DEPTH_MOVE, new Pair<>(
+ Car.PERMISSION_CONTROL_CAR_SEATS,
+ Car.PERMISSION_CONTROL_CAR_SEATS));
+ mProps.put(VehicleProperty.SEAT_TILT_POS, new Pair<>(
+ Car.PERMISSION_CONTROL_CAR_SEATS,
+ Car.PERMISSION_CONTROL_CAR_SEATS));
+ mProps.put(VehicleProperty.SEAT_TILT_MOVE, new Pair<>(
+ Car.PERMISSION_CONTROL_CAR_SEATS,
+ Car.PERMISSION_CONTROL_CAR_SEATS));
+ mProps.put(VehicleProperty.SEAT_LUMBAR_FORE_AFT_POS, new Pair<>(
+ Car.PERMISSION_CONTROL_CAR_SEATS,
+ Car.PERMISSION_CONTROL_CAR_SEATS));
+ mProps.put(VehicleProperty.SEAT_LUMBAR_FORE_AFT_MOVE, new Pair<>(
+ Car.PERMISSION_CONTROL_CAR_SEATS,
+ Car.PERMISSION_CONTROL_CAR_SEATS));
+ mProps.put(VehicleProperty.SEAT_LUMBAR_SIDE_SUPPORT_POS, new Pair<>(
+ Car.PERMISSION_CONTROL_CAR_SEATS,
+ Car.PERMISSION_CONTROL_CAR_SEATS));
+ mProps.put(VehicleProperty.SEAT_LUMBAR_SIDE_SUPPORT_MOVE, new Pair<>(
+ Car.PERMISSION_CONTROL_CAR_SEATS,
+ Car.PERMISSION_CONTROL_CAR_SEATS));
+ mProps.put(VehicleProperty.SEAT_HEADREST_HEIGHT_POS, new Pair<>(
+ Car.PERMISSION_CONTROL_CAR_SEATS,
+ Car.PERMISSION_CONTROL_CAR_SEATS));
+ mProps.put(VehicleProperty.SEAT_HEADREST_HEIGHT_MOVE, new Pair<>(
+ Car.PERMISSION_CONTROL_CAR_SEATS,
+ Car.PERMISSION_CONTROL_CAR_SEATS));
+ mProps.put(VehicleProperty.SEAT_HEADREST_ANGLE_POS, new Pair<>(
+ Car.PERMISSION_CONTROL_CAR_SEATS,
+ Car.PERMISSION_CONTROL_CAR_SEATS));
+ mProps.put(VehicleProperty.SEAT_HEADREST_ANGLE_MOVE, new Pair<>(
+ Car.PERMISSION_CONTROL_CAR_SEATS,
+ Car.PERMISSION_CONTROL_CAR_SEATS));
+ mProps.put(VehicleProperty.SEAT_HEADREST_FORE_AFT_POS, new Pair<>(
+ Car.PERMISSION_CONTROL_CAR_SEATS,
+ Car.PERMISSION_CONTROL_CAR_SEATS));
+ mProps.put(VehicleProperty.SEAT_HEADREST_FORE_AFT_MOVE, new Pair<>(
+ Car.PERMISSION_CONTROL_CAR_SEATS,
+ Car.PERMISSION_CONTROL_CAR_SEATS));
+ mProps.put(VehicleProperty.WINDOW_POS, new Pair<>(
+ Car.PERMISSION_CONTROL_CAR_WINDOWS,
+ Car.PERMISSION_CONTROL_CAR_WINDOWS));
+ mProps.put(VehicleProperty.WINDOW_MOVE, new Pair<>(
+ Car.PERMISSION_CONTROL_CAR_WINDOWS,
+ Car.PERMISSION_CONTROL_CAR_WINDOWS));
+ mProps.put(VehicleProperty.WINDOW_LOCK, new Pair<>(
+ Car.PERMISSION_CONTROL_CAR_WINDOWS,
+ Car.PERMISSION_CONTROL_CAR_WINDOWS));
+
+ // HVAC properties
+ mProps.put(VehicleProperty.HVAC_FAN_SPEED, new Pair<>(
+ Car.PERMISSION_CONTROL_CAR_CLIMATE,
+ Car.PERMISSION_CONTROL_CAR_CLIMATE));
+ mProps.put(VehicleProperty.HVAC_FAN_DIRECTION, new Pair<>(
+ Car.PERMISSION_CONTROL_CAR_CLIMATE,
+ Car.PERMISSION_CONTROL_CAR_CLIMATE));
+ mProps.put(VehicleProperty.HVAC_TEMPERATURE_CURRENT, new Pair<>(
+ Car.PERMISSION_CONTROL_CAR_CLIMATE,
+ Car.PERMISSION_CONTROL_CAR_CLIMATE));
+ mProps.put(VehicleProperty.HVAC_TEMPERATURE_SET, new Pair<>(
+ Car.PERMISSION_CONTROL_CAR_CLIMATE,
+ Car.PERMISSION_CONTROL_CAR_CLIMATE));
+ mProps.put(VehicleProperty.HVAC_DEFROSTER, new Pair<>(
+ Car.PERMISSION_CONTROL_CAR_CLIMATE,
+ Car.PERMISSION_CONTROL_CAR_CLIMATE));
+ mProps.put(VehicleProperty.HVAC_AC_ON, new Pair<>(
+ Car.PERMISSION_CONTROL_CAR_CLIMATE,
+ Car.PERMISSION_CONTROL_CAR_CLIMATE));
+ mProps.put(VehicleProperty.HVAC_MAX_AC_ON, new Pair<>(
+ Car.PERMISSION_CONTROL_CAR_CLIMATE,
+ Car.PERMISSION_CONTROL_CAR_CLIMATE));
+ mProps.put(VehicleProperty.HVAC_MAX_DEFROST_ON, new Pair<>(
+ Car.PERMISSION_CONTROL_CAR_CLIMATE,
+ Car.PERMISSION_CONTROL_CAR_CLIMATE));
+ mProps.put(VehicleProperty.HVAC_RECIRC_ON, new Pair<>(
+ Car.PERMISSION_CONTROL_CAR_CLIMATE,
+ Car.PERMISSION_CONTROL_CAR_CLIMATE));
+ mProps.put(VehicleProperty.HVAC_DUAL_ON, new Pair<>(
+ Car.PERMISSION_CONTROL_CAR_CLIMATE,
+ Car.PERMISSION_CONTROL_CAR_CLIMATE));
+ mProps.put(VehicleProperty.HVAC_AUTO_ON, new Pair<>(
+ Car.PERMISSION_CONTROL_CAR_CLIMATE,
+ Car.PERMISSION_CONTROL_CAR_CLIMATE));
+ mProps.put(VehicleProperty.HVAC_SEAT_TEMPERATURE, new Pair<>(
+ Car.PERMISSION_CONTROL_CAR_CLIMATE,
+ Car.PERMISSION_CONTROL_CAR_CLIMATE));
+ mProps.put(VehicleProperty.HVAC_SIDE_MIRROR_HEAT, new Pair<>(
+ Car.PERMISSION_CONTROL_CAR_CLIMATE,
+ Car.PERMISSION_CONTROL_CAR_CLIMATE));
+ mProps.put(VehicleProperty.HVAC_STEERING_WHEEL_HEAT, new Pair<>(
+ Car.PERMISSION_CONTROL_CAR_CLIMATE,
+ Car.PERMISSION_CONTROL_CAR_CLIMATE));
+ mProps.put(VehicleProperty.HVAC_TEMPERATURE_DISPLAY_UNITS, new Pair<>(
+ Car.PERMISSION_CONTROL_CAR_CLIMATE,
+ Car.PERMISSION_CONTROL_CAR_CLIMATE));
+ mProps.put(VehicleProperty.HVAC_ACTUAL_FAN_SPEED_RPM, new Pair<>(
+ Car.PERMISSION_CONTROL_CAR_CLIMATE,
+ Car.PERMISSION_CONTROL_CAR_CLIMATE));
+ mProps.put(VehicleProperty.HVAC_POWER_ON, new Pair<>(
+ Car.PERMISSION_CONTROL_CAR_CLIMATE,
+ Car.PERMISSION_CONTROL_CAR_CLIMATE));
+ mProps.put(VehicleProperty.HVAC_FAN_DIRECTION_AVAILABLE, new Pair<>(
+ Car.PERMISSION_CONTROL_CAR_CLIMATE,
+ Car.PERMISSION_CONTROL_CAR_CLIMATE));
+ mProps.put(VehicleProperty.HVAC_AUTO_RECIRC_ON, new Pair<>(
+ Car.PERMISSION_CONTROL_CAR_CLIMATE,
+ Car.PERMISSION_CONTROL_CAR_CLIMATE));
+ mProps.put(VehicleProperty.HVAC_SEAT_VENTILATION, new Pair<>(
+ Car.PERMISSION_CONTROL_CAR_CLIMATE,
+ Car.PERMISSION_CONTROL_CAR_CLIMATE));
+ mProps.put(VehicleProperty.ENV_OUTSIDE_TEMPERATURE, new Pair<>(
+ Car.PERMISSION_CONTROL_CAR_CLIMATE,
+ Car.PERMISSION_CONTROL_CAR_CLIMATE));
+
+ // Info properties
+ mProps.put(VehicleProperty.INFO_VIN, new Pair<>(
+ Car.PERMISSION_IDENTIFICATION,
+ Car.PERMISSION_IDENTIFICATION));
+ mProps.put(VehicleProperty.INFO_MAKE, new Pair<>(
+ Car.PERMISSION_CAR_INFO,
+ Car.PERMISSION_CAR_INFO));
+ mProps.put(VehicleProperty.INFO_MODEL, new Pair<>(
+ Car.PERMISSION_CAR_INFO,
+ Car.PERMISSION_CAR_INFO));
+ mProps.put(VehicleProperty.INFO_MODEL_YEAR, new Pair<>(
+ Car.PERMISSION_CAR_INFO,
+ Car.PERMISSION_CAR_INFO));
+ mProps.put(VehicleProperty.INFO_FUEL_CAPACITY, new Pair<>(
+ Car.PERMISSION_CAR_INFO,
+ Car.PERMISSION_CAR_INFO));
+ mProps.put(VehicleProperty.INFO_FUEL_TYPE, new Pair<>(
+ Car.PERMISSION_CAR_INFO,
+ Car.PERMISSION_CAR_INFO));
+ mProps.put(VehicleProperty.INFO_EV_BATTERY_CAPACITY, new Pair<>(
+ Car.PERMISSION_CAR_INFO,
+ Car.PERMISSION_CAR_INFO));
+ mProps.put(VehicleProperty.INFO_EV_CONNECTOR_TYPE, new Pair<>(
+ Car.PERMISSION_CAR_INFO,
+ Car.PERMISSION_CAR_INFO));
+ mProps.put(VehicleProperty.INFO_FUEL_DOOR_LOCATION, new Pair<>(
+ Car.PERMISSION_CAR_INFO,
+ Car.PERMISSION_CAR_INFO));
+ mProps.put(VehicleProperty.INFO_EV_PORT_LOCATION, new Pair<>(
+ Car.PERMISSION_CAR_INFO,
+ Car.PERMISSION_CAR_INFO));
+ mProps.put(VehicleProperty.INFO_DRIVER_SEAT, new Pair<>(
+ Car.PERMISSION_CAR_INFO,
+ Car.PERMISSION_CAR_INFO));
+
+ // Sensor properties
+ mProps.put(VehicleProperty.PERF_ODOMETER, new Pair<>(
+ Car.PERMISSION_MILEAGE,
+ Car.PERMISSION_MILEAGE));
+ mProps.put(VehicleProperty.PERF_VEHICLE_SPEED, 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));
+ mProps.put(VehicleProperty.ENGINE_OIL_LEVEL, new Pair<>(
+ Car.PERMISSION_CAR_ENGINE_DETAILED,
+ Car.PERMISSION_CAR_ENGINE_DETAILED));
+ mProps.put(VehicleProperty.ENGINE_OIL_TEMP, new Pair<>(
+ Car.PERMISSION_CAR_ENGINE_DETAILED,
+ Car.PERMISSION_CAR_ENGINE_DETAILED));
+ mProps.put(VehicleProperty.ENGINE_RPM, new Pair<>(
+ Car.PERMISSION_CAR_ENGINE_DETAILED,
+ Car.PERMISSION_CAR_ENGINE_DETAILED));
+ mProps.put(VehicleProperty.WHEEL_TICK, new Pair<>(
+ Car.PERMISSION_SPEED,
+ Car.PERMISSION_SPEED));
+ mProps.put(VehicleProperty.FUEL_LEVEL, new Pair<>(
+ Car.PERMISSION_ENERGY,
+ Car.PERMISSION_ENERGY));
+ mProps.put(VehicleProperty.FUEL_DOOR_OPEN, new Pair<>(
+ Car.PERMISSION_ENERGY_PORTS,
+ Car.PERMISSION_ENERGY_PORTS));
+ mProps.put(VehicleProperty.EV_BATTERY_LEVEL, new Pair<>(
+ Car.PERMISSION_ENERGY,
+ Car.PERMISSION_ENERGY));
+ mProps.put(VehicleProperty.EV_CHARGE_PORT_OPEN, new Pair<>(
+ Car.PERMISSION_ENERGY_PORTS,
+ Car.PERMISSION_ENERGY_PORTS));
+ mProps.put(VehicleProperty.EV_CHARGE_PORT_CONNECTED, new Pair<>(
+ Car.PERMISSION_ENERGY_PORTS,
+ Car.PERMISSION_ENERGY_PORTS));
+ mProps.put(VehicleProperty.EV_BATTERY_INSTANTANEOUS_CHARGE_RATE, new Pair<>(
+ Car.PERMISSION_ENERGY,
+ Car.PERMISSION_ENERGY));
+ mProps.put(VehicleProperty.RANGE_REMAINING, new Pair<>(
+ Car.PERMISSION_ENERGY,
+ Car.PERMISSION_ENERGY));
+ mProps.put(VehicleProperty.TIRE_PRESSURE, new Pair<>(
+ Car.PERMISSION_TIRES,
+ Car.PERMISSION_TIRES));
+ mProps.put(VehicleProperty.GEAR_SELECTION, new Pair<>(
+ Car.PERMISSION_POWERTRAIN,
+ Car.PERMISSION_POWERTRAIN));
+ mProps.put(VehicleProperty.CURRENT_GEAR, new Pair<>(
+ Car.PERMISSION_POWERTRAIN,
+ Car.PERMISSION_POWERTRAIN));
+ mProps.put(VehicleProperty.PARKING_BRAKE_ON, new Pair<>(
+ Car.PERMISSION_POWERTRAIN,
+ Car.PERMISSION_POWERTRAIN));
+ mProps.put(VehicleProperty.PARKING_BRAKE_AUTO_APPLY, new Pair<>(
+ Car.PERMISSION_POWERTRAIN,
+ Car.PERMISSION_POWERTRAIN));
+ mProps.put(VehicleProperty.FUEL_LEVEL_LOW, new Pair<>(
+ Car.PERMISSION_ENERGY,
+ Car.PERMISSION_ENERGY));
+ mProps.put(VehicleProperty.NIGHT_MODE, new Pair<>(
+ Car.PERMISSION_EXTERIOR_ENVIRONMENT,
+ Car.PERMISSION_EXTERIOR_ENVIRONMENT));
+ mProps.put(VehicleProperty.TURN_SIGNAL_STATE, new Pair<>(
+ Car.PERMISSION_EXTERIOR_LIGHTS,
+ Car.PERMISSION_EXTERIOR_LIGHTS));
+ mProps.put(VehicleProperty.IGNITION_STATE, new Pair<>(
+ Car.PERMISSION_CAR_POWER,
+ Car.PERMISSION_CAR_POWER));
+ mProps.put(VehicleProperty.ABS_ACTIVE, new Pair<>(
+ Car.PERMISSION_CAR_DYNAMICS_STATE,
+ Car.PERMISSION_CAR_DYNAMICS_STATE));
+ mProps.put(VehicleProperty.TRACTION_CONTROL_ACTIVE, new Pair<>(
+ Car.PERMISSION_CAR_DYNAMICS_STATE,
+ Car.PERMISSION_CAR_DYNAMICS_STATE));
+ mProps.put(VehicleProperty.ENV_OUTSIDE_TEMPERATURE, new Pair<>(
+ Car.PERMISSION_EXTERIOR_ENVIRONMENT,
+ Car.PERMISSION_EXTERIOR_ENVIRONMENT));
+ mProps.put(VehicleProperty.HEADLIGHTS_STATE, new Pair<>(
+ Car.PERMISSION_EXTERIOR_LIGHTS,
+ Car.PERMISSION_EXTERIOR_LIGHTS));
+ mProps.put(VehicleProperty.HIGH_BEAM_LIGHTS_STATE, new Pair<>(
+ Car.PERMISSION_EXTERIOR_LIGHTS,
+ Car.PERMISSION_EXTERIOR_LIGHTS));
+ mProps.put(VehicleProperty.FOG_LIGHTS_STATE, new Pair<>(
+ Car.PERMISSION_EXTERIOR_LIGHTS,
+ Car.PERMISSION_EXTERIOR_LIGHTS));
+ mProps.put(VehicleProperty.HAZARD_LIGHTS_STATE, new Pair<>(
+ Car.PERMISSION_EXTERIOR_LIGHTS,
+ Car.PERMISSION_EXTERIOR_LIGHTS));
+ mProps.put(VehicleProperty.HEADLIGHTS_SWITCH, new Pair<>(
+ Car.PERMISSION_EXTERIOR_LIGHTS,
+ Car.PERMISSION_CONTROL_EXTERIOR_LIGHTS));
+ mProps.put(VehicleProperty.HIGH_BEAM_LIGHTS_SWITCH, new Pair<>(
+ Car.PERMISSION_EXTERIOR_LIGHTS,
+ Car.PERMISSION_CONTROL_EXTERIOR_LIGHTS));
+ mProps.put(VehicleProperty.FOG_LIGHTS_SWITCH, new Pair<>(
+ Car.PERMISSION_EXTERIOR_LIGHTS,
+ Car.PERMISSION_CONTROL_EXTERIOR_LIGHTS));
+ mProps.put(VehicleProperty.HAZARD_LIGHTS_SWITCH, new Pair<>(
+ Car.PERMISSION_EXTERIOR_LIGHTS,
+ Car.PERMISSION_CONTROL_EXTERIOR_LIGHTS));
+ }
+
+ /**
+ * Returns read permission string for given property ID.
+ */
+ @Nullable
+ public String getReadPermission(int propId) {
+ Pair<String, String> p = mProps.get(propId);
+ if (p != null) {
+ // Property ID exists. Return read permission.
+ return p.first;
+ } else {
+ return null;
+ }
+ }
+
+ /**
+ * Returns write permission string for given property ID.
+ */
+ @Nullable
+ public String getWritePermission(int propId) {
+ Pair<String, String> p = mProps.get(propId);
+ if (p != null) {
+ // Property ID exists. Return write permission.
+ return p.second;
+ } else {
+ return null;
+ }
+ }
+
+ /**
+ * Return true if property is a vendor property and was added
+ */
+ public boolean insertVendorProperty(int propId) {
+ if ((propId & VehiclePropertyGroup.MASK) == VehiclePropertyGroup.VENDOR) {
+ mProps.put(propId, new Pair<>(
+ Car.PERMISSION_VENDOR_EXTENSION, Car.PERMISSION_VENDOR_EXTENSION));
+ return true;
+ } else {
+ // This is not a vendor extension property, it is not added
+ return false;
+ }
+ }
+
+ /**
+ * Check if property ID is in the list of known IDs that PropertyHalService is interested it.
+ */
+ public boolean isSupportedProperty(int propId) {
+ if (mProps.get(propId) != null) {
+ // Property is in the list of supported properties
+ return true;
+ } else {
+ // If it's a vendor property, insert it into the propId list and handle it
+ return insertVendorProperty(propId);
+ }
+ }
+}
diff --git a/service/src/com/android/car/hal/RadioHalService.java b/service/src/com/android/car/hal/RadioHalService.java
deleted file mode 100644
index 3c20d72..0000000
--- a/service/src/com/android/car/hal/RadioHalService.java
+++ /dev/null
@@ -1,276 +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.hal;
-
-import android.annotation.Nullable;
-import android.car.hardware.radio.CarRadioEvent;
-import android.car.hardware.radio.CarRadioPreset;
-import android.hardware.radio.RadioManager;
-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.hardware.automotive.vehicle.V2_0.VehicleRadioConstants;
-import android.util.Log;
-
-import com.android.car.CarLog;
-
-import java.io.PrintWriter;
-import java.util.Arrays;
-import java.util.Collection;
-import java.util.LinkedList;
-import java.util.List;
-
-/**
- * This class exposes the Radio related features in the HAL layer.
- *
- * The current set of features support radio presets. The rest of the radio functionality is already
- * covered under RadioManager API.
- */
-public class RadioHalService extends HalServiceBase {
- public static boolean DBG = false;
- public static String TAG = CarLog.TAG_HAL + ".RadioHalService";
-
- private int mPresetCount = 0;
- private VehicleHal mHal;
- private RadioListener mListener;
-
- public interface RadioListener {
- void onEvent(CarRadioEvent event);
- }
-
- public RadioHalService(VehicleHal hal) {
- mHal = hal;
- }
-
- @Override
- public synchronized void init() {
- }
-
- @Override
- public synchronized void release() {
- mListener = null;
- }
-
- @Override
- public synchronized Collection<VehiclePropConfig> takeSupportedProperties(
- Collection<VehiclePropConfig> allProperties) {
- Collection<VehiclePropConfig> supported = new LinkedList<>();
- for (VehiclePropConfig p : allProperties) {
- if (handleRadioProperty(p)) {
- supported.add(p);
- }
- }
- return supported;
- }
-
- @Override
- public void handleHalEvents(List<VehiclePropValue> values) {
- if (DBG) {
- Log.d(TAG, "handleHalEvents");
- }
- RadioHalService.RadioListener radioListener;
- synchronized (this) {
- radioListener = mListener;
- }
-
- if (radioListener == null) {
- Log.e(TAG, "radio listener is null, ignoring event: " + values);
- return;
- }
-
- for (VehiclePropValue v : values) {
- CarRadioEvent radioEvent = createCarRadioEvent(v);
- if (radioEvent != null) {
- if (DBG) {
- Log.d(TAG, "Sending event to listener: " + radioEvent);
- }
- radioListener.onEvent(radioEvent);
- } else {
- Log.w(TAG, "Value conversion failed: " + v);
- }
- }
- }
-
- @Override
- public void dump(PrintWriter writer) {
- writer.println("*RadioHal*");
- writer.println("**Supported properties**");
- writer.println(VehicleProperty.RADIO_PRESET);
- if (mListener != null) {
- writer.println("Hal service registered.");
- }
- }
-
- public synchronized void registerListener(RadioListener listener) {
- if (DBG) {
- Log.d(TAG, "registerListener");
- }
- mListener = listener;
-
- // Subscribe to all radio properties.
- mHal.subscribeProperty(this, VehicleProperty.RADIO_PRESET);
- }
-
- public synchronized void unregisterListener() {
- if (DBG) {
- Log.d(TAG, "unregisterListener");
- }
- mListener = null;
-
- // Unsubscribe from all properties.
- mHal.unsubscribeProperty(this, VehicleProperty.RADIO_PRESET);
- }
-
- public synchronized int getPresetCount() {
- Log.d(TAG, "get preset count: " + mPresetCount);
- return mPresetCount;
- }
-
- @Nullable
- public CarRadioPreset getRadioPreset(int presetNumber) {
- // Check if the preset number is out of range. We should return NULL if that is the case.
- if (DBG) {
- Log.d(TAG, "getRadioPreset called with preset number " + presetNumber);
- }
- if (!isValidPresetNumber(presetNumber)) {
- throw new IllegalArgumentException("Preset number not valid: " + presetNumber);
- }
-
- VehiclePropValue presetNumberValue = new VehiclePropValue();
- presetNumberValue.prop = VehicleProperty.RADIO_PRESET;
- presetNumberValue.value.int32Values.addAll(Arrays.asList(presetNumber, 0, 0, 0));
-
- VehiclePropValue presetConfig;
- try {
- presetConfig = mHal.get(presetNumberValue);
- } catch (PropertyTimeoutException e) {
- Log.e(TAG, "property VehicleProperty.RADIO_PRESET not ready", e);
- return null;
- }
- // Sanity check the output from HAL.
- if (presetConfig.value.int32Values.size() != 4) {
- Log.e(TAG, "Return value does not have 4 elements: " +
- Arrays.toString(presetConfig.value.int32Values.toArray()));
- throw new IllegalStateException(
- "Invalid preset returned from service: "
- + Arrays.toString(presetConfig.value.int32Values.toArray()));
- }
-
- int retPresetNumber = presetConfig.value.int32Values.get(0);
- int retBand = presetConfig.value.int32Values.get(1);
- int retChannel = presetConfig.value.int32Values.get(2);
- int retSubChannel = presetConfig.value.int32Values.get(3);
- if (retPresetNumber != presetNumber) {
- Log.e(TAG, "Preset number is not the same: " + presetNumber + " vs " + retPresetNumber);
- return null;
- }
- if (!isValidBand(retBand)) return null;
-
- // Return the actual config.
- CarRadioPreset retConfig =
- new CarRadioPreset(retPresetNumber, retBand, retChannel, retSubChannel);
- if (DBG) {
- Log.d(TAG, "Preset obtained: " + retConfig);
- }
- return retConfig;
- }
-
- public boolean setRadioPreset(CarRadioPreset preset) {
- if (DBG) {
- Log.d(TAG, "setRadioPreset with config " + preset);
- }
-
- if (!isValidPresetNumber(preset.getPresetNumber()) ||
- !isValidBand(preset.getBand())) {
- return false;
- }
-
- try {
- mHal.set(VehicleProperty.RADIO_PRESET).to(new int[] {
- preset.getPresetNumber(),
- preset.getBand(),
- preset.getChannel(),
- preset.getSubChannel()});
- } catch (PropertyTimeoutException e) {
- Log.e(CarLog.TAG_POWER, "cannot set to RADIO_PRESET", e);
- return false;
- }
- return true;
- }
-
- private boolean isValidPresetNumber(int presetNumber) {
- // Check for preset number.
- if (presetNumber < VehicleRadioConstants.VEHICLE_RADIO_PRESET_MIN_VALUE
- || presetNumber > mPresetCount) {
- Log.e(TAG, "Preset number not in range (1, " + mPresetCount + ") - " + presetNumber);
- return false;
- }
- return true;
- }
-
- private boolean isValidBand(int band) {
- // Check for band info.
- if (band != RadioManager.BAND_AM &&
- band != RadioManager.BAND_FM &&
- band != RadioManager.BAND_FM_HD &&
- band != RadioManager.BAND_AM_HD) {
- Log.e(TAG, "Preset band is not valid: " + band);
- return false;
- }
- return true;
- }
-
- private boolean handleRadioProperty(VehiclePropConfig property) {
- switch (property.prop) {
- case VehicleProperty.RADIO_PRESET:
- // Extract the count of presets.
- mPresetCount = property.configArray.get(0);
- Log.d(TAG, "Read presets count: " + mPresetCount);
- return true;
- default:
- return false;
- }
- // Should never come here.
- }
-
- private CarRadioEvent createCarRadioEvent(VehiclePropValue v) {
- switch (v.prop) {
- case VehicleProperty.RADIO_PRESET:
- int vecSize = v.value.int32Values.size();
- if (vecSize != 4) {
- Log.e(TAG, "Returned a wrong array size: " + vecSize);
- return null;
- }
-
- Integer intValues[] = new Integer[4];
- v.value.int32Values.toArray(intValues);
-
- // Verify the correctness of the values.
- if (!isValidPresetNumber(intValues[0]) && !isValidBand(intValues[1])) {
- return null;
- }
-
- CarRadioPreset preset =
- new CarRadioPreset(intValues[0], intValues[1], intValues[2], intValues[3]);
- CarRadioEvent event = new CarRadioEvent(CarRadioEvent.RADIO_PRESET, preset);
- return event;
- default:
- Log.e(TAG, "createCarRadioEvent: Value not supported as event: " + v);
- return null;
- }
- }
-}
diff --git a/service/src/com/android/car/hal/SensorHalService.java b/service/src/com/android/car/hal/SensorHalService.java
deleted file mode 100644
index 6ee56a4..0000000
--- a/service/src/com/android/car/hal/SensorHalService.java
+++ /dev/null
@@ -1,339 +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.hal;
-
-import static java.lang.Integer.toHexString;
-
-import android.annotation.Nullable;
-import android.car.hardware.CarSensorConfig;
-import android.car.hardware.CarSensorEvent;
-import android.car.hardware.CarSensorManager;
-import android.hardware.automotive.vehicle.V2_0.VehicleGear;
-import android.hardware.automotive.vehicle.V2_0.VehicleIgnitionState;
-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.hardware.automotive.vehicle.V2_0.VehiclePropertyAccess;
-import android.hardware.automotive.vehicle.V2_0.VehiclePropertyChangeMode;
-import android.hardware.automotive.vehicle.V2_0.VehiclePropertyType;
-import android.os.Bundle;
-import android.util.Log;
-import android.util.SparseIntArray;
-import com.android.car.CarLog;
-import com.android.car.CarSensorEventFactory;
-import java.io.PrintWriter;
-import java.util.ArrayList;
-import java.util.LinkedList;
-import java.util.List;
-
-/**
- * Sensor HAL implementation for physical sensors in car.
- */
-public class SensorHalService extends SensorHalServiceBase {
- private static final String TAG = CarLog.concatTag(CarLog.TAG_SENSOR, SensorHalService.class);
- private static final boolean DBG_EVENTS = false;
-
- /**
- * Listener for monitoring sensor event. Only sensor service will implement this.
- */
- public interface SensorListener {
- /**
- * Sensor events are available.
- *
- * @param events
- */
- void onSensorEvents(List<CarSensorEvent> events);
- }
-
- // Manager property Id to HAL property Id mapping.
- private final static ManagerToHalPropIdMap mManagerToHalPropIdMap =
- ManagerToHalPropIdMap.create(
- CarSensorManager.SENSOR_TYPE_CAR_SPEED, VehicleProperty.PERF_VEHICLE_SPEED,
- CarSensorManager.SENSOR_TYPE_RPM, VehicleProperty.ENGINE_RPM,
- CarSensorManager.SENSOR_TYPE_ODOMETER, VehicleProperty.PERF_ODOMETER,
- CarSensorManager.SENSOR_TYPE_GEAR, VehicleProperty.GEAR_SELECTION,
- CarSensorManager.SENSOR_TYPE_NIGHT, VehicleProperty.NIGHT_MODE,
- CarSensorManager.SENSOR_TYPE_PARKING_BRAKE, VehicleProperty.PARKING_BRAKE_ON,
- CarSensorManager.SENSOR_TYPE_DRIVING_STATUS, VehicleProperty.DRIVING_STATUS,
- CarSensorManager.SENSOR_TYPE_FUEL_LEVEL, VehicleProperty.FUEL_LEVEL_LOW,
- CarSensorManager.SENSOR_TYPE_IGNITION_STATE, VehicleProperty.IGNITION_STATE,
- CarSensorManager.SENSOR_TYPE_WHEEL_TICK_DISTANCE, VehicleProperty.WHEEL_TICK,
- CarSensorManager.SENSOR_TYPE_ABS_ACTIVE, VehicleProperty.ABS_ACTIVE,
- CarSensorManager.SENSOR_TYPE_TRACTION_CONTROL_ACTIVE,
- VehicleProperty.TRACTION_CONTROL_ACTIVE
- );
-
- private final static SparseIntArray mMgrGearToHalMap = initSparseIntArray(
- VehicleGear.GEAR_NEUTRAL, CarSensorEvent.GEAR_NEUTRAL,
- VehicleGear.GEAR_REVERSE, CarSensorEvent.GEAR_REVERSE,
- VehicleGear.GEAR_PARK, CarSensorEvent.GEAR_PARK,
- VehicleGear.GEAR_DRIVE, CarSensorEvent.GEAR_DRIVE,
- VehicleGear.GEAR_LOW, CarSensorEvent.GEAR_FIRST, // Also GEAR_1 - the value is the same.
- VehicleGear.GEAR_2, CarSensorEvent.GEAR_SECOND,
- VehicleGear.GEAR_3, CarSensorEvent.GEAR_THIRD,
- VehicleGear.GEAR_4, CarSensorEvent.GEAR_FOURTH,
- VehicleGear.GEAR_5, CarSensorEvent.GEAR_FIFTH,
- VehicleGear.GEAR_6, CarSensorEvent.GEAR_SIXTH,
- VehicleGear.GEAR_7, CarSensorEvent.GEAR_SEVENTH,
- VehicleGear.GEAR_8, CarSensorEvent.GEAR_EIGHTH,
- VehicleGear.GEAR_9, CarSensorEvent.GEAR_NINTH);
-
- private final static SparseIntArray mMgrIgnitionStateToHalMap = initSparseIntArray(
- VehicleIgnitionState.UNDEFINED, CarSensorEvent.IGNITION_STATE_UNDEFINED,
- VehicleIgnitionState.LOCK, CarSensorEvent.IGNITION_STATE_LOCK,
- VehicleIgnitionState.OFF, CarSensorEvent.IGNITION_STATE_OFF,
- VehicleIgnitionState.ACC, CarSensorEvent.IGNITION_STATE_ACC,
- VehicleIgnitionState.ON, CarSensorEvent.IGNITION_STATE_ON,
- VehicleIgnitionState.START, CarSensorEvent.IGNITION_STATE_START);
-
- private SensorListener mSensorListener;
-
- private int[] mMicrometersPerWheelTick = {0, 0, 0, 0};
-
- @Override
- public void init() {
- VehiclePropConfig config;
- // Populate internal values if available
- synchronized (this) {
- config = mSensorToPropConfig.get(CarSensorManager.SENSOR_TYPE_WHEEL_TICK_DISTANCE);
- }
- if (config == null) {
- Log.e(TAG, "init: unable to get property config for SENSOR_TYPE_WHEEL_TICK_DISTANCE");
- } else {
- for (int i = 0; i < 4; i++) {
- mMicrometersPerWheelTick[i] = config.configArray.get(i +
- INDEX_WHEEL_DISTANCE_FRONT_LEFT);
- }
- }
- super.init();
- }
-
- public SensorHalService(VehicleHal hal) {
- super(hal);
- }
-
- public synchronized void registerSensorListener(SensorListener listener) {
- mSensorListener = listener;
- }
-
- @Override
- protected int getTokenForProperty(VehiclePropConfig halProperty) {
- int sensor = mManagerToHalPropIdMap.getManagerPropId(halProperty.prop);
- if (sensor != SENSOR_TYPE_INVALID
- && halProperty.changeMode != VehiclePropertyChangeMode.STATIC
- && ((halProperty.access & VehiclePropertyAccess.READ) != 0)) {
- return sensor;
- }
- return SENSOR_TYPE_INVALID;
- }
-
- // Should be used only inside handleHalEvents method.
- private final LinkedList<CarSensorEvent> mEventsToDispatch = new LinkedList<>();
-
- @Override
- public void handleHalEvents(List<VehiclePropValue> values) {
- for (VehiclePropValue v : values) {
- CarSensorEvent event = createCarSensorEvent(v);
- if (event != null) {
- mEventsToDispatch.add(event);
- }
- }
- SensorListener sensorListener;
- synchronized (this) {
- sensorListener = mSensorListener;
- }
- if (DBG_EVENTS) Log.d(TAG, "handleHalEvents, listener: " + sensorListener);
- if (sensorListener != null) {
- sensorListener.onSensorEvents(mEventsToDispatch);
- }
- mEventsToDispatch.clear();
- }
-
- @Nullable
- private Integer mapHalEnumValueToMgr(int propId, int halValue) {
- int mgrValue = halValue;
-
- switch (propId) {
- case VehicleProperty.GEAR_SELECTION:
- mgrValue = mMgrGearToHalMap.get(halValue, -1);
- break;
- case VehicleProperty.IGNITION_STATE:
- mgrValue = mMgrIgnitionStateToHalMap.get(halValue, -1);
- default:
- break; // Do nothing
- }
- return mgrValue == -1 ? null : mgrValue;
- }
-
- @Nullable
- private CarSensorEvent createCarSensorEvent(VehiclePropValue v) {
- int property = v.prop;
- int sensorType = mManagerToHalPropIdMap.getManagerPropId(property);
- if (sensorType == SENSOR_TYPE_INVALID) {
- throw new RuntimeException("no sensor defined for property 0x" + toHexString(property));
- }
- // Handle the valid sensor
- int dataType = property & VehiclePropertyType.MASK;
- CarSensorEvent event = null;
- switch (dataType) {
- case VehiclePropertyType.BOOLEAN:
- event = CarSensorEventFactory.createBooleanEvent(sensorType, v.timestamp,
- v.value.int32Values.get(0) == 1);
- break;
- case VehiclePropertyType.COMPLEX:
- event = CarSensorEventFactory.createComplexEvent(sensorType, v.timestamp, v);
- break;
- case VehiclePropertyType.INT32:
- Integer mgrVal = mapHalEnumValueToMgr(property, v.value.int32Values.get(0));
- event = mgrVal == null ? null
- : CarSensorEventFactory.createIntEvent(sensorType, v.timestamp, mgrVal);
- break;
- case VehiclePropertyType.FLOAT:
- event = CarSensorEventFactory.createFloatEvent(sensorType, v.timestamp,
- v.value.floatValues.get(0));
- break;
- default:
- Log.w(TAG, "createCarSensorEvent: unsupported type: 0x" + toHexString(dataType));
- break;
- }
- // Perform property specific actions
- switch (property) {
- case VehicleProperty.WHEEL_TICK:
- // Apply the um/tick scaling factor, then divide by 1000 to generate mm
- for (int i = 0; i < 4; i++) {
- // ResetCounts is at longValues[0]
- if (event.longValues[i + CarSensorEvent.INDEX_WHEEL_DISTANCE_FRONT_LEFT] !=
- Long.MAX_VALUE) {
- event.longValues[i + CarSensorEvent.INDEX_WHEEL_DISTANCE_FRONT_LEFT] *=
- mMicrometersPerWheelTick[i];
- event.longValues[i + CarSensorEvent.INDEX_WHEEL_DISTANCE_FRONT_LEFT] /=
- 1000;
- }
- }
- break;
- }
- if (DBG_EVENTS) Log.i(TAG, "Sensor event created: " + event);
- return event;
- }
-
- @Nullable
- public CarSensorEvent getCurrentSensorValue(int sensorType) {
- VehiclePropValue propValue = getCurrentSensorVehiclePropValue(sensorType);
- return (null != propValue) ? createCarSensorEvent(propValue) : null;
- }
-
- @Override
- protected float fixSamplingRateForProperty(VehiclePropConfig prop, int carSensorManagerRate) {
- switch (prop.changeMode) {
- case VehiclePropertyChangeMode.ON_CHANGE:
- case VehiclePropertyChangeMode.ON_SET:
- return 0;
- }
- float rate = 1.0f;
- switch (carSensorManagerRate) {
- case CarSensorManager.SENSOR_RATE_FASTEST:
- rate = prop.maxSampleRate;
- break;
- case CarSensorManager.SENSOR_RATE_FAST:
- rate = 10f; // every 100ms
- break;
- case CarSensorManager.SENSOR_RATE_UI:
- rate = 5f; // every 200ms
- break;
- default: // fall back to default.
- break;
- }
- if (rate > prop.maxSampleRate) {
- rate = prop.maxSampleRate;
- }
- if (rate < prop.minSampleRate) {
- rate = prop.minSampleRate;
- }
- return rate;
- }
-
- @Override
- public void dump(PrintWriter writer) {
- writer.println("*Sensor HAL*");
- writer.println("**Supported properties**");
- for (int i = 0; i < mSensorToPropConfig.size(); i++) {
- writer.println(mSensorToPropConfig.valueAt(i).toString());
- }
- for (int i = 0; i < mMicrometersPerWheelTick.length; i++) {
- writer.println("mMicrometersPerWheelTick[" + i + "] = " + mMicrometersPerWheelTick[i]);
- }
- }
-
- private static SparseIntArray initSparseIntArray(int... keyValuePairs) {
- int inputLength = keyValuePairs.length;
- if (inputLength % 2 != 0) {
- throw new IllegalArgumentException("Odd number of key-value elements");
- }
-
- SparseIntArray map = new SparseIntArray(inputLength / 2);
- for (int i = 0; i < keyValuePairs.length; i += 2) {
- map.put(keyValuePairs[i], keyValuePairs[i + 1]);
- }
- return map;
- }
-
- private static final int INDEX_WHEEL_DISTANCE_ENABLE_FLAG = 0;
- private static final int INDEX_WHEEL_DISTANCE_FRONT_LEFT = 1;
- private static final int INDEX_WHEEL_DISTANCE_FRONT_RIGHT = 2;
- private static final int INDEX_WHEEL_DISTANCE_REAR_RIGHT = 3;
- private static final int INDEX_WHEEL_DISTANCE_REAR_LEFT = 4;
- private static final int WHEEL_TICK_DISTANCE_BUNDLE_SIZE = 6;
-
- private Bundle createWheelDistanceTickBundle(ArrayList<Integer> configArray) {
- Bundle b = new Bundle(WHEEL_TICK_DISTANCE_BUNDLE_SIZE);
- b.putInt(CarSensorConfig.WHEEL_TICK_DISTANCE_SUPPORTED_WHEELS,
- configArray.get(INDEX_WHEEL_DISTANCE_ENABLE_FLAG));
- b.putInt(CarSensorConfig.WHEEL_TICK_DISTANCE_FRONT_LEFT_UM_PER_TICK,
- configArray.get(INDEX_WHEEL_DISTANCE_FRONT_LEFT));
- b.putInt(CarSensorConfig.WHEEL_TICK_DISTANCE_FRONT_RIGHT_UM_PER_TICK,
- configArray.get(INDEX_WHEEL_DISTANCE_FRONT_RIGHT));
- b.putInt(CarSensorConfig.WHEEL_TICK_DISTANCE_REAR_RIGHT_UM_PER_TICK,
- configArray.get(INDEX_WHEEL_DISTANCE_REAR_RIGHT));
- b.putInt(CarSensorConfig.WHEEL_TICK_DISTANCE_REAR_LEFT_UM_PER_TICK,
- configArray.get(INDEX_WHEEL_DISTANCE_REAR_LEFT));
- return b;
- }
-
-
- public CarSensorConfig getSensorConfig(int sensorType) {
- VehiclePropConfig cfg;
- synchronized (this) {
- cfg = mSensorToPropConfig.get(sensorType);
- }
- if (cfg == null) {
- /* Invalid sensor type. */
- throw new IllegalArgumentException("Unknown sensorType = " + sensorType);
- } else {
- Bundle b;
- switch(sensorType) {
- case CarSensorManager.SENSOR_TYPE_WHEEL_TICK_DISTANCE:
- b = createWheelDistanceTickBundle(cfg.configArray);
- break;
- default:
- /* Unhandled config. Create empty bundle */
- b = Bundle.EMPTY;
- break;
- }
- return new CarSensorConfig(sensorType, b);
- }
- }
-}
\ No newline at end of file
diff --git a/service/src/com/android/car/hal/VehicleHal.java b/service/src/com/android/car/hal/VehicleHal.java
index 21f8f51..f73d07c 100644
--- a/service/src/com/android/car/hal/VehicleHal.java
+++ b/service/src/com/android/car/hal/VehicleHal.java
@@ -19,10 +19,10 @@
import static com.android.car.CarServiceUtils.toByteArray;
import static com.android.car.CarServiceUtils.toFloatArray;
import static com.android.car.CarServiceUtils.toIntArray;
+
import static java.lang.Integer.toHexString;
import android.annotation.CheckResult;
-import android.car.annotation.FutureFeature;
import android.hardware.automotive.vehicle.V2_0.IVehicle;
import android.hardware.automotive.vehicle.V2_0.IVehicleCallback;
import android.hardware.automotive.vehicle.V2_0.SubscribeFlags;
@@ -33,6 +33,7 @@
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.VehiclePropertyType;
import android.os.HandlerThread;
import android.os.RemoteException;
import android.os.SystemClock;
@@ -40,12 +41,11 @@
import android.util.Log;
import android.util.SparseArray;
-import com.google.android.collect.Lists;
-
import com.android.car.CarLog;
-import com.android.car.internal.FeatureConfiguration;
import com.android.internal.annotations.VisibleForTesting;
+import com.google.android.collect.Lists;
+
import java.io.PrintWriter;
import java.lang.ref.WeakReference;
import java.util.ArrayList;
@@ -69,21 +69,12 @@
private static final int NO_AREA = -1;
private final HandlerThread mHandlerThread;
- private final SensorHalService mSensorHal;
- private final InfoHalService mInfoHal;
- private final AudioHalService mAudioHal;
- private final CabinHalService mCabinHal;
- private final RadioHalService mRadioHal;
private final PowerHalService mPowerHal;
- private final HvacHalService mHvacHal;
+ private final PropertyHalService mPropertyHal;
private final InputHalService mInputHal;
- private final VendorExtensionHalService mVendorExtensionHal;
+ private final VmsHalService mVmsHal;
private DiagnosticHalService mDiagnosticHal = null;
- @FutureFeature
- private VmsHalService mVmsHal;
-
-
/** Might be re-assigned if Vehicle HAL is reconnected. */
private volatile HalClient mHalClient;
@@ -95,83 +86,39 @@
private final HashMap<Integer, VehiclePropConfig> mAllProperties = new HashMap<>();
private final HashMap<Integer, VehiclePropertyEventInfo> mEventLog = new HashMap<>();
+ // Used by injectVHALEvent for testing purposes. Delimiter for an array of data
+ private static final String DATA_DELIMITER = ",";
+
public VehicleHal(IVehicle vehicle) {
mHandlerThread = new HandlerThread("VEHICLE-HAL");
mHandlerThread.start();
// passing this should be safe as long as it is just kept and not used in constructor
mPowerHal = new PowerHalService(this);
- mSensorHal = new SensorHalService(this);
- mInfoHal = new InfoHalService(this);
- mAudioHal = new AudioHalService(this);
- mCabinHal = new CabinHalService(this);
- mRadioHal = new RadioHalService(this);
- mHvacHal = new HvacHalService(this);
+ mPropertyHal = new PropertyHalService(this);
mInputHal = new InputHalService(this);
- mVendorExtensionHal = new VendorExtensionHalService(this);
- if (FeatureConfiguration.ENABLE_VEHICLE_MAP_SERVICE) {
- mVmsHal = new VmsHalService(this);
- }
+ mVmsHal = new VmsHalService(this);
mDiagnosticHal = new DiagnosticHalService(this);
mAllServices.addAll(Arrays.asList(mPowerHal,
- mSensorHal,
- mInfoHal,
- mAudioHal,
- mCabinHal,
- mRadioHal,
- mHvacHal,
mInputHal,
- mVendorExtensionHal,
- mDiagnosticHal));
- if (FeatureConfiguration.ENABLE_VEHICLE_MAP_SERVICE) {
- mAllServices.add(mVmsHal);
- }
+ mPropertyHal,
+ mDiagnosticHal,
+ mVmsHal));
mHalClient = new HalClient(vehicle, mHandlerThread.getLooper(), this /*IVehicleCallback*/);
}
/** Dummy version only for testing */
@VisibleForTesting
- public VehicleHal(PowerHalService powerHal, SensorHalService sensorHal, InfoHalService infoHal,
- AudioHalService audioHal, CabinHalService cabinHal,
- RadioHalService radioHal, HvacHalService hvacHal, HalClient halClient) {
+ public VehicleHal(PowerHalService powerHal, DiagnosticHalService diagnosticHal,
+ HalClient halClient, PropertyHalService propertyHal) {
mHandlerThread = null;
mPowerHal = powerHal;
- mSensorHal = sensorHal;
- mInfoHal = infoHal;
- mAudioHal = audioHal;
- mCabinHal = cabinHal;
- mRadioHal = radioHal;
- mHvacHal = hvacHal;
+ mPropertyHal = propertyHal;
+ mDiagnosticHal = diagnosticHal;
mInputHal = null;
- mVendorExtensionHal = null;
- mDiagnosticHal = null;
-
- if (FeatureConfiguration.ENABLE_VEHICLE_MAP_SERVICE) {
- mVmsHal = null;
- }
-
+ mVmsHal = null;
mHalClient = halClient;
- }
-
- /** Dummy version only for testing */
- @VisibleForTesting
- public VehicleHal(PowerHalService powerHal, SensorHalService sensorHal, InfoHalService infoHal,
- AudioHalService audioHal, CabinHalService cabinHal, DiagnosticHalService diagnosticHal,
- RadioHalService radioHal, HvacHalService hvacHal, HalClient halClient) {
- mHandlerThread = null;
- mPowerHal = powerHal;
- mSensorHal = sensorHal;
- mInfoHal = infoHal;
- mAudioHal = audioHal;
- mCabinHal = cabinHal;
- mDiagnosticHal = diagnosticHal;
- mRadioHal = radioHal;
- mHvacHal = hvacHal;
- mInputHal = null;
- mVendorExtensionHal = null;
- mVmsHal = null;
- mHalClient = halClient;
- mDiagnosticHal = diagnosticHal;
+ mDiagnosticHal = diagnosticHal;
}
public void vehicleHalReconnected(IVehicle vehicle) {
@@ -243,45 +190,20 @@
// keep the looper thread as should be kept for the whole life cycle.
}
- public SensorHalService getSensorHal() {
- return mSensorHal;
- }
-
- public InfoHalService getInfoHal() {
- return mInfoHal;
- }
-
- public AudioHalService getAudioHal() {
- return mAudioHal;
- }
-
- public CabinHalService getCabinHal() {
- return mCabinHal;
- }
-
public DiagnosticHalService getDiagnosticHal() { return mDiagnosticHal; }
- public RadioHalService getRadioHal() {
- return mRadioHal;
- }
-
public PowerHalService getPowerHal() {
return mPowerHal;
}
- public HvacHalService getHvacHal() {
- return mHvacHal;
+ public PropertyHalService getPropertyHal() {
+ return mPropertyHal;
}
public InputHalService getInputHal() {
return mInputHal;
}
- public VendorExtensionHalService getVendorExtensionHal() {
- return mVendorExtensionHal;
- }
-
- @FutureFeature
public VmsHalService getVmsHal() { return mVmsHal; }
private void assertServiceOwnerLocked(HalServiceBase service, int property) {
@@ -298,7 +220,7 @@
*/
public void subscribeProperty(HalServiceBase service, int property)
throws IllegalArgumentException {
- subscribeProperty(service, property, 0f, SubscribeFlags.DEFAULT);
+ subscribeProperty(service, property, 0f, SubscribeFlags.EVENTS_FROM_CAR);
}
/**
@@ -308,7 +230,7 @@
*/
public void subscribeProperty(HalServiceBase service, int property, float sampleRateHz)
throws IllegalArgumentException {
- subscribeProperty(service, property, sampleRateHz, SubscribeFlags.DEFAULT);
+ subscribeProperty(service, property, sampleRateHz, SubscribeFlags.EVENTS_FROM_CAR);
}
/**
@@ -448,6 +370,23 @@
return mHalClient.getValue(requestedPropValue);
}
+ /**
+ *
+ * @param propId Property ID to return the current sample rate for.
+ *
+ * @return float Returns the current sample rate of the specified propId, or -1 if the
+ * property is not currently subscribed.
+ */
+ public float getSampleRate(int propId) {
+ SubscribeOptions opts = mSubscribedProperties.get(propId);
+ if (opts == null) {
+ // No sample rate for this property
+ return -1;
+ } else {
+ return opts.sampleRate;
+ }
+ }
+
void set(VehiclePropValue propValue) throws PropertyTimeoutException {
mHalClient.setValue(propValue);
}
@@ -538,9 +477,9 @@
for (VehiclePropConfig config : configList) {
StringBuilder builder = new StringBuilder()
.append("Property:0x").append(toHexString(config.prop))
+ .append(",Property name:").append(VehicleProperty.toString(config.prop))
.append(",access:0x").append(toHexString(config.access))
.append(",changeMode:0x").append(toHexString(config.changeMode))
- .append(",areas:0x").append(toHexString(config.supportedAreas))
.append(",config:0x").append(Arrays.toString(config.configArray.toArray()))
.append(",fs min:").append(config.minSampleRate)
.append(",fs max:").append(config.maxSampleRate);
@@ -571,25 +510,44 @@
}
/**
- * Inject a fake boolean HAL event - for testing purposes.
- * @param propId - VehicleProperty ID
- * @param areaId - Vehicle Area ID
- * @param value - true/false to inject
+ * Inject a VHAL event
+ *
+ * @param property the Vehicle property Id as defined in the HAL
+ * @param zone Zone that this event services
+ * @param value Data value of the event
*/
- public void injectBooleanEvent(int propId, int areaId, boolean value) {
- VehiclePropValue v = createPropValue(propId, areaId);
- v.value.int32Values.add(value? 1 : 0);
- onPropertyEvent(Lists.newArrayList(v));
- }
-
- /**
- * Inject a fake Integer HAL event - for testing purposes.
- * @param propId - VehicleProperty ID
- * @param value - Integer value to inject
- */
- public void injectIntegerEvent(int propId, int value) {
- VehiclePropValue v = createPropValue(propId, 0);
- v.value.int32Values.add(value);
+ public void injectVhalEvent(String property, String zone, String value)
+ throws NumberFormatException {
+ if (value == null || zone == null || property == null) {
+ return;
+ }
+ int propId = Integer.decode(property);
+ int zoneId = Integer.decode(zone);
+ VehiclePropValue v = createPropValue(propId, zoneId);
+ int propertyType = propId & VehiclePropertyType.MASK;
+ // Values can be comma separated list
+ List<String> dataList = new ArrayList<>(Arrays.asList(value.split(DATA_DELIMITER)));
+ switch (propertyType) {
+ case VehiclePropertyType.BOOLEAN:
+ boolean boolValue = Boolean.valueOf(value);
+ v.value.int32Values.add(boolValue ? 1 : 0);
+ break;
+ case VehiclePropertyType.INT32:
+ case VehiclePropertyType.INT32_VEC:
+ for (String s : dataList) {
+ v.value.int32Values.add(Integer.decode(s));
+ }
+ break;
+ case VehiclePropertyType.FLOAT:
+ case VehiclePropertyType.FLOAT_VEC:
+ for (String s : dataList) {
+ v.value.floatValues.add(Float.parseFloat(s));
+ }
+ break;
+ default:
+ Log.e(CarLog.TAG_HAL, "Property type unsupported:" + propertyType);
+ return;
+ }
v.timestamp = SystemClock.elapsedRealtimeNanos();
onPropertyEvent(Lists.newArrayList(v));
}
diff --git a/service/src/com/android/car/hal/VendorExtensionHalService.java b/service/src/com/android/car/hal/VendorExtensionHalService.java
deleted file mode 100644
index ab351be..0000000
--- a/service/src/com/android/car/hal/VendorExtensionHalService.java
+++ /dev/null
@@ -1,47 +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.hal;
-
-import android.hardware.automotive.vehicle.V2_0.VehiclePropertyGroup;
-
-/**
- * Implementation of {@link HalServiceBase} that responsible for custom properties that were defined
- * by OEMs.
- */
-public class VendorExtensionHalService extends PropertyHalServiceBase {
-
- private final static String TAG = VendorExtensionHalService.class.getSimpleName();
- private final static boolean DEBUG = false;
-
- VendorExtensionHalService(VehicleHal vehicleHal) {
- super(vehicleHal, TAG, DEBUG);
- }
-
- @Override
- protected int managerToHalPropId(int managerPropId) {
- return isVendorProperty(managerPropId) ? managerPropId : NOT_SUPPORTED_PROPERTY;
- }
-
- @Override
- protected int halToManagerPropId(int halPropId) {
- return isVendorProperty(halPropId) ? halPropId : NOT_SUPPORTED_PROPERTY;
- }
-
- private static boolean isVendorProperty(int property) {
- return (property & VehiclePropertyGroup.MASK) == VehiclePropertyGroup.VENDOR;
- }
-}
\ No newline at end of file
diff --git a/service/src/com/android/car/hal/VmsHalService.java b/service/src/com/android/car/hal/VmsHalService.java
index d20a453..fd84e2b 100644
--- a/service/src/com/android/car/hal/VmsHalService.java
+++ b/service/src/com/android/car/hal/VmsHalService.java
@@ -16,13 +16,15 @@
package com.android.car.hal;
import static com.android.car.CarServiceUtils.toByteArray;
+
import static java.lang.Integer.toHexString;
+import android.annotation.SystemApi;
import android.car.VehicleAreaType;
-import android.car.annotation.FutureFeature;
import android.car.vms.IVmsSubscriberClient;
-import android.car.vms.VmsLayer;
import android.car.vms.VmsAssociatedLayer;
+import android.car.vms.VmsAvailableLayers;
+import android.car.vms.VmsLayer;
import android.car.vms.VmsLayerDependency;
import android.car.vms.VmsLayersOffering;
import android.car.vms.VmsOperationRecorder;
@@ -33,11 +35,12 @@
import android.hardware.automotive.vehicle.V2_0.VmsBaseMessageIntegerValuesIndex;
import android.hardware.automotive.vehicle.V2_0.VmsMessageType;
import android.hardware.automotive.vehicle.V2_0.VmsMessageWithLayerAndPublisherIdIntegerValuesIndex;
-import android.hardware.automotive.vehicle.V2_0.VmsOfferingMessageIntegerValuesIndex;
import android.hardware.automotive.vehicle.V2_0.VmsMessageWithLayerIntegerValuesIndex;
+import android.hardware.automotive.vehicle.V2_0.VmsOfferingMessageIntegerValuesIndex;
import android.os.Binder;
import android.os.IBinder;
import android.util.Log;
+
import com.android.car.CarLog;
import com.android.car.VmsLayersAvailability;
import com.android.car.VmsPublishersInfo;
@@ -45,8 +48,8 @@
import com.android.internal.annotations.GuardedBy;
import java.io.PrintWriter;
-import java.util.Arrays;
import java.util.ArrayList;
+import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
@@ -61,7 +64,7 @@
* This is a glue layer between the VehicleHal and the VmsService. It sends VMS properties back and
* forth.
*/
-@FutureFeature
+@SystemApi
public class VmsHalService extends HalServiceBase {
private static final boolean DBG = true;
@@ -105,7 +108,7 @@
void onDataMessage(VmsLayer layer, int publisherId, byte[] payload);
// Notifies the listener on a change in available layers.
- void onLayersAvaiabilityChange(List<VmsAssociatedLayer> availableLayers);
+ void onLayersAvaiabilityChange(VmsAvailableLayers availableLayers);
}
/**
@@ -136,6 +139,9 @@
public void addSubscription(IVmsSubscriberClient listener, VmsLayer layer) {
boolean firstSubscriptionForLayer = false;
+ if (DBG) {
+ Log.d(TAG, "Checking for first subscription. Layer: " + layer);
+ }
synchronized (mLock) {
// Check if publishers need to be notified about this change in subscriptions.
firstSubscriptionForLayer = !mRouting.hasLayerSubscriptions(layer);
@@ -153,7 +159,9 @@
boolean layerHasSubscribers = true;
synchronized (mLock) {
if (!mRouting.hasLayerSubscriptions(layer)) {
- Log.i(TAG, "Trying to remove a layer with no subscription: " + layer);
+ if (DBG) {
+ Log.d(TAG, "Trying to remove a layer with no subscription: " + layer);
+ }
return;
}
@@ -353,17 +361,13 @@
}
public void setPublisherLayersOffering(IBinder publisherToken, VmsLayersOffering offering) {
- Set<VmsAssociatedLayer> availableLayers = Collections.EMPTY_SET;
synchronized (mLock) {
updateOffering(publisherToken, offering);
VmsOperationRecorder.get().setPublisherLayersOffering(offering);
- availableLayers = mAvailableLayers.getAvailableLayers();
}
- notifyOfAvailabilityChange(availableLayers);
}
- public Set<VmsAssociatedLayer> getAvailableLayers() {
- //TODO(b/36872877): wrap available layers in VmsAvailabilityState similar to VmsSubscriptionState.
+ public VmsAvailableLayers getAvailableLayers() {
synchronized (mLock) {
return mAvailableLayers.getAvailableLayers();
}
@@ -401,13 +405,13 @@
*
* @param availableLayers the layers which publishers claim they made publish.
*/
- private void notifyOfAvailabilityChange(Set<VmsAssociatedLayer> availableLayers) {
+ private void notifyOfAvailabilityChange(VmsAvailableLayers availableLayers) {
// notify the HAL
notifyAvailabilityChangeToHal(availableLayers);
// Notify the App subscribers
for (VmsHalSubscriberListener listener : mSubscriberListeners) {
- listener.onLayersAvaiabilityChange(new ArrayList<>(availableLayers));
+ listener.onLayersAvaiabilityChange(availableLayers);
}
}
@@ -489,7 +493,7 @@
handleHalAvailabilityRequestEvent();
break;
case VmsMessageType.SUBSCRIPTIONS_REQUEST:
- handleSubscriptionRequestEvent();
+ handleSubscriptionsRequestEvent();
break;
default:
throw new IllegalArgumentException("Unexpected message type: " + messageType);
@@ -677,7 +681,7 @@
*/
private void handleHalAvailabilityRequestEvent() {
synchronized (mLock) {
- Collection<VmsAssociatedLayer> availableLayers = mAvailableLayers.getAvailableLayers();
+ VmsAvailableLayers availableLayers = mAvailableLayers.getAvailableLayers();
VehiclePropValue vehiclePropertyValue =
toAvailabilityUpdateVehiclePropValue(
availableLayers,
@@ -701,7 +705,7 @@
* <li>Layer type/subtype/version.
* </ul>
*/
- private void handleSubscriptionRequestEvent() {
+ private void handleSubscriptionsRequestEvent() {
VmsSubscriptionState subscription = getSubscriptionState();
VehiclePropValue vehicleProp =
toTypedVmsVehiclePropValue(VmsMessageType.SUBSCRIPTIONS_RESPONSE);
@@ -723,7 +727,7 @@
}
private void updateOffering(IBinder publisherToken, VmsLayersOffering offering) {
- Set<VmsAssociatedLayer> availableLayers = Collections.EMPTY_SET;
+ VmsAvailableLayers availableLayers;
synchronized (mLock) {
mOfferings.put(publisherToken, offering);
@@ -776,7 +780,7 @@
return setPropertyValue(vehiclePropertyValue);
}
- public boolean notifyAvailabilityChangeToHal(Collection<VmsAssociatedLayer> availableLayers) {
+ public boolean notifyAvailabilityChangeToHal(VmsAvailableLayers availableLayers) {
VehiclePropValue vehiclePropertyValue =
toAvailabilityUpdateVehiclePropValue(
availableLayers,
@@ -798,7 +802,7 @@
private static VehiclePropValue toTypedVmsVehiclePropValue(int messageType) {
VehiclePropValue vehicleProp = new VehiclePropValue();
vehicleProp.prop = HAL_PROPERTY_ID;
- vehicleProp.areaId = VehicleAreaType.VEHICLE_AREA_TYPE_NONE;
+ vehicleProp.areaId = VehicleAreaType.VEHICLE_AREA_TYPE_GLOBAL;
VehiclePropValue.RawValue v = vehicleProp.value;
v.int32Values.add(messageType);
@@ -819,25 +823,26 @@
}
private static VehiclePropValue toAvailabilityUpdateVehiclePropValue(
- Collection<VmsAssociatedLayer> availableAssociatedLayers, int messageType) {
+ VmsAvailableLayers availableLayers, int messageType) {
if (!AVAILABILITY_MESSAGE_TYPES.contains(messageType)) {
throw new IllegalArgumentException("Unsupported availability type: " + messageType);
}
VehiclePropValue vehicleProp =
toTypedVmsVehiclePropValue(messageType);
- populateAvailabilityPropValueFields(availableAssociatedLayers, vehicleProp);
+ populateAvailabilityPropValueFields(availableLayers, vehicleProp);
return vehicleProp;
}
private static void populateAvailabilityPropValueFields(
- Collection<VmsAssociatedLayer> availableAssociatedLayers,
+ VmsAvailableLayers availableAssociatedLayers,
VehiclePropValue vehicleProp) {
VehiclePropValue.RawValue v = vehicleProp.value;
- int numLayers = availableAssociatedLayers.size();
+ v.int32Values.add(availableAssociatedLayers.getSequence());
+ int numLayers = availableAssociatedLayers.getAssociatedLayers().size();
v.int32Values.add(numLayers);
- for (VmsAssociatedLayer layer : availableAssociatedLayers) {
+ for (VmsAssociatedLayer layer : availableAssociatedLayers.getAssociatedLayers()) {
v.int32Values.add(layer.getVmsLayer().getType());
v.int32Values.add(layer.getVmsLayer().getSubtype());
v.int32Values.add(layer.getVmsLayer().getVersion());
diff --git a/service/src/com/android/car/pm/ActivityBlockingActivity.java b/service/src/com/android/car/pm/ActivityBlockingActivity.java
index 136fe1a..3e55405 100644
--- a/service/src/com/android/car/pm/ActivityBlockingActivity.java
+++ b/service/src/com/android/car/pm/ActivityBlockingActivity.java
@@ -19,18 +19,20 @@
import android.car.Car;
import android.car.CarNotConnectedException;
import android.car.content.pm.CarPackageManager;
+import android.car.drivingstate.CarUxRestrictions;
+import android.car.drivingstate.CarUxRestrictionsManager;
import android.content.ComponentName;
import android.content.Intent;
import android.content.ServiceConnection;
+import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
-import android.content.pm.ResolveInfo;
import android.os.Bundle;
-import android.os.Handler;
import android.os.IBinder;
-import android.os.Looper;
+import android.text.TextUtils;
import android.util.Log;
import android.view.View;
import android.widget.Button;
+import android.widget.TextView;
import com.android.car.CarLog;
import com.android.car.R;
@@ -38,44 +40,60 @@
/**
* Default activity that will be launched when the current foreground activity is not allowed.
* Additional information on blocked Activity will be passed as extra in Intent
- * via {@link #INTENT_KEY_BLOCKED_ACTIVITY} key. *
+ * via {@link #INTENT_KEY_BLOCKED_ACTIVITY} key.
*/
public class ActivityBlockingActivity extends Activity {
-
public static final String INTENT_KEY_BLOCKED_ACTIVITY = "blocked_activity";
+ public static final String EXTRA_BLOCKED_TASK = "blocked_task";
- private static final long AUTO_DISMISS_TIME_MS = 3000;
-
- private Handler mHandler;
-
- private Button mExitButton;
+ private static final int INVALID_TASK_ID = -1;
private Car mCar;
+ private CarUxRestrictionsManager mUxRManager;
+ private TextView mBlockedTitle;
+ private Button mExitButton;
+ // Exiting depends on Car connection, which might not be available at the time exit was
+ // requested (e.g. user presses Exit Button). In that case, we record exiting was requested, and
+ // Car connection will perform exiting once it is established.
private boolean mExitRequested;
-
- private final Runnable mFinishRunnable = () -> handleFinish();
+ private int mBlockedTaskId;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_blocking);
- mHandler = new Handler(Looper.getMainLooper());
- mExitButton = (Button) findViewById(R.id.botton_exit_now);
- mExitButton.setOnClickListener((View v) -> handleFinish());
- mCar = Car.createCar(this, new ServiceConnection() {
+ mBlockedTitle = findViewById(R.id.activity_blocked_title);
+ mExitButton = findViewById(R.id.exit);
+ mExitButton.setOnClickListener(v -> handleFinish());
+
+ // Listen to the CarUxRestrictions so this blocking activity can be dismissed when the
+ // restrictions are lifted.
+ mCar = Car.createCar(this, new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
- if (mExitRequested) {
- handleFinish();
+ try {
+ if (mExitRequested) {
+ handleFinish();
+ }
+ mUxRManager = (CarUxRestrictionsManager) mCar.getCarManager(
+ Car.CAR_UX_RESTRICTION_SERVICE);
+ // This activity would have been launched only in a restricted state.
+ // But ensuring when the service connection is established, that we are still
+ // in a restricted state.
+ handleUxRChange(mUxRManager.getCurrentCarUxRestrictions());
+ mUxRManager.registerListener(ActivityBlockingActivity.this::handleUxRChange);
+ } catch (CarNotConnectedException e) {
+ Log.e(CarLog.TAG_AM, "Failed to get CarUxRestrictionsManager", e);
}
}
@Override
public void onServiceDisconnected(ComponentName name) {
+ finish();
+ mUxRManager = null;
}
-
});
mCar.connect();
}
@@ -83,14 +101,85 @@
@Override
protected void onResume() {
super.onResume();
- mHandler.postDelayed(mFinishRunnable, AUTO_DISMISS_TIME_MS);
+
+ // Display message about the current blocked activity, and optionally show an exit button
+ // to restart the blocked task (stack of activities) if its root activity is DO.
+
+ // blockedActivity is expected to be always passed in as the topmost activity of task.
+ String blockedActivity = getIntent().getStringExtra(INTENT_KEY_BLOCKED_ACTIVITY);
+ mBlockedTitle.setText(getString(R.string.activity_blocked_string,
+ findHumanReadableLabel(blockedActivity)));
+ if (Log.isLoggable(CarLog.TAG_AM, Log.DEBUG)) {
+ Log.d(CarLog.TAG_AM, "Blocking activity " + blockedActivity);
+ }
+
+ // taskId is available as extra if the task can be restarted.
+ mBlockedTaskId = getIntent().getIntExtra(EXTRA_BLOCKED_TASK, INVALID_TASK_ID);
+
+ mExitButton.setVisibility(mBlockedTaskId == INVALID_TASK_ID ? View.GONE : View.VISIBLE);
+ if (Log.isLoggable(CarLog.TAG_AM, Log.DEBUG) && mBlockedTaskId == INVALID_TASK_ID) {
+ Log.d(CarLog.TAG_AM, "Blocked task ID is not available. Hiding exit button.");
+ }
+ }
+
+ @Override
+ protected void onNewIntent(Intent intent) {
+ super.onNewIntent(intent);
+ setIntent(intent);
}
@Override
protected void onDestroy() {
super.onDestroy();
- mHandler.removeCallbacks(mFinishRunnable);
- mCar.disconnect();
+ if (mCar.isConnected() && mUxRManager != null) {
+ try {
+ mUxRManager.unregisterListener();
+ } catch (CarNotConnectedException e) {
+ Log.e(CarLog.TAG_AM, "Cannot unregisterListener", e);
+ }
+ mUxRManager = null;
+ mCar.disconnect();
+ }
+ }
+
+ // If no distraction optimization is required in the new restrictions, then dismiss the
+ // blocking activity (self).
+ private void handleUxRChange(CarUxRestrictions restrictions) {
+ if (restrictions == null) {
+ return;
+ }
+ if (!restrictions.isRequiresDistractionOptimization()) {
+ finish();
+ }
+ }
+
+ /**
+ * Returns a human-readable string for {@code flattenComponentName}.
+ *
+ * <p>It first attempts to return the application label for this activity. If that fails,
+ * it will return the last part in the activity name.
+ */
+ private String findHumanReadableLabel(String flattenComponentName) {
+ ComponentName componentName = ComponentName.unflattenFromString(flattenComponentName);
+ String label = null;
+ // Attempt to find application label.
+ try {
+ ApplicationInfo applicationInfo = getPackageManager().getApplicationInfo(
+ componentName.getPackageName(), 0);
+ CharSequence appLabel = getPackageManager().getApplicationLabel(applicationInfo);
+ if (appLabel != null) {
+ label = appLabel.toString();
+ }
+ } catch (PackageManager.NameNotFoundException e) {
+ if (Log.isLoggable(CarLog.TAG_AM, Log.INFO)) {
+ Log.i(CarLog.TAG_AM, "Could not find package for component name "
+ + componentName.toString());
+ }
+ }
+ if (TextUtils.isEmpty(label)) {
+ label = componentName.getClass().getSimpleName();
+ }
+ return label;
}
private void handleFinish() {
@@ -101,30 +190,18 @@
if (isFinishing()) {
return;
}
- try {
- CarPackageManager carPm = (CarPackageManager) mCar.getCarManager(Car.PACKAGE_SERVICE);
- // finish itself only when it will not lead into another blocking
- if (carPm.isActivityBackedBySafeActivity(getComponentName())) {
- finish();
+ // Lock on self (assuming single instance) to avoid restarting the same task twice.
+ synchronized (this) {
+ try {
+ CarPackageManager carPm = (CarPackageManager)
+ mCar.getCarManager(Car.PACKAGE_SERVICE);
+ carPm.restartTask(mBlockedTaskId);
+ } catch (CarNotConnectedException e) {
+ // We should never be here since Car connection is already checked.
+ Log.e(CarLog.TAG_AM, "Car connection is not available.", e);
return;
}
- // back activity is not safe either. Now try home
- Intent homeIntent = new Intent(Intent.ACTION_MAIN);
- homeIntent.addCategory(Intent.CATEGORY_HOME);
- PackageManager pm = getPackageManager();
- ComponentName homeComponent = homeIntent.resolveActivity(pm);
- if (carPm.isActivityAllowedWhileDriving(homeComponent.getPackageName(),
- homeComponent.getClassName())) {
- startActivity(homeIntent);
- finish();
- return;
- } else {
- Log.w(CarLog.TAG_AM, "Home activity is not in white list. Keep blocking activity. "
- + ", Home Activity:" + homeComponent);
- }
- } catch (CarNotConnectedException e) {
- Log.w(CarLog.TAG_AM, "Car service not avaiable, will finish", e);
finish();
}
}
diff --git a/service/src/com/android/car/pm/AppBlockingPolicyProxy.java b/service/src/com/android/car/pm/AppBlockingPolicyProxy.java
index 3ab7df4..9404ac6 100644
--- a/service/src/com/android/car/pm/AppBlockingPolicyProxy.java
+++ b/service/src/com/android/car/pm/AppBlockingPolicyProxy.java
@@ -78,7 +78,7 @@
public void connect() {
Intent intent = new Intent();
- intent.setClassName(mServiceInfo.packageName, mServiceInfo.name);
+ intent.setComponent(mServiceInfo.getComponentName());
mContext.bindServiceAsUser(intent, this, Context.BIND_AUTO_CREATE | Context.BIND_IMPORTANT,
UserHandle.SYSTEM);
synchronized (this) {
diff --git a/service/src/com/android/car/pm/CarAppMetadataReader.java b/service/src/com/android/car/pm/CarAppMetadataReader.java
index b54e192..7c1e115 100644
--- a/service/src/com/android/car/pm/CarAppMetadataReader.java
+++ b/service/src/com/android/car/pm/CarAppMetadataReader.java
@@ -15,140 +15,79 @@
*/
package com.android.car.pm;
+import android.annotation.Nullable;
import android.content.Context;
-import android.content.pm.ApplicationInfo;
+import android.content.pm.ActivityInfo;
+import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.content.pm.PackageManager.NameNotFoundException;
-import android.content.res.Resources;
-import android.content.res.XmlResourceParser;
+import android.os.Bundle;
import android.util.Log;
import com.android.car.CarLog;
-import java.io.IOException;
-import java.util.LinkedList;
-
-import org.xmlpull.v1.XmlPullParser;
-import org.xmlpull.v1.XmlPullParserException;
+import java.util.ArrayList;
+import java.util.List;
/**
- * Read meta data containing car application info.
+ * Read App meta data and look for Distraction Optimization(DO) tags.
+ * An app can tag a distraction optimized activity to be DO by adding the following meta-data
+ * to that <activity> element:
+ *
+ * <pre>{@code
+ * <activity>
+ * <meta-data android:name="distractionOptimized" android:value="true"/>
+ * </activity>
+ * }</pre>
+ *
*/
public class CarAppMetadataReader {
- /** Name of the meta-data attribute for the automotive application XML resource */
- private static final String METADATA_ATTRIBUTE = "android.car.application";
- /** Name of the tag to declare automotive usage */
- private static final String USES_TAG = "uses";
- /** Name of the attribute to name the usage type */
- private static final String NAME_ATTRIBUTE = "name";
-
- private static final String NAME_ATTR_TYPE_SERVICE = "service";
- private static final String NAME_ATTR_TYPE_ACTIVITY = "activity";
-
- private static final String CLASS_ATTRIBUTE = "class";
-
- public static CarAppMetadataInfo parseMetadata(Context context, String packageName) {
- int metadataId = 0;
- Resources resources = null;
- try {
- metadataId = getMetadataId(context, packageName);
- if (metadataId == 0) {
- return null;
- }
- PackageManager pm = context.getPackageManager();
- resources = pm.getResourcesForApplication(packageName);
- } catch (NameNotFoundException e) {
- Log.w(CarLog.TAG_PACKAGE, "Cannot read mta data, package:" + packageName, e);
- return null;
- }
-
- // Try to open the XML resource
- XmlResourceParser parser = null;
- try {
- parser = resources.getXml(metadataId);
- } catch (Resources.NotFoundException e) {
- Log.w(CarLog.TAG_PACKAGE, "Resource not found [" + packageName + "]");
- return null;
- }
-
- boolean useService = false;
- boolean useAllActivities = false;
- LinkedList<String> activities = null;
- // Now, read the XML and pull out the appropriate "uses" attribute
- int eventType;
- try {
- eventType = parser.next();
- while (eventType != XmlPullParser.END_DOCUMENT) {
- if (eventType == XmlPullParser.START_TAG && USES_TAG.equals(parser.getName())) {
- String nameAttribute =
- parser.getAttributeValue(null /*namespace*/, NAME_ATTRIBUTE);
- if (nameAttribute == null) {
- Log.w(CarLog.TAG_PACKAGE, "Bad metadata," + METADATA_ATTRIBUTE +
- " for pavkage:" + packageName);
- return null;
- }
- switch (nameAttribute) {
- case NAME_ATTR_TYPE_SERVICE:
- useService = true;
- break;
- case NAME_ATTR_TYPE_ACTIVITY: {
- String classAttribute = parser.getAttributeValue(null /*namespace*/,
- CLASS_ATTRIBUTE);
- if (classAttribute == null) { // all activities
- useAllActivities = true;
- } else {
- if (activities == null) {
- activities = new LinkedList<>();
- }
- activities.add(classAttribute);
- }
- } break;
- }
- }
- eventType = parser.next();
- }
- } catch (XmlPullParserException | IOException e) {
- Log.w(CarLog.TAG_PACKAGE, "Resource not parsable [" + packageName + "]");
- return null;
- }
- String[] activityStrings = null;
- if (activities != null) {
- activityStrings = activities.toArray(new String[activities.size()]);
- }
- return new CarAppMetadataInfo(useService, useAllActivities, activityStrings);
- }
+ /** Name of the meta-data attribute of the Activity that denotes distraction optimized */
+ private static final String DO_METADATA_ATTRIBUTE = "distractionOptimized";
/**
- * Returns the resource ID of the automotive application XML
- * @throws NameNotFoundException
+ * Parses the given package and returns Distraction Optimized information, if present.
+ *
+ * @return Array of DO activity names in the given package
*/
- private static int getMetadataId(Context context, String packageName)
+ @Nullable
+ public static String[] findDistractionOptimizedActivities(Context context, String packageName)
throws NameNotFoundException {
final PackageManager pm = context.getPackageManager();
- ApplicationInfo appInfo;
- appInfo = pm.getApplicationInfo(packageName, PackageManager.GET_META_DATA /*flags*/);
- if (appInfo.metaData == null) {
- return 0;
- }
- return appInfo.metaData.getInt(METADATA_ATTRIBUTE, 0);
- }
- /**
- * App's metada for car application
- */
- public static class CarAppMetadataInfo {
- /** has "service" use */
- public final boolean useService;
- /** has "activity" use with no specific class */
- public final boolean useAllActivities;
- /** has "activity" uses with specific classes */
- public String[] activities;
-
- private CarAppMetadataInfo(boolean useService, boolean useAllActivities,
- String[] activities) {
- this.useService = useService;
- this.useAllActivities = useAllActivities;
- this.activities = activities;
+ // Check if any of the activities in the package are DO by checking all the
+ // <activity> elements.
+ PackageInfo pkgInfo =
+ pm.getPackageInfo(
+ packageName, PackageManager.GET_ACTIVITIES
+ | PackageManager.GET_META_DATA
+ | PackageManager.MATCH_DIRECT_BOOT_AWARE
+ | PackageManager.MATCH_DIRECT_BOOT_UNAWARE);
+ if (pkgInfo == null) {
+ return null;
}
+
+ ActivityInfo[] activities = pkgInfo.activities;
+ if (activities == null) {
+ if (Log.isLoggable(CarLog.TAG_PACKAGE, Log.DEBUG)) {
+ Log.d(CarLog.TAG_PACKAGE, "Null Activities for " + packageName);
+ }
+ return null;
+ }
+ List<String> optimizedActivityList = new ArrayList();
+ for (ActivityInfo activity : activities) {
+ Bundle mData = activity.metaData;
+ if (mData != null && mData.getBoolean(DO_METADATA_ATTRIBUTE, false)) {
+ if (Log.isLoggable(CarLog.TAG_PACKAGE, Log.DEBUG)) {
+ Log.d(CarLog.TAG_PACKAGE,
+ "DO Activity:" + activity.packageName + "/" + activity.name);
+ }
+ optimizedActivityList.add(activity.name);
+ }
+ }
+ if (optimizedActivityList.isEmpty()) {
+ return null;
+ }
+ return optimizedActivityList.toArray(new String[optimizedActivityList.size()]);
}
}
diff --git a/service/src/com/android/car/pm/CarPackageManagerService.java b/service/src/com/android/car/pm/CarPackageManagerService.java
index 13ceaa9..930a9e4 100644
--- a/service/src/com/android/car/pm/CarPackageManagerService.java
+++ b/service/src/com/android/car/pm/CarPackageManagerService.java
@@ -13,8 +13,10 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
+
package com.android.car.pm;
+import android.annotation.Nullable;
import android.app.ActivityManager.StackInfo;
import android.car.Car;
import android.car.content.pm.AppBlockingPackageInfo;
@@ -22,12 +24,14 @@
import android.car.content.pm.CarAppBlockingPolicyService;
import android.car.content.pm.CarPackageManager;
import android.car.content.pm.ICarPackageManager;
-import android.car.hardware.CarSensorEvent;
-import android.car.hardware.CarSensorManager;
-import android.car.hardware.ICarSensorEventListener;
+import android.car.drivingstate.CarUxRestrictions;
+import android.car.drivingstate.ICarUxRestrictionsChangeListener;
+import android.content.BroadcastReceiver;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
+import android.content.IntentFilter;
+import android.content.pm.ActivityInfo;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.content.pm.PackageManager.NameNotFoundException;
@@ -35,74 +39,112 @@
import android.content.pm.ServiceInfo;
import android.content.pm.Signature;
import android.content.res.Resources;
+import android.os.Binder;
import android.os.Handler;
import android.os.HandlerThread;
import android.os.Looper;
import android.os.Message;
+import android.os.Process;
+import android.text.format.DateFormat;
import android.util.ArraySet;
import android.util.Log;
import android.util.Pair;
import com.android.car.CarLog;
-import com.android.car.CarSensorService;
import com.android.car.CarServiceBase;
import com.android.car.CarServiceUtils;
+import com.android.car.CarUxRestrictionsManagerService;
import com.android.car.R;
import com.android.car.SystemActivityMonitoringService;
import com.android.car.SystemActivityMonitoringService.TopTaskInfoContainer;
-import com.android.car.pm.CarAppMetadataReader.CarAppMetadataInfo;
import com.android.internal.annotations.GuardedBy;
+import com.android.internal.annotations.VisibleForTesting;
import java.io.PrintWriter;
+import java.util.ArrayList;
+import java.util.Arrays;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
+import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
-//TODO monitor app installing and refresh policy, bug: 31970400
-
public class CarPackageManagerService extends ICarPackageManager.Stub implements CarServiceBase {
- static final boolean DBG_POLICY_SET = false;
- static final boolean DBG_POLICY_CHECK = false;
- static final boolean DBG_POLICY_ENFORCEMENT = false;
+ private static final boolean DBG_POLICY_SET = false;
+ private static final boolean DBG_POLICY_CHECK = false;
+ private static final boolean DBG_POLICY_ENFORCEMENT = false;
+ // Delimiters to parse packages and activities in the configuration XML resource.
+ private static final String PACKAGE_DELIMITER = ",";
+ private static final String PACKAGE_ACTIVITY_DELIMITER = "/";
+ private static final int LOG_SIZE = 20;
private final Context mContext;
private final SystemActivityMonitoringService mSystemActivityMonitoringService;
- private final CarSensorService mSensorService;
private final PackageManager mPackageManager;
private final HandlerThread mHandlerThread;
private final PackageHandler mHandler;
- private String mDefauiltActivityWhitelist;
+ // For dumpsys logging.
+ private final LinkedList<String> mBlockedActivityLogs = new LinkedList<>();
+
+ // Store the white list and black list strings from the resource file.
+ private String mConfiguredWhitelist;
+ private String mConfiguredBlacklist;
/**
* Hold policy set from policy service or client.
* Key: packageName of policy service
*/
@GuardedBy("this")
- private final HashMap<String, ClientPolicy> mClientPolicies =
- new HashMap<>();
+ private final HashMap<String, ClientPolicy> mClientPolicies = new HashMap<>();
@GuardedBy("this")
- private HashMap<String, AppBlockingPackageInfoWrapper> mSystemWhitelists = new HashMap<>();
+ private HashMap<String, AppBlockingPackageInfoWrapper> mActivityWhitelistMap = new HashMap<>();
+ // The list corresponding to the one configured in <activityBlacklist>
+ @GuardedBy("this")
+ private HashMap<String, AppBlockingPackageInfoWrapper> mActivityBlacklistMap = new HashMap<>();
@GuardedBy("this")
private LinkedList<AppBlockingPolicyProxy> mProxies;
@GuardedBy("this")
private final LinkedList<CarAppBlockingPolicy> mWaitingPolicies = new LinkedList<>();
- private final boolean mEnableActivityBlocking;
+ private final CarUxRestrictionsManagerService mCarUxRestrictionsService;
+ private boolean mEnableActivityBlocking;
private final ComponentName mActivityBlockingActivity;
private final ActivityLaunchListener mActivityLaunchListener = new ActivityLaunchListener();
- private final SensorListener mDrivingStateListener = new SensorListener();
+ private final UxRestrictionsListener mUxRestrictionsListener;
- public CarPackageManagerService(Context context, CarSensorService sensorService,
+ // Information related to when the installed packages should be parsed for building a white and
+ // black list
+ private final List<String> mPackageManagerActions = Arrays.asList(
+ Intent.ACTION_PACKAGE_ADDED,
+ Intent.ACTION_PACKAGE_CHANGED,
+ Intent.ACTION_PACKAGE_DATA_CLEARED,
+ Intent.ACTION_PACKAGE_REMOVED,
+ Intent.ACTION_PACKAGE_REPLACED,
+ Intent.ACTION_PACKAGE_FULLY_REMOVED);
+
+ private final PackageParsingEventReceiver mPackageParsingEventReceiver =
+ new PackageParsingEventReceiver();
+ private final BootEventReceiver mBootEventReceiver = new BootEventReceiver();
+
+ // To track if the packages have been parsed for building white/black lists. If we haven't had
+ // received any intents (boot complete or package changed), then the white list is null leading
+ // to blocking everything. So, no blocking until we have had a chance to parse the packages.
+ private boolean mHasParsedPackages;
+ // To track if we received the boot complete intent.
+ private boolean mBootLockedIntentRx;
+
+ public CarPackageManagerService(Context context,
+ CarUxRestrictionsManagerService uxRestrictionsService,
SystemActivityMonitoringService systemActivityMonitoringService) {
mContext = context;
- mSensorService = sensorService;
+ mCarUxRestrictionsService = uxRestrictionsService;
mSystemActivityMonitoringService = systemActivityMonitoringService;
mPackageManager = mContext.getPackageManager();
+ mUxRestrictionsListener = new UxRestrictionsListener(uxRestrictionsService);
mHandlerThread = new HandlerThread(CarLog.TAG_PACKAGE);
mHandlerThread.start();
mHandler = new PackageHandler(mHandlerThread.getLooper());
@@ -120,6 +162,14 @@
doSetAppBlockingPolicy(packageName, policy, flags, true /*setNow*/);
}
+ /**
+ * Restarts the requested task. If task with {@code taskId} does not exist, do nothing.
+ */
+ @Override
+ public void restartTask(int taskId) {
+ mSystemActivityMonitoringService.restartTask(taskId);
+ }
+
private void doSetAppBlockingPolicy(String packageName, CarAppBlockingPolicy policy, int flags,
boolean setNow) {
if (mContext.checkCallingOrSelfPermission(Car.PERMISSION_CONTROL_APP_BLOCKING)
@@ -151,12 +201,12 @@
}
@Override
- public boolean isActivityAllowedWhileDriving(String packageName, String className) {
+ public boolean isActivityDistractionOptimized(String packageName, String className) {
assertPackageAndClassName(packageName, className);
synchronized (this) {
if (DBG_POLICY_CHECK) {
- Log.i(CarLog.TAG_PACKAGE, "isActivityAllowedWhileDriving" +
- dumpPoliciesLocked(false));
+ Log.i(CarLog.TAG_PACKAGE, "isActivityDistractionOptimized"
+ + dumpPoliciesLocked(false));
}
AppBlockingPackageInfo info = searchFromBlacklistsLocked(packageName);
if (info != null) {
@@ -167,14 +217,14 @@
}
@Override
- public boolean isServiceAllowedWhileDriving(String packageName, String className) {
+ public boolean isServiceDistractionOptimized(String packageName, String className) {
if (packageName == null) {
throw new IllegalArgumentException("Package name null");
}
synchronized (this) {
if (DBG_POLICY_CHECK) {
- Log.i(CarLog.TAG_PACKAGE, "isServiceAllowedWhileDriving" +
- dumpPoliciesLocked(false));
+ Log.i(CarLog.TAG_PACKAGE, "isServiceDistractionOptimized"
+ + dumpPoliciesLocked(false));
}
AppBlockingPackageInfo info = searchFromBlacklistsLocked(packageName);
if (info != null) {
@@ -190,7 +240,7 @@
@Override
public boolean isActivityBackedBySafeActivity(ComponentName activityName) {
- if (!mEnableActivityBlocking || !mDrivingStateListener.isRestricted()) {
+ if (!mUxRestrictionsListener.isRestricted()) {
return true;
}
StackInfo info = mSystemActivityMonitoringService.getFocusedStackForTopActivity(
@@ -203,7 +253,7 @@
}
ComponentName activityBehind = ComponentName.unflattenFromString(
info.taskNames[info.taskNames.length - 2]);
- return isActivityAllowedWhileDriving(activityBehind.getPackageName(),
+ return isActivityDistractionOptimized(activityBehind.getPackageName(),
activityBehind.getClassName());
}
@@ -220,6 +270,7 @@
}
}
+ @GuardedBy("this")
private AppBlockingPackageInfo searchFromBlacklistsLocked(String packageName) {
for (ClientPolicy policy : mClientPolicies.values()) {
AppBlockingPackageInfoWrapper wrapper = policy.blacklistsMap.get(packageName);
@@ -227,9 +278,11 @@
return wrapper.info;
}
}
- return null;
+ AppBlockingPackageInfoWrapper wrapper = mActivityBlacklistMap.get(packageName);
+ return (wrapper != null) ? wrapper.info : null;
}
+ @GuardedBy("this")
private AppBlockingPackageInfo searchFromWhitelistsLocked(String packageName) {
for (ClientPolicy policy : mClientPolicies.values()) {
AppBlockingPackageInfoWrapper wrapper = policy.whitelistsMap.get(packageName);
@@ -237,23 +290,27 @@
return wrapper.info;
}
}
- AppBlockingPackageInfoWrapper wrapper = mSystemWhitelists.get(packageName);
+ AppBlockingPackageInfoWrapper wrapper = mActivityWhitelistMap.get(packageName);
return (wrapper != null) ? wrapper.info : null;
}
+ @GuardedBy("this")
private boolean isActivityInWhitelistsLocked(String packageName, String className) {
for (ClientPolicy policy : mClientPolicies.values()) {
if (isActivityInMapAndMatching(policy.whitelistsMap, packageName, className)) {
return true;
}
}
- return isActivityInMapAndMatching(mSystemWhitelists, packageName, className);
+ return isActivityInMapAndMatching(mActivityWhitelistMap, packageName, className);
}
private boolean isActivityInMapAndMatching(HashMap<String, AppBlockingPackageInfoWrapper> map,
String packageName, String className) {
AppBlockingPackageInfoWrapper wrapper = map.get(packageName);
if (wrapper == null || !wrapper.isMatching) {
+ if (DBG_POLICY_CHECK) {
+ Log.d(CarLog.TAG_PACKAGE, "Pkg not in whitelist:" + packageName);
+ }
return false;
}
return wrapper.info.isActivityCovered(className);
@@ -261,9 +318,6 @@
@Override
public void init() {
- if (!mEnableActivityBlocking) {
- return;
- }
synchronized (this) {
mHandler.requestInit();
}
@@ -271,9 +325,6 @@
@Override
public void release() {
- if (!mEnableActivityBlocking) {
- return;
- }
synchronized (this) {
mHandler.requestRelease();
// wait for release do be done. This guarantees that init is done.
@@ -281,7 +332,9 @@
wait();
} catch (InterruptedException e) {
}
- mSystemWhitelists.clear();
+ mHasParsedPackages = false;
+ mActivityWhitelistMap.clear();
+ mActivityBlacklistMap.clear();
mClientPolicies.clear();
if (mProxies != null) {
for (AppBlockingPolicyProxy proxy : mProxies) {
@@ -291,33 +344,49 @@
}
wakeupClientsWaitingForPolicySetitngLocked();
}
- mSensorService.unregisterSensorListener(CarSensorManager.SENSOR_TYPE_DRIVING_STATUS,
- mDrivingStateListener);
+ mContext.unregisterReceiver(mPackageParsingEventReceiver);
+ mContext.unregisterReceiver(mBootEventReceiver);
+ mCarUxRestrictionsService.unregisterUxRestrictionsChangeListener(mUxRestrictionsListener);
mSystemActivityMonitoringService.registerActivityLaunchListener(null);
}
// run from HandlerThread
private void doHandleInit() {
startAppBlockingPolicies();
- generateSystemWhitelists();
+ IntentFilter bootIntent = new IntentFilter();
+ bootIntent.addAction(Intent.ACTION_LOCKED_BOOT_COMPLETED);
+ mContext.registerReceiver(mBootEventReceiver, bootIntent);
+ IntentFilter pkgParseIntent = new IntentFilter();
+ for (String action : mPackageManagerActions) {
+ pkgParseIntent.addAction(action);
+ }
+ pkgParseIntent.addDataScheme("package");
+ mContext.registerReceiver(mPackageParsingEventReceiver, pkgParseIntent);
try {
- mSensorService.registerOrUpdateSensorListener(
- CarSensorManager.SENSOR_TYPE_DRIVING_STATUS, 0, mDrivingStateListener);
+ mCarUxRestrictionsService.registerUxRestrictionsChangeListener(mUxRestrictionsListener);
} catch (IllegalArgumentException e) {
// can happen while mocking is going on while init is still done.
Log.w(CarLog.TAG_PACKAGE, "sensor subscription failed", e);
return;
}
- mDrivingStateListener.resetState();
mSystemActivityMonitoringService.registerActivityLaunchListener(
mActivityLaunchListener);
- blockTopActivitiesIfNecessary();
+ }
+
+ private void doParseInstalledPackages() {
+ generateActivityWhitelistMap();
+ generateActivityBlacklistMap();
+ synchronized (this) {
+ mHasParsedPackages = true;
+ }
+ mUxRestrictionsListener.checkIfTopActivityNeedsBlocking();
}
private synchronized void doHandleRelease() {
notifyAll();
}
+ @GuardedBy("this")
private void wakeupClientsWaitingForPolicySetitngLocked() {
for (CarAppBlockingPolicy waitingPolicy : mWaitingPolicies) {
synchronized (waitingPolicy) {
@@ -442,22 +511,195 @@
}
/**
- * Return list of whitelist including default activity. Key is package name while
- * value is list of activities. If list is empty, whole activities in the package
- * are whitelisted.
- * @return
+ * Generate a map of whitelisted packages and activities of the form {pkgName, Whitelisted
+ * activities}. The whitelist information can come from a configuration XML resource or from
+ * the apps marking their activities as distraction optimized.
*/
- private HashMap<String, Set<String>> parseConfigWhitelist() {
- HashMap<String, Set<String>> packageToActivityMap = new HashMap<>();
+ private void generateActivityWhitelistMap() {
+ HashMap<String, AppBlockingPackageInfoWrapper> activityWhitelist = new HashMap<>();
+ mConfiguredWhitelist = mContext.getString(R.string.activityWhitelist);
+ if (mConfiguredWhitelist == null) {
+ if (DBG_POLICY_CHECK) {
+ Log.d(CarLog.TAG_PACKAGE, "Null whitelist in config");
+ }
+ return;
+ }
+ // Get the apps/activities that are whitelisted in the configuration XML resource
+ HashMap<String, Set<String>> configWhitelist = parseConfiglist(mConfiguredWhitelist);
+ if (configWhitelist == null) {
+ if (DBG_POLICY_CHECK) {
+ Log.w(CarLog.TAG_PACKAGE, "White list null. No apps whitelisted");
+ }
+ return;
+ }
+ // Add the blocking overlay activity to the whitelist, since that needs to run in a
+ // restricted state to communicate the reason an app was blocked.
Set<String> defaultActivity = new ArraySet<>();
defaultActivity.add(mActivityBlockingActivity.getClassName());
- packageToActivityMap.put(mActivityBlockingActivity.getPackageName(), defaultActivity);
- Resources res = mContext.getResources();
- String whitelist = res.getString(R.string.defauiltActivityWhitelist);
- mDefauiltActivityWhitelist = whitelist;
- String[] entries = whitelist.split(",");
+ configWhitelist.put(mActivityBlockingActivity.getPackageName(), defaultActivity);
+
+ List<PackageInfo> packages = mPackageManager.getInstalledPackages(
+ PackageManager.GET_SIGNATURES | PackageManager.GET_ACTIVITIES
+ | PackageManager.MATCH_DIRECT_BOOT_AWARE
+ | PackageManager.MATCH_DIRECT_BOOT_UNAWARE);
+
+ for (PackageInfo info : packages) {
+ if (info.applicationInfo == null) {
+ continue;
+ }
+
+ int flags = 0;
+ String[] activities = null;
+
+ if (info.applicationInfo.isSystemApp()
+ || info.applicationInfo.isUpdatedSystemApp()) {
+ flags = AppBlockingPackageInfo.FLAG_SYSTEM_APP;
+ }
+
+ /* 1. Check if all or some of this app is in the <activityWhitelist>
+ in config.xml */
+ Set<String> configActivitiesForPackage = configWhitelist.get(info.packageName);
+ if (configActivitiesForPackage != null) {
+ if (DBG_POLICY_CHECK) {
+ Log.d(CarLog.TAG_PACKAGE, info.packageName + " whitelisted");
+ }
+ if (configActivitiesForPackage.size() == 0) {
+ // Whole Pkg has been whitelisted
+ flags |= AppBlockingPackageInfo.FLAG_WHOLE_ACTIVITY;
+ // Add all activities to the whitelist
+ activities = getActivitiesInPackage(info);
+ if (activities == null && DBG_POLICY_CHECK) {
+ Log.d(CarLog.TAG_PACKAGE, info.packageName + ": Activities null");
+ }
+ } else {
+ if (DBG_POLICY_CHECK) {
+ Log.d(CarLog.TAG_PACKAGE, "Partially Whitelisted. WL Activities:");
+ for (String a : configActivitiesForPackage) {
+ Log.d(CarLog.TAG_PACKAGE, a);
+ }
+ }
+ activities = configActivitiesForPackage.toArray(
+ new String[configActivitiesForPackage.size()]);
+ }
+ } else {
+ /* 2. If app is not listed in the config.xml check their Manifest meta-data to
+ see if they have any Distraction Optimized(DO) activities */
+ try {
+ activities = CarAppMetadataReader.findDistractionOptimizedActivities(
+ mContext,
+ info.packageName);
+ } catch (NameNotFoundException e) {
+ Log.w(CarLog.TAG_PACKAGE, "Error reading metadata: " + info.packageName);
+ continue;
+ }
+ if (activities != null) {
+ // Some of the activities in this app are Distraction Optimized.
+ if (DBG_POLICY_CHECK) {
+ for (String activity : activities) {
+ Log.d(CarLog.TAG_PACKAGE,
+ "adding " + activity + " from " + info.packageName
+ + " to whitelist");
+ }
+ }
+ }
+ }
+ // Nothing to add to whitelist
+ if (activities == null) {
+ continue;
+ }
+
+ Signature[] signatures;
+ signatures = info.signatures;
+ AppBlockingPackageInfo appBlockingInfo = new AppBlockingPackageInfo(
+ info.packageName, 0, 0, flags, signatures, activities);
+ AppBlockingPackageInfoWrapper wrapper = new AppBlockingPackageInfoWrapper(
+ appBlockingInfo, true);
+ activityWhitelist.put(info.packageName, wrapper);
+ }
+ synchronized (this) {
+ mActivityWhitelistMap.clear();
+ mActivityWhitelistMap.putAll(activityWhitelist);
+ }
+ }
+
+ /**
+ * Generate a map of blacklisted packages and activities of the form {pkgName, Blacklisted
+ * activities}. The blacklist information comes from a configuration XML resource.
+ */
+ private void generateActivityBlacklistMap() {
+ HashMap<String, AppBlockingPackageInfoWrapper> activityBlacklist = new HashMap<>();
+ mConfiguredBlacklist = mContext.getString(R.string.activityBlacklist);
+ if (mConfiguredBlacklist == null) {
+ if (DBG_POLICY_CHECK) {
+ Log.d(CarLog.TAG_PACKAGE, "Null blacklist in config");
+ }
+ return;
+ }
+ Map<String, Set<String>> configBlacklist = parseConfiglist(mConfiguredBlacklist);
+ if (configBlacklist == null) {
+ if (DBG_POLICY_CHECK) {
+ Log.w(CarLog.TAG_PACKAGE, "Black list null. No apps blacklisted");
+ }
+ return;
+ }
+
+ for (String pkg : configBlacklist.keySet()) {
+ int flags = 0;
+ PackageInfo pkgInfo;
+ String[] activities;
+ try {
+ pkgInfo = mPackageManager.getPackageInfo(
+ pkg, PackageManager.GET_ACTIVITIES
+ | PackageManager.GET_SIGNING_CERTIFICATES
+ | PackageManager.MATCH_DIRECT_BOOT_AWARE
+ | PackageManager.MATCH_DIRECT_BOOT_UNAWARE);
+ } catch (NameNotFoundException e) {
+ Log.e(CarLog.TAG_PACKAGE, pkg + " not found to blacklist " + e);
+ continue;
+ }
+
+ if (pkgInfo.applicationInfo.isSystemApp()
+ || pkgInfo.applicationInfo.isUpdatedSystemApp()) {
+ flags |= AppBlockingPackageInfo.FLAG_SYSTEM_APP;
+ }
+ Set<String> configActivities = configBlacklist.get(pkg);
+ if (configActivities.size() == 0) {
+ // whole package
+ flags |= AppBlockingPackageInfo.FLAG_WHOLE_ACTIVITY;
+ activities = getActivitiesInPackage(pkgInfo);
+ } else {
+ activities = configActivities.toArray(new String[configActivities.size()]);
+ }
+
+ if (activities == null) {
+ continue;
+ }
+ AppBlockingPackageInfo appBlockingInfo = new AppBlockingPackageInfo(pkg, 0, 0, flags,
+ pkgInfo.signatures, activities);
+ AppBlockingPackageInfoWrapper wrapper = new AppBlockingPackageInfoWrapper(
+ appBlockingInfo, true);
+ activityBlacklist.put(pkg, wrapper);
+ }
+ synchronized (this) {
+ mActivityBlacklistMap.clear();
+ mActivityBlacklistMap.putAll(activityBlacklist);
+ }
+ }
+
+ /**
+ * Parses the given resource and returns a map of packages and activities.
+ * Key is package name and value is list of activities. Empty list implies whole package is
+ * included.
+ */
+ @Nullable
+ private HashMap<String, Set<String>> parseConfiglist(String configList) {
+ if (configList == null) {
+ return null;
+ }
+ HashMap<String, Set<String>> packageToActivityMap = new HashMap<>();
+ String[] entries = configList.split(PACKAGE_DELIMITER);
for (String entry : entries) {
- String[] packageActivityPair = entry.split("/");
+ String[] packageActivityPair = entry.split(PACKAGE_ACTIVITY_DELIMITER);
Set<String> activities = packageToActivityMap.get(packageActivityPair[0]);
boolean newPackage = false;
if (activities == null) {
@@ -477,56 +719,24 @@
return packageToActivityMap;
}
- private void generateSystemWhitelists() {
- HashMap<String, AppBlockingPackageInfoWrapper> systemWhitelists = new HashMap<>();
- HashMap<String, Set<String>> configWhitelist = parseConfigWhitelist();
- // trust all system apps for services and trust all activities with car app meta-data.
- List<PackageInfo> packages = mPackageManager.getInstalledPackages(0);
- for (PackageInfo info : packages) {
- if (info.applicationInfo != null && (info.applicationInfo.isSystemApp() ||
- info.applicationInfo.isUpdatedSystemApp())) {
- int flags = AppBlockingPackageInfo.FLAG_SYSTEM_APP;
- Set<String> configActivitiesForPackage =
- configWhitelist.get(info.packageName);
- if (configActivitiesForPackage != null) {
- if(configActivitiesForPackage.size() == 0) {
- flags |= AppBlockingPackageInfo.FLAG_WHOLE_ACTIVITY;
- }
- } else {
- configActivitiesForPackage = new ArraySet<>();
- }
- String[] activities = null;
- // Go through meta data if whole activities are not allowed already
- if ((flags & AppBlockingPackageInfo.FLAG_WHOLE_ACTIVITY) == 0) {
- CarAppMetadataInfo metadataInfo = CarAppMetadataReader.parseMetadata(mContext,
- info.packageName);
- if (metadataInfo != null) {
- if (metadataInfo.useAllActivities) {
- flags |= AppBlockingPackageInfo.FLAG_WHOLE_ACTIVITY;
- } else if(metadataInfo.activities != null) {
- for (String activity : metadataInfo.activities) {
- configActivitiesForPackage.add(activity);
- }
- }
- }
- if (configActivitiesForPackage.size() > 0) {
- activities = configActivitiesForPackage.toArray(
- new String[configActivitiesForPackage.size()]);
- }
- }
- AppBlockingPackageInfo appBlockingInfo = new AppBlockingPackageInfo(
- info.packageName, 0, 0, flags, null, activities);
- AppBlockingPackageInfoWrapper wrapper = new AppBlockingPackageInfoWrapper(
- appBlockingInfo, true);
- systemWhitelists.put(info.packageName, wrapper);
- }
+ @Nullable
+ private String[] getActivitiesInPackage(PackageInfo info) {
+ if (info == null || info.activities == null) {
+ return null;
}
- synchronized (this) {
- mSystemWhitelists.putAll(systemWhitelists);
+ List<String> activityList = new ArrayList<>();
+ for (ActivityInfo aInfo : info.activities) {
+ activityList.add(aInfo.name);
}
+ return activityList.toArray(new String[activityList.size()]);
}
- private void startAppBlockingPolicies() {
+ /**
+ * Checks if there are any {@link CarAppBlockingPolicyService} and creates a proxy to
+ * bind to them and retrieve the {@link CarAppBlockingPolicy}
+ */
+ @VisibleForTesting
+ public void startAppBlockingPolicies() {
Intent policyIntent = new Intent();
policyIntent.setAction(CarAppBlockingPolicyService.SERVICE_INTERFACE);
List<ResolveInfo> policyInfos = mPackageManager.queryIntentServices(policyIntent, 0);
@@ -601,16 +811,24 @@
synchronized (this) {
writer.println("*PackageManagementService*");
writer.println("mEnableActivityBlocking:" + mEnableActivityBlocking);
- writer.println("ActivityRestricted:" + mDrivingStateListener.isRestricted());
+ writer.println("mHasParsedPackages:" + mHasParsedPackages);
+ writer.println("mBootLockedIntentRx:" + mBootLockedIntentRx);
+ writer.println("ActivityRestricted:" + mUxRestrictionsListener.isRestricted());
+ writer.println(String.join("\n", mBlockedActivityLogs));
writer.print(dumpPoliciesLocked(true));
}
}
+ @GuardedBy("this")
private String dumpPoliciesLocked(boolean dumpAll) {
StringBuilder sb = new StringBuilder();
if (dumpAll) {
sb.append("**System white list**\n");
- for (AppBlockingPackageInfoWrapper wrapper : mSystemWhitelists.values()) {
+ for (AppBlockingPackageInfoWrapper wrapper : mActivityWhitelistMap.values()) {
+ sb.append(wrapper.toString() + "\n");
+ }
+ sb.append("**System Black list**\n");
+ for (AppBlockingPackageInfoWrapper wrapper : mActivityBlacklistMap.values()) {
sb.append(wrapper.toString() + "\n");
}
}
@@ -632,14 +850,17 @@
sb.append(proxy.toString() + "\n");
}
}
- sb.append("**Default Whitelist string**\n");
- sb.append(mDefauiltActivityWhitelist + "\n");
+ sb.append("**Whitelist string in resource**\n");
+ sb.append(mConfiguredWhitelist + "\n");
+
+ sb.append("**Blacklist string in resource**\n");
+ sb.append(mConfiguredBlacklist + "\n");
return sb.toString();
}
private void blockTopActivityIfNecessary(TopTaskInfoContainer topTask) {
- boolean restricted = mDrivingStateListener.isRestricted();
+ boolean restricted = mUxRestrictionsListener.isRestricted();
if (!restricted) {
return;
}
@@ -647,27 +868,72 @@
}
private void doBlockTopActivityIfNotAllowed(TopTaskInfoContainer topTask) {
- boolean allowed = isActivityAllowedWhileDriving(
+ if (topTask.topActivity == null) {
+ return;
+ }
+ boolean allowed = isActivityDistractionOptimized(
topTask.topActivity.getPackageName(),
topTask.topActivity.getClassName());
if (DBG_POLICY_ENFORCEMENT) {
Log.i(CarLog.TAG_PACKAGE, "new activity:" + topTask.toString() + " allowed:" + allowed);
}
- if (!allowed) {
+ if (allowed) {
+ return;
+ }
+ synchronized (this) {
+ if (!mEnableActivityBlocking) {
+ Log.d(CarLog.TAG_PACKAGE, "Current activity " + topTask.topActivity +
+ " not allowed, blocking disabled. Number of tasks in stack:"
+ + topTask.stackInfo.taskIds.length);
+ return;
+ }
+ }
+ if (DBG_POLICY_CHECK) {
Log.i(CarLog.TAG_PACKAGE, "Current activity " + topTask.topActivity +
" not allowed, will block, number of tasks in stack:" +
topTask.stackInfo.taskIds.length);
- Intent newActivityIntent = new Intent();
- newActivityIntent.setComponent(mActivityBlockingActivity);
- newActivityIntent.putExtra(
- ActivityBlockingActivity.INTENT_KEY_BLOCKED_ACTIVITY,
- topTask.topActivity.flattenToString());
- mSystemActivityMonitoringService.blockActivity(topTask, newActivityIntent);
}
+ StringBuilder blockedActivityLog = new StringBuilder();
+ Intent newActivityIntent = new Intent();
+ newActivityIntent.setComponent(mActivityBlockingActivity);
+ newActivityIntent.putExtra(
+ ActivityBlockingActivity.INTENT_KEY_BLOCKED_ACTIVITY,
+ topTask.topActivity.flattenToString());
+ blockedActivityLog.append("Blocked activity ")
+ .append(topTask.topActivity.flattenToShortString())
+ .append(". Task id ").append(topTask.taskId);
+
+ // If root activity of blocked task is DO, also pass its task id into blocking activity,
+ // which uses the id to display a button for restarting the blocked task.
+ for (int i = 0; i < topTask.stackInfo.taskIds.length; i++) {
+ // topTask.taskId is the task that should be blocked.
+ if (topTask.stackInfo.taskIds[i] == topTask.taskId) {
+ // stackInfo represents an ActivityStack. Its fields taskIds and taskNames
+ // are 1:1 mapped, where taskNames is the name of root activity in this task.
+ String taskRootActivity = topTask.stackInfo.taskNames[i];
+
+ ComponentName rootActivityName = ComponentName.unflattenFromString(
+ taskRootActivity);
+ if (isActivityDistractionOptimized(
+ rootActivityName.getPackageName(), rootActivityName.getClassName())) {
+ newActivityIntent.putExtra(
+ ActivityBlockingActivity.EXTRA_BLOCKED_TASK, topTask.taskId);
+ if (Log.isLoggable(CarLog.TAG_PACKAGE, Log.INFO)) {
+ Log.i(CarLog.TAG_PACKAGE, "Blocked task " + topTask.taskId
+ + " has DO root activity " + taskRootActivity);
+ }
+ blockedActivityLog.append(". Root DO activity ")
+ .append(rootActivityName.flattenToShortString());
+ }
+ break;
+ }
+ }
+ addLog(blockedActivityLog.toString());
+ mSystemActivityMonitoringService.blockActivity(topTask, newActivityIntent);
}
private void blockTopActivitiesIfNecessary() {
- boolean restricted = mDrivingStateListener.isRestricted();
+ boolean restricted = mUxRestrictionsListener.isRestricted();
if (!restricted) {
return;
}
@@ -677,14 +943,59 @@
}
}
+ @Override
+ public synchronized void setEnableActivityBlocking(boolean enable) {
+ // Check if the caller has the same signature as that of the car service.
+ if (mPackageManager.checkSignatures(Process.myUid(), Binder.getCallingUid())
+ != PackageManager.SIGNATURE_MATCH) {
+ throw new SecurityException(
+ "Caller " + mPackageManager.getNameForUid(Binder.getCallingUid())
+ + " does not have the right signature");
+ }
+ mEnableActivityBlocking = enable;
+ }
+
+ /**
+ * Get the distraction optimized activities for the given package.
+ *
+ * @param pkgName Name of the package
+ * @return Array of the distraction optimized activities in the package
+ */
+ @Nullable
+ public String[] getDistractionOptimizedActivities(String pkgName) {
+ try {
+ return CarAppMetadataReader.findDistractionOptimizedActivities(mContext, pkgName);
+ } catch (NameNotFoundException e) {
+ return null;
+ }
+ }
+
+ /**
+ * Append one line of log for dumpsys.
+ *
+ * <p>Maintains the size of log by {@link #LOG_SIZE} and appends tag and timestamp to the line.
+ */
+ private void addLog(String log) {
+ while (mBlockedActivityLogs.size() >= LOG_SIZE) {
+ mBlockedActivityLogs.remove();
+ }
+ StringBuffer sb = new StringBuffer()
+ .append(CarLog.TAG_PACKAGE).append(':')
+ .append(DateFormat.format(
+ "MM-dd HH:mm:ss", System.currentTimeMillis())).append(": ")
+ .append(log);
+ mBlockedActivityLogs.add(sb.toString());
+ }
+
/**
* Reading policy and setting policy can take time. Run it in a separate handler thread.
*/
private class PackageHandler extends Handler {
private final int MSG_INIT = 0;
- private final int MSG_SET_POLICY = 1;
- private final int MSG_UPDATE_POLICY = 2;
- private final int MSG_RELEASE = 3;
+ private final int MSG_PARSE_PKG = 1;
+ private final int MSG_SET_POLICY = 2;
+ private final int MSG_UPDATE_POLICY = 3;
+ private final int MSG_RELEASE = 4;
private PackageHandler(Looper looper) {
super(looper);
@@ -715,12 +1026,25 @@
sendMessage(msg);
}
+ private void requestParsingInstalledPkgs(long delayMs) {
+ Message msg = obtainMessage(MSG_PARSE_PKG);
+ if (delayMs == 0) {
+ sendMessage(msg);
+ } else {
+ sendMessageDelayed(msg, delayMs);
+ }
+ }
+
@Override
public void handleMessage(Message msg) {
switch (msg.what) {
case MSG_INIT:
doHandleInit();
break;
+ case MSG_PARSE_PKG:
+ removeMessages(MSG_PARSE_PKG);
+ doParseInstalledPackages();
+ break;
case MSG_SET_POLICY:
doSetPolicy();
break;
@@ -745,7 +1069,7 @@
private boolean isMatching;
private AppBlockingPackageInfoWrapper(AppBlockingPackageInfo info, boolean isMatching) {
- this.info =info;
+ this.info = info;
this.isMatching = isMatching;
}
@@ -822,44 +1146,155 @@
}
private class ActivityLaunchListener
- implements SystemActivityMonitoringService.ActivityLaunchListener {
+ implements SystemActivityMonitoringService.ActivityLaunchListener {
@Override
public void onActivityLaunch(TopTaskInfoContainer topTask) {
blockTopActivityIfNecessary(topTask);
}
}
- private class SensorListener extends ICarSensorEventListener.Stub {
- private int mLatestDrivingState;
+ /**
+ * Listens to the UX restrictions from {@link CarUxRestrictionsManagerService} and initiates
+ * checking if the foreground Activity should be blocked.
+ */
+ private class UxRestrictionsListener extends ICarUxRestrictionsChangeListener.Stub {
+ @GuardedBy("this")
+ @Nullable
+ private CarUxRestrictions mCurrentUxRestrictions;
+ private final CarUxRestrictionsManagerService uxRestrictionsService;
- private void resetState() {
- CarSensorEvent lastEvent = mSensorService.getLatestSensorEvent(
- CarSensorManager.SENSOR_TYPE_DRIVING_STATUS);
- boolean shouldBlock = false;
+ public UxRestrictionsListener(CarUxRestrictionsManagerService service) {
+ uxRestrictionsService = service;
+ mCurrentUxRestrictions = uxRestrictionsService.getCurrentUxRestrictions();
+ }
+
+ @Override
+ public void onUxRestrictionsChanged(CarUxRestrictions restrictions) {
+ if (DBG_POLICY_CHECK) {
+ Log.d(CarLog.TAG_PACKAGE, "Received uxr restrictions: "
+ + restrictions.isRequiresDistractionOptimization()
+ + " : " + restrictions.getActiveRestrictions());
+ }
+ // We are not handling the restrictions until we know what is allowed and what is not.
+ // This is to handle some situations, where car service is ready and getting sensor
+ // data but we haven't received the boot complete intents.
+ if (!mHasParsedPackages) {
+ return;
+ }
+
synchronized (this) {
- if (lastEvent == null) {
- // When driving status is not available yet, do not block.
- // This happens during bootup.
- mLatestDrivingState = CarSensorEvent.DRIVE_STATUS_UNRESTRICTED;
- } else {
- mLatestDrivingState = lastEvent.intValues[0];
- }
- if (mLatestDrivingState != CarSensorEvent.DRIVE_STATUS_UNRESTRICTED) {
- shouldBlock = true;
+ mCurrentUxRestrictions = new CarUxRestrictions(restrictions);
+ }
+ checkIfTopActivityNeedsBlocking();
+ }
+
+ private void checkIfTopActivityNeedsBlocking() {
+ boolean shouldCheck = false;
+ synchronized (this) {
+ if (mCurrentUxRestrictions != null
+ && mCurrentUxRestrictions.isRequiresDistractionOptimization()) {
+ shouldCheck = true;
}
}
- if (shouldBlock) {
+ if (DBG_POLICY_CHECK) {
+ Log.d(CarLog.TAG_PACKAGE, "block?: " + shouldCheck);
+ }
+ if (shouldCheck) {
blockTopActivitiesIfNecessary();
}
}
private synchronized boolean isRestricted() {
- return mLatestDrivingState != CarSensorEvent.DRIVE_STATUS_UNRESTRICTED;
+ // if current restrictions is null, try querying the service, once.
+ if (mCurrentUxRestrictions == null) {
+ mCurrentUxRestrictions = uxRestrictionsService.getCurrentUxRestrictions();
+ }
+ if (mCurrentUxRestrictions != null) {
+ return mCurrentUxRestrictions.isRequiresDistractionOptimization();
+ }
+ // If restriction information is still not available (could happen during bootup),
+ // return not restricted. This maintains parity with previous implementation but needs
+ // a revisit as we test more.
+ return false;
}
+ }
+
+ /**
+ * Listens to the Boot intent to initiate parsing installed packages.
+ */
+ private class BootEventReceiver extends BroadcastReceiver {
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ if (intent == null || intent.getAction() == null) {
+ return;
+ }
+ if (DBG_POLICY_CHECK) {
+ Log.d(CarLog.TAG_PACKAGE, "BootEventReceiver Received " + intent.getAction());
+ }
+ if (Intent.ACTION_LOCKED_BOOT_COMPLETED.equals(intent.getAction())) {
+ mHandler.requestParsingInstalledPkgs(0);
+ mBootLockedIntentRx = true;
+ }
+ }
+ }
+
+ /**
+ * Listens to the package install/uninstall events to know when to initiate parsing
+ * installed packages.
+ */
+ private class PackageParsingEventReceiver extends BroadcastReceiver {
+ private static final long PACKAGE_PARSING_DELAY_MS = 500;
@Override
- public void onSensorChanged(List<CarSensorEvent> events) {
- resetState();
+ public void onReceive(Context context, Intent intent) {
+ if (intent == null || intent.getAction() == null) {
+ return;
+ }
+ if (DBG_POLICY_CHECK) {
+ Log.d(CarLog.TAG_PACKAGE,
+ "PackageParsingEventReceiver Received " + intent.getAction());
+ }
+ String action = intent.getAction();
+ if (isPackageManagerAction(action)) {
+ // send a delayed message so if we received multiple related intents, we parse
+ // only once.
+ logEventChange(intent);
+ mHandler.requestParsingInstalledPkgs(PACKAGE_PARSING_DELAY_MS);
+ }
+ }
+
+ private boolean isPackageManagerAction(String action) {
+ return mPackageManagerActions.indexOf(action) != -1;
+ }
+
+ /**
+ * Convenience log function to log what changed. Logs only when more debug logs
+ * are needed - DBG_POLICY_CHECK needs to be true
+ */
+ private void logEventChange(Intent intent) {
+ if (!DBG_POLICY_CHECK || intent == null) {
+ return;
+ }
+
+ String packageName = intent.getData().getSchemeSpecificPart();
+ Log.d(CarLog.TAG_PACKAGE, "Pkg Changed:" + packageName);
+ String action = intent.getAction();
+ if (action == null) {
+ return;
+ }
+ if (action.equals(Intent.ACTION_PACKAGE_CHANGED)) {
+ Log.d(CarLog.TAG_PACKAGE, "Changed components");
+ String[] cc = intent.getStringArrayExtra(Intent.EXTRA_CHANGED_COMPONENT_NAME_LIST);
+ if (cc != null) {
+ for (String c : cc) {
+ Log.d(CarLog.TAG_PACKAGE, c);
+ }
+ }
+ } else if (action.equals(Intent.ACTION_PACKAGE_REMOVED)
+ || action.equals(Intent.ACTION_PACKAGE_ADDED)) {
+ Log.d(CarLog.TAG_PACKAGE, action + " Replacing?: " + intent.getBooleanExtra(
+ Intent.EXTRA_REPLACING, false));
+ }
}
}
}
diff --git a/service/src/com/android/car/storagemonitoring/EMmcWearInformationProvider.java b/service/src/com/android/car/storagemonitoring/EMmcWearInformationProvider.java
new file mode 100644
index 0000000..3940578
--- /dev/null
+++ b/service/src/com/android/car/storagemonitoring/EMmcWearInformationProvider.java
@@ -0,0 +1,106 @@
+/*
+ * 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.android.car.storagemonitoring;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.util.Log;
+import com.android.car.CarLog;
+import com.android.internal.annotations.VisibleForTesting;
+import java.io.File;
+import java.io.FileReader;
+import java.io.BufferedReader;
+import java.io.IOException;
+
+/**
+ * Loads wear information from the eMMC sysfs entry points.
+ * sysfs exposes eMMC lifetime data in /sys/bus/mmc/devices/mmc0:0001/{pre_eol_info|life_time}
+ * The first file contains the value of the PRE_EOL_INFO register as an hexadecimal string
+ * The second file contains the values of the LIFE_TIME_EST A and B registers as two hexadecimal
+ * strings separated by a space.
+ */
+public class EMmcWearInformationProvider implements WearInformationProvider {
+ private static File DEFAULT_LIFE_TIME_FILE =
+ new File("/sys/bus/mmc/devices/mmc0:0001/life_time");
+
+ private static File DEFAULT_PRE_EOL_FILE =
+ new File("/sys/bus/mmc/devices/mmc0:0001/pre_eol_info");
+
+ private File mLifetimeFile;
+ private File mPreEolFile;
+
+ public EMmcWearInformationProvider() {
+ this(DEFAULT_LIFE_TIME_FILE, DEFAULT_PRE_EOL_FILE);
+ }
+
+ @VisibleForTesting
+ EMmcWearInformationProvider(@NonNull File lifetimeFile, @NonNull File preEolFile) {
+ mLifetimeFile = lifetimeFile;
+ mPreEolFile = preEolFile;
+ }
+
+ private String readLineFromFile(File f) {
+ if (!f.exists() || !f.isFile()) {
+ Log.i(CarLog.TAG_STORAGE, f + " does not exist or is not a file");
+ return null;
+ }
+
+ try {
+ BufferedReader reader = new BufferedReader(new FileReader(f));
+ String data = reader.readLine();
+ reader.close();
+ return data;
+ } catch (IOException e) {
+ Log.w(CarLog.TAG_STORAGE, f + " cannot be read from", e);
+ return null;
+ }
+ }
+
+ @Nullable
+ @Override
+ public WearInformation load() {
+ String lifetimeData = readLineFromFile(mLifetimeFile);
+ String eolData = readLineFromFile(mPreEolFile);
+
+ if ((lifetimeData == null) || (eolData == null)) {
+ return null;
+ }
+
+ String[] lifetimes = lifetimeData.split(" ");
+ if (lifetimes.length != 2) {
+ Log.w(CarLog.TAG_STORAGE, "lifetime data not in expected format: " + lifetimeData);
+ return null;
+ }
+
+ int lifetimeA;
+ int lifetimeB;
+ int eol;
+
+ try {
+ lifetimeA = Integer.decode(lifetimes[0]);
+ lifetimeB = Integer.decode(lifetimes[1]);
+ eol = Integer.decode("0x" + eolData);
+ } catch (NumberFormatException e) {
+ Log.w(CarLog.TAG_STORAGE,
+ "lifetime data not in expected format: " + lifetimeData, e);
+ return null;
+ }
+
+ return new WearInformation(convertLifetime(lifetimeA),
+ convertLifetime(lifetimeB),
+ adjustEol(eol));
+ }
+}
diff --git a/service/src/com/android/car/storagemonitoring/IoStatsTracker.java b/service/src/com/android/car/storagemonitoring/IoStatsTracker.java
new file mode 100644
index 0000000..724cd08
--- /dev/null
+++ b/service/src/com/android/car/storagemonitoring/IoStatsTracker.java
@@ -0,0 +1,118 @@
+/*
+ * 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.android.car.storagemonitoring;
+
+import android.car.storagemonitoring.IoStatsEntry;
+import android.car.storagemonitoring.UidIoRecord;
+import android.util.SparseArray;
+import com.android.car.SparseArrayStream;
+import com.android.car.procfsinspector.ProcessInfo;
+import com.android.car.systeminterface.SystemStateInterface;
+import java.util.List;
+import java.util.Optional;
+
+public class IoStatsTracker {
+ private abstract class Lazy<T> {
+ protected Optional<T> mLazy = Optional.empty();
+
+ protected abstract T supply();
+
+ public synchronized T get() {
+ if (!mLazy.isPresent()) {
+ mLazy = Optional.of(supply());
+ }
+ return mLazy.get();
+ }
+ }
+
+ private final long mSampleWindowMs;
+ private final SystemStateInterface mSystemStateInterface;
+ private SparseArray<IoStatsEntry> mTotal;
+ private SparseArray<IoStatsEntry> mCurrentSample;
+
+ public IoStatsTracker(List<IoStatsEntry> initialValue,
+ long sampleWindowMs, SystemStateInterface systemStateInterface) {
+ mTotal = new SparseArray<>(initialValue.size());
+ initialValue.forEach(uidIoStats -> mTotal.append(uidIoStats.uid, uidIoStats));
+ mCurrentSample = mTotal.clone();
+ mSampleWindowMs = sampleWindowMs;
+ mSystemStateInterface = systemStateInterface;
+ }
+
+ public synchronized void update(SparseArray<UidIoRecord> newMetrics) {
+ final Lazy<List<ProcessInfo>> processTable = new Lazy<List<ProcessInfo>>() {
+ @Override
+ protected List<ProcessInfo> supply() {
+ return mSystemStateInterface.getRunningProcesses();
+ }
+ };
+
+ SparseArray<IoStatsEntry> newSample = new SparseArray<>();
+ SparseArray<IoStatsEntry> newTotal = new SparseArray<>();
+
+ // prepare the new values
+ SparseArrayStream.valueStream(newMetrics).forEach( newRecord -> {
+ final int uid = newRecord.uid;
+ final IoStatsEntry oldRecord = mTotal.get(uid);
+
+ IoStatsEntry newStats = null;
+
+ if (oldRecord == null) {
+ // this user id has just showed up, so just add it to the current sample
+ // and its runtime is the size of our sample window
+ newStats = new IoStatsEntry(newRecord, mSampleWindowMs);
+ } else {
+ // this user id has already been detected
+
+ if (oldRecord.representsSameMetrics(newRecord)) {
+ // if no new I/O happened, try to figure out if any process on behalf
+ // of this user has happened, and use that to update the runtime metrics
+ if (processTable.get().stream().anyMatch(pi -> pi.uid == uid)) {
+ newStats = new IoStatsEntry(newRecord.delta(oldRecord),
+ oldRecord.runtimeMillis + mSampleWindowMs);
+ }
+ // if no new I/O happened and no process is running for this user
+ // then do not prepare a new sample, as nothing has changed
+ } else {
+ // but if new I/O happened, assume something was running for the entire
+ // sample window and compute the delta
+ newStats = new IoStatsEntry(newRecord.delta(oldRecord),
+ oldRecord.runtimeMillis + mSampleWindowMs);
+ }
+ }
+
+ if (newStats != null) {
+ newSample.put(uid, newStats);
+ newTotal.append(uid, new IoStatsEntry(newRecord, newStats.runtimeMillis));
+ } else {
+ // if oldRecord were null, newStats would be != null and we wouldn't be here
+ newTotal.append(uid, oldRecord);
+ }
+ });
+
+ // now update the stored values
+ mCurrentSample = newSample;
+ mTotal = newTotal;
+ }
+
+ public synchronized SparseArray<IoStatsEntry> getTotal() {
+ return mTotal;
+ }
+
+ public synchronized SparseArray<IoStatsEntry> getCurrentSample() {
+ return mCurrentSample;
+ }
+}
diff --git a/car-lib/src/android/car/hardware/radio/CarRadioEvent.aidl b/service/src/com/android/car/storagemonitoring/LifetimeWriteInfoProvider.java
similarity index 66%
copy from car-lib/src/android/car/hardware/radio/CarRadioEvent.aidl
copy to service/src/com/android/car/storagemonitoring/LifetimeWriteInfoProvider.java
index 0865646..5b2e042 100644
--- a/car-lib/src/android/car/hardware/radio/CarRadioEvent.aidl
+++ b/service/src/com/android/car/storagemonitoring/LifetimeWriteInfoProvider.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,7 +13,12 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
+package com.android.car.storagemonitoring;
-package android.car.hardware.radio;
+import android.annotation.NonNull;
+import android.car.storagemonitoring.LifetimeWriteInfo;
-parcelable CarRadioEvent;
+public interface LifetimeWriteInfoProvider {
+ @NonNull
+ LifetimeWriteInfo[] load();
+}
diff --git a/service/src/com/android/car/storagemonitoring/ProcfsUidIoStatsProvider.java b/service/src/com/android/car/storagemonitoring/ProcfsUidIoStatsProvider.java
new file mode 100644
index 0000000..69f37bd
--- /dev/null
+++ b/service/src/com/android/car/storagemonitoring/ProcfsUidIoStatsProvider.java
@@ -0,0 +1,105 @@
+/*
+ * 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.android.car.storagemonitoring;
+
+import android.annotation.Nullable;
+import android.car.storagemonitoring.UidIoRecord;
+import android.util.Log;
+import android.util.SparseArray;
+import com.android.car.CarLog;
+import com.android.internal.annotations.VisibleForTesting;
+import java.io.File;
+import java.io.IOException;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.util.List;
+import java.util.Objects;
+import java.util.StringTokenizer;
+
+/**
+ * Loads I/O stats from procfs
+ *
+ * The Android kernel can be configured to provide uid I/O stats in /proc/uid_io/stats.
+ */
+public class ProcfsUidIoStatsProvider implements UidIoStatsProvider {
+ private static Path DEFAULT_STATS_FILE = new File("/proc/uid_io/stats").toPath();
+
+ private final Path mStatsFile;
+
+ public ProcfsUidIoStatsProvider() {
+ this(DEFAULT_STATS_FILE);
+ }
+
+ @VisibleForTesting
+ ProcfsUidIoStatsProvider(Path statsFile) {
+ mStatsFile = Objects.requireNonNull(statsFile);
+ }
+
+ @Nullable
+ @Override
+ public SparseArray<UidIoRecord> load() {
+ List<String> lines;
+ SparseArray<UidIoRecord> result = new SparseArray<>();
+ try {
+ lines = Files.readAllLines(mStatsFile);
+ } catch (IOException e) {
+ Log.w(CarLog.TAG_STORAGE, "can't read I/O stats from " + mStatsFile, e);
+ return null;
+ }
+
+ for (String line : lines) {
+ StringTokenizer tokenizer = new StringTokenizer(line);
+ if (tokenizer.countTokens() != 11) {
+ Log.w(CarLog.TAG_STORAGE, "malformed I/O stats entry: " + line);
+ return null;
+ }
+
+ try {
+ int uid = Integer.valueOf(tokenizer.nextToken());
+ long foreground_rchar = Long.valueOf(tokenizer.nextToken());
+ long foreground_wchar = Long.valueOf(tokenizer.nextToken());
+ long foreground_read_bytes = Long.valueOf(tokenizer.nextToken());
+ long foreground_write_bytes = Long.valueOf(tokenizer.nextToken());
+ long background_rchar = Long.valueOf(tokenizer.nextToken());
+ long background_wchar = Long.valueOf(tokenizer.nextToken());
+ long background_read_bytes = Long.valueOf(tokenizer.nextToken());
+ long background_write_bytes = Long.valueOf(tokenizer.nextToken());
+ long foreground_fsync = Long.valueOf(tokenizer.nextToken());
+ long background_fsync = Long.valueOf(tokenizer.nextToken());
+
+ result.append(uid, new UidIoRecord(uid,
+ foreground_rchar,
+ foreground_wchar,
+ foreground_read_bytes,
+ foreground_write_bytes,
+ foreground_fsync,
+ background_rchar,
+ background_wchar,
+ background_read_bytes,
+ background_write_bytes,
+ background_fsync));
+
+ } catch (NumberFormatException e) {
+ Log.w(CarLog.TAG_STORAGE, "malformed I/O stats entry: " + line, e);
+ return null;
+ }
+ }
+
+ return result;
+ }
+}
+
+
diff --git a/service/src/com/android/car/storagemonitoring/SysfsLifetimeWriteInfoProvider.java b/service/src/com/android/car/storagemonitoring/SysfsLifetimeWriteInfoProvider.java
new file mode 100644
index 0000000..50cc57c
--- /dev/null
+++ b/service/src/com/android/car/storagemonitoring/SysfsLifetimeWriteInfoProvider.java
@@ -0,0 +1,111 @@
+/*
+ * 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.storagemonitoring;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.car.storagemonitoring.LifetimeWriteInfo;
+import android.util.Log;
+import com.android.internal.annotations.VisibleForTesting;
+import java.io.File;
+import java.io.IOException;
+import java.nio.file.Files;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import java.util.Objects;
+
+/**
+ * <p>Loads lifetime write data for mounted filesystems via sysfs.</p>
+ *
+ * <p>ext4 and f2fs currently offer this information via
+ * /sys/fs/<i>type</i>/<i>partition</i>/lifetime_write_kbytes VFS entry points.</p>
+ */
+public class SysfsLifetimeWriteInfoProvider implements LifetimeWriteInfoProvider {
+ private static final String TAG = SysfsLifetimeWriteInfoProvider.class.getSimpleName();
+
+ private static final String DEFAULT_PATH = "/sys/fs/";
+ private static final String[] KNOWN_FILESYSTEMS = new String[] {
+ "ext4",
+ "f2fs"
+ };
+ private static final String FILENAME = "lifetime_write_kbytes";
+
+ private final File mWriteInfosPath;
+
+ public SysfsLifetimeWriteInfoProvider() {
+ this(new File(DEFAULT_PATH));
+ }
+
+ @VisibleForTesting
+ SysfsLifetimeWriteInfoProvider(File writeInfosPath) {
+ mWriteInfosPath = writeInfosPath;
+ }
+
+ @Nullable
+ private LifetimeWriteInfo tryParse(File dir) {
+ File writefile = new File(dir, FILENAME);
+ if (!writefile.exists() || !writefile.isFile()) {
+ Log.d(TAG, writefile + " not a valid source of lifetime writes");
+ return null;
+ }
+ List<String> datalines;
+ try {
+ datalines = Files.readAllLines(writefile.toPath());
+ } catch (IOException e) {
+ Log.e(TAG, "unable to read write info from " + writefile, e);
+ return null;
+ }
+ if (datalines == null || datalines.size() != 1) {
+ Log.e(TAG, "unable to read valid write info from " + writefile);
+ return null;
+ }
+ String data = datalines.get(0);
+ try {
+ long writtenBytes = 1024L * Long.parseLong(data);
+ if (writtenBytes < 0) {
+ Log.e(TAG, "file at location " + writefile +
+ " contained a negative data amount " + data + ". Ignoring.");
+ return null;
+ } else {
+ return new LifetimeWriteInfo(
+ dir.getName(),
+ dir.getParentFile().getName(),
+ writtenBytes);
+ }
+ } catch (NumberFormatException e) {
+ Log.e(TAG, "unable to read valid write info from " + writefile, e);
+ return null;
+ }
+ }
+
+ @Override
+ @NonNull
+ public LifetimeWriteInfo[] load() {
+ List<LifetimeWriteInfo> writeInfos = new ArrayList<>();
+
+ for (String fstype : KNOWN_FILESYSTEMS) {
+ File fspath = new File(mWriteInfosPath, fstype);
+ if (!fspath.exists() || !fspath.isDirectory()) continue;
+ Arrays.stream(fspath.listFiles(File::isDirectory))
+ .map(this::tryParse)
+ .filter(Objects::nonNull)
+ .forEach(writeInfos::add);
+ }
+
+ return writeInfos.toArray(new LifetimeWriteInfo[0]);
+ }
+}
diff --git a/service/src/com/android/car/storagemonitoring/UfsWearInformationProvider.java b/service/src/com/android/car/storagemonitoring/UfsWearInformationProvider.java
new file mode 100644
index 0000000..fa7ba8b
--- /dev/null
+++ b/service/src/com/android/car/storagemonitoring/UfsWearInformationProvider.java
@@ -0,0 +1,112 @@
+/*
+ * 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.android.car.storagemonitoring;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.util.Log;
+import com.android.car.CarLog;
+import com.android.internal.annotations.VisibleForTesting;
+import java.io.File;
+import java.io.IOException;
+import java.util.List;
+import java.util.Optional;
+import java.util.Scanner;
+import java.util.regex.MatchResult;
+import java.util.regex.Pattern;
+
+/**
+ * Loads wear information from the UFS sysfs entry points.
+ * sysfs exposes UFS lifetime data in /sys/devices/soc/624000.ufshc/health
+ * The first line of the file contains the UFS version
+ * Subsequent lines contains individual information points in the format:
+ * Health Descriptor[Byte offset 0x%d]: %31s = 0x%hx
+ * Of these we care about the key values bPreEOLInfo and bDeviceLifeTimeEstA bDeviceLifeTimeEstB
+ */
+public class UfsWearInformationProvider implements WearInformationProvider {
+ private static File DEFAULT_FILE =
+ new File("/sys/devices/soc/624000.ufshc/health");
+
+ private File mFile;
+
+ public UfsWearInformationProvider() {
+ this(DEFAULT_FILE);
+ }
+
+ @VisibleForTesting
+ public UfsWearInformationProvider(@NonNull File file) {
+ mFile = file;
+ }
+
+ @Nullable
+ @Override
+ public WearInformation load() {
+ List<String> lifetimeData;
+ try {
+ lifetimeData = java.nio.file.Files.readAllLines(mFile.toPath());
+ } catch (IOException e) {
+ Log.w(CarLog.TAG_STORAGE, "error reading " + mFile, e);
+ return null;
+ }
+ if (lifetimeData == null || lifetimeData.size() < 4) {
+ return null;
+ }
+
+ Pattern infoPattern = Pattern.compile(
+ "Health Descriptor\\[Byte offset 0x\\d+\\]: (\\w+) = 0x([0-9a-fA-F]+)");
+
+ Optional<Integer> lifetimeA = Optional.empty();
+ Optional<Integer> lifetimeB = Optional.empty();
+ Optional<Integer> eol = Optional.empty();
+
+ for(String lifetimeInfo : lifetimeData) {
+ Scanner scanner = new Scanner(lifetimeInfo);
+ if (null == scanner.findInLine(infoPattern)) {
+ continue;
+ }
+ MatchResult match = scanner.match();
+ if (match.groupCount() != 2) {
+ continue;
+ }
+ String name = match.group(1);
+ String value = "0x" + match.group(2);
+ try {
+ switch (name) {
+ case "bPreEOLInfo":
+ eol = Optional.of(Integer.decode(value));
+ break;
+ case "bDeviceLifeTimeEstA":
+ lifetimeA = Optional.of(Integer.decode(value));
+ break;
+ case "bDeviceLifeTimeEstB":
+ lifetimeB = Optional.of(Integer.decode(value));
+ break;
+ }
+ } catch (NumberFormatException e) {
+ Log.w(CarLog.TAG_STORAGE,
+ "trying to decode key " + name + " value " + value + " didn't parse properly", e);
+ }
+ }
+
+ if (!lifetimeA.isPresent() || !lifetimeB.isPresent() || !eol.isPresent()) {
+ return null;
+ }
+
+ return new WearInformation(convertLifetime(lifetimeA.get()),
+ convertLifetime(lifetimeB.get()),
+ adjustEol(eol.get()));
+ }
+}
diff --git a/car-lib/src/android/car/media/ICarAudioCallback.aidl b/service/src/com/android/car/storagemonitoring/UidIoStatsProvider.java
similarity index 70%
copy from car-lib/src/android/car/media/ICarAudioCallback.aidl
copy to service/src/com/android/car/storagemonitoring/UidIoStatsProvider.java
index 7e01c71..8756509 100644
--- a/car-lib/src/android/car/media/ICarAudioCallback.aidl
+++ b/service/src/com/android/car/storagemonitoring/UidIoStatsProvider.java
@@ -13,10 +13,13 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
+package com.android.car.storagemonitoring;
-package android.car.media;
+import android.annotation.Nullable;
+import android.car.storagemonitoring.UidIoRecord;
+import android.util.SparseArray;
-/** @hide */
-oneway interface ICarAudioCallback {
- void onParameterChange(in String params) = 0;
+public interface UidIoStatsProvider {
+ @Nullable
+ SparseArray<UidIoRecord> load();
}
diff --git a/service/src/com/android/car/storagemonitoring/WearEstimateRecord.java b/service/src/com/android/car/storagemonitoring/WearEstimateRecord.java
new file mode 100644
index 0000000..d199325
--- /dev/null
+++ b/service/src/com/android/car/storagemonitoring/WearEstimateRecord.java
@@ -0,0 +1,178 @@
+/*
+ * 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.android.car.storagemonitoring;
+
+import android.annotation.NonNull;
+import android.car.storagemonitoring.WearEstimate;
+import android.car.storagemonitoring.WearEstimateChange;
+import android.util.JsonWriter;
+import java.io.IOException;
+import java.time.Instant;
+import java.util.Objects;
+import org.json.JSONException;
+import org.json.JSONObject;
+
+/**
+ * This class represents a wear estimate record as stored by CarStorageMonitoringService.
+ *
+ * Because it is meant to map 1:1 to on-disk records, it is not directly convertible to a
+ * WearEstimateChange because it does not include information about "acceptable degradation".
+ */
+public class WearEstimateRecord {
+
+ private final WearEstimate mOldWearEstimate;
+ private final WearEstimate mNewWearEstimate;
+ private final long mTotalCarServiceUptime;
+ private final Instant mUnixTimestamp;
+
+ public WearEstimateRecord(@NonNull WearEstimate oldWearEstimate,
+ @NonNull WearEstimate newWearEstimate,
+ long totalCarServiceUptime,
+ @NonNull Instant unixTimestamp) {
+ mOldWearEstimate = Objects.requireNonNull(oldWearEstimate);
+ mNewWearEstimate = Objects.requireNonNull(newWearEstimate);
+ mTotalCarServiceUptime = totalCarServiceUptime;
+ mUnixTimestamp = Objects.requireNonNull(unixTimestamp);
+ }
+
+ WearEstimateRecord(@NonNull JSONObject json) throws JSONException {
+ mOldWearEstimate = new WearEstimate(json.getJSONObject("oldWearEstimate"));
+ mNewWearEstimate = new WearEstimate(json.getJSONObject("newWearEstimate"));
+ mTotalCarServiceUptime = json.getLong("totalCarServiceUptime");
+ mUnixTimestamp = Instant.ofEpochMilli(json.getLong("unixTimestamp"));
+
+ }
+
+ void writeToJson(@NonNull JsonWriter jsonWriter) throws IOException {
+ jsonWriter.beginObject();
+ jsonWriter.name("oldWearEstimate"); mOldWearEstimate.writeToJson(jsonWriter);
+ jsonWriter.name("newWearEstimate"); mNewWearEstimate.writeToJson(jsonWriter);
+ jsonWriter.name("totalCarServiceUptime").value(mTotalCarServiceUptime);
+ jsonWriter.name("unixTimestamp").value(mUnixTimestamp.toEpochMilli());
+ jsonWriter.endObject();
+ }
+
+ public WearEstimate getOldWearEstimate() {
+ return mOldWearEstimate;
+ }
+
+ public WearEstimate getNewWearEstimate() {
+ return mNewWearEstimate;
+ }
+
+ public long getTotalCarServiceUptime() {
+ return mTotalCarServiceUptime;
+ }
+
+ public Instant getUnixTimestamp() {
+ return mUnixTimestamp;
+ }
+
+ WearEstimateChange toWearEstimateChange(boolean isAcceptableDegradation) {
+ return new WearEstimateChange(mOldWearEstimate,
+ mNewWearEstimate, mTotalCarServiceUptime, mUnixTimestamp, isAcceptableDegradation);
+ }
+
+ @Override
+ public boolean equals(Object other) {
+ if (other instanceof WearEstimateRecord) {
+ WearEstimateRecord wer = (WearEstimateRecord)other;
+ if (!wer.mOldWearEstimate.equals(mOldWearEstimate)) return false;
+ if (!wer.mNewWearEstimate.equals(mNewWearEstimate)) return false;
+ if (wer.mTotalCarServiceUptime != mTotalCarServiceUptime) return false;
+ if (!wer.mUnixTimestamp.equals(mUnixTimestamp)) return false;
+ return true;
+ }
+ return false;
+ }
+
+ /**
+ * Checks whether this record tracks the same change as the provided estimate.
+ * That means the two objects have the same values for:
+ * <ul>
+ * <li>old wear indicators</li>
+ * <li>new wear indicators</li>
+ * <li>uptime at event</li>
+ * </ul>
+ */
+ public boolean isSameAs(@NonNull WearEstimateChange wearEstimateChange) {
+ if (!mOldWearEstimate.equals(wearEstimateChange.oldEstimate)) return false;
+ if (!mNewWearEstimate.equals(wearEstimateChange.newEstimate)) return false;
+ return (mTotalCarServiceUptime == wearEstimateChange.uptimeAtChange);
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(mOldWearEstimate,
+ mNewWearEstimate, mTotalCarServiceUptime, mUnixTimestamp);
+ }
+
+ @Override
+ public String toString() {
+ return String.format("WearEstimateRecord {" +
+ "mOldWearEstimate = %s, " +
+ "mNewWearEstimate = %s, " +
+ "mTotalCarServiceUptime = %d, " +
+ "mUnixTimestamp = %s}",
+ mOldWearEstimate, mNewWearEstimate, mTotalCarServiceUptime, mUnixTimestamp);
+ }
+
+ public static final class Builder {
+ private WearEstimate mOldWearEstimate = null;
+ private WearEstimate mNewWearEstimate = null;
+ private long mTotalCarServiceUptime = -1;
+ private Instant mUnixTimestamp = null;
+
+ private Builder() {}
+
+ public static Builder newBuilder() {
+ return new Builder();
+ }
+
+ public Builder fromWearEstimate(@NonNull WearEstimate wearEstimate) {
+ mOldWearEstimate = Objects.requireNonNull(wearEstimate);
+ return this;
+ }
+
+ public Builder toWearEstimate(@NonNull WearEstimate wearEstimate) {
+ mNewWearEstimate = Objects.requireNonNull(wearEstimate);
+ return this;
+ }
+
+ public Builder atUptime(long uptime) {
+ if (uptime < 0) {
+ throw new IllegalArgumentException("uptime must be >= 0");
+ }
+ mTotalCarServiceUptime = uptime;
+ return this;
+ }
+
+ public Builder atTimestamp(@NonNull Instant now) {
+ mUnixTimestamp = Objects.requireNonNull(now);
+ return this;
+ }
+
+ public WearEstimateRecord build() {
+ if (mOldWearEstimate == null || mNewWearEstimate == null ||
+ mTotalCarServiceUptime < 0 || mUnixTimestamp == null) {
+ throw new IllegalStateException("malformed builder state");
+ }
+ return new WearEstimateRecord(
+ mOldWearEstimate, mNewWearEstimate, mTotalCarServiceUptime, mUnixTimestamp);
+ }
+ }
+}
diff --git a/service/src/com/android/car/storagemonitoring/WearHistory.java b/service/src/com/android/car/storagemonitoring/WearHistory.java
new file mode 100644
index 0000000..38982aa
--- /dev/null
+++ b/service/src/com/android/car/storagemonitoring/WearHistory.java
@@ -0,0 +1,147 @@
+/*
+ * 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.android.car.storagemonitoring;
+
+import android.annotation.NonNull;
+import android.car.storagemonitoring.WearEstimateChange;
+import android.util.JsonWriter;
+import com.android.car.CarStorageMonitoringService;
+import com.android.car.R;
+import java.io.File;
+import java.io.IOException;
+import java.nio.file.Files;
+import java.time.Duration;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+import java.util.function.BiPredicate;
+import org.json.JSONArray;
+import org.json.JSONException;
+import org.json.JSONObject;
+
+/**
+ * This class represents the entire history of flash wear changes as tracked
+ * by CarStorageMonitoringService. It is a set of WearEstimateRecords.
+ *
+ * This is convertible to a list of WearEstimateChanges given policy about what constitutes
+ * acceptable or not acceptable degradation across change events. This policy is subject to
+ * modifications across OS versions, and as such it is not suitable for permanent storage.
+ */
+public class WearHistory {
+ private final List<WearEstimateRecord> mWearHistory = new ArrayList<>();
+
+ public WearHistory() {}
+
+ WearHistory(@NonNull JSONObject jsonObject) throws JSONException {
+ final JSONArray wearHistory = jsonObject.getJSONArray("wearHistory");
+ for (int i = 0; i < wearHistory.length(); ++i) {
+ JSONObject wearRecordJson = wearHistory.getJSONObject(i);
+ WearEstimateRecord wearRecord = new WearEstimateRecord(wearRecordJson);
+ add(wearRecord);
+ }
+ }
+
+ public static WearHistory fromRecords(@NonNull WearEstimateRecord... records) {
+ WearHistory wearHistory = new WearHistory();
+ Arrays.stream(records).forEach(wearHistory::add);
+ return wearHistory;
+ }
+
+ public static WearHistory fromJson(@NonNull File in) throws IOException, JSONException {
+ JSONObject jsonObject = new JSONObject(new String(Files.readAllBytes(in.toPath())));
+ return new WearHistory(jsonObject);
+ }
+
+ public void writeToJson(@NonNull JsonWriter out) throws IOException {
+ out.beginObject();
+ out.name("wearHistory").beginArray();
+ for (WearEstimateRecord wearRecord : mWearHistory) {
+ wearRecord.writeToJson(out);
+ }
+ out.endArray();
+ out.endObject();
+ }
+
+ public boolean add(@NonNull WearEstimateRecord record) {
+ if (record != null && mWearHistory.add(record)) {
+ mWearHistory.sort((WearEstimateRecord o1, WearEstimateRecord o2) ->
+ Long.valueOf(o1.getTotalCarServiceUptime()).compareTo(
+ o2.getTotalCarServiceUptime()));
+ return true;
+ }
+ return false;
+ }
+
+ public int size() {
+ return mWearHistory.size();
+ }
+
+ public WearEstimateRecord get(int i) {
+ return mWearHistory.get(i);
+ }
+
+ public WearEstimateRecord getLast() {
+ return get(size() - 1);
+ }
+
+ public List<WearEstimateChange> toWearEstimateChanges(
+ long acceptableHoursPerOnePercentFlashWear) {
+ // current technology allows us to detect wear in 10% increments
+ final int WEAR_PERCENTAGE_INCREMENT = 10;
+ final long acceptableWearRate = WEAR_PERCENTAGE_INCREMENT *
+ Duration.ofHours(acceptableHoursPerOnePercentFlashWear).toMillis();
+ final int numRecords = size();
+
+ if (numRecords == 0) return Collections.emptyList();
+
+ List<WearEstimateChange> result = new ArrayList<>();
+ result.add(get(0).toWearEstimateChange(true));
+
+ for (int i = 1; i < numRecords; ++i) {
+ WearEstimateRecord previousRecord = get(i - 1);
+ WearEstimateRecord currentRecord = get(i);
+ final long timeForChange =
+ currentRecord.getTotalCarServiceUptime() -
+ previousRecord.getTotalCarServiceUptime();
+ final boolean isAcceptableDegradation = timeForChange >= acceptableWearRate;
+ result.add(currentRecord.toWearEstimateChange(isAcceptableDegradation));
+ }
+
+ return Collections.unmodifiableList(result);
+ }
+
+ @Override
+ public boolean equals(Object other) {
+ if (other instanceof WearHistory) {
+ WearHistory wi = (WearHistory)other;
+ return wi.mWearHistory.equals(mWearHistory);
+ }
+ return false;
+ }
+
+ @Override
+ public int hashCode() {
+ return mWearHistory.hashCode();
+ }
+
+ @Override
+ public String toString() {
+ return mWearHistory.stream().map(WearEstimateRecord::toString).reduce(
+ "WearHistory[size = " + size() + "] -> ",
+ (String s, String t) -> s + ", " + t);
+ }
+}
diff --git a/service/src/com/android/car/storagemonitoring/WearInformation.java b/service/src/com/android/car/storagemonitoring/WearInformation.java
new file mode 100644
index 0000000..da38afe
--- /dev/null
+++ b/service/src/com/android/car/storagemonitoring/WearInformation.java
@@ -0,0 +1,91 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.car.storagemonitoring;
+
+import static java.util.Objects.hash;
+
+import android.car.storagemonitoring.WearEstimate;
+import java.time.Instant;
+
+public final class WearInformation {
+ public static final int UNKNOWN_LIFETIME_ESTIMATE = -1;
+
+ public static final int UNKNOWN_PRE_EOL_INFO = 0;
+ public static final int PRE_EOL_INFO_NORMAL = 1;
+ public static final int PRE_EOL_INFO_WARNING = 2;
+ public static final int PRE_EOL_INFO_URGENT = 3;
+
+ private static final String UNKNOWN = "unknown";
+ private static final String[] PRE_EOL_STRINGS = new String[] {
+ UNKNOWN, "normal", "warning", "urgent"
+ };
+
+ /**
+ * A lower bound on the lifetime estimate for "type A" memory cells, expressed as a percentage.
+ */
+ public final int lifetimeEstimateA;
+
+ /**
+ * A lower bound on the lifetime estimate for "type B" memory cells, expressed as a percentage.
+ */
+ public final int lifetimeEstimateB;
+
+ /**
+ * An estimate of the lifetime based on reserved block consumption.
+ */
+ public final int preEolInfo;
+
+ public WearInformation(int lifetimeA, int lifetimeB, int preEol) {
+ lifetimeEstimateA = lifetimeA;
+ lifetimeEstimateB = lifetimeB;
+ preEolInfo = preEol;
+ }
+
+ @Override
+ public int hashCode() {
+ return hash(lifetimeEstimateA, lifetimeEstimateB, preEolInfo);
+ }
+
+ @Override
+ public boolean equals(Object other) {
+ if (other instanceof WearInformation) {
+ WearInformation wi = (WearInformation)other;
+ return (wi.lifetimeEstimateA == lifetimeEstimateA) &&
+ (wi.lifetimeEstimateB == lifetimeEstimateB) &&
+ (wi.preEolInfo == preEolInfo);
+ } else {
+ return false;
+ }
+ }
+
+ private String lifetimeToString(int lifetime) {
+ if (lifetime == UNKNOWN_LIFETIME_ESTIMATE) return UNKNOWN;
+
+ return lifetime + "%";
+ }
+
+ @Override
+ public String toString() {
+ return String.format("lifetime estimate: A = %s, B = %s; pre EOL info: %s",
+ lifetimeToString(lifetimeEstimateA),
+ lifetimeToString(lifetimeEstimateB),
+ PRE_EOL_STRINGS[preEolInfo]);
+ }
+
+ public WearEstimate toWearEstimate() {
+ return new WearEstimate(lifetimeEstimateA, lifetimeEstimateB);
+ }
+}
diff --git a/service/src/com/android/car/storagemonitoring/WearInformationProvider.java b/service/src/com/android/car/storagemonitoring/WearInformationProvider.java
new file mode 100644
index 0000000..65574d7
--- /dev/null
+++ b/service/src/com/android/car/storagemonitoring/WearInformationProvider.java
@@ -0,0 +1,34 @@
+/*
+ * 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.android.car.storagemonitoring;
+
+import android.annotation.Nullable;
+
+public interface WearInformationProvider {
+ @Nullable
+ WearInformation load();
+
+ default int convertLifetime(int lifetime) {
+ if ((lifetime <= 0) || (lifetime > 11)) return WearInformation.UNKNOWN_LIFETIME_ESTIMATE;
+ return 10 * (lifetime - 1);
+ }
+
+ default int adjustEol(int eol) {
+ if ((eol <= 0) || (eol > 3)) return WearInformation.UNKNOWN_PRE_EOL_INFO;
+ return eol;
+ }
+
+}
diff --git a/service/src/com/android/car/systeminterface/DisplayInterface.java b/service/src/com/android/car/systeminterface/DisplayInterface.java
new file mode 100644
index 0000000..015f54d
--- /dev/null
+++ b/service/src/com/android/car/systeminterface/DisplayInterface.java
@@ -0,0 +1,182 @@
+/*
+ * 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.systeminterface;
+
+import android.content.ContentResolver;
+import android.content.Context;
+import android.database.ContentObserver;
+import android.hardware.display.DisplayManager;
+import android.hardware.display.DisplayManager.DisplayListener;
+import android.os.Handler;
+import android.os.Looper;
+import android.os.PowerManager;
+import android.os.SystemClock;
+import android.provider.Settings.SettingNotFoundException;
+import android.provider.Settings.System;
+import android.util.Log;
+import android.view.Display;
+
+import com.android.car.CarLog;
+import com.android.car.CarPowerManagementService;
+
+/**
+ * Interface that abstracts display operations
+ */
+public interface DisplayInterface {
+ /**
+ * @param brightness Level from 0 to 100%
+ */
+ void setDisplayBrightness(int brightness);
+ void setDisplayState(boolean on);
+ void startDisplayStateMonitoring(CarPowerManagementService service);
+ void stopDisplayStateMonitoring();
+
+ class DefaultImpl implements DisplayInterface {
+ private final ContentResolver mContentResolver;
+ private final Context mContext;
+ private final DisplayManager mDisplayManager;
+ private final int mMaximumBacklight;
+ private final int mMinimumBacklight;
+ private final PowerManager mPowerManager;
+ private final WakeLockInterface mWakeLockInterface;
+ private CarPowerManagementService mService;
+ private boolean mDisplayStateSet;
+
+ private ContentObserver mBrightnessObserver =
+ new ContentObserver(new Handler(Looper.getMainLooper())) {
+ @Override
+ public void onChange(boolean selfChange) {
+ int brightness = mMinimumBacklight;
+ int range = mMaximumBacklight - mMinimumBacklight;
+
+ try {
+ brightness = System.getInt(mContentResolver, System.SCREEN_BRIGHTNESS);
+ } catch (SettingNotFoundException e) {
+ Log.e(CarLog.TAG_POWER, "Could not get SCREEN_BRIGHTNESS: " + e);
+ }
+ // Convert brightness from 0-255 to 0-100%
+ brightness -= mMinimumBacklight;
+ brightness *= 100;
+ brightness += (range + 1) / 2;
+ brightness /= range;
+ mService.sendDisplayBrightness(brightness);
+ }
+ };
+
+ private final DisplayManager.DisplayListener mDisplayListener = new DisplayListener() {
+ @Override
+ public void onDisplayAdded(int displayId) {
+ //ignore
+ }
+
+ @Override
+ public void onDisplayRemoved(int displayId) {
+ //ignore
+ }
+
+ @Override
+ public void onDisplayChanged(int displayId) {
+ if (displayId == Display.DEFAULT_DISPLAY) {
+ handleMainDisplayChanged();
+ }
+ }
+ };
+
+ DefaultImpl(Context context, WakeLockInterface wakeLockInterface) {
+ mContext = context;
+ mContentResolver = mContext.getContentResolver();
+ mDisplayManager = (DisplayManager) context.getSystemService(Context.DISPLAY_SERVICE);
+ mPowerManager = (PowerManager) context.getSystemService(Context.POWER_SERVICE);
+ mMaximumBacklight = mPowerManager.getMaximumScreenBrightnessSetting();
+ mMinimumBacklight = mPowerManager.getMinimumScreenBrightnessSetting();
+ mWakeLockInterface = wakeLockInterface;
+ }
+
+ private void handleMainDisplayChanged() {
+ boolean isOn = isMainDisplayOn();
+ CarPowerManagementService service;
+ synchronized (this) {
+ if (mDisplayStateSet == isOn) { // same as what is set
+ return;
+ }
+ service = mService;
+ }
+ service.handleMainDisplayChanged(isOn);
+ }
+
+ private boolean isMainDisplayOn() {
+ Display disp = mDisplayManager.getDisplay(Display.DEFAULT_DISPLAY);
+ return disp.getState() == Display.STATE_ON;
+ }
+
+ @Override
+ public void setDisplayBrightness(int brightness) {
+ // Brightness is set in percent. Need to convert this into 0-255 scale. The actual
+ // brightness algorithm should look like this:
+ //
+ // newBrightness = (brightness * (max - min)) + min
+ //
+ // Since we're using integer arithmetic, do the multiplication first, then add 50 to
+ // round up as needed.
+ brightness *= mMaximumBacklight - mMinimumBacklight; // Multiply by full range
+ brightness += 50; // Integer rounding
+ brightness /= 100; // Divide by 100
+ brightness += mMinimumBacklight;
+ // Range checking
+ if (brightness < mMinimumBacklight) {
+ brightness = mMinimumBacklight;
+ } else if (brightness > mMaximumBacklight) {
+ brightness = mMaximumBacklight;
+ }
+ // Set the brightness
+ System.putInt(mContentResolver, System.SCREEN_BRIGHTNESS, brightness);
+ }
+
+ @Override
+ public void startDisplayStateMonitoring(CarPowerManagementService service) {
+ synchronized (this) {
+ mService = service;
+ mDisplayStateSet = isMainDisplayOn();
+ }
+ mContentResolver.registerContentObserver(System.getUriFor(System.SCREEN_BRIGHTNESS),
+ false, mBrightnessObserver);
+ mDisplayManager.registerDisplayListener(mDisplayListener, service.getHandler());
+ }
+
+ @Override
+ public void stopDisplayStateMonitoring() {
+ mDisplayManager.unregisterDisplayListener(mDisplayListener);
+ mContentResolver.unregisterContentObserver(mBrightnessObserver);
+ }
+
+ @Override
+ public void setDisplayState(boolean on) {
+ synchronized (this) {
+ mDisplayStateSet = on;
+ }
+ if (on) {
+ mWakeLockInterface.switchToFullWakeLock();
+ Log.i(CarLog.TAG_POWER, "on display");
+ mPowerManager.wakeUp(SystemClock.uptimeMillis());
+ } else {
+ mWakeLockInterface.switchToPartialWakeLock();
+ Log.i(CarLog.TAG_POWER, "off display");
+ mPowerManager.goToSleep(SystemClock.uptimeMillis());
+ }
+ }
+ }
+}
diff --git a/service/src/com/android/car/systeminterface/IOInterface.java b/service/src/com/android/car/systeminterface/IOInterface.java
new file mode 100644
index 0000000..2ce9174
--- /dev/null
+++ b/service/src/com/android/car/systeminterface/IOInterface.java
@@ -0,0 +1,40 @@
+/*
+ * 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.systeminterface;
+
+import android.content.Context;
+import java.io.File;
+
+/**
+ * Interface that abstracts I/O operations
+ */
+public interface IOInterface {
+ File getFilesDir();
+
+ class DefaultImpl implements IOInterface {
+ private final File mFilesDir;
+
+ DefaultImpl(Context context) {
+ mFilesDir = context.getFilesDir();
+ }
+
+ @Override
+ public File getFilesDir() {
+ return mFilesDir;
+ }
+ }
+}
diff --git a/service/src/com/android/car/systeminterface/StorageMonitoringInterface.java b/service/src/com/android/car/systeminterface/StorageMonitoringInterface.java
new file mode 100644
index 0000000..c0cceb0
--- /dev/null
+++ b/service/src/com/android/car/systeminterface/StorageMonitoringInterface.java
@@ -0,0 +1,47 @@
+/*
+ * 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.systeminterface;
+
+import com.android.car.storagemonitoring.EMmcWearInformationProvider;
+import com.android.car.storagemonitoring.LifetimeWriteInfoProvider;
+import com.android.car.storagemonitoring.ProcfsUidIoStatsProvider;
+import com.android.car.storagemonitoring.SysfsLifetimeWriteInfoProvider;
+import com.android.car.storagemonitoring.UfsWearInformationProvider;
+import com.android.car.storagemonitoring.UidIoStatsProvider;
+import com.android.car.storagemonitoring.WearInformationProvider;
+
+/**
+ * Interface that abstracts storage monitoring operations
+ */
+public interface StorageMonitoringInterface {
+ default WearInformationProvider[] getFlashWearInformationProviders() {
+ return new WearInformationProvider[] {
+ new EMmcWearInformationProvider(),
+ new UfsWearInformationProvider()
+ };
+ }
+
+ default UidIoStatsProvider getUidIoStatsProvider() {
+ return new ProcfsUidIoStatsProvider();
+ }
+
+ default LifetimeWriteInfoProvider getLifetimeWriteInfoProvider() {
+ return new SysfsLifetimeWriteInfoProvider();
+ }
+
+ class DefaultImpl implements StorageMonitoringInterface {}
+}
diff --git a/service/src/com/android/car/systeminterface/SystemInterface.java b/service/src/com/android/car/systeminterface/SystemInterface.java
new file mode 100644
index 0000000..b508988
--- /dev/null
+++ b/service/src/com/android/car/systeminterface/SystemInterface.java
@@ -0,0 +1,251 @@
+/*
+ * 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.systeminterface;
+
+import android.content.Context;
+
+import com.android.car.CarPowerManagementService;
+import com.android.car.procfsinspector.ProcessInfo;
+import com.android.car.storagemonitoring.LifetimeWriteInfoProvider;
+import com.android.car.storagemonitoring.UidIoStatsProvider;
+import com.android.car.storagemonitoring.WearInformationProvider;
+import com.android.internal.car.ICarServiceHelper;
+
+import java.io.File;
+import java.time.Duration;
+import java.util.List;
+import java.util.Objects;
+
+/**
+ * This class contains references to all the different wrapper interfaces between
+ * CarService and the Android OS APIs.
+ */
+public final class SystemInterface implements DisplayInterface, IOInterface,
+ StorageMonitoringInterface, SystemStateInterface, TimeInterface,
+ WakeLockInterface {
+ private final DisplayInterface mDisplayInterface;
+ private final IOInterface mIOInterface;
+ private final StorageMonitoringInterface mStorageMonitoringInterface;
+ private final SystemStateInterface mSystemStateInterface;
+ private final TimeInterface mTimeInterface;
+ private final WakeLockInterface mWakeLockInterface;
+
+ SystemInterface(DisplayInterface displayInterface,
+ IOInterface ioInterface,
+ StorageMonitoringInterface storageMonitoringInterface,
+ SystemStateInterface systemStateInterface,
+ TimeInterface timeInterface,
+ WakeLockInterface wakeLockInterface) {
+ mDisplayInterface = displayInterface;
+ mIOInterface = ioInterface;
+ mStorageMonitoringInterface = storageMonitoringInterface;
+ mSystemStateInterface = systemStateInterface;
+ mTimeInterface = timeInterface;
+ mWakeLockInterface = wakeLockInterface;
+ }
+
+ public DisplayInterface getDisplayInterface() { return mDisplayInterface; }
+ public IOInterface getIOInterface() { return mIOInterface; }
+ public SystemStateInterface getSystemStateInterface() { return mSystemStateInterface; }
+ public TimeInterface getTimeInterface() { return mTimeInterface; }
+ public WakeLockInterface getWakeLockInterface() { return mWakeLockInterface; }
+ public void setCarServiceHelper(ICarServiceHelper helper) {
+ mSystemStateInterface.setCarServiceHelper(helper);
+ }
+
+ @Override
+ public File getFilesDir() {
+ return mIOInterface.getFilesDir();
+ }
+
+ @Override
+ public void releaseAllWakeLocks() {
+ mWakeLockInterface.releaseAllWakeLocks();
+ }
+
+ @Override
+ public void switchToPartialWakeLock() {
+ mWakeLockInterface.switchToPartialWakeLock();
+ }
+
+ @Override
+ public void switchToFullWakeLock() {
+ mWakeLockInterface.switchToFullWakeLock();
+ }
+
+ @Override
+ public long getUptime() {
+ return mTimeInterface.getUptime();
+ }
+
+ @Override
+ public long getUptime(boolean includeDeepSleepTime) {
+ return mTimeInterface.getUptime(includeDeepSleepTime);
+ }
+
+ @Override
+ public void scheduleAction(Runnable r, long delayMs) {
+ mTimeInterface.scheduleAction(r, delayMs);
+ }
+
+ @Override
+ public List<ProcessInfo> getRunningProcesses() {
+ return mSystemStateInterface.getRunningProcesses();
+ }
+
+ @Override
+ public void cancelAllActions() {
+ mTimeInterface.cancelAllActions();
+ }
+
+ @Override
+ public void setDisplayBrightness(int brightness) {
+ mDisplayInterface.setDisplayBrightness(brightness);
+ }
+
+ @Override
+ public void setDisplayState(boolean on) {
+ mDisplayInterface.setDisplayState(on);
+ }
+
+ @Override
+ public void startDisplayStateMonitoring(CarPowerManagementService service) {
+ mDisplayInterface.startDisplayStateMonitoring(service);
+ }
+
+ @Override
+ public void stopDisplayStateMonitoring() {
+ mDisplayInterface.stopDisplayStateMonitoring();
+ }
+
+ @Override
+ public WearInformationProvider[] getFlashWearInformationProviders() {
+ return mStorageMonitoringInterface.getFlashWearInformationProviders();
+ }
+
+ @Override
+ public UidIoStatsProvider getUidIoStatsProvider() {
+ return mStorageMonitoringInterface.getUidIoStatsProvider();
+ }
+
+ @Override
+ public LifetimeWriteInfoProvider getLifetimeWriteInfoProvider() {
+ return mStorageMonitoringInterface.getLifetimeWriteInfoProvider();
+ }
+
+ @Override
+ public void shutdown() {
+ mSystemStateInterface.shutdown();
+ }
+
+ @Override
+ public boolean enterDeepSleep(int wakeupTimeSec) {
+ return mSystemStateInterface.enterDeepSleep(wakeupTimeSec);
+ }
+
+ @Override
+ public void scheduleActionForBootCompleted(Runnable action, Duration delay) {
+ mSystemStateInterface.scheduleActionForBootCompleted(action, delay);
+ }
+
+ @Override
+ public boolean isWakeupCausedByTimer() {
+ return mSystemStateInterface.isWakeupCausedByTimer();
+ }
+
+ @Override
+ public boolean isSystemSupportingDeepSleep() {
+ return mSystemStateInterface.isSystemSupportingDeepSleep();
+ }
+
+ public final static class Builder {
+ private DisplayInterface mDisplayInterface;
+ private IOInterface mIOInterface;
+ private StorageMonitoringInterface mStorageMonitoringInterface;
+ private SystemStateInterface mSystemStateInterface;
+ private TimeInterface mTimeInterface;
+ private WakeLockInterface mWakeLockInterface;
+
+ private Builder() {}
+
+ public static Builder newSystemInterface() {
+ return new Builder();
+ }
+
+ public static Builder defaultSystemInterface(Context context) {
+ Objects.requireNonNull(context);
+ Builder builder = newSystemInterface();
+ builder.withWakeLockInterface(new WakeLockInterface.DefaultImpl(context));
+ builder.withDisplayInterface(new DisplayInterface.DefaultImpl(context,
+ builder.mWakeLockInterface));
+ builder.withIOInterface(new IOInterface.DefaultImpl(context));
+ builder.withStorageMonitoringInterface(new StorageMonitoringInterface.DefaultImpl());
+ builder.withSystemStateInterface(new SystemStateInterface.DefaultImpl(context));
+ return builder.withTimeInterface(new TimeInterface.DefaultImpl());
+ }
+
+ public static Builder fromBuilder(Builder otherBuilder) {
+ return newSystemInterface()
+ .withDisplayInterface(otherBuilder.mDisplayInterface)
+ .withIOInterface(otherBuilder.mIOInterface)
+ .withStorageMonitoringInterface(otherBuilder.mStorageMonitoringInterface)
+ .withSystemStateInterface(otherBuilder.mSystemStateInterface)
+ .withTimeInterface(otherBuilder.mTimeInterface)
+ .withWakeLockInterface(otherBuilder.mWakeLockInterface);
+ }
+
+ public Builder withDisplayInterface(DisplayInterface displayInterface) {
+ mDisplayInterface = displayInterface;
+ return this;
+ }
+
+ public Builder withIOInterface(IOInterface ioInterface) {
+ mIOInterface = ioInterface;
+ return this;
+ }
+
+ public Builder withStorageMonitoringInterface(StorageMonitoringInterface
+ storageMonitoringInterface) {
+ mStorageMonitoringInterface = storageMonitoringInterface;
+ return this;
+ }
+
+ public Builder withSystemStateInterface(SystemStateInterface systemStateInterface) {
+ mSystemStateInterface = systemStateInterface;
+ return this;
+ }
+
+ public Builder withTimeInterface(TimeInterface timeInterface) {
+ mTimeInterface = timeInterface;
+ return this;
+ }
+
+ public Builder withWakeLockInterface(WakeLockInterface wakeLockInterface) {
+ mWakeLockInterface = wakeLockInterface;
+ return this;
+ }
+
+ public SystemInterface build() {
+ return new SystemInterface(Objects.requireNonNull(mDisplayInterface),
+ Objects.requireNonNull(mIOInterface),
+ Objects.requireNonNull(mStorageMonitoringInterface),
+ Objects.requireNonNull(mSystemStateInterface),
+ Objects.requireNonNull(mTimeInterface),
+ Objects.requireNonNull(mWakeLockInterface));
+ }
+ }
+}
diff --git a/service/src/com/android/car/systeminterface/SystemStateInterface.java b/service/src/com/android/car/systeminterface/SystemStateInterface.java
new file mode 100644
index 0000000..5fb7185
--- /dev/null
+++ b/service/src/com/android/car/systeminterface/SystemStateInterface.java
@@ -0,0 +1,137 @@
+/*
+ * 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.systeminterface;
+
+import java.time.Duration;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.concurrent.Executors;
+import java.util.concurrent.ScheduledExecutorService;
+import java.util.concurrent.TimeUnit;
+
+import com.android.car.procfsinspector.ProcessInfo;
+import com.android.car.procfsinspector.ProcfsInspector;
+import com.android.internal.car.ICarServiceHelper;
+
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.os.PowerManager;
+import android.os.SystemClock;
+import android.util.Log;
+import android.util.Pair;
+
+/**
+ * Interface that abstracts system status (booted, sleeping, ...) operations
+ */
+public interface SystemStateInterface {
+ static final String TAG = SystemStateInterface.class.getSimpleName();
+ void shutdown();
+ boolean enterDeepSleep(int sleepDurationSec);
+ void scheduleActionForBootCompleted(Runnable action, Duration delay);
+
+ default boolean isWakeupCausedByTimer() {
+ //TODO bug: 32061842, check wake up reason and do necessary operation information should
+ // come from kernel. it can be either power on or wake up for maintenance
+ // power on will involve GPIO trigger from power controller
+ // its own wakeup will involve timer expiration.
+ return false;
+ }
+
+ default boolean isSystemSupportingDeepSleep() {
+ //TODO should return by checking some kernel suspend control sysfs, bug: 32061842
+ return false;
+ }
+
+ default List<ProcessInfo> getRunningProcesses() {
+ return ProcfsInspector.readProcessTable();
+ }
+
+ default void setCarServiceHelper(ICarServiceHelper helper) {
+ // Do nothing
+ }
+
+ class DefaultImpl implements SystemStateInterface {
+ private final static Duration MIN_BOOT_COMPLETE_ACTION_DELAY = Duration.ofSeconds(10);
+ private final static int SUSPEND_TRY_TIMEOUT_MS = 1000;
+
+ private ICarServiceHelper mICarServiceHelper;
+ private final Context mContext;
+ private final PowerManager mPowerManager;
+ private List<Pair<Runnable, Duration>> mActionsList = new ArrayList<>();
+ private ScheduledExecutorService mExecutorService;
+ private final BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() {
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ if (Intent.ACTION_BOOT_COMPLETED.equals(intent.getAction())) {
+ for (Pair<Runnable, Duration> action : mActionsList) {
+ mExecutorService.schedule(action.first,
+ action.second.toMillis(), TimeUnit.MILLISECONDS);
+ }
+ }
+ }
+ };
+
+ DefaultImpl(Context context) {
+ mContext = context;
+ mPowerManager = (PowerManager) context.getSystemService(Context.POWER_SERVICE);
+ }
+
+ @Override
+ public void shutdown() {
+ mPowerManager.shutdown(false /* no confirm*/, null, true /* true */);
+ }
+
+ @Override
+ public boolean enterDeepSleep(int sleepDurationSec) {
+ boolean deviceEnteredSleep;
+ //TODO set wake up time via VHAL, bug: 32061842
+ try {
+ int retVal;
+ retVal = mICarServiceHelper.forceSuspend(SUSPEND_TRY_TIMEOUT_MS);
+ deviceEnteredSleep = retVal == 0;
+
+ } catch (Exception e) {
+ Log.e(TAG, "Unable to enter deep sleep", e);
+ deviceEnteredSleep = false;
+ }
+ return deviceEnteredSleep;
+ }
+
+ @Override
+ public void scheduleActionForBootCompleted(Runnable action, Duration delay) {
+ if (MIN_BOOT_COMPLETE_ACTION_DELAY.compareTo(delay) < 0) {
+ // TODO: consider adding some degree of randomness here
+ delay = MIN_BOOT_COMPLETE_ACTION_DELAY;
+ }
+ if (mActionsList.isEmpty()) {
+ final int corePoolSize = 1;
+ mExecutorService = Executors.newScheduledThreadPool(corePoolSize);
+ IntentFilter intentFilter = new IntentFilter(Intent.ACTION_BOOT_COMPLETED);
+ mContext.registerReceiver(mBroadcastReceiver, intentFilter);
+ }
+ mActionsList.add(Pair.create(action, delay));
+ }
+
+ @Override
+ public void setCarServiceHelper(ICarServiceHelper helper) {
+ mICarServiceHelper = helper;
+ }
+ }
+}
diff --git a/service/src/com/android/car/systeminterface/TimeInterface.java b/service/src/com/android/car/systeminterface/TimeInterface.java
new file mode 100644
index 0000000..dea1153
--- /dev/null
+++ b/service/src/com/android/car/systeminterface/TimeInterface.java
@@ -0,0 +1,57 @@
+/*
+ * 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.systeminterface;
+
+import static java.util.concurrent.Executors.newSingleThreadScheduledExecutor;
+
+import android.os.SystemClock;
+import java.util.concurrent.ScheduledExecutorService;
+import java.util.concurrent.TimeUnit;
+
+/**
+ * Interface that abstracts time operations
+ */
+public interface TimeInterface {
+ public static final boolean INCLUDE_DEEP_SLEEP_TIME = true;
+ public static final boolean EXCLUDE_DEEP_SLEEP_TIME = false;
+
+ default long getUptime() {
+ return getUptime(EXCLUDE_DEEP_SLEEP_TIME);
+ }
+ default long getUptime(boolean includeDeepSleepTime) {
+ return includeDeepSleepTime ?
+ SystemClock.elapsedRealtime() :
+ SystemClock.uptimeMillis();
+ }
+
+ void scheduleAction(Runnable r, long delayMs);
+ void cancelAllActions();
+
+ class DefaultImpl implements TimeInterface {
+ private final ScheduledExecutorService mExecutor = newSingleThreadScheduledExecutor();
+
+ @Override
+ public void scheduleAction(Runnable r, long delayMs) {
+ mExecutor.scheduleAtFixedRate(r, delayMs, delayMs, TimeUnit.MILLISECONDS);
+ }
+
+ @Override
+ public void cancelAllActions() {
+ mExecutor.shutdownNow();
+ }
+ }
+}
diff --git a/service/src/com/android/car/systeminterface/WakeLockInterface.java b/service/src/com/android/car/systeminterface/WakeLockInterface.java
new file mode 100644
index 0000000..cde6e5b
--- /dev/null
+++ b/service/src/com/android/car/systeminterface/WakeLockInterface.java
@@ -0,0 +1,75 @@
+/*
+ * 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.systeminterface;
+
+import android.content.Context;
+import android.os.PowerManager;
+import android.os.PowerManager.WakeLock;
+import com.android.car.CarLog;
+
+/**
+ * Interface that abstracts wake lock operations
+ */
+public interface WakeLockInterface {
+ void releaseAllWakeLocks();
+ void switchToPartialWakeLock();
+ void switchToFullWakeLock();
+
+ class DefaultImpl implements WakeLockInterface {
+ private final WakeLock mPartialWakeLock;
+ private final WakeLock mFullWakeLock;
+
+ DefaultImpl(Context context) {
+ PowerManager powerManager =
+ (PowerManager) context.getSystemService(Context.POWER_SERVICE);
+ mFullWakeLock = powerManager.newWakeLock(PowerManager.SCREEN_DIM_WAKE_LOCK,
+ CarLog.TAG_POWER);
+ mPartialWakeLock = powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK,
+ CarLog.TAG_POWER);
+ }
+
+ @Override
+ public void switchToPartialWakeLock() {
+ if (!mPartialWakeLock.isHeld()) {
+ mPartialWakeLock.acquire();
+ }
+ if (mFullWakeLock.isHeld()) {
+ mFullWakeLock.release();
+ }
+ }
+
+ @Override
+ public void switchToFullWakeLock() {
+ if (!mFullWakeLock.isHeld()) {
+ mFullWakeLock.acquire();
+ }
+ if (mPartialWakeLock.isHeld()) {
+ mPartialWakeLock.release();
+ }
+ }
+
+ @Override
+ public void releaseAllWakeLocks() {
+ if (mPartialWakeLock.isHeld()) {
+ mPartialWakeLock.release();
+ }
+ if (mFullWakeLock.isHeld()) {
+ mFullWakeLock.release();
+ }
+ }
+ }
+}
diff --git a/service/src/com/android/car/user/CarUserService.java b/service/src/com/android/car/user/CarUserService.java
new file mode 100644
index 0000000..74ff78d
--- /dev/null
+++ b/service/src/com/android/car/user/CarUserService.java
@@ -0,0 +1,99 @@
+/*
+ * 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.user;
+
+import android.annotation.Nullable;
+import android.car.settings.CarSettings;
+import android.car.user.CarUserManagerHelper;
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.content.pm.UserInfo;
+import android.util.Log;
+
+import com.android.car.CarServiceBase;
+import com.android.internal.annotations.VisibleForTesting;
+
+import java.io.PrintWriter;
+
+/**
+ * User service for cars. Manages users at boot time. Including:
+ *
+ * <ol>
+ * <li> Creates a secondary admin user on first run.
+ * <li> Log in to a default user.
+ * <ol/>
+ */
+public class CarUserService extends BroadcastReceiver implements CarServiceBase {
+ // Place holder for user name of the first user created.
+ @VisibleForTesting
+ static final String OWNER_NAME = "Owner";
+ private static final String TAG = "CarUserService";
+ private final Context mContext;
+ private final CarUserManagerHelper mCarUserManagerHelper;
+
+ public CarUserService(
+ @Nullable Context context, @Nullable CarUserManagerHelper carUserManagerHelper) {
+ if (Log.isLoggable(TAG, Log.DEBUG)) {
+ Log.d(TAG, "constructed");
+ }
+ mContext = context;
+ mCarUserManagerHelper = carUserManagerHelper;
+ }
+
+ @Override
+ public void init() {
+ if (Log.isLoggable(TAG, Log.DEBUG)) {
+ Log.d(TAG, "init");
+ }
+ IntentFilter filter = new IntentFilter();
+ filter.addAction(Intent.ACTION_LOCKED_BOOT_COMPLETED);
+
+ mContext.registerReceiver(this, filter);
+ }
+
+ @Override
+ public void release() {
+ if (Log.isLoggable(TAG, Log.DEBUG)) {
+ Log.d(TAG, "release");
+ }
+ mContext.unregisterReceiver(this);
+ }
+
+ @Override
+ public void dump(PrintWriter writer) {
+ writer.println(TAG);
+ writer.println("Context: " + mContext);
+ }
+
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ if (Log.isLoggable(TAG, Log.DEBUG)) {
+ Log.d(TAG, "onReceive " + intent);
+ }
+
+ if (intent.getAction() == Intent.ACTION_LOCKED_BOOT_COMPLETED) {
+ if (mCarUserManagerHelper.getAllUsers().size() == 0) {
+ UserInfo admin = mCarUserManagerHelper.createNewAdminUser(OWNER_NAME);
+ mCarUserManagerHelper.switchToUser(admin);
+ } else {
+ mCarUserManagerHelper.switchToUserId(CarSettings.DEFAULT_USER_ID_TO_BOOT_INTO);
+ }
+ }
+ }
+}
diff --git a/tests/CarDiagnosticVerifier/Android.mk b/tests/CarDiagnosticVerifier/Android.mk
index 780fa6a..e66c7a1 100644
--- a/tests/CarDiagnosticVerifier/Android.mk
+++ b/tests/CarDiagnosticVerifier/Android.mk
@@ -22,28 +22,26 @@
# Only compile source java files in this apk.
LOCAL_SRC_FILES := $(call all-java-files-under, src)
-LOCAL_RESOURCE_DIR := \
- $(LOCAL_PATH)/res \
- $(TOP)/frameworks/support/v7/recyclerview/res \
+LOCAL_RESOURCE_DIR := $(LOCAL_PATH)/res
LOCAL_PACKAGE_NAME := CarDiagnosticVerifier
LOCAL_PRIVATE_PLATFORM_APIS := true
-LOCAL_AAPT_FLAGS := --auto-add-overlay \
- --extra-packages android.support.v7.recyclerview \
-
LOCAL_JAVA_VERSION := 1.8
LOCAL_PROGUARD_ENABLED := disabled
LOCAL_DEX_PREOPT := false
+LOCAL_USE_AAPT2 := true
+
LOCAL_PRIVILEGED_MODULE := true
-LOCAL_STATIC_JAVA_LIBRARIES += \
- vehicle-hal-support-lib \
- android-support-v4 \
- android-support-v7-recyclerview \
+LOCAL_STATIC_JAVA_LIBRARIES += vehicle-hal-support-lib
+
+LOCAL_STATIC_ANDROID_LIBRARIES := \
+ androidx.legacy_legacy-support-v4 \
+ androidx.recyclerview_recyclerview
LOCAL_JAVA_LIBRARIES += android.car
diff --git a/tests/CarDiagnosticVerifier/AndroidManifest.xml b/tests/CarDiagnosticVerifier/AndroidManifest.xml
index 443825a..6fa5d3c 100644
--- a/tests/CarDiagnosticVerifier/AndroidManifest.xml
+++ b/tests/CarDiagnosticVerifier/AndroidManifest.xml
@@ -16,10 +16,12 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.google.android.car.diagnosticverifier">
- <uses-permission android:name="android.car.permission.DIAGNOSTIC_READ_ALL" />
+ <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"/>
diff --git a/tests/CarDiagnosticVerifier/res/layout/verifier_activity.xml b/tests/CarDiagnosticVerifier/res/layout/verifier_activity.xml
index 0c33ed8..5aa2a6b 100644
--- a/tests/CarDiagnosticVerifier/res/layout/verifier_activity.xml
+++ b/tests/CarDiagnosticVerifier/res/layout/verifier_activity.xml
@@ -24,7 +24,7 @@
android:layout_width="fill_parent"
android:layout_height="wrap_content" />
- <android.support.v7.widget.RecyclerView
+ <androidx.recyclerview.widget.RecyclerView
android:id="@+id/verification_results"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
diff --git a/tests/CarDiagnosticVerifier/src/com/google/android/car/diagnosticverifier/MainActivity.java b/tests/CarDiagnosticVerifier/src/com/google/android/car/diagnosticverifier/MainActivity.java
index 75db2ed..6814ad0 100644
--- a/tests/CarDiagnosticVerifier/src/com/google/android/car/diagnosticverifier/MainActivity.java
+++ b/tests/CarDiagnosticVerifier/src/com/google/android/car/diagnosticverifier/MainActivity.java
@@ -30,12 +30,13 @@
import android.os.Bundle;
import android.os.Environment;
import android.os.IBinder;
-import android.support.v7.widget.LinearLayoutManager;
-import android.support.v7.widget.RecyclerView;
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;
diff --git a/tests/CarDiagnosticVerifier/src/com/google/android/car/diagnosticverifier/VerificationResultAdapter.java b/tests/CarDiagnosticVerifier/src/com/google/android/car/diagnosticverifier/VerificationResultAdapter.java
index e6453b6..36e584d 100644
--- a/tests/CarDiagnosticVerifier/src/com/google/android/car/diagnosticverifier/VerificationResultAdapter.java
+++ b/tests/CarDiagnosticVerifier/src/com/google/android/car/diagnosticverifier/VerificationResultAdapter.java
@@ -16,12 +16,13 @@
package com.google.android.car.diagnosticverifier;
import android.content.Context;
-import android.support.v7.widget.RecyclerView;
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;
/**
diff --git a/tools/bootanalyze/stressfs/Android.mk b/tests/DefaultStorageMonitoringCompanionApp/Android.mk
similarity index 65%
copy from tools/bootanalyze/stressfs/Android.mk
copy to tests/DefaultStorageMonitoringCompanionApp/Android.mk
index 2e54e64..ff28cf6 100644
--- a/tools/bootanalyze/stressfs/Android.mk
+++ b/tests/DefaultStorageMonitoringCompanionApp/Android.mk
@@ -14,16 +14,27 @@
#
#
-LOCAL_PATH := $(call my-dir)
+LOCAL_PATH:= $(call my-dir)
include $(CLEAR_VARS)
-LOCAL_PACKAGE_NAME := StressFS
LOCAL_SRC_FILES := $(call all-java-files-under, src)
-LOCAL_MODULE_TAGS := tests
-LOCAL_SDK_VERSION := current
+LOCAL_RESOURCE_DIR := $(LOCAL_PATH)/res
-LOCAL_PROGUARD_FLAG_FILES := proguard.flags
+LOCAL_PACKAGE_NAME := DefaultStorageMonitoringCompanionApp
+LOCAL_PRIVATE_PLATFORM_APIS := true
+
+LOCAL_AAPT_FLAGS := --auto-add-overlay
+
+LOCAL_MODULE_TAGS := optional
+
+LOCAL_PROGUARD_ENABLED := disabled
+
+LOCAL_PRIVILEGED_MODULE := true
+
+LOCAL_DEX_PREOPT := false
+
+LOCAL_JAVA_LIBRARIES += android.car
include $(BUILD_PACKAGE)
diff --git a/tests/DefaultStorageMonitoringCompanionApp/AndroidManifest.xml b/tests/DefaultStorageMonitoringCompanionApp/AndroidManifest.xml
new file mode 100644
index 0000000..a676e18
--- /dev/null
+++ b/tests/DefaultStorageMonitoringCompanionApp/AndroidManifest.xml
@@ -0,0 +1,46 @@
+<?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.defaultstoragemonitoringcompanionapp">
+
+ <uses-permission android:name="android.car.permission.STORAGE_MONITORING" />
+
+ <application
+ android:allowBackup="true"
+ android:icon="@mipmap/ic_launcher"
+ android:label="@string/app_name"
+ android:roundIcon="@mipmap/ic_launcher_round"
+ android:supportsRtl="true"
+ android:theme="@style/AppTheme">
+ <activity
+ android:name=".MainActivity"
+ android:exported="true"
+ android:permission="android.car.permission.STORAGE_MONITORING">
+ </activity>
+
+ <receiver
+ android:name=".ExcessiveIoIntentReceiver"
+ android:exported="true"
+ android:permission="android.car.permission.STORAGE_MONITORING">
+ <intent-filter>
+ <action android:name="android.car.storagemonitoring.EXCESSIVE_IO"/>
+ </intent-filter>
+ </receiver>
+
+ </application>
+
+</manifest>
diff --git a/tests/DefaultStorageMonitoringCompanionApp/res/layout/activity_main.xml b/tests/DefaultStorageMonitoringCompanionApp/res/layout/activity_main.xml
new file mode 100644
index 0000000..017ebcc
--- /dev/null
+++ b/tests/DefaultStorageMonitoringCompanionApp/res/layout/activity_main.xml
@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="utf-8"?>
+<RelativeLayout
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:app="http://schemas.android.com/apk/res-auto"
+ xmlns:tools="http://schemas.android.com/tools"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent">
+
+ <TextView
+ android:id="@+id/notification"
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"
+ android:minLines="10"
+ android:textSize="24dp"
+ android:textColor="#ff0000"
+ android:text="Gathering data..."/>
+
+</RelativeLayout>
diff --git a/tests/DefaultStorageMonitoringCompanionApp/res/mipmap-hdpi/ic_launcher.png b/tests/DefaultStorageMonitoringCompanionApp/res/mipmap-hdpi/ic_launcher.png
new file mode 100644
index 0000000..cde69bc
--- /dev/null
+++ b/tests/DefaultStorageMonitoringCompanionApp/res/mipmap-hdpi/ic_launcher.png
Binary files differ
diff --git a/tests/DefaultStorageMonitoringCompanionApp/res/mipmap-hdpi/ic_launcher_round.png b/tests/DefaultStorageMonitoringCompanionApp/res/mipmap-hdpi/ic_launcher_round.png
new file mode 100644
index 0000000..9a078e3
--- /dev/null
+++ b/tests/DefaultStorageMonitoringCompanionApp/res/mipmap-hdpi/ic_launcher_round.png
Binary files differ
diff --git a/tests/DefaultStorageMonitoringCompanionApp/res/mipmap-mdpi/ic_launcher.png b/tests/DefaultStorageMonitoringCompanionApp/res/mipmap-mdpi/ic_launcher.png
new file mode 100644
index 0000000..c133a0c
--- /dev/null
+++ b/tests/DefaultStorageMonitoringCompanionApp/res/mipmap-mdpi/ic_launcher.png
Binary files differ
diff --git a/tests/DefaultStorageMonitoringCompanionApp/res/mipmap-mdpi/ic_launcher_round.png b/tests/DefaultStorageMonitoringCompanionApp/res/mipmap-mdpi/ic_launcher_round.png
new file mode 100644
index 0000000..efc028a
--- /dev/null
+++ b/tests/DefaultStorageMonitoringCompanionApp/res/mipmap-mdpi/ic_launcher_round.png
Binary files differ
diff --git a/tests/DefaultStorageMonitoringCompanionApp/res/mipmap-xhdpi/ic_launcher.png b/tests/DefaultStorageMonitoringCompanionApp/res/mipmap-xhdpi/ic_launcher.png
new file mode 100644
index 0000000..bfa42f0
--- /dev/null
+++ b/tests/DefaultStorageMonitoringCompanionApp/res/mipmap-xhdpi/ic_launcher.png
Binary files differ
diff --git a/tests/DefaultStorageMonitoringCompanionApp/res/mipmap-xhdpi/ic_launcher_round.png b/tests/DefaultStorageMonitoringCompanionApp/res/mipmap-xhdpi/ic_launcher_round.png
new file mode 100644
index 0000000..3af2608
--- /dev/null
+++ b/tests/DefaultStorageMonitoringCompanionApp/res/mipmap-xhdpi/ic_launcher_round.png
Binary files differ
diff --git a/tests/DefaultStorageMonitoringCompanionApp/res/mipmap-xxhdpi/ic_launcher.png b/tests/DefaultStorageMonitoringCompanionApp/res/mipmap-xxhdpi/ic_launcher.png
new file mode 100644
index 0000000..324e72c
--- /dev/null
+++ b/tests/DefaultStorageMonitoringCompanionApp/res/mipmap-xxhdpi/ic_launcher.png
Binary files differ
diff --git a/tests/DefaultStorageMonitoringCompanionApp/res/mipmap-xxhdpi/ic_launcher_round.png b/tests/DefaultStorageMonitoringCompanionApp/res/mipmap-xxhdpi/ic_launcher_round.png
new file mode 100644
index 0000000..9bec2e6
--- /dev/null
+++ b/tests/DefaultStorageMonitoringCompanionApp/res/mipmap-xxhdpi/ic_launcher_round.png
Binary files differ
diff --git a/tests/DefaultStorageMonitoringCompanionApp/res/mipmap-xxxhdpi/ic_launcher.png b/tests/DefaultStorageMonitoringCompanionApp/res/mipmap-xxxhdpi/ic_launcher.png
new file mode 100644
index 0000000..aee44e1
--- /dev/null
+++ b/tests/DefaultStorageMonitoringCompanionApp/res/mipmap-xxxhdpi/ic_launcher.png
Binary files differ
diff --git a/tests/DefaultStorageMonitoringCompanionApp/res/mipmap-xxxhdpi/ic_launcher_round.png b/tests/DefaultStorageMonitoringCompanionApp/res/mipmap-xxxhdpi/ic_launcher_round.png
new file mode 100644
index 0000000..34947cd
--- /dev/null
+++ b/tests/DefaultStorageMonitoringCompanionApp/res/mipmap-xxxhdpi/ic_launcher_round.png
Binary files differ
diff --git a/tests/DefaultStorageMonitoringCompanionApp/res/values/colors.xml b/tests/DefaultStorageMonitoringCompanionApp/res/values/colors.xml
new file mode 100644
index 0000000..5a077b3
--- /dev/null
+++ b/tests/DefaultStorageMonitoringCompanionApp/res/values/colors.xml
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <color name="colorPrimary">#3F51B5</color>
+ <color name="colorPrimaryDark">#303F9F</color>
+ <color name="colorAccent">#FF4081</color>
+</resources>
diff --git a/tests/DefaultStorageMonitoringCompanionApp/res/values/strings.xml b/tests/DefaultStorageMonitoringCompanionApp/res/values/strings.xml
new file mode 100644
index 0000000..8c0a9bb
--- /dev/null
+++ b/tests/DefaultStorageMonitoringCompanionApp/res/values/strings.xml
@@ -0,0 +1,3 @@
+<resources>
+ <string name="app_name">Flash Storage Wear Notification</string>
+</resources>
diff --git a/tests/DefaultStorageMonitoringCompanionApp/res/values/styles.xml b/tests/DefaultStorageMonitoringCompanionApp/res/values/styles.xml
new file mode 100644
index 0000000..a7a0615
--- /dev/null
+++ b/tests/DefaultStorageMonitoringCompanionApp/res/values/styles.xml
@@ -0,0 +1,8 @@
+<resources>
+
+ <!-- Base application theme. -->
+ <style name="AppTheme" parent="android:Theme.Material.Light.DarkActionBar">
+ <!-- Customize your theme here. -->
+ </style>
+
+</resources>
diff --git a/tests/DefaultStorageMonitoringCompanionApp/src/com/google/android/car/defaultstoragemonitoringcompanionapp/ExcessiveIoIntentReceiver.java b/tests/DefaultStorageMonitoringCompanionApp/src/com/google/android/car/defaultstoragemonitoringcompanionapp/ExcessiveIoIntentReceiver.java
new file mode 100644
index 0000000..2190bbd
--- /dev/null
+++ b/tests/DefaultStorageMonitoringCompanionApp/src/com/google/android/car/defaultstoragemonitoringcompanionapp/ExcessiveIoIntentReceiver.java
@@ -0,0 +1,20 @@
+package com.google.android.car.defaultstoragemonitoringcompanionapp;
+
+import android.car.storagemonitoring.CarStorageMonitoringManager;
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.util.Log;
+
+public class ExcessiveIoIntentReceiver extends BroadcastReceiver {
+ private final static String TAG = ExcessiveIoIntentReceiver.class.getSimpleName();
+
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ if (CarStorageMonitoringManager.INTENT_EXCESSIVE_IO.equals(intent.getAction())) {
+ Log.d(TAG, "excessive I/O activity detected.");
+ } else {
+ Log.w(TAG, "unexpected intent received: " + intent);
+ }
+ }
+}
diff --git a/tests/DefaultStorageMonitoringCompanionApp/src/com/google/android/car/defaultstoragemonitoringcompanionapp/MainActivity.java b/tests/DefaultStorageMonitoringCompanionApp/src/com/google/android/car/defaultstoragemonitoringcompanionapp/MainActivity.java
new file mode 100644
index 0000000..bcec38b
--- /dev/null
+++ b/tests/DefaultStorageMonitoringCompanionApp/src/com/google/android/car/defaultstoragemonitoringcompanionapp/MainActivity.java
@@ -0,0 +1,172 @@
+/*
+ * 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.defaultstoragemonitoringcompanionapp;
+
+import android.app.Activity;
+import android.car.Car;
+import android.car.CarNotConnectedException;
+import android.car.storagemonitoring.CarStorageMonitoringManager;
+import android.car.storagemonitoring.WearEstimate;
+import android.car.storagemonitoring.WearEstimateChange;
+import android.content.ComponentName;
+import android.content.ServiceConnection;
+import android.os.Bundle;
+import android.os.Handler;
+import android.os.IBinder;
+import android.util.Log;
+import android.widget.TextView;
+import java.time.Duration;
+import java.time.ZoneId;
+import java.time.format.DateTimeFormatter;
+import java.time.format.FormatStyle;
+import java.util.List;
+import java.util.Locale;
+
+public class MainActivity extends Activity {
+ private static final boolean DEBUG = false;
+ private static final String TAG = MainActivity.class.getSimpleName();
+
+ private final ServiceConnection mCarConnectionListener = new ServiceConnection() {
+ private String wearLevelToString(int wearLevel) {
+ if (wearLevel == WearEstimate.UNKNOWN) return "unknown";
+ return wearLevel + "%";
+ }
+
+ private String durationPairToString(long value1, String name1,
+ long value2, String name2) {
+ if (value1 > 0) {
+ String s = value1 + " " + name1;
+ if (value2 > 0) {
+ s += " and " + value2 + " " + name2;
+ }
+ return s;
+ }
+ return null;
+ }
+
+ private String durationToString(Duration duration) {
+ final long days = duration.toDays();
+ duration = duration.minusDays(days);
+ final long hours = duration.toHours();
+ duration = duration.minusHours(hours);
+ final long minutes = duration.toMinutes();
+
+ // for a week or more, just return days
+ if (days >= 7) {
+ return days + " days";
+ }
+
+ // otherwise try a few pairs of units
+ final String daysHours = durationPairToString(days, "days", hours, "hours");
+ if (daysHours != null) return daysHours;
+ final String hoursMinutes = durationPairToString(hours, "hours", minutes, "minutes");
+ if (hoursMinutes != null) return hoursMinutes;
+
+ // either minutes, or less than a minute
+ if (minutes > 0) {
+ return minutes + " minutes";
+ } else {
+ return "less than a minute";
+ }
+ }
+
+ private String wearChangeToString(WearEstimateChange wearEstimateChange) {
+ final int oldLevel = Math.max(wearEstimateChange.oldEstimate.typeA,
+ wearEstimateChange.oldEstimate.typeB);
+ final int newLevel = Math.max(wearEstimateChange.newEstimate.typeA,
+ wearEstimateChange.newEstimate.typeB);
+
+ final String oldLevelString = wearLevelToString(oldLevel);
+ final String newLevelString = wearLevelToString(newLevel);
+
+ final DateTimeFormatter formatter =
+ DateTimeFormatter.ofLocalizedDateTime(FormatStyle.SHORT).withZone(
+ ZoneId.systemDefault()).withLocale(Locale.getDefault());
+
+ final String wallClockTimeAtChange = formatter.format(wearEstimateChange.dateAtChange);
+ final String uptimeAtChange = durationToString(
+ Duration.ofMillis(wearEstimateChange.uptimeAtChange));
+
+ return String.format(
+ "Wear level went from %s to %s.\nThe vehicle has been running for %s.\nWall clock time: %s",
+ oldLevelString,
+ newLevelString,
+ uptimeAtChange,
+ wallClockTimeAtChange);
+ }
+
+ @Override
+ public void onServiceConnected(ComponentName name, IBinder service) {
+ Log.d(TAG, "Connected to " + name.flattenToString());
+
+ try {
+ CarStorageMonitoringManager storageMonitoringManager =
+ (CarStorageMonitoringManager) mCar.getCarManager(
+ Car.STORAGE_MONITORING_SERVICE);
+ Log.d(TAG, "Acquired a CarStorageMonitoringManager " + storageMonitoringManager);
+ List<WearEstimateChange> wearEstimateChanges = storageMonitoringManager
+ .getWearEstimateHistory();
+ if (wearEstimateChanges.isEmpty()) {
+ finish();
+ }
+
+ WearEstimateChange currentChange = wearEstimateChanges
+ .get(wearEstimateChanges.size() - 1);
+
+ if (!DEBUG && currentChange.isAcceptableDegradation) {
+ finish();
+ }
+
+ mNotificationTextView.setText(wearChangeToString(currentChange));
+ } 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;
+ }
+ };
+
+ private final Handler mHandler = new Handler();
+
+ private Car mCar = null;
+ private TextView mNotificationTextView = null;
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.activity_main);
+
+ mNotificationTextView = findViewById(R.id.notification);
+
+ mCar = Car.createCar(this, mCarConnectionListener);
+ mCar.connect();
+
+ mHandler.postDelayed(this::finish, 30000);
+ }
+
+ @Override
+ protected void onDestroy() {
+ if (mCar != null) {
+ mCar.disconnect();
+ }
+ super.onDestroy();
+ }
+}
diff --git a/tests/DirectRenderingClusterSample/Android.mk b/tests/DirectRenderingClusterSample/Android.mk
index 9253d1f..f3469fb 100644
--- a/tests/DirectRenderingClusterSample/Android.mk
+++ b/tests/DirectRenderingClusterSample/Android.mk
@@ -30,7 +30,11 @@
LOCAL_PROGUARD_FLAG_FILES := proguard.flags
LOCAL_PROGUARD_ENABLED := disabled
+LOCAL_USE_AAPT2 := true
+
+LOCAL_RESOURCE_DIR := $(LOCAL_PATH)/res
+
LOCAL_JAVA_LIBRARIES += android.car
-LOCAL_STATIC_JAVA_LIBRARIES += android-support-v4
+LOCAL_STATIC_ANDROID_LIBRARIES += androidx.legacy_legacy-support-v4
include $(BUILD_PACKAGE)
diff --git a/tests/DirectRenderingClusterSample/AndroidManifest.xml b/tests/DirectRenderingClusterSample/AndroidManifest.xml
index fc41ef0..17880d0 100644
--- a/tests/DirectRenderingClusterSample/AndroidManifest.xml
+++ b/tests/DirectRenderingClusterSample/AndroidManifest.xml
@@ -29,11 +29,12 @@
tools:ignore="ProtectedPermissions"/>
<uses-permission android:name="android.permission.MANAGE_ACTIVITY_STACKS"/>
<uses-permission android:name="android.permission.INJECT_EVENTS"/>
+ <uses-permission android:name="android.permission.INTERNET" />
+ <uses-permission android:name="android.permission.INTERNAL_SYSTEM_WINDOW"/>
<application android:label="@string/app_name"
android:icon="@mipmap/ic_launcher"
- android:directBootAware="true"
- android:persistent="true">
+ android:directBootAware="true">
<service android:name=".SampleClusterServiceImpl"
android:exported="false"
android:permission="android.car.permission.BIND_INSTRUMENT_CLUSTER_RENDERER_SERVICE"/>
diff --git a/tests/DirectRenderingClusterSample/res/layout/activity_main.xml b/tests/DirectRenderingClusterSample/res/layout/activity_main.xml
index 7e1ef9f..f711ba6 100644
--- a/tests/DirectRenderingClusterSample/res/layout/activity_main.xml
+++ b/tests/DirectRenderingClusterSample/res/layout/activity_main.xml
@@ -13,7 +13,7 @@
android:layout_height="match_parent"
android:orientation="vertical">
- <android.support.v4.view.ViewPager
+ <androidx.viewpager.widget.ViewPager
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/pager"
android:layout_width="match_parent"
diff --git a/tests/DirectRenderingClusterSample/src/android/car/cluster/sample/CarInfoFragment.java b/tests/DirectRenderingClusterSample/src/android/car/cluster/sample/CarInfoFragment.java
index d1e7112..87d57e5 100644
--- a/tests/DirectRenderingClusterSample/src/android/car/cluster/sample/CarInfoFragment.java
+++ b/tests/DirectRenderingClusterSample/src/android/car/cluster/sample/CarInfoFragment.java
@@ -15,13 +15,12 @@
*/
package android.car.cluster.sample;
-
import android.os.Bundle;
-import android.support.v4.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
+import androidx.fragment.app.Fragment;
/**
* A simple {@link Fragment} subclass.
diff --git a/tests/DirectRenderingClusterSample/src/android/car/cluster/sample/ClusterDisplayProvider.java b/tests/DirectRenderingClusterSample/src/android/car/cluster/sample/ClusterDisplayProvider.java
new file mode 100644
index 0000000..623fc0a
--- /dev/null
+++ b/tests/DirectRenderingClusterSample/src/android/car/cluster/sample/ClusterDisplayProvider.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 android.car.cluster.sample;
+
+import android.annotation.Nullable;
+import android.content.Context;
+import android.hardware.display.DisplayManager;
+import android.hardware.display.DisplayManager.DisplayListener;
+import android.text.TextUtils;
+import android.util.Log;
+import android.view.Display;
+
+/**
+ * This class provides a display for instrument cluster renderer.
+ * <p>
+ * By default it will try to provide physical secondary display if it is connected, if secondary
+ * display is not connected during creation of this class then it will start networked virtual
+ * display and listens for incoming connections.
+ *
+ * @see {@link NetworkedVirtualDisplay}
+ */
+public class ClusterDisplayProvider {
+ private static final String TAG = ClusterDisplayProvider.class.getSimpleName();
+
+ private static final int NETWORKED_DISPLAY_WIDTH = 1280;
+ private static final int NETWORKED_DISPLAY_HEIGHT = 720;
+ private static final int NETWORKED_DISPLAY_DPI = 320;
+
+ private final DisplayListener mListener;
+ private final DisplayManager mDisplayManager;
+
+ private NetworkedVirtualDisplay mNetworkedVirtualDisplay;
+ private int mClusterDisplayId = -1;
+
+ ClusterDisplayProvider(Context context, DisplayListener clusterDisplayListener) {
+ mListener = clusterDisplayListener;
+ mDisplayManager = context.getSystemService(DisplayManager.class);
+
+ Display clusterDisplay = getInstrumentClusterDisplay(mDisplayManager);
+ if (clusterDisplay != null) {
+ mClusterDisplayId = clusterDisplay.getDisplayId();
+ clusterDisplayListener.onDisplayAdded(clusterDisplay.getDisplayId());
+ trackClusterDisplay(null /* no need to track display by name */);
+ } else {
+ Log.i(TAG, "No physical cluster display found, starting network display");
+ setupNetworkDisplay(context);
+ }
+ }
+
+ private void setupNetworkDisplay(Context context) {
+ mNetworkedVirtualDisplay = new NetworkedVirtualDisplay(context,
+ NETWORKED_DISPLAY_WIDTH, NETWORKED_DISPLAY_HEIGHT, NETWORKED_DISPLAY_DPI);
+ String displayName = mNetworkedVirtualDisplay.start();
+ trackClusterDisplay(displayName);
+ }
+
+ private void trackClusterDisplay(@Nullable String displayName) {
+ mDisplayManager.registerDisplayListener(new DisplayListener() {
+ @Override
+ public void onDisplayAdded(int displayId) {
+ boolean clusterDisplayAdded = false;
+
+ if (displayName == null && mClusterDisplayId == -1) {
+ mClusterDisplayId = displayId;
+ clusterDisplayAdded = true;
+ } else {
+ Display display = mDisplayManager.getDisplay(displayId);
+ if (display != null && TextUtils.equals(display.getName(), displayName)) {
+ mClusterDisplayId = displayId;
+ clusterDisplayAdded = true;
+ }
+ }
+
+ if (clusterDisplayAdded) {
+ mListener.onDisplayAdded(displayId);
+ }
+ }
+
+ @Override
+ public void onDisplayRemoved(int displayId) {
+ if (displayId == mClusterDisplayId) {
+ mClusterDisplayId = -1;
+ mListener.onDisplayRemoved(displayId);
+ }
+ }
+
+ @Override
+ public void onDisplayChanged(int displayId) {
+ if (displayId == mClusterDisplayId) {
+ mListener.onDisplayChanged(displayId);
+ }
+ }
+
+ }, null);
+ }
+
+ private static Display getInstrumentClusterDisplay(DisplayManager displayManager) {
+ Display[] displays = displayManager.getDisplays();
+ Log.d(TAG, "There are currently " + displays.length + " displays connected.");
+
+ if (displays.length > 1) {
+ // TODO: assuming that secondary display is instrument cluster. Put this into settings?
+ // We could use name and ownerPackageName to verify this is the right display.
+ return displays[1];
+ }
+ return null;
+ }
+
+ @Override
+ public String toString() {
+ return getClass().getSimpleName() + "{"
+ + " clusterDisplayId = " + mClusterDisplayId
+ + "}";
+ }
+}
diff --git a/tests/DirectRenderingClusterSample/src/android/car/cluster/sample/MainClusterActivity.java b/tests/DirectRenderingClusterSample/src/android/car/cluster/sample/MainClusterActivity.java
index 1c3f7af..ae1d7a0 100644
--- a/tests/DirectRenderingClusterSample/src/android/car/cluster/sample/MainClusterActivity.java
+++ b/tests/DirectRenderingClusterSample/src/android/car/cluster/sample/MainClusterActivity.java
@@ -22,20 +22,20 @@
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.Bundle;
-import android.os.Handler;
import android.os.IBinder;
-import android.support.v4.app.Fragment;
-import android.support.v4.app.FragmentActivity;
-import android.support.v4.app.FragmentManager;
-import android.support.v4.app.FragmentPagerAdapter;
-import android.support.v4.view.ViewPager;
-import android.text.TextUtils;
import android.util.Log;
import android.util.SparseArray;
+import android.view.InputDevice;
import android.view.KeyEvent;
import android.view.View;
+import android.view.inputmethod.InputMethodManager;
import android.widget.Button;
-import android.widget.TextView;
+
+import androidx.fragment.app.Fragment;
+import androidx.fragment.app.FragmentActivity;
+import androidx.fragment.app.FragmentManager;
+import androidx.fragment.app.FragmentPagerAdapter;
+import androidx.viewpager.widget.ViewPager;
import java.lang.reflect.InvocationTargetException;
import java.util.HashMap;
@@ -44,20 +44,15 @@
implements Listener {
private static final String TAG = MainClusterActivity.class.getSimpleName();
- private Button mNavButton;
- private Button mPhoneButton;
- private Button mCarInfoButton;
- private Button mMusicButton;
- private TextView mTextOverlay;
private ViewPager mPager;
private SampleClusterServiceImpl mService;
- private final Handler mHandler = new Handler();
-
private HashMap<Button, Facet<?>> mButtonToFacet = new HashMap<>();
private SparseArray<Facet<?>> mOrderToFacet = new SparseArray<>();
+ private InputMethodManager mInputMethodManager;
+
private final View.OnFocusChangeListener mFacetButtonFocusListener =
new View.OnFocusChangeListener() {
@Override
@@ -73,6 +68,8 @@
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
+ mInputMethodManager = getSystemService(InputMethodManager.class);
+
Intent intent = new Intent(this, SampleClusterServiceImpl.class);
intent.setAction(LOCAL_BINDING_ACTION);
bindService(intent,
@@ -92,22 +89,15 @@
}
}, BIND_AUTO_CREATE);
- mNavButton = findViewById(R.id.btn_nav);
- mPhoneButton = findViewById(R.id.btn_phone);
- mCarInfoButton = findViewById(R.id.btn_car_info);
- mMusicButton = findViewById(R.id.btn_music);
- mTextOverlay = findViewById(R.id.text_overlay);
-
registerFacets(
- new Facet<>(mNavButton, 0, NavigationFragment.class),
- new Facet<>(mPhoneButton, 1, PhoneFragment.class),
- new Facet<>(mMusicButton, 2, MusicFragment.class),
- new Facet<>(mCarInfoButton, 3, CarInfoFragment.class));
+ new Facet<>(findViewById(R.id.btn_nav), 0, NavigationFragment.class),
+ new Facet<>(findViewById(R.id.btn_phone), 1, PhoneFragment.class),
+ new Facet<>(findViewById(R.id.btn_music), 2, MusicFragment.class),
+ new Facet<>(findViewById(R.id.btn_car_info), 3, CarInfoFragment.class));
- mPager = (ViewPager) findViewById(R.id.pager);
+ mPager = findViewById(R.id.pager);
mPager.setAdapter(new ClusterPageAdapter(getSupportFragmentManager()));
-
- mNavButton.requestFocus();
+ mOrderToFacet.get(0).button.requestFocus();
}
@Override
@@ -119,47 +109,16 @@
}
@Override
- public void onShowToast(String text) {
- if (mTextOverlay.getVisibility() == View.VISIBLE) {
- if (!TextUtils.isEmpty(mTextOverlay.getText())) {
- mTextOverlay.setText(mTextOverlay.getText() + "\n" + text);
- } else {
- mTextOverlay.setText(text);
- }
- }
-
- mTextOverlay.setVisibility(View.VISIBLE);
-
- mHandler.removeCallbacksAndMessages(null);
- mHandler.postDelayed(() -> {
- mTextOverlay.setVisibility(View.GONE);
- mTextOverlay.setText("");
- }, 3000);
- }
-
- @Override
public void onKeyEvent(KeyEvent event) {
Log.i(TAG, "onKeyEvent, event: " + event);
- dispatchKeyEvent(event); // TODO: dispatch event doesn't work for some reason.
- if (event.getAction() == KeyEvent.ACTION_DOWN) {
- if (event.getKeyCode() == KeyEvent.KEYCODE_DPAD_RIGHT) {
- int nextItem = (mPager.getCurrentItem() + 1) % mButtonToFacet.size();
- mOrderToFacet.get(nextItem).button.requestFocus();
- } else if (event.getKeyCode() == KeyEvent.KEYCODE_DPAD_LEFT) {
- int nextItem = (mPager.getCurrentItem() - 1);
- if (nextItem < 0) nextItem = mButtonToFacet.size() - 1;
- mOrderToFacet.get(nextItem).button.requestFocus();
- }
- }
+ // This is a hack. We use SOURCE_CLASS_POINTER here because this type of input is associated
+ // with the display. otherwise this event will be ignored in ViewRootImpl because injecting
+ // KeyEvent w/o activity being focused is useless.
+ event.setSource(event.getSource() | InputDevice.SOURCE_CLASS_POINTER);
+ mInputMethodManager.dispatchKeyEventFromInputMethod(getCurrentFocus(), event);
}
- @Override
- public boolean dispatchKeyEvent(KeyEvent event) {
- boolean consumed = super.dispatchKeyEvent(event);
- Log.i(TAG, "dispatchKeyEvent, event: " + event + ", consumed: " + consumed);
- return consumed;
- }
public class ClusterPageAdapter extends FragmentPagerAdapter {
public ClusterPageAdapter(FragmentManager fm) {
diff --git a/tests/DirectRenderingClusterSample/src/android/car/cluster/sample/MusicFragment.java b/tests/DirectRenderingClusterSample/src/android/car/cluster/sample/MusicFragment.java
index 2c82065..c0a1fb7 100644
--- a/tests/DirectRenderingClusterSample/src/android/car/cluster/sample/MusicFragment.java
+++ b/tests/DirectRenderingClusterSample/src/android/car/cluster/sample/MusicFragment.java
@@ -16,11 +16,12 @@
package android.car.cluster.sample;
import android.os.Bundle;
-import android.support.v4.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
+import androidx.fragment.app.Fragment;
+
/**
* A simple {@link Fragment} subclass.
*/
diff --git a/tests/DirectRenderingClusterSample/src/android/car/cluster/sample/NavigationFragment.java b/tests/DirectRenderingClusterSample/src/android/car/cluster/sample/NavigationFragment.java
index 0ffac1e..3ca74e2 100644
--- a/tests/DirectRenderingClusterSample/src/android/car/cluster/sample/NavigationFragment.java
+++ b/tests/DirectRenderingClusterSample/src/android/car/cluster/sample/NavigationFragment.java
@@ -26,7 +26,6 @@
import android.hardware.display.VirtualDisplay;
import android.os.Bundle;
import android.os.Handler;
-import android.support.v4.app.Fragment;
import android.util.Log;
import android.view.Display;
import android.view.LayoutInflater;
@@ -37,6 +36,8 @@
import android.view.View;
import android.view.ViewGroup;
+import androidx.fragment.app.Fragment;
+
public class NavigationFragment extends Fragment {
private final static String TAG = "Cluster.NavigationFragment";
diff --git a/tests/DirectRenderingClusterSample/src/android/car/cluster/sample/NetworkedVirtualDisplay.java b/tests/DirectRenderingClusterSample/src/android/car/cluster/sample/NetworkedVirtualDisplay.java
new file mode 100644
index 0000000..5066162
--- /dev/null
+++ b/tests/DirectRenderingClusterSample/src/android/car/cluster/sample/NetworkedVirtualDisplay.java
@@ -0,0 +1,417 @@
+/*
+ * 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.cluster.sample;
+
+import android.annotation.NonNull;
+import android.content.Context;
+import android.hardware.display.DisplayManager;
+import android.hardware.display.DisplayManager.DisplayListener;
+import android.hardware.display.VirtualDisplay;
+import android.media.MediaCodec;
+import android.media.MediaCodec.BufferInfo;
+import android.media.MediaCodec.CodecException;
+import android.media.MediaCodecInfo;
+import android.media.MediaCodecInfo.CodecProfileLevel;
+import android.media.MediaFormat;
+import android.os.Handler;
+import android.os.HandlerThread;
+import android.os.Looper;
+import android.os.Message;
+import android.util.Log;
+import android.view.Display;
+import android.view.Surface;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.net.ServerSocket;
+import java.net.Socket;
+import java.nio.ByteBuffer;
+import java.util.UUID;
+
+/**
+ * This class encapsulates all work related to managing networked virtual display.
+ * <p>
+ * It opens server socket and listens on port {@code PORT} for incoming connections. Once connection
+ * is established it creates virtual display and media encoder and starts streaming video to that
+ * socket. If the receiving part is disconnected, it will keep port open and virtual display won't
+ * be destroyed.
+ */
+public class NetworkedVirtualDisplay {
+ private static final String TAG = "Cluster." + NetworkedVirtualDisplay.class.getSimpleName();
+
+ private final String mUniqueId = UUID.randomUUID().toString();
+
+ private final DisplayManager mDisplayManager;
+ private final int mWidth;
+ private final int mHeight;
+ private final int mDpi;
+
+ private static final int PORT = 5151;
+ private static final int FPS = 25;
+ private static final int BITRATE = 6144000;
+ private static final String MEDIA_FORMAT_MIMETYPE = MediaFormat.MIMETYPE_VIDEO_AVC;
+
+ private static final int MSG_START = 0;
+ private static final int MSG_STOP = 1;
+ private static final int MSG_RESUBMIT_FRAME = 2;
+
+ private VirtualDisplay mVirtualDisplay;
+ private MediaCodec mVideoEncoder;
+ private HandlerThread mThread = new HandlerThread("NetworkThread");
+ private Handler mHandler;
+ private ServerSocket mServerSocket;
+ private OutputStream mOutputStream;
+ private byte[] mBuffer = null;
+ private int mLastFrameLength = 0;
+
+ private final DebugCounter mCounter = new DebugCounter();
+
+ NetworkedVirtualDisplay(Context context, int width, int height, int dpi) {
+ mDisplayManager = context.getSystemService(DisplayManager.class);
+ mWidth = width;
+ mHeight = height;
+ mDpi = dpi;
+
+ DisplayListener displayListener = new DisplayListener() {
+ @Override
+ public void onDisplayAdded(int i) {
+ final Display display = mDisplayManager.getDisplay(i);
+ if (display != null && getDisplayName().equals(display.getName())) {
+ onVirtualDisplayReady(display);
+ }
+ }
+
+ @Override
+ public void onDisplayRemoved(int i) {}
+
+ @Override
+ public void onDisplayChanged(int i) {}
+ };
+
+ mDisplayManager.registerDisplayListener(displayListener, new Handler());
+ }
+
+ /**
+ * Opens socket and creates virtual display asynchronously once connection established. Clients
+ * of this class may subscribe to
+ * {@link android.hardware.display.DisplayManager#registerDisplayListener(
+ * DisplayListener, Handler)} to be notified when virtual display is created.
+ * Note, that this method should be called only once.
+ *
+ * @return Unique display name associated with the instance of this class.
+ *
+ * @see {@link Display#getName()}
+ *
+ * @throws IllegalStateException thrown if networked display already started
+ */
+ public String start() {
+ if (mThread.isAlive()) {
+ throw new IllegalStateException("Already started");
+ }
+ mThread.start();
+ mHandler = new NetworkThreadHandler(mThread.getLooper());
+ mHandler.sendMessage(Message.obtain(mHandler, MSG_START));
+
+ return getDisplayName();
+ }
+
+ public void release() {
+ stopCasting();
+
+ if (mVirtualDisplay != null) {
+ mVirtualDisplay.release();
+ mVirtualDisplay = null;
+ }
+ mThread.quit();
+ }
+
+ private String getDisplayName() {
+ return "Cluster-" + mUniqueId;
+ }
+
+
+ private VirtualDisplay createVirtualDisplay() {
+ Log.i(TAG, "createVirtualDisplay " + mWidth + "x" + mHeight +"@" + mDpi);
+ return mDisplayManager.createVirtualDisplay(getDisplayName(), mWidth, mHeight, mDpi,
+ null, 0 /* flags */, null, null );
+ }
+
+ private void onVirtualDisplayReady(Display display) {
+ Log.i(TAG, "onVirtualDisplayReady, display: " + display);
+ }
+
+ private void startCasting(Handler handler) {
+ Log.i(TAG, "Start casting...");
+ mVideoEncoder = createVideoStream(handler);
+
+ if (mVirtualDisplay == null) {
+ mVirtualDisplay = createVirtualDisplay();
+ }
+ mVirtualDisplay.setSurface(mVideoEncoder.createInputSurface());
+ mVideoEncoder.start();
+
+ Log.i(TAG, "Video encoder started");
+ }
+
+ private MediaCodec createVideoStream(Handler handler) {
+ MediaCodec encoder;
+ try {
+ encoder = MediaCodec.createEncoderByType(MEDIA_FORMAT_MIMETYPE);
+ } catch (IOException e) {
+ Log.e(TAG, "Failed to create video encoder for " + MEDIA_FORMAT_MIMETYPE, e);
+ return null;
+ }
+
+ encoder.setCallback(new MediaCodec.Callback() {
+ @Override
+ public void onInputBufferAvailable(@NonNull MediaCodec codec, int index) {
+ Log.i(TAG, "onInputBufferAvailable, index: " + index);
+ }
+
+ @Override
+ public void onOutputBufferAvailable(@NonNull MediaCodec codec, int index,
+ @NonNull BufferInfo info) {
+ Log.i(TAG, "onOutputBufferAvailable, index: " + index);
+ mCounter.outputBuffers++;
+ doOutputBufferAvailable(index, info);
+ }
+
+ @Override
+ public void onError(@NonNull MediaCodec codec, @NonNull CodecException e) {
+ Log.e(TAG, "onError, codec: " + codec, e);
+ mCounter.bufferErrors++;
+ }
+
+ @Override
+ public void onOutputFormatChanged(@NonNull MediaCodec codec,
+ @NonNull MediaFormat format) {
+ Log.i(TAG, "onOutputFormatChanged, codec: " + codec + ", format: " + format);
+
+ }
+ }, handler);
+
+ configureVideoEncoder(encoder, mWidth, mHeight);
+ return encoder;
+ }
+
+ private void doOutputBufferAvailable(int index, @NonNull BufferInfo info) {
+ mHandler.removeMessages(MSG_RESUBMIT_FRAME);
+
+ ByteBuffer encodedData = mVideoEncoder.getOutputBuffer(index);
+ if (encodedData == null) {
+ throw new RuntimeException("couldn't fetch buffer at index " + index);
+ }
+
+ if (info.size != 0) {
+ encodedData.position(info.offset);
+ encodedData.limit(info.offset + info.size);
+ mLastFrameLength = encodedData.remaining();
+ if (mBuffer == null || mBuffer.length < mLastFrameLength) {
+ Log.i(TAG, "Allocating new buffer: " + mLastFrameLength);
+ mBuffer = new byte[mLastFrameLength];
+ }
+ encodedData.get(mBuffer, 0, mLastFrameLength);
+ mVideoEncoder.releaseOutputBuffer(index, false);
+
+ sendFrame(mBuffer, mLastFrameLength);
+
+ // If nothing happens in Virtual Display we won't receive new frames. If we won't keep
+ // sending frames it could be a problem for the receiver because it needs certain
+ // number of frames in order to start decoding.
+ scheduleResendingLastFrame(1000 / FPS);
+ } else {
+ Log.e(TAG, "Skipping empty buffer");
+ mVideoEncoder.releaseOutputBuffer(index, false);
+ }
+ }
+
+ private void scheduleResendingLastFrame(long delayMs) {
+ Message msg = mHandler.obtainMessage(MSG_RESUBMIT_FRAME);
+ mHandler.sendMessageDelayed(msg, delayMs);
+ }
+
+ private void sendFrame(byte[] buf, int len) {
+ try {
+ mOutputStream.write(buf, 0, len);
+ Log.i(TAG, "Bytes written: " + len);
+ } catch (IOException e) {
+ mCounter.clientsDisconnected++;
+ mOutputStream = null;
+ Log.e(TAG, "Failed to write data to socket, restart casting", e);
+ restart();
+ }
+ }
+
+ private void stopCasting() {
+ Log.i(TAG, "Stopping casting...");
+ if (mServerSocket != null) {
+ try {
+ mServerSocket.close();
+ } catch (IOException e) {
+ Log.w(TAG, "Failed to close server socket, ignoring", e);
+ }
+ mServerSocket = null;
+ }
+
+ if (mVirtualDisplay != null) {
+ // We do not want to destroy virtual display (as it will also destroy all the
+ // activities on that display, instead we will turn off the display by setting
+ // a null surface.
+ Surface surface = mVirtualDisplay.getSurface();
+ if (surface != null) surface.release();
+ mVirtualDisplay.setSurface(null);
+ }
+
+ if (mVideoEncoder != null) {
+ // Releasing encoder as stop/start didn't work well (couldn't create or reuse input
+ // surface).
+ mVideoEncoder.stop();
+ mVideoEncoder.release();
+ mVideoEncoder = null;
+ }
+ Log.i(TAG, "Casting stopped");
+ }
+
+ private synchronized void restart() {
+ // This method could be called from different threads when receiver has disconnected.
+ if (mHandler.hasMessages(MSG_START)) return;
+
+ mHandler.sendMessage(Message.obtain(mHandler, MSG_STOP));
+ mHandler.sendMessage(Message.obtain(mHandler, MSG_START));
+ }
+
+ private class NetworkThreadHandler extends Handler {
+
+ NetworkThreadHandler(Looper looper) {
+ super(looper);
+ }
+
+ @Override
+ public void handleMessage(Message msg) {
+ switch (msg.what) {
+ case MSG_START:
+ if (mServerSocket == null) {
+ mServerSocket = openServerSocket();
+ }
+ Log.i(TAG, "Server socket opened");
+
+ mOutputStream = waitForReceiver(mServerSocket);
+ if (mOutputStream == null) {
+ sendMessage(Message.obtain(this, MSG_START));
+ break;
+ }
+ mCounter.clientsConnected++;
+
+ startCasting(this);
+ break;
+
+ case MSG_STOP:
+ stopCasting();
+ break;
+
+ case MSG_RESUBMIT_FRAME:
+ if (mServerSocket != null && mOutputStream != null) {
+ Log.i(TAG, "Resending the last frame again. Buffer: " + mLastFrameLength);
+ sendFrame(mBuffer, mLastFrameLength);
+ }
+ // We will keep sending last frame every second as a heartbeat.
+ scheduleResendingLastFrame(1000L);
+ break;
+ }
+ }
+ }
+
+ private static void configureVideoEncoder(MediaCodec codec, int width, int height) {
+ MediaFormat format = MediaFormat.createVideoFormat(MEDIA_FORMAT_MIMETYPE, width, height);
+
+ format.setInteger(MediaFormat.KEY_COLOR_FORMAT,
+ MediaCodecInfo.CodecCapabilities.COLOR_FormatSurface);
+ format.setInteger(MediaFormat.KEY_BIT_RATE, BITRATE);
+ format.setInteger(MediaFormat.KEY_FRAME_RATE, FPS);
+ format.setInteger(MediaFormat.KEY_CAPTURE_RATE, FPS);
+ format.setInteger(MediaFormat.KEY_CHANNEL_COUNT, 1);
+ format.setFloat(MediaFormat.KEY_I_FRAME_INTERVAL, 1); // 1 second between I-frames
+ format.setInteger(MediaFormat.KEY_LEVEL, CodecProfileLevel.AVCLevel31);
+ format.setInteger(MediaFormat.KEY_PROFILE,
+ MediaCodecInfo.CodecProfileLevel.AVCProfileBaseline);
+
+ codec.configure(format, null, null, MediaCodec.CONFIGURE_FLAG_ENCODE);
+ }
+
+ private OutputStream waitForReceiver(ServerSocket serverSocket) {
+ try {
+ Log.i(TAG, "Listening for incoming connections on port: " + PORT);
+ Socket socket = serverSocket.accept();
+
+ Log.i(TAG, "Receiver connected: " + socket);
+ listenReceiverDisconnected(socket.getInputStream());
+
+ return socket.getOutputStream();
+ } catch (IOException e) {
+ Log.e(TAG, "Failed to accept connection");
+ return null;
+ }
+ }
+
+ private void listenReceiverDisconnected(InputStream inputStream) {
+ new Thread(() -> {
+ try {
+ if (inputStream.read() == -1) throw new IOException();
+ } catch (IOException e) {
+ Log.w(TAG, "Receiver has disconnected", e);
+ }
+ restart();
+ }).start();
+ }
+
+ private static ServerSocket openServerSocket() {
+ try {
+ return new ServerSocket(PORT);
+ } catch (IOException e) {
+ Log.e(TAG, "Failed to create server socket", e);
+ throw new RuntimeException(e);
+ }
+ }
+
+ @Override
+ public String toString() {
+ return getClass() + "{"
+ + mServerSocket
+ +", receiver connected: " + (mOutputStream != null)
+ +", encoder: " + mVideoEncoder
+ +", virtualDisplay" + mVirtualDisplay
+ + "}";
+ }
+
+ private static class DebugCounter {
+ long outputBuffers;
+ long bufferErrors;
+ long clientsConnected;
+ long clientsDisconnected;
+
+ @Override
+ public String toString() {
+ return getClass().getSimpleName() + "{"
+ + "outputBuffers=" + outputBuffers
+ + ", bufferErrors=" + bufferErrors
+ + ", clientsConnected=" + clientsConnected
+ + ", clientsDisconnected= " + clientsDisconnected
+ + "}";
+ }
+ }
+}
diff --git a/tests/DirectRenderingClusterSample/src/android/car/cluster/sample/PhoneFragment.java b/tests/DirectRenderingClusterSample/src/android/car/cluster/sample/PhoneFragment.java
index 9930ec5..31c165f 100644
--- a/tests/DirectRenderingClusterSample/src/android/car/cluster/sample/PhoneFragment.java
+++ b/tests/DirectRenderingClusterSample/src/android/car/cluster/sample/PhoneFragment.java
@@ -16,11 +16,11 @@
package android.car.cluster.sample;
import android.os.Bundle;
-import android.support.v4.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
+import androidx.fragment.app.Fragment;
/**
* A simple {@link Fragment} subclass.
diff --git a/tests/DirectRenderingClusterSample/src/android/car/cluster/sample/SampleClusterServiceImpl.java b/tests/DirectRenderingClusterSample/src/android/car/cluster/sample/SampleClusterServiceImpl.java
index 1457708..1fa028e 100644
--- a/tests/DirectRenderingClusterSample/src/android/car/cluster/sample/SampleClusterServiceImpl.java
+++ b/tests/DirectRenderingClusterSample/src/android/car/cluster/sample/SampleClusterServiceImpl.java
@@ -16,6 +16,7 @@
package android.car.cluster.sample;
import static android.content.Intent.FLAG_ACTIVITY_NEW_TASK;
+
import static java.lang.Integer.parseInt;
import android.app.ActivityOptions;
@@ -24,18 +25,16 @@
import android.car.cluster.renderer.InstrumentClusterRenderingService;
import android.car.cluster.renderer.NavigationRenderer;
import android.car.navigation.CarNavigationInstrumentCluster;
-import android.content.Context;
import android.content.Intent;
-import android.graphics.Bitmap;
import android.graphics.Rect;
-import android.hardware.display.DisplayManager;
+import android.hardware.display.DisplayManager.DisplayListener;
import android.os.Binder;
+import android.os.Bundle;
import android.os.IBinder;
import android.os.SystemClock;
import android.provider.Settings;
import android.provider.Settings.Global;
import android.util.Log;
-import android.view.Display;
import android.view.InputDevice;
import android.view.KeyEvent;
@@ -54,6 +53,8 @@
private final Binder mLocalBinder = new LocalBinder();
static final String LOCAL_BINDING_ACTION = "local";
+ private ClusterDisplayProvider mDisplayProvider;
+
@Override
public IBinder onBind(Intent intent) {
Log.i(TAG, "onBind, intent: " + intent);
@@ -66,14 +67,29 @@
super.onCreate();
Log.i(TAG, "onCreate");
- Display clusterDisplay = getInstrumentClusterDisplay(this);
- if (clusterDisplay == null) {
- Log.e(TAG, "Unable to find instrument cluster display");
- return;
- }
+ mDisplayProvider = new ClusterDisplayProvider(this,
+ new DisplayListener() {
+ @Override
+ public void onDisplayAdded(int displayId) {
+ Log.i(TAG, "Cluster display found, displayId: " + displayId);
+ doClusterDisplayConnected(displayId);
+ }
+ @Override
+ public void onDisplayRemoved(int displayId) {
+ Log.w(TAG, "Cluster display has been removed");
+ }
+
+ @Override
+ public void onDisplayChanged(int displayId) {
+
+ }
+ });
+ }
+
+ private void doClusterDisplayConnected(int displayId) {
ActivityOptions options = ActivityOptions.makeBasic();
- options.setLaunchDisplayId(clusterDisplay.getDisplayId());
+ options.setLaunchDisplayId(displayId);
Intent intent = new Intent(this, MainClusterActivity.class);
intent.setFlags(FLAG_ACTIVITY_NEW_TASK);
startActivity(intent, options.toBundle());
@@ -87,6 +103,12 @@
}
}
+ @Override
+ public void onDestroy() {
+ super.onDestroy();
+ Log.w(TAG, "onDestroy");
+ }
+
void registerListener(Listener listener) {
mListener = listener;
}
@@ -108,32 +130,15 @@
}
@Override
- public void onStartNavigation() {
- Log.i(TAG, "onStartNavigation");
- }
-
- @Override
- public void onStopNavigation() {
- Log.i(TAG, "onStopNavigation");
- }
-
- @Override
- public void onNextTurnChanged(int event, CharSequence eventName, int turnAngle,
- int turnNumber, Bitmap image, int turnSide) {
- Log.i(TAG, "event: " + event + ", eventName: " + eventName +
- ", turnAngle: " + turnAngle + ", turnNumber: " + turnNumber +
- ", image: " + image + ", turnSide: " + turnSide);
- mListener.onShowToast("Next turn: " + eventName);
- }
-
- @Override
- public void onNextTurnDistanceChanged(int distanceMeters, int timeSeconds,
- int displayDistanceMillis, int displayDistanceUnit) {
- Log.i(TAG, "onNextTurnDistanceChanged, distanceMeters: " + distanceMeters
- + ", timeSeconds: " + timeSeconds
- + ", displayDistanceMillis: " + displayDistanceMillis
- + ", displayDistanceUnit: " + displayDistanceUnit);
- mListener.onShowToast("Next turn distance: " + distanceMeters + " meters.");
+ public void onEvent(int eventType, Bundle bundle) {
+ StringBuilder bundleSummary = new StringBuilder();
+ for (String key : bundle.keySet()) {
+ bundleSummary.append(key);
+ bundleSummary.append("=");
+ bundleSummary.append(bundle.get(key));
+ bundleSummary.append(" ");
+ }
+ Log.i(TAG, "onEvent(" + eventType + ", " + bundleSummary + ")");
}
};
@@ -150,18 +155,23 @@
interface Listener {
void onKeyEvent(KeyEvent event);
- void onShowToast(String text);
}
@Override
protected void dump(FileDescriptor fd, PrintWriter writer, String[] args) {
if (args != null && args.length > 0) {
execShellCommand(args);
+ } else {
+
+ if (args == null || args.length == 0) {
+ writer.println("* dump " + getClass().getCanonicalName() + " *");
+ writer.println("DisplayProvider: " + mDisplayProvider);
+ }
}
}
- private void doKeyEvent(int keyCode) {
- Log.i(TAG, "doKeyEvent, keyCode: " + keyCode);
+ private void emulateKeyEvent(int keyCode) {
+ Log.i(TAG, "emulateKeyEvent, keyCode: " + keyCode);
long downTime = SystemClock.uptimeMillis();
long eventTime = SystemClock.uptimeMillis();
KeyEvent event = obtainKeyEvent(keyCode, downTime, eventTime, KeyEvent.ACTION_DOWN);
@@ -201,7 +211,7 @@
switch (command) {
case "injectKey": {
if (args.length > 1) {
- doKeyEvent(parseInt(args[1]));
+ emulateKeyEvent(parseInt(args[1]));
} else {
Log.i(TAG, "Not enough arguments");
}
@@ -240,20 +250,4 @@
}
}
- private static Display getInstrumentClusterDisplay(Context context) {
- DisplayManager displayManager = context.getSystemService(DisplayManager.class);
- Display[] displays = displayManager.getDisplays();
-
- Log.d(TAG, "There are currently " + displays.length + " displays connected.");
- for (Display display : displays) {
- Log.d(TAG, " " + display);
- }
-
- if (displays.length > 1) {
- // TODO: assuming that secondary display is instrument cluster. Put this into settings?
- return displays[1];
- }
- return null;
- }
-
}
diff --git a/tests/EmbeddedKitchenSinkApp/Android.mk b/tests/EmbeddedKitchenSinkApp/Android.mk
index 165e82c..7a8c145 100644
--- a/tests/EmbeddedKitchenSinkApp/Android.mk
+++ b/tests/EmbeddedKitchenSinkApp/Android.mk
@@ -23,7 +23,6 @@
LOCAL_SRC_FILES := $(call all-java-files-under, src)
-
LOCAL_USE_AAPT2 := true
LOCAL_RESOURCE_DIR := $(LOCAL_PATH)/res
@@ -42,16 +41,15 @@
LOCAL_DEX_PREOPT := false
LOCAL_STATIC_ANDROID_LIBRARIES += \
+ android-support-car \
car-service-lib-for-test
LOCAL_STATIC_JAVA_LIBRARIES += \
android.hidl.base-V1.0-java \
android.hardware.automotive.vehicle-V2.0-java \
- vehicle-hal-support-lib
+ vehicle-hal-support-lib \
+ com.android.car.keventreader-client
-LOCAL_JAVA_LIBRARIES += android.car
-
-include packages/apps/Car/libs/car-stream-ui-lib/car-stream-ui-lib.mk
include packages/services/Car/car-support-lib/car-support.mk
include $(BUILD_PACKAGE)
diff --git a/tests/EmbeddedKitchenSinkApp/AndroidManifest.xml b/tests/EmbeddedKitchenSinkApp/AndroidManifest.xml
index 2a96898..bc89ad4 100644
--- a/tests/EmbeddedKitchenSinkApp/AndroidManifest.xml
+++ b/tests/EmbeddedKitchenSinkApp/AndroidManifest.xml
@@ -25,14 +25,15 @@
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
<uses-permission android:name="android.car.permission.CAR_SPEED" />
<uses-permission android:name="android.car.permission.CAR_MILEAGE" />
- <uses-permission android:name="android.car.permission.CAR_FUEL" />
- <uses-permission android:name="android.car.permission.CAR_HVAC" />
+ <uses-permission android:name="android.car.permission.CAR_ENERGY" />
+ <uses-permission android:name="android.car.permission.CONTROL_CAR_CLIMATE" />
<uses-permission android:name="android.car.permission.CAR_MOCK_VEHICLE_HAL" />
<uses-permission android:name="android.car.permission.CAR_CAMERA" />
<uses-permission android:name="android.car.permission.CAR_NAVIGATION_MANAGER"/>
<uses-permission android:name="android.car.permission.CAR_CONTROL_AUDIO_VOLUME"/>
<uses-permission android:name="android.car.permission.VEHICLE_DYNAMICS_STATE"/>
<uses-permission android:name="android.car.permission.CAR_DISPLAY_IN_CLUSTER"/>
+ <uses-permission android:name="android.car.permission.STORAGE_MONITORING" />
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
<uses-permission android:name="android.permission.MANAGE_USB" />
<uses-permission android:name="android.permission.WRITE_SETTINGS" />
@@ -41,12 +42,16 @@
<uses-permission android:name="android.permission.READ_SMS"/>
<uses-permission android:name="android.permission.BLUETOOTH" />
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />
+ <uses-permission android:name="android.permission.INJECT_EVENTS" />
+
<application android:label="@string/app_title"
android:icon="@drawable/ic_launcher">
+ <uses-library android:name="android.test.runner" />
+
<!-- This is for embedded mode. -->
<activity android:name=".KitchenSinkActivity"
- android:theme="@style/CarDrawerActivityTheme"
+ android:theme="@style/KitchenSinkActivityTheme"
android:label="@string/app_title">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
@@ -89,18 +94,26 @@
android:theme="@android:style/Theme.Material.Light.Dialog"
android:launchMode="singleTop">
</activity>
-
<activity android:name=".cluster.FakeClusterNavigationActivity"
android:theme="@android:style/Theme.NoTitleBar.Fullscreen"
android:launchMode="singleInstance"
android:resizeableActivity="true"
android:allowEmbedded="true"
android:permission="android.car.permission.CAR_INSTRUMENT_CLUSTER_CONTROL">
- <intent-filter>
+ <intent-filter android:priority="-1">
<action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.DEFAULT"/>
<category android:name="android.car.cluster.NAVIGATION"/>
</intent-filter>
</activity>
+
+ <activity android:name=".activityview.ActivityViewTestFragment"/>
+
+ <!-- temporary solution until b/68882625 is fixed. -->
+ <receiver android:name=".touchsound.DisableTouchSoundOnBoot" android:exported="true">
+ <intent-filter>
+ <action android:name="android.intent.action.BOOT_COMPLETED"/>
+ </intent-filter>
+ </receiver>
</application>
</manifest>
diff --git a/tests/EmbeddedKitchenSinkApp/res/drawable/ic_check_box.xml b/tests/EmbeddedKitchenSinkApp/res/drawable/ic_check_box.xml
new file mode 100644
index 0000000..e985f39
--- /dev/null
+++ b/tests/EmbeddedKitchenSinkApp/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/tests/EmbeddedKitchenSinkApp/res/drawable/ic_check_box_checked.xml b/tests/EmbeddedKitchenSinkApp/res/drawable/ic_check_box_checked.xml
new file mode 100644
index 0000000..d64d4fc
--- /dev/null
+++ b/tests/EmbeddedKitchenSinkApp/res/drawable/ic_check_box_checked.xml
@@ -0,0 +1,26 @@
+<!--
+ ~ 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/tests/EmbeddedKitchenSinkApp/res/drawable/ic_check_box_unchecked.xml b/tests/EmbeddedKitchenSinkApp/res/drawable/ic_check_box_unchecked.xml
new file mode 100644
index 0000000..96246a3
--- /dev/null
+++ b/tests/EmbeddedKitchenSinkApp/res/drawable/ic_check_box_unchecked.xml
@@ -0,0 +1,26 @@
+<!--
+ ~ 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/tests/EmbeddedKitchenSinkApp/res/layout/activity_view_test_fragment.xml b/tests/EmbeddedKitchenSinkApp/res/layout/activity_view_test_fragment.xml
new file mode 100644
index 0000000..bd74423
--- /dev/null
+++ b/tests/EmbeddedKitchenSinkApp/res/layout/activity_view_test_fragment.xml
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="utf-8"?>
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:orientation="vertical"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent">
+
+ <LinearLayout android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:orientation="horizontal">
+ <Button android:id="@+id/av_launch_activity"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="@string/av_start_activity"/>
+ <Button android:id="@+id/av_resize"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="@string/av_resize"/>
+ </LinearLayout>
+ <RelativeLayout android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:padding="20dp">
+ <ActivityView android:id="@+id/av_activityview"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"/>
+ </RelativeLayout>
+
+</LinearLayout>
\ No newline at end of file
diff --git a/tests/EmbeddedKitchenSinkApp/res/layout/alert_dialog_bluetooth_pin_confirm.xml b/tests/EmbeddedKitchenSinkApp/res/layout/alert_dialog_bluetooth_pin_confirm.xml
new file mode 100644
index 0000000..d613e4a
--- /dev/null
+++ b/tests/EmbeddedKitchenSinkApp/res/layout/alert_dialog_bluetooth_pin_confirm.xml
@@ -0,0 +1,92 @@
+<?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.
+*/
+-->
+
+<ScrollView
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_height="match_parent"
+ android:layout_width="match_parent">
+
+ <LinearLayout
+ android:layout_marginStart="@dimen/car_keyline_1"
+ android:layout_marginEnd="@dimen/car_keyline_1"
+ android:layout_height="match_parent"
+ android:layout_width="match_parent"
+ android:orientation="vertical">
+
+ <RelativeLayout
+ android:layout_height="@dimen/car_double_line_list_item_height"
+ android:layout_width="match_parent" >
+ <LinearLayout
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:orientation="vertical"
+ android:layout_centerVertical="true"
+ android:gravity="center_vertical"
+ android:layout_alignParentStart="true">
+ <TextView
+ android:id="@+id/pairing_caption"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:text="@string/bluetooth_pairing_key_msg"
+ android:visibility="gone"
+ style="@style/TextAppearance.Car.Body2.SingleLine" />
+ <TextView
+ android:id="@+id/pairing_subhead"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:visibility="gone"
+ style="@style/TextAppearance.Car.Body1.SingleLine"
+ android:layout_marginTop="@dimen/car_padding_1" />
+ </LinearLayout>
+ </RelativeLayout>
+
+ <TextView
+ android:id="@+id/pairing_code_message"
+ android:layout_width="wrap_content"
+ android:layout_height="@dimen/car_single_line_list_item_height"
+ android:gravity="center_vertical"
+ android:text="@string/bluetooth_enter_passkey_msg"
+ style="@style/TextAppearance.Car.Body2"
+ android:visibility="gone" />
+
+ <RelativeLayout
+ android:layout_height="@dimen/car_double_line_list_item_height"
+ android:layout_width="match_parent" >
+ <CheckBox
+ android:id="@+id/phonebook_sharing_message_confirm_pin"
+ android:layout_width="@dimen/car_icon_size"
+ android:layout_height="@dimen/car_icon_size"
+ android:button="@drawable/ic_check_box"
+ android:layout_alignParentStart="true"
+ android:layout_centerVertical="true" />
+ <TextView
+ android:text="@string/bluetooth_pairing_shares_phonebook"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_alignParentStart="true"
+ android:layout_centerVertical="true"
+ android:layout_marginStart="@dimen/car_keyline_3"
+ android:layout_marginEnd="@dimen/car_keyline_3"
+ style="@style/TextAppearance.Car.Body2.SingleLine"
+ android:gravity="center_vertical"/>
+ </RelativeLayout>
+
+ </LinearLayout>
+
+</ScrollView>
diff --git a/tests/EmbeddedKitchenSinkApp/res/layout/alert_dialog_bluetooth_pin_entry.xml b/tests/EmbeddedKitchenSinkApp/res/layout/alert_dialog_bluetooth_pin_entry.xml
new file mode 100644
index 0000000..898cf4d
--- /dev/null
+++ b/tests/EmbeddedKitchenSinkApp/res/layout/alert_dialog_bluetooth_pin_entry.xml
@@ -0,0 +1,109 @@
+<?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.
+*/
+-->
+
+<ScrollView
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_height="match_parent"
+ android:layout_width="match_parent">
+
+ <LinearLayout
+ android:layout_height="match_parent"
+ android:layout_width="match_parent"
+ android:layout_marginStart="@dimen/car_keyline_1"
+ android:layout_marginEnd="@dimen/car_keyline_1"
+ android:orientation="vertical">
+
+ <TextView
+ android:id="@+id/message_below_pin"
+ android:layout_width="wrap_content"
+ android:layout_height="@dimen/car_single_line_list_item_height"
+ android:gravity="center_vertical"
+ style="@style/TextAppearance.Car.Body2"/>
+
+ <FrameLayout
+ android:layout_height="@dimen/car_double_line_list_item_height"
+ android:layout_width="match_parent" >
+ <LinearLayout
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:orientation="vertical"
+ android:layout_gravity="center_vertical">
+ <EditText
+ android:id="@+id/text"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ style="@style/TextAppearance.Car.Body1"
+ android:inputType="textPassword"
+ android:maxLines="1" />
+ <TextView
+ android:id="@+id/pin_values_hint"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_marginTop="@dimen/car_padding_2"
+ android:text="@string/bluetooth_pin_values_hint"
+ style="@style/TextAppearance.Car.Body2.SingleLine" />
+ </LinearLayout>
+ </FrameLayout>
+
+ <RelativeLayout
+ android:layout_height="@dimen/car_double_line_list_item_height"
+ android:layout_width="match_parent" >
+ <CheckBox
+ android:id="@+id/alphanumeric_pin"
+ android:layout_width="@dimen/car_primary_icon_size"
+ android:layout_height="@dimen/car_primary_icon_size"
+ android:button="@drawable/ic_check_box"
+ android:layout_alignParentStart="true"
+ android:layout_centerVertical="true" />
+ <TextView
+ android:text="@string/bluetooth_enable_alphanumeric_pin"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_alignParentStart="true"
+ android:layout_centerVertical="true"
+ android:layout_marginStart="@dimen/car_keyline_3"
+ android:layout_marginEnd="@dimen/car_keyline_3"
+ style="@style/TextAppearance.Car.Body2.SingleLine"
+ android:gravity="center_vertical"/>
+ </RelativeLayout>
+
+ <RelativeLayout
+ android:layout_height="@dimen/car_double_line_list_item_height"
+ android:layout_width="match_parent">
+ <CheckBox
+ android:id="@+id/phonebook_sharing_message_entry_pin"
+ android:layout_width="@dimen/car_primary_icon_size"
+ android:layout_height="@dimen/car_primary_icon_size"
+ android:button="@drawable/ic_check_box"
+ android:layout_alignParentStart="true"
+ android:layout_centerVertical="true" />
+ <TextView
+ android:text="@string/bluetooth_pairing_shares_phonebook"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_alignParentStart="true"
+ android:layout_centerVertical="true"
+ android:layout_marginStart="@dimen/car_keyline_3"
+ android:layout_marginEnd="@dimen/car_keyline_3"
+ style="@style/TextAppearance.Car.Body2.SingleLine"
+ android:gravity="center_vertical"/>
+ </RelativeLayout>
+ </LinearLayout>
+
+</ScrollView>
diff --git a/tests/EmbeddedKitchenSinkApp/res/layout/alert_dialog_test.xml b/tests/EmbeddedKitchenSinkApp/res/layout/alert_dialog_test.xml
new file mode 100644
index 0000000..f5082b4
--- /dev/null
+++ b/tests/EmbeddedKitchenSinkApp/res/layout/alert_dialog_test.xml
@@ -0,0 +1,35 @@
+<?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.
+-->
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:orientation="vertical" >
+ <Button
+ android:id="@+id/alert_message_btn"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="Show Alert Dialog with Message"/>
+ <Button
+ android:id="@+id/alert_bluetooth_pin_enter_view_btn"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="Show Alert Dialog with bt pin entery"/>
+ <Button
+ android:id="@+id/alert_bluetooth_pin_confirm_view_btn"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="Show Alert Dialog with bt pin confirm"/>
+</LinearLayout>
diff --git a/tests/EmbeddedKitchenSinkApp/res/layout/audio.xml b/tests/EmbeddedKitchenSinkApp/res/layout/audio.xml
index 6e44213..deb4f13 100644
--- a/tests/EmbeddedKitchenSinkApp/res/layout/audio.xml
+++ b/tests/EmbeddedKitchenSinkApp/res/layout/audio.xml
@@ -28,12 +28,6 @@
android:layout_height="wrap_content"
android:textOn="@string/mock_audio_on"
android:textOff="@string/mock_audio_off" />
- <ToggleButton
- android:id="@+id/button_reject_audio_focus"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:textOn="@string/reject_audio_focus_on"
- android:textOff="@string/reject_audio_focus_off" />
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
@@ -217,11 +211,5 @@
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/radio_end" />
- <ToggleButton
- android:id="@+id/button_mute_media"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:textOn="@string/unmute_media"
- android:textOff="@string/mute_media" />
</LinearLayout>
</LinearLayout>
diff --git a/tests/EmbeddedKitchenSinkApp/res/layout/bluetooth_headset.xml b/tests/EmbeddedKitchenSinkApp/res/layout/bluetooth_headset.xml
index 5dbefc1..0f2a8e7 100644
--- a/tests/EmbeddedKitchenSinkApp/res/layout/bluetooth_headset.xml
+++ b/tests/EmbeddedKitchenSinkApp/res/layout/bluetooth_headset.xml
@@ -62,4 +62,14 @@
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/bluetooth_hold_call"/>
+ <Button
+ android:id="@+id/bluetooth_voice_recognition_enable"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="@string/bluetooth_voice_recognition_enable"/>
+ <Button
+ android:id="@+id/bluetooth_voice_recognition_disable"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="@string/bluetooth_voice_recognition_disable"/>
</LinearLayout>
diff --git a/tests/EmbeddedKitchenSinkApp/res/layout/car_assistant.xml b/tests/EmbeddedKitchenSinkApp/res/layout/car_assistant.xml
index 759a73e..89d67be 100644
--- a/tests/EmbeddedKitchenSinkApp/res/layout/car_assistant.xml
+++ b/tests/EmbeddedKitchenSinkApp/res/layout/car_assistant.xml
@@ -17,8 +17,13 @@
android:orientation="vertical" android:layout_width="match_parent"
android:layout_height="match_parent">
<ImageView
- android:id="@+id/voice_button"
+ android:id="@+id/voice_button_intent"
android:layout_gravity="center"
android:src="@drawable/ic_voice_assistant_mic"
style="@style/OverviewButton"/>
-</LinearLayout>
\ No newline at end of file
+ <ImageView
+ android:id="@+id/voice_button_service"
+ android:layout_gravity="center"
+ android:src="@drawable/ic_voice_assistant_mic"
+ style="@style/OverviewButton"/>
+</LinearLayout>
diff --git a/tests/EmbeddedKitchenSinkApp/res/layout/display_info.xml b/tests/EmbeddedKitchenSinkApp/res/layout/display_info.xml
new file mode 100644
index 0000000..f67cd07
--- /dev/null
+++ b/tests/EmbeddedKitchenSinkApp/res/layout/display_info.xml
@@ -0,0 +1,24 @@
+<?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.
+-->
+<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent">
+ <LinearLayout
+ android:id="@+id/list"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:orientation="vertical" />
+</ScrollView>
diff --git a/tests/EmbeddedKitchenSinkApp/res/layout/input_test.xml b/tests/EmbeddedKitchenSinkApp/res/layout/input_test.xml
index e730b03..03a90e0 100644
--- a/tests/EmbeddedKitchenSinkApp/res/layout/input_test.xml
+++ b/tests/EmbeddedKitchenSinkApp/res/layout/input_test.xml
@@ -16,19 +16,29 @@
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
- android:orientation="vertical" >
- <!-- dummy one for top area -->
- <LinearLayout
- android:layout_width="match_parent"
- android:layout_height="50dp"
- android:orientation="vertical"
- android:layout_weight="1" />
+ android:orientation="vertical">
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="vertical"
- android:layout_weight="1"
android:id="@+id/input_buttons">
<!-- Filled at runtime. -->
</LinearLayout>
+ <ScrollView
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_weight="1"
+ android:layout_marginLeft="15dp"
+ android:layout_marginRight="15dp"
+ android:layout_marginTop="20dp"
+ android:fillViewport="true">
+ <TextView
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:gravity="bottom"
+ android:scrollbars="vertical"
+ android:textSize="24px"
+ android:typeface="monospace"
+ android:id="@+id/events_list"/>
+ </ScrollView>
</LinearLayout>
diff --git a/tests/EmbeddedKitchenSinkApp/res/layout/instrument_cluster.xml b/tests/EmbeddedKitchenSinkApp/res/layout/instrument_cluster.xml
index cb785a9..f58af8f 100644
--- a/tests/EmbeddedKitchenSinkApp/res/layout/instrument_cluster.xml
+++ b/tests/EmbeddedKitchenSinkApp/res/layout/instrument_cluster.xml
@@ -22,20 +22,31 @@
<LinearLayout
android:orientation="vertical"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content">
- <LinearLayout
- android:orientation="horizontal"
- android:layout_width="match_parent"
- android:layout_height="wrap_content">
- <Button android:layout_width="wrap_content" android:layout_height="wrap_content"
- android:text="@string/cluster_start" android:id="@+id/cluster_start_button"/>
- <Button android:layout_width="wrap_content" android:layout_height="wrap_content"
- android:text="@string/cluster_turn_left" android:id="@+id/cluster_turn_left_button"/>
- <Button android:layout_width="wrap_content" android:layout_height="wrap_content"
- android:text="@string/cluster_stop" android:id="@+id/cluster_stop_button"/>
- <Button android:layout_width="wrap_content" android:layout_height="wrap_content"
- android:text="@string/cluster_start_activity" android:id="@+id/cluster_start_activity"/>
- </LinearLayout>
+ android:layout_width="match_parent"
+ android:layout_height="match_parent">
+ <Button
+ android:layout_width="match_parent"
+ android:layout_height="0dp"
+ android:layout_weight="1"
+ android:text="@string/cluster_start"
+ android:id="@+id/cluster_start_button"/>
+ <Button
+ android:layout_width="match_parent"
+ android:layout_height="0dp"
+ android:layout_weight="1"
+ android:text="@string/cluster_turn_left"
+ android:id="@+id/cluster_turn_left_button"/>
+ <Button
+ android:layout_width="match_parent"
+ android:layout_height="0dp"
+ android:layout_weight="1"
+ android:text="@string/cluster_stop"
+ android:id="@+id/cluster_stop_button"/>
+ <Button
+ android:layout_width="match_parent"
+ android:layout_height="0dp"
+ android:layout_weight="1"
+ android:text="@string/cluster_start_activity"
+ android:id="@+id/cluster_start_activity"/>
</LinearLayout>
-</LinearLayout>
\ No newline at end of file
+</LinearLayout>
diff --git a/tests/EmbeddedKitchenSinkApp/res/layout/kitchen_content.xml b/tests/EmbeddedKitchenSinkApp/res/layout/kitchen_content.xml
index 49497a2..45b38dc 100644
--- a/tests/EmbeddedKitchenSinkApp/res/layout/kitchen_content.xml
+++ b/tests/EmbeddedKitchenSinkApp/res/layout/kitchen_content.xml
@@ -21,5 +21,5 @@
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingStart="56dp"
- android:paddingTop="@dimen/lens_header_height">
-</FrameLayout>
\ No newline at end of file
+ android:paddingTop="@dimen/car_app_bar_height">
+</FrameLayout>
diff --git a/tests/EmbeddedKitchenSinkApp/res/layout/notification_fragment.xml b/tests/EmbeddedKitchenSinkApp/res/layout/notification_fragment.xml
new file mode 100644
index 0000000..b9b8e8b
--- /dev/null
+++ b/tests/EmbeddedKitchenSinkApp/res/layout/notification_fragment.xml
@@ -0,0 +1,68 @@
+<?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:orientation="vertical" >
+ <Button
+ android:id="@+id/cancel_all_button"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="Cancel All"
+ android:textSize="35sp"/>
+ <Button
+ android:id="@+id/importance_high_button"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="Importance: HIGH (Shows heads-up)"
+ android:textSize="35sp"/>
+ <Button
+ android:id="@+id/importance_high_button_2"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="Importance: HIGH (Shows heads-up) 2"
+ android:textSize="35sp"/>
+ <Button
+ android:id="@+id/importance_default_button"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="Importance: DEFAULT"
+ android:textSize="35sp"/>
+ <Button
+ android:id="@+id/importance_low_button"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="Importance: LOW"
+ android:textSize="35sp"/>
+ <Button
+ android:id="@+id/importance_min_button"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="Importance: MIN"
+ android:textSize="35sp"/>
+ <Button
+ android:id="@+id/ongoing_button"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="Ongoing"
+ android:textSize="35sp"/>
+ <Button
+ android:id="@+id/category_message_button"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="Category: CATEGORY_MESSAGE"
+ android:textSize="35sp"/>
+</LinearLayout>
diff --git a/tests/EmbeddedKitchenSinkApp/res/layout/power_test.xml b/tests/EmbeddedKitchenSinkApp/res/layout/power_test.xml
new file mode 100644
index 0000000..62f80d0
--- /dev/null
+++ b/tests/EmbeddedKitchenSinkApp/res/layout/power_test.xml
@@ -0,0 +1,71 @@
+<?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:gravity="center"
+ android:layout_height="match_parent"
+ android:layout_width="match_parent"
+ android:orientation="vertical">
+
+ <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_height="wrap_content"
+ android:layout_width="match_parent"
+ android:orientation="horizontal">
+ <Button
+ android:clickable="true"
+ android:id="@+id/btnPwrShutdown"
+ android:layout_height="@dimen/powerBtnHeight"
+ android:layout_width ="@dimen/powerBtnWidth"
+ android:text="@string/power_shutdown"
+ android:textSize="@dimen/powerTextSize"/>
+
+ <Button
+ android:clickable="true"
+ android:id="@+id/btnPwrSleep"
+ android:layout_height="@dimen/powerBtnHeight"
+ android:layout_width ="@dimen/powerBtnWidth"
+ android:text="@string/power_sleep"
+ android:textSize="@dimen/powerTextSize"/>
+ </LinearLayout>
+
+ <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_height="wrap_content"
+ android:layout_width="match_parent"
+ android:orientation="horizontal">
+
+ <Button
+ android:clickable="true"
+ android:id="@+id/btnPwrRequestShutdown"
+ android:layout_height="@dimen/powerBtnHeight"
+ android:layout_width ="@dimen/powerBtnWidth"
+ android:text="@string/power_request_shutdown"
+ android:textSize="@dimen/powerTextSize"/>
+
+ <Button
+ android:clickable="true"
+ android:id="@+id/btnPwrGetBootReason"
+ android:layout_height="@dimen/powerBtnHeight"
+ android:layout_width ="@dimen/powerBtnWidth"
+ android:text="@string/power_get_boot_reason"
+ android:textSize="@dimen/powerTextSize"/>
+
+ <TextView
+ android:id="@+id/tvPowerBootReason"
+ android:layout_height="@dimen/powerBtnHeight"
+ android:layout_width ="@dimen/powerBtnWidth"
+ android:layout_weight="1"
+ android:textSize="@dimen/powerTextSize"/>
+ </LinearLayout>
+</LinearLayout>
diff --git a/tests/EmbeddedKitchenSinkApp/res/layout/property.xml b/tests/EmbeddedKitchenSinkApp/res/layout/property.xml
new file mode 100644
index 0000000..f8f6f79
--- /dev/null
+++ b/tests/EmbeddedKitchenSinkApp/res/layout/property.xml
@@ -0,0 +1,106 @@
+<?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:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:orientation="horizontal" >
+ <ListView
+ android:id="@+id/lvPropertyList"
+ android:layout_height="match_parent"
+ android:layout_weight="1"
+ android:layout_width="0dp"
+ android:scrollbars="vertical">
+ </ListView>
+ <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_height="match_parent"
+ android:layout_weight="1"
+ android:layout_width="0dp"
+ android:orientation="vertical" >
+
+ <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_height="0dp"
+ android:layout_weight="2"
+ android:layout_width="match_parent"
+ android:orientation="horizontal" >
+ <Spinner
+ android:id="@+id/sPropertyId"
+ android:layout_height="wrap_content"
+ android:layout_weight="1"
+ android:layout_width="0dp" />
+ <Button
+ android:id="@+id/bGetProperty"
+ android:layout_height="wrap_content"
+ android:layout_weight="1"
+ android:layout_width="0dp"
+ android:text="@string/property_get"
+ android:textSize="@dimen/propertyTextSize"/>
+ <TextView
+ android:id="@+id/tvGetPropertyValue"
+ android:gravity="center"
+ android:layout_height="wrap_content"
+ android:layout_weight="2"
+ android:layout_width="0dp"
+ android:textSize="@dimen/propertyValueTextSize"/>
+ </LinearLayout>
+
+ <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_height="0dp"
+ android:layout_weight="1"
+ android:layout_width="match_parent"
+ android:orientation="horizontal" >
+ <Spinner
+ android:id="@+id/sAreaId"
+ android:layout_height="wrap_content"
+ android:layout_weight="1"
+ android:layout_width="0dp" />
+ <EditText
+ android:id="@+id/etSetPropertyValue"
+ android:layout_height="wrap_content"
+ android:layout_weight="2"
+ android:layout_width="0dp"
+ android:inputType="phone" />
+ <Button
+ android:id="@+id/bSetProperty"
+ android:layout_height="wrap_content"
+ android:layout_weight="1"
+ android:layout_width="0dp"
+ android:text="@string/property_set"
+ android:textSize="@dimen/propertyTextSize"/>
+ </LinearLayout>
+
+ <!-- Event Log -->
+ <ScrollView
+ android:id="@+id/svEventLog"
+ android:layout_height="0dp"
+ android:layout_weight="6"
+ android:layout_width="match_parent"
+ android:scrollbars="vertical">
+ <TextView
+ android:id="@+id/tvEventLog"
+ android:gravity="left"
+ android:layout_height="match_parent"
+ android:layout_width="match_parent"
+ android:textSize="@dimen/propertyValueTextSize"/>
+ </ScrollView>
+ <Button
+ android:id="@+id/bClearLog"
+ android:layout_height="0dp"
+ android:layout_weight="1"
+ android:layout_width="match_parent"
+ android:text="@string/property_clear"
+ android:textSize="@dimen/propertyTextSize"/>
+ </LinearLayout>
+</LinearLayout>
diff --git a/tests/EmbeddedKitchenSinkApp/res/layout/property_list_item.xml b/tests/EmbeddedKitchenSinkApp/res/layout/property_list_item.xml
new file mode 100644
index 0000000..f8051ee
--- /dev/null
+++ b/tests/EmbeddedKitchenSinkApp/res/layout/property_list_item.xml
@@ -0,0 +1,38 @@
+<?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.
+-->
+
+<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent" >
+
+ <TextView
+ android:id="@+id/tvPropertyName"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_centerVertical="true"
+ android:layout_alignParentLeft="true"
+ android:paddingLeft="8dp"
+ android:textSize="@dimen/propertyTextSize" />
+
+ <ToggleButton
+ android:id="@+id/tbRegisterPropertyBtn"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_alignParentRight="true"
+ android:layout_centerVertical="true"
+ android:text="@string/property_register" />
+
+</RelativeLayout>
diff --git a/tests/EmbeddedKitchenSinkApp/res/layout/radio.xml b/tests/EmbeddedKitchenSinkApp/res/layout/radio.xml
deleted file mode 100644
index 590e7f1..0000000
--- a/tests/EmbeddedKitchenSinkApp/res/layout/radio.xml
+++ /dev/null
@@ -1,179 +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.
--->
-<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:orientation="vertical" >
- <!-- dummy one for top area -->
- <LinearLayout
- android:layout_width="match_parent"
- android:layout_height="70dp"
- android:orientation="vertical"
- android:layout_weight="1" />
- <LinearLayout
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:orientation="horizontal"
- android:layout_weight="1" >
- <Button
- android:id="@+id/button_open_radio"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:text="@string/radio_open" />
- <Button
- android:id="@+id/button_close_radio"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:text="@string/radio_close" />
- <ToggleButton
- android:id="@+id/togglebutton_mute_radio"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:textOn="@string/radio_muted"
- android:textOff="@string/radio_unmuted" />
- </LinearLayout>
- <LinearLayout
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:orientation="horizontal"
- android:layout_weight="1" >
- <Button
- android:id="@+id/button_get_radio_focus"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:text="@string/radio_get_radio_focus" />
- <Button
- android:id="@+id/button_release_radio_focus"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:text="@string/radio_release_radio_focus" />
- </LinearLayout>
- <LinearLayout
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:orientation="horizontal"
- android:layout_weight="1" >
- <Button
- android:id="@+id/button_get_focus_in_radio"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:text="@string/radio_get_focus" />
- <Button
- android:id="@+id/button_release_focus_in_radio"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:text="@string/radio_release_focus" />
- </LinearLayout>
- <LinearLayout
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:orientation="horizontal"
- android:layout_weight="1" >
- <EditText
- android:id="@+id/edittext_station_frequency"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:hint="@string/radio_enter_station_hint"
- android:inputType="number" />
- <Button
- android:id="@+id/button_radio_tune_to_station"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:text="@string/radio_tune_to_station" />
- <Button
- android:id="@+id/button_radio_step_up"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:text="@string/radio_step_up" />
- <Button
- android:id="@+id/button_radio_step_down"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:text="@string/radio_step_down" />
- </LinearLayout>
- <LinearLayout
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:orientation="horizontal"
- android:layout_weight="1" >
- <ToggleButton
- android:id="@+id/button_band_selection"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:checked="true"
- android:textOn="@string/radio_fm"
- android:textOff="@string/radio_am" />
- <Button
- android:id="@+id/button_radio_next"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:text="@string/radio_next" />
- <Button
- android:id="@+id/button_radio_prev"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:text="@string/radio_prev" />
- <Button
- android:id="@+id/button_radio_scan_cancel"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:text="@string/radio_scan_cancel" />
- <Button
- android:id="@+id/button_radio_get_program_info"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:text="@string/radio_get_program_info" />
- </LinearLayout>
- <LinearLayout
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:orientation="horizontal"
- android:layout_weight="1" >
- <TextView
- android:id="@+id/radio_station_info"
- android:layout_marginRight="@dimen/radioInfoMargin"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content" />
- <TextView
- android:id="@+id/radio_channel_info"
- android:layout_marginRight="@dimen/radioInfoMargin"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content" />
- <TextView
- android:id="@+id/radio_song_info"
- android:layout_marginRight="@dimen/radioInfoMargin"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content" />
- <TextView
- android:id="@+id/radio_artist_info"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content" />
- </LinearLayout>
- <LinearLayout
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:orientation="horizontal"
- android:layout_weight="1" >
- <TextView
- android:id="@+id/radio_log"
- android:maxLines="@integer/radio_log_lines"
- android:scrollbars="vertical"
- android:gravity="bottom"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content" />
- </LinearLayout>
-
-</LinearLayout>
diff --git a/tests/EmbeddedKitchenSinkApp/res/layout/sms_received.xml b/tests/EmbeddedKitchenSinkApp/res/layout/sms_received.xml
index 4743a34..4e3c3da 100644
--- a/tests/EmbeddedKitchenSinkApp/res/layout/sms_received.xml
+++ b/tests/EmbeddedKitchenSinkApp/res/layout/sms_received.xml
@@ -51,6 +51,26 @@
android:layout_height="wrap_content"
android:layout_gravity="center"
android:text="@string/sms_listing_button"/>
+ <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/sms_enter_tel_num"/>
+ <EditText
+ android:id="@+id/sms_tel_num"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="+1-650-000-0000 "
+ android:inputType="text" />
+ <Button
+ android:id="@+id/sms_new_message"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_gravity="center"
+ android:text="@string/sms_new_message_button"/>
+ </LinearLayout>
<CheckBox android:layout_width="wrap_content" android:layout_height="wrap_content"
android:id="@+id/sent_checkbox"
@@ -60,4 +80,4 @@
android:id="@+id/delivered_checkbox"
android:clickable="false"
android:text="@string/sms_reply_delivered"/>
-</LinearLayout>
\ No newline at end of file
+</LinearLayout>
diff --git a/tests/EmbeddedKitchenSinkApp/res/layout/storagewear.xml b/tests/EmbeddedKitchenSinkApp/res/layout/storagewear.xml
new file mode 100644
index 0000000..cf98695
--- /dev/null
+++ b/tests/EmbeddedKitchenSinkApp/res/layout/storagewear.xml
@@ -0,0 +1,78 @@
+<?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:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:orientation="vertical">
+ <TextView
+ android:id="@+id/storage_wear_info"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:text="Storage Wear Information"
+ android:textSize="24dp"
+ android:textColor="#ff0000"
+ android:minLines="5"/>
+ <ListView
+ android:id="@+id/storage_events_list"
+ android:layout_width="match_parent"
+ android:layout_height="75dp"/>
+ <LinearLayout
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:orientation="horizontal">
+ <Button
+ android:id="@+id/write_one_megabyte"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_weight="1"
+ android:text="Write 1M"/>
+ <Button
+ android:id="@+id/write_one_kilobyte"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_weight="1"
+ android:text="Write 1K"/>
+ <Button
+ android:id="@+id/perform_fsync"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_weight="1"
+ android:text="Call fsync()"/>
+ </LinearLayout>
+ <TextView
+ android:id="@+id/free_disk_space"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:text="Free Disk Space: 1 byte"
+ android:textSize="24dp"
+ android:textColor="#ff0000"
+ android:minLines="4"/>
+ <ScrollView
+ android:id="@+id/scroll_view"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:scrollbars="vertical"
+ android:fillViewport="true">
+ <TextView
+ android:id="@+id/last_io_snapshot"
+ android:layout_width="fill_parent"
+ android:layout_height="fill_parent"
+ android:text="No I/O activity on record"
+ android:textSize="20dp"
+ android:textColor="#ff0000"
+ android:minLines="10"/>
+ </ScrollView>
+</LinearLayout>
diff --git a/tests/EmbeddedKitchenSinkApp/res/layout/vhal.xml b/tests/EmbeddedKitchenSinkApp/res/layout/vhal.xml
new file mode 100644
index 0000000..6c423ea
--- /dev/null
+++ b/tests/EmbeddedKitchenSinkApp/res/layout/vhal.xml
@@ -0,0 +1,26 @@
+<?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:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:orientation="vertical" >
+ <ListView
+ android:id="@+id/hal_prop_list"
+ android:layout_height="match_parent"
+ android:layout_width="match_parent"
+ android:scrollbars="vertical">
+ </ListView>
+</LinearLayout>
diff --git a/tests/EmbeddedKitchenSinkApp/res/layout/volume_item.xml b/tests/EmbeddedKitchenSinkApp/res/layout/volume_item.xml
index f62e527..2b0babf 100644
--- a/tests/EmbeddedKitchenSinkApp/res/layout/volume_item.xml
+++ b/tests/EmbeddedKitchenSinkApp/res/layout/volume_item.xml
@@ -9,7 +9,7 @@
android:layout_width="0dp"
android:layout_height="wrap_content"
android:textSize="20sp"
- android:layout_weight="2">
+ android:layout_weight="1">
</TextView>
<TextView
android:id="@+id/volume_limit"
@@ -18,7 +18,7 @@
android:layout_marginLeft="10dp"
android:gravity="center"
android:textSize="20sp"
- android:layout_weight="2">
+ android:layout_weight="1">
</TextView>
<TextView
android:id="@+id/current_volume"
@@ -26,20 +26,8 @@
android:layout_height="wrap_content"
android:layout_marginLeft="10dp"
android:textSize="20sp"
- android:layout_weight="2">
+ android:layout_weight="1">
</TextView>
- <TextView
- android:id="@+id/logical_max"
- android:layout_width="0dp"
- android:layout_height="wrap_content"
- android:textSize="20dp"
- android:layout_weight="2"/>
- <TextView
- android:id="@+id/logical_volume"
- android:layout_width="0dp"
- android:layout_height="wrap_content"
- android:textSize="20dp"
- android:layout_weight="2"/>
<Button
android:id="@+id/volume_up"
android:layout_width="wrap_content"
@@ -56,4 +44,4 @@
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/request" />
-</LinearLayout>
\ No newline at end of file
+</LinearLayout>
diff --git a/tests/EmbeddedKitchenSinkApp/res/layout/volume_test.xml b/tests/EmbeddedKitchenSinkApp/res/layout/volume_test.xml
index c42d20f..db48680 100644
--- a/tests/EmbeddedKitchenSinkApp/res/layout/volume_test.xml
+++ b/tests/EmbeddedKitchenSinkApp/res/layout/volume_test.xml
@@ -48,4 +48,37 @@
android:layout_height="wrap_content"
android:text="@string/volume_down"/>
</LinearLayout>
+
+ <LinearLayout
+ android:layout_width="0dp"
+ android:layout_height="match_parent"
+ android:layout_marginLeft="80dp"
+ android:orientation="vertical"
+ android:layout_weight="1">
+
+ <TextView
+ android:id="@+id/fader_title"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="Fade" />
+
+ <SeekBar
+ android:id="@+id/fade_bar"
+ android:max="200"
+ android:layout_width="200dp"
+ android:layout_height="200dp"
+ android:rotation="270"/>
+
+ <TextView
+ android:id="@+id/balance_title"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="Balance" />
+
+ <SeekBar
+ android:id="@+id/balance_bar"
+ android:max="200"
+ android:layout_width="200dp"
+ android:layout_height="20dp"/>
+ </LinearLayout>
</LinearLayout>
\ No newline at end of file
diff --git a/tests/EmbeddedKitchenSinkApp/res/layout/wear_estimate_change_textview.xml b/tests/EmbeddedKitchenSinkApp/res/layout/wear_estimate_change_textview.xml
new file mode 100644
index 0000000..0b09562
--- /dev/null
+++ b/tests/EmbeddedKitchenSinkApp/res/layout/wear_estimate_change_textview.xml
@@ -0,0 +1,23 @@
+<?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.
+-->
+<TextView xmlns:android="http://schemas.android.com/apk/res/android"
+ android:id="@+id/wear_estimate_change_textview"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:text="Wear Estimate Change"
+ android:textSize="18dp"
+ android:textColor="#ff0000"
+ android:minLines="2"/>
diff --git a/tests/EmbeddedKitchenSinkApp/res/values/dimens.xml b/tests/EmbeddedKitchenSinkApp/res/values/dimens.xml
index 5057d18..c8806bc 100644
--- a/tests/EmbeddedKitchenSinkApp/res/values/dimens.xml
+++ b/tests/EmbeddedKitchenSinkApp/res/values/dimens.xml
@@ -17,6 +17,11 @@
<dimen name="hvacBtnHeight">60dp</dimen>
<dimen name="hvacBtnMargin">10dp</dimen>
<dimen name="hvacTextSize">24sp</dimen>
+ <dimen name="powerBtnHeight">80dp</dimen>
+ <dimen name="powerBtnWidth">300dp</dimen>
+ <dimen name="powerTextSize">24sp</dimen>
+ <dimen name="propertyTextSize">24sp</dimen>
+ <dimen name="propertyValueTextSize">14sp</dimen>
<dimen name="rvcBtnHeight">40dp</dimen>
<dimen name="rvcBtnWidth">150dp</dimen>
<dimen name="rvcTextSize">10dp</dimen>
@@ -24,4 +29,36 @@
<dimen name="radioInfoMargin">5dp</dimen>
<dimen name="sensorInfoMargin">5dp</dimen>
<dimen name="overview_icon_size">72dp</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_button_text_size">32sp</dimen>
+
+ <!-- Common icon size for car app -->
+ <dimen name="car_icon_size">56dp</dimen>
+
+ <dimen name="car_card_header_height">96dp</dimen>
+ <dimen name="car_card_action_bar_height">96dp</dimen>
+
+ <!-- Paddings -->
+ <dimen name="car_padding_1">4dp</dimen>
+ <dimen name="car_padding_2">10dp</dimen>
+ <dimen name="car_padding_3">16dp</dimen>
+ <dimen name="car_padding_4">28dp</dimen>
+ <dimen name="car_padding_5">32dp</dimen>
+
+ <!-- Radius -->
+ <dimen name="car_radius_1">4dp</dimen>
+ <dimen name="car_radius_2">8dp</dimen>
+ <dimen name="car_radius_3">16dp</dimen>
+ <dimen name="car_radius_5">100dp</dimen>
+
+ <!-- Keylines for content. -->
+ <dimen name="car_keyline_1">48dp</dimen>
+ <dimen name="car_keyline_2">108dp</dimen>
+ <dimen name="car_keyline_3">152dp</dimen>
+ <dimen name="car_keyline_4">182dp</dimen>
</resources>
diff --git a/tests/EmbeddedKitchenSinkApp/res/values/strings.xml b/tests/EmbeddedKitchenSinkApp/res/values/strings.xml
index fbba2a0..74c7c26 100644
--- a/tests/EmbeddedKitchenSinkApp/res/values/strings.xml
+++ b/tests/EmbeddedKitchenSinkApp/res/values/strings.xml
@@ -13,8 +13,41 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
-<resources>
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_title">Kitchen Sink</string>
+
+ <!-- alert dialog -->
+ <!-- Notification ticker text (shown in the status bar) when a Bluetooth device wants to pair with us -->
+ <string name="bluetooth_notif_ticker">Bluetooth pairing request</string>
+ <!-- Bluetooth settings. Context menu item for a device. Action will first pair, and then connect to all profiles on the device. -->
+ <string name="bluetooth_device_context_pair_connect">Pair & connect</string>
+ <!-- Used as setting title (for checkbox) on second screen after selecting Bluetooth settings -->
+ <string name="bluetooth">Bluetooth</string>
+ <!-- Message when bluetooth is informing the user of the pairing key. [CHAR LIMIT=NONE] -->
+ <string name="bluetooth_pairing_key_msg">Bluetooth pairing code</string>
+ <!-- Checkbox label for alphanumeric PIN entry (default is numeric PIN). [CHAR LIMIT=50] -->
+ <string name="bluetooth_enable_alphanumeric_pin">PIN contains letters or symbols</string>
+ <!-- Message when bluetooth dialog for passkey entry is showing. [CHAR LIMIT=NONE] -->
+ <string name="bluetooth_enter_passkey_msg">Type the pairing code then press Return or Enter</string>
+ <!-- Title for the dialog to enter PIN. [CHAR LIMIT=40] -->
+ <string name="bluetooth_pairing_request">Pair with <xliff:g id="device_name">%1$s</xliff:g>?</string>
+ <!-- Checkbox message in pairing dialogs. [CHAR LIMIT=NONE] -->
+ <string name="bluetooth_pairing_shares_phonebook">Allow <xliff:g id="device_name">%1$s</xliff:g> to access your contacts and call history</string>
+ <!-- Pairing dialog text to remind user to enter the PIN on the other device. [CHAR LIMIT=NONE] -->
+ <string name="bluetooth_enter_pin_other_device">You may also need to type this PIN on the other device.</string>
+ <!-- Pairing dialog text to remind user to enter the passkey on the other device. [CHAR LIMIT=NONE] -->
+ <string name="bluetooth_enter_passkey_other_device">You may also need to type this passkey on the other device.</string>
+ <!-- Bluetooth PIN hint text (below the text entry box). [CHAR LIMIT=30] -->
+ <string name="bluetooth_pin_values_hint_16_digits">Must be 16 digits</string>
+ <!-- Bluetooth PIN hint text (below the text entry box). [CHAR LIMIT=30] -->
+ <string name="bluetooth_pin_values_hint">Usually 0000 or 1234</string>
+ <!-- Notification title when a Bluetooth device wants to pair with us -->
+ <string name="bluetooth_notif_title">Pairing request</string>
+ <!-- Notification message when a Bluetooth device wants to pair with us -->
+ <string name="bluetooth_notif_message">Tap to pair with <xliff:g id="device_name">%1$s</xliff:g>.</string>
+ <!-- Title for BT error dialogs. -->
+ <string name="bluetooth_error_title"></string>
+
<!-- hvac -->
<string name="hvac_acOff">AC OFF</string>
<string name="hvac_acOn">AC ON</string>
@@ -83,10 +116,6 @@
<string name="microphone_off">Mic Off</string>
<string name="mock_audio_on">Audio Mocking On</string>
<string name="mock_audio_off">Audio Mocking Off</string>
- <string name="reject_audio_focus_on">Reject Audio Focus</string>
- <string name="reject_audio_focus_off">Allow Audio Focus</string>
- <string name="unmute_media">Unmute Media</string>
- <string name="mute_media">Mute Media</string>
<!-- job scheduler -->
<string name="schedule_button">Schedule a New Job</string>
@@ -137,16 +166,32 @@
<string name="tune_left">Tune -</string>
<string name="music_play">Play</string>
<string name="music_stop">Stop</string>
+ <string name="steering_wheel">Steering Wheel Buttons:</string>
+ <string name="sw_left">Left</string>
+ <string name="sw_right">Right</string>
+ <string name="sw_up">Up</string>
+ <string name="sw_down">Down</string>
+ <string name="sw_center">Center</string>
+ <string name="sw_back">Back</string>
+
+ <!-- power test -->
+ <string name="power_get_boot_reason">Get Boot Reason</string>
+ <string name="power_request_shutdown">Request Shutdown</string>
+ <string name="power_shutdown">Shutdown</string>
+ <string name="power_sleep">Sleep</string>
+
+ <!-- property test -->
+ <string name="property_clear">Clear Log</string>
+ <string name="property_get">Get</string>
+ <string name="property_register">Register</string>
+ <string name="property_set">Set</string>
+ <string name="property_unregister">Unregister</string>
<!-- radio test -->
<string name="radio_open">Open</string>
<string name="radio_close">Close</string>
<string name="radio_muted">Muted</string>
<string name="radio_unmuted">Unmuted</string>
- <string name="radio_get_radio_focus">Get Radio focus</string>
- <string name="radio_release_radio_focus">Release Radio focus</string>
- <string name="radio_get_focus">Get Audio focus</string>
- <string name="radio_release_focus">Release Audio focus</string>
<string name="radio_next">Next</string>
<string name="radio_prev">Previous</string>
<string name="radio_scan_cancel">Cancel scan</string>
@@ -170,7 +215,6 @@
<string name="sensor_night">Night[%1$s]: isNight=%2$s</string>
<string name="sensor_gear">Gear[%1$s]: gear=%2$s</string>
<string name="sensor_parking_brake">Parking brake[%1$s]: isEngaged=%2$s</string>
- <string name="sensor_fuel_level">Fuel level[%1$s]: level=%2$s, range=%3$s, lowFuelWarning=%4$s</string>
<string name="sensor_odometer">Odometer[%1$s]: kms=%2$s</string>
<string name="sensor_rpm">RPM[%1$s]: rpm=%2$s</string>
<string name="sensor_speed">Speed[%1$s]: speed=%2$s</string>
@@ -185,6 +229,13 @@
<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>
<string name="sensor_traction_control_is_active">Traction Control[%1$s]: isActive=%2$s</string>
+ <string name="sensor_fuel_level">Fuel Level[%1$s]: %2$s</string>
+ <string name="sensor_fuel_door_open">Fuel Door Open[%1$s]: %2$s</string>
+ <string name="sensor_engine_is_on">Engine Is On[%1$s]: %2$s</string>
+ <string name="sensor_ev_battery_level">EV Battery Level[%1$s]: %2$s</string>
+ <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="volume_test">Volume Test</string>
<string name="volume_up_logical">Vol +</string>
@@ -197,12 +248,14 @@
<string name="sms_connect" translatable="false">Connect</string>
<string name="sms_disconnect" translatable="false">Disconnect</string>
<string name="sms_send_message" translatable="false">Send</string>
+ <string name="sms_new_message_button" translatable="false">Send new message</string>
<string name="sms_notifications" translatable="false">Toggle Notifications</string>
<string name="sms_listing_button" translatable="false">List SMS</string>
<string name="sms_listing_label_folder" translatable="false">Folder</string>
<string name="sms_listing_label_count" translatable="false">Count</string>
<string name="sms_listing_label_offset" translatable="false">Offset</string>
<string name="sms_activity_label" translatable="false">Bt Sms Tester</string>
+ <string name="sms_enter_tel_num">Enter Tel Num to send msg to</string>
<string name="sms_reply_busy" translatable="false">Reply "I'm Busy"</string>
<string name="sms_reply_sent" translatable="false">Reply Sent</string>
<string name="sms_reply_delivered" translatable="false">Reply Delivered</string>
@@ -213,6 +266,8 @@
<string name="bluetooth_pick_device">Pick Device</string>
<string name="bluetooth_quiet_mode_enable">Quiet Mode</string>
<string name="bluetooth_hold_call">Hold call</string>
+ <string name="bluetooth_voice_recognition_enable">Start Voice Recognition</string>
+ <string name="bluetooth_voice_recognition_disable">Stop Voice Recognition</string>
<!--Car Service Settings-->
<string name="garage_title">Garage Mode</string>
@@ -252,4 +307,8 @@
<!-- Action to start assistant activity -->
<string name="assistant_activity_action" translatable="false">"com.google.android.demandspace.START"</string>
+
+ <!-- Virtual Display -->
+ <string name="av_start_activity">Start Activity</string>
+ <string name="av_resize">Resize</string>
</resources>
diff --git a/tests/EmbeddedKitchenSinkApp/res/values/styles.xml b/tests/EmbeddedKitchenSinkApp/res/values/styles.xml
index 75cdb36..f16d19d 100644
--- a/tests/EmbeddedKitchenSinkApp/res/values/styles.xml
+++ b/tests/EmbeddedKitchenSinkApp/res/values/styles.xml
@@ -16,6 +16,16 @@
*/
-->
<resources>
+ <style name="TextAppearance.Car.Body1.SingleLine" parent="TextAppearance.Car.Body1">
+ <item name="android:maxLines">1</item>
+ <item name="android:ellipsize">marquee</item>
+ </style>
+
+ <style name="TextAppearance.Car.Body2.SingleLine" parent="TextAppearance.Car.Body2">
+ <item name="android:maxLines">1</item>
+ <item name="android:ellipsize">end</item>
+ </style>
+
<style name="OverviewButton">
<item name="android:layout_width">@dimen/overview_icon_size</item>
<item name="android:layout_height">@dimen/overview_icon_size</item>
@@ -25,4 +35,8 @@
<item name="android:scaleType">fitCenter</item>
<item name="android:clickable">true</item>
</style>
-</resources>
\ No newline at end of file
+
+ <style name="KitchenSinkActivityTheme" parent="Theme.Car.Light.NoActionBar.Drawer">
+ <item name="android:colorPrimary">@android:color/transparent</item>
+ </style>
+</resources>
diff --git a/tests/EmbeddedKitchenSinkApp/res/xml/automotive_app_desc.xml b/tests/EmbeddedKitchenSinkApp/res/xml/automotive_app_desc.xml
index 20d5d81..a78e62d 100644
--- a/tests/EmbeddedKitchenSinkApp/res/xml/automotive_app_desc.xml
+++ b/tests/EmbeddedKitchenSinkApp/res/xml/automotive_app_desc.xml
@@ -16,5 +16,6 @@
<automotiveApp>
<uses name="service" />
<uses name="projection" />
+ <uses name="notification"/>
<uses name="activity" class="com.google.android.car.kitchensink.KitchenSinkActivity" />
</automotiveApp>
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 7dddd1f..ecb734d 100644
--- a/tests/EmbeddedKitchenSinkApp/src/com/google/android/car/kitchensink/CarEmulator.java
+++ b/tests/EmbeddedKitchenSinkApp/src/com/google/android/car/kitchensink/CarEmulator.java
@@ -1,3 +1,4 @@
+
/*
* Copyright (C) 2015 The Android Open Source Project
*
@@ -16,47 +17,26 @@
package com.google.android.car.kitchensink;
-import static android.hardware.automotive.vehicle.V2_0.VehicleProperty.AUDIO_VOLUME_LIMIT;
-
-import com.google.android.collect.Lists;
-
import android.car.Car;
import android.content.Context;
-import android.hardware.automotive.vehicle.V2_0.VehicleAudioFocusIndex;
-import android.hardware.automotive.vehicle.V2_0.VehicleAudioFocusRequest;
-import android.hardware.automotive.vehicle.V2_0.VehicleAudioFocusState;
-import android.hardware.automotive.vehicle.V2_0.VehicleAudioVolumeIndex;
-import android.hardware.automotive.vehicle.V2_0.VehicleAudioVolumeLimitIndex;
import android.hardware.automotive.vehicle.V2_0.VehicleHwKeyInputAction;
import android.hardware.automotive.vehicle.V2_0.VehiclePropValue;
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;
+import com.android.car.systeminterface.SystemInterface;
import com.android.car.vehiclehal.VehiclePropValueBuilder;
import com.android.car.vehiclehal.test.MockedVehicleHal;
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;
private final MockedVehicleHal mHalEmulator;
- private final AudioFocusPropertyHandler mAudioFocusPropertyHandler =
- new AudioFocusPropertyHandler();
- private final AudioVolumeLimitPropertyHandler mAudioVolumeLimitPropertyHandler =
- new AudioVolumeLimitPropertyHandler();
-
- private static final Integer[] STREAM_MAX_VOLUME = {30, 30};
-
public static CarEmulator create(Context context) {
CarEmulator emulator = new CarEmulator(context);
emulator.init();
@@ -66,7 +46,8 @@
private CarEmulator(Context context) {
mHalEmulator = new MockedVehicleHal();
ICarImpl carService = new ICarImpl(context, mHalEmulator,
- SystemInterface.getDefault(context), null /* error notifier */);
+ SystemInterface.Builder.defaultSystemInterface(context).build(),
+ null /* error notifier */, "CarEmulator");
mCar = new Car(context, carService, null /* Handler */);
}
@@ -75,36 +56,6 @@
}
private void init() {
- final int streamCount = STREAM_MAX_VOLUME.length;
- SingleChannelVolumeHandler volumeHandler = new SingleChannelVolumeHandler(streamCount);
-
- int supportedStreams = (1 << streamCount) - 1; // A bitwise mask of supported streams.
-
- List<Integer> audioVolumeConfigArray = Lists.newArrayList(supportedStreams, 0, 0, 0);
- audioVolumeConfigArray.addAll(Arrays.asList(STREAM_MAX_VOLUME));
-
- mHalEmulator.addProperty(
- VehiclePropConfigBuilder.newBuilder(VehicleProperty.AUDIO_FOCUS).build(),
- mAudioFocusPropertyHandler);
- //TODO(b/32665590): no internal properties in Vehicle Hal 2.0
-// mHalEmulator.addProperty(
-// VehiclePropConfigUtil.getBuilder(
-// INTERNAL_AUDIO_STREAM_STATE,
-// VehiclePropertyAccess.READ_WRITE,
-// VehiclePropertyChangeMode.ON_CHANGE,
-// VehicleValueType.VEHICLE_VALUE_TYPE_INT32_VEC2,
-// VehiclePermissionModel.SYSTEM_APP_ONLY,
-// 0 /*configFlags*/, 0 /*sampleRateMax*/, 0 /*sampleRateMin*/).build(),
-// NoOpPropertyHandler);
- mHalEmulator.addProperty(
- VehiclePropConfigBuilder.newBuilder(VehicleProperty.AUDIO_VOLUME)
- .setConfigArray(audioVolumeConfigArray)
- .build(),
- volumeHandler);
- mHalEmulator.addProperty(
- VehiclePropConfigBuilder.newBuilder(VehicleProperty.AUDIO_VOLUME_LIMIT).build(),
- mAudioVolumeLimitPropertyHandler);
-
mHalEmulator.addProperty(
VehiclePropConfigBuilder.newBuilder(VehicleProperty.HW_KEY_INPUT)
.setAccess(VehiclePropertyAccess.READ)
@@ -118,10 +69,6 @@
public void stop() {
}
- public void setAudioFocusControl(boolean reject) {
- mAudioFocusPropertyHandler.setAudioFocusControl(reject);
- }
-
public void injectKey(int keyCode, int action) {
VehiclePropValue injectValue =
VehiclePropValueBuilder.newBuilder(VehicleProperty.HW_KEY_INPUT)
@@ -148,137 +95,4 @@
}
};
-
- private class AudioFocusPropertyHandler implements VehicleHalPropertyHandler {
- private boolean mRejectFocus;
- private int mCurrentFocusState = VehicleAudioFocusState.STATE_LOSS;
- private int mCurrentFocusStreams = 0;
- private int mCurrentFocusExtState = 0;
-
- void setAudioFocusControl(boolean reject) {
- boolean inject = false;
- synchronized (this) {
- if (reject) {
- if (!mRejectFocus) {
- mCurrentFocusState = VehicleAudioFocusState.STATE_LOSS_TRANSIENT_EXLCUSIVE;
- mCurrentFocusStreams = 0;
- mCurrentFocusExtState = 0;
- mRejectFocus = true;
- inject = true;
- }
- } else {
- if (mRejectFocus) {
- mCurrentFocusState = VehicleAudioFocusState.STATE_LOSS;
- mCurrentFocusStreams = 0;
- mCurrentFocusExtState = 0;
- inject = true;
- }
- mRejectFocus = false;
- }
- }
-
- if (inject) {
- injectCurrentStateToHal();
- }
- }
-
- @Override
- public void onPropertySet(VehiclePropValue value) {
- synchronized (this) {
- if (!mRejectFocus) {
- ArrayList<Integer> v = value.value.int32Values;
-
- int request = v.get(VehicleAudioFocusIndex.FOCUS);
- int requestedStreams = v.get(VehicleAudioFocusIndex.STREAMS);
- int requestedExtFocus = v.get(VehicleAudioFocusIndex.EXTERNAL_FOCUS_STATE);
- int response = VehicleAudioFocusState.STATE_LOSS;
- switch (request) {
- case VehicleAudioFocusRequest.REQUEST_GAIN:
- response = VehicleAudioFocusState.STATE_GAIN;
- break;
- case VehicleAudioFocusRequest.REQUEST_GAIN_TRANSIENT:
- case VehicleAudioFocusRequest.REQUEST_GAIN_TRANSIENT_MAY_DUCK:
- response =
- VehicleAudioFocusState.STATE_GAIN_TRANSIENT;
- break;
- case VehicleAudioFocusRequest.REQUEST_RELEASE:
- response = VehicleAudioFocusState.STATE_LOSS;
- break;
- }
- mCurrentFocusState = response;
- mCurrentFocusStreams = requestedStreams;
- mCurrentFocusExtState = requestedExtFocus;
- }
- }
- injectCurrentStateToHal();
- }
-
- private void injectCurrentStateToHal() {
- mHalEmulator.injectEvent(VehiclePropValueBuilder.newBuilder(VehicleProperty.AUDIO_FOCUS)
- .setTimestamp()
- .addIntValue(mCurrentFocusState, mCurrentFocusStreams, mCurrentFocusExtState, 0)
- .build());
- }
-
- @Override
- public synchronized VehiclePropValue onPropertyGet(VehiclePropValue value) {
- return VehiclePropValueBuilder.newBuilder(VehicleProperty.AUDIO_FOCUS)
- .setTimestamp(SystemClock.elapsedRealtimeNanos())
- .addIntValue(mCurrentFocusState, mCurrentFocusStreams, mCurrentFocusExtState, 0)
- .build();
- }
- }
-
- private static class AudioVolumeLimitPropertyHandler implements VehicleHalPropertyHandler {
- @Override
- public VehiclePropValue onPropertyGet(VehiclePropValue value) {
- int stream = value.value.int32Values.get(VehicleAudioVolumeLimitIndex.STREAM);
-
- return VehiclePropValueBuilder.newBuilder(AUDIO_VOLUME_LIMIT)
- .setTimestamp(SystemClock.elapsedRealtimeNanos())
- .addIntValue(stream, 20)
- .build();
- }
- }
-
- private class SingleChannelVolumeHandler implements VehicleHalPropertyHandler {
- private final SparseIntArray mCurrent;
-
- SingleChannelVolumeHandler(int streamCount) {
- mCurrent = new SparseIntArray(streamCount);
- // Initialize the vol to be the min (mute) volume.
- for (int i = 0; i < streamCount; i++) {
- mCurrent.put(i, 0);
- }
- }
-
- @Override
- public void onPropertySet(VehiclePropValue value) {
- ArrayList<Integer> v = value.value.int32Values;
-
- int stream = v.get(VehicleAudioVolumeIndex.STREAM);
- int volume = v.get(VehicleAudioVolumeIndex.VOLUME);
- int state = v.get(VehicleAudioVolumeIndex.STATE);
-
- VehiclePropValue injectValue =
- VehiclePropValueBuilder.newBuilder(VehicleProperty.AUDIO_VOLUME)
- .setTimestamp(SystemClock.elapsedRealtimeNanos())
- .addIntValue(state, volume, state)
- .build();
-
- mCurrent.put(stream, volume);
- mHalEmulator.injectEvent(injectValue);
- }
-
- @Override
- public VehiclePropValue onPropertyGet(VehiclePropValue value) {
- int stream = value.value.int32Values.get(VehicleAudioVolumeIndex.STREAM);
- int volume = mCurrent.get(stream);
-
- return VehiclePropValueBuilder.newBuilder(VehicleProperty.AUDIO_VOLUME)
- .setTimestamp(SystemClock.elapsedRealtimeNanos())
- .addIntValue(stream, volume, 0)
- .build();
- }
- }
}
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 e68c3fa..7837f2e 100644
--- a/tests/EmbeddedKitchenSinkApp/src/com/google/android/car/kitchensink/KitchenSinkActivity.java
+++ b/tests/EmbeddedKitchenSinkApp/src/com/google/android/car/kitchensink/KitchenSinkActivity.java
@@ -16,7 +16,11 @@
package com.google.android.car.kitchensink;
+
+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.Intent;
import android.content.pm.PackageManager;
import android.os.Bundle;
@@ -24,17 +28,15 @@
import android.support.car.CarAppFocusManager;
import android.support.car.CarConnectionCallback;
import android.support.car.CarNotConnectedException;
-import android.support.car.hardware.CarSensorManager;
import android.support.v4.app.Fragment;
import android.util.Log;
-import android.view.HapticFeedbackConstants;
-import android.view.View;
-import android.widget.ImageView;
-import android.widget.Toast;
-import com.android.car.app.CarDrawerActivity;
-import com.android.car.app.CarDrawerAdapter;
-import com.android.car.app.DrawerItemViewHolder;
+import androidx.car.drawer.CarDrawerActivity;
+import androidx.car.drawer.CarDrawerAdapter;
+import androidx.car.drawer.DrawerItemViewHolder;
+
+import com.google.android.car.kitchensink.activityview.ActivityViewTestFragment;
+import com.google.android.car.kitchensink.alertdialog.AlertDialogTestFragment;
import com.google.android.car.kitchensink.assistant.CarAssistantFragment;
import com.google.android.car.kitchensink.audio.AudioTestFragment;
import com.google.android.car.kitchensink.bluetooth.BluetoothHeadsetFragment;
@@ -42,15 +44,21 @@
import com.google.android.car.kitchensink.cluster.InstrumentClusterFragment;
import com.google.android.car.kitchensink.cube.CubesTestFragment;
import com.google.android.car.kitchensink.diagnostic.DiagnosticTestFragment;
+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.radio.RadioTestFragment;
+import com.google.android.car.kitchensink.power.PowerTestFragment;
+import com.google.android.car.kitchensink.property.PropertyTestFragment;
import com.google.android.car.kitchensink.sensor.SensorsTestFragment;
import com.google.android.car.kitchensink.setting.CarServiceSettingsActivity;
+import com.google.android.car.kitchensink.storagelifetime.StorageLifetimeFragment;
import com.google.android.car.kitchensink.touch.TouchTestFragment;
+import com.google.android.car.kitchensink.vhal.VehicleHalFragment;
import com.google.android.car.kitchensink.volume.VolumeTestFragment;
+
import java.util.ArrayList;
import java.util.List;
@@ -132,26 +140,33 @@
private final List<MenuEntry> mMenuEntries = new ArrayList<MenuEntry>() {
{
- add("audio", AudioTestFragment.class);
- add("hvac", HvacTestFragment.class);
- add("job scheduler", JobSchedulerFragment.class);
- add("inst cluster", InstrumentClusterFragment.class);
- add("input test", InputTestFragment.class);
- add("radio", RadioTestFragment.class);
+ add("alert window", AlertDialogTestFragment.class);
add("assistant", CarAssistantFragment.class);
- add("sensors", SensorsTestFragment.class);
- add("diagnostic", DiagnosticTestFragment.class);
- add("volume test", VolumeTestFragment.class);
- add("touch test", TouchTestFragment.class);
- add("cubes test", CubesTestFragment.class);
- add("orientation test", OrientationTestFragment.class);
+ add("audio", AudioTestFragment.class);
add("bluetooth headset",BluetoothHeadsetFragment.class);
add("bluetooth messaging test", MapMceTestFragment.class);
+ add("cubes test", CubesTestFragment.class);
+ add("diagnostic", DiagnosticTestFragment.class);
+ add("display info", DisplayInfoFragment.class);
+ 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);
+ add("property test", PropertyTestFragment.class);
+ add("sensors", SensorsTestFragment.class);
+ add("storage lifetime", StorageLifetimeFragment.class);
+ add("touch test", TouchTestFragment.class);
+ add("volume test", VolumeTestFragment.class);
+ add("vehicle hal", VehicleHalFragment.class);
add("car service settings", () -> {
Intent intent = new Intent(KitchenSinkActivity.this,
CarServiceSettingsActivity.class);
startActivity(intent);
});
+ add("activity view", ActivityViewTestFragment.class);
add("quit", KitchenSinkActivity.this::finish);
}
@@ -164,29 +179,36 @@
};
private Car mCarApi;
private CarHvacManager mHvacManager;
- private CarSensorManager mCarSensorManager;
+ private CarPowerManager mPowerManager;
+ private CarPropertyManager mPropertyManager;
+ private CarSensorManager mSensorManager;
private CarAppFocusManager mCarAppFocusManager;
- private final CarSensorManager.OnSensorChangedListener mListener = (manager, event) -> {
- switch (event.sensorType) {
- case CarSensorManager.SENSOR_TYPE_DRIVING_STATUS:
- Log.d(TAG, "driving status:" + event.intValues[0]);
- break;
- }
- };
-
public CarHvacManager getHvacManager() {
return mHvacManager;
}
+ public CarPowerManager getPowerManager() {
+ return mPowerManager;
+ }
+
+ public CarPropertyManager getPropertyManager() {
+ return mPropertyManager;
+ }
+
@Override
protected CarDrawerAdapter getRootAdapter() {
return new DrawerAdapter();
}
+ public CarSensorManager getSensorManager() {
+ return mSensorManager;
+ }
+
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
+ setToolbarElevation(0f);
setMainContent(R.layout.kitchen_content);
// Connection to Car Service does not work for non-automotive yet.
if (getPackageManager().hasSystemFeature(PackageManager.FEATURE_AUTOMOTIVE)) {
@@ -229,9 +251,6 @@
@Override
protected void onDestroy() {
super.onDestroy();
- if (mCarSensorManager != null) {
- mCarSensorManager.removeListener(mListener);
- }
if (mCarApi != null) {
mCarApi.disconnect();
}
@@ -251,10 +270,12 @@
Log.d(TAG, "Connected to Car Service");
try {
mHvacManager = (CarHvacManager) mCarApi.getCarManager(android.car.Car.HVAC_SERVICE);
- mCarSensorManager = (CarSensorManager) mCarApi.getCarManager(Car.SENSOR_SERVICE);
- mCarSensorManager.addListener(mListener,
- CarSensorManager.SENSOR_TYPE_DRIVING_STATUS,
- CarSensorManager.SENSOR_RATE_NORMAL);
+ mPowerManager = (CarPowerManager) mCarApi.getCarManager(
+ android.car.Car.POWER_SERVICE);
+ mPropertyManager = (CarPropertyManager) mCarApi.getCarManager(
+ android.car.Car.PROPERTY_SERVICE);
+ mSensorManager = (CarSensorManager) mCarApi.getCarManager(
+ android.car.Car.SENSOR_SERVICE);
mCarAppFocusManager =
(CarAppFocusManager) mCarApi.getCarManager(Car.APP_FOCUS_SERVICE);
} catch (CarNotConnectedException e) {
@@ -298,7 +319,7 @@
mMenuEntries.get(position).onClick();
- closeDrawer();
+ getDrawerController().closeDrawer();
}
}
}
diff --git a/tests/EmbeddedKitchenSinkApp/src/com/google/android/car/kitchensink/activityview/ActivityViewTestFragment.java b/tests/EmbeddedKitchenSinkApp/src/com/google/android/car/kitchensink/activityview/ActivityViewTestFragment.java
new file mode 100644
index 0000000..2df0b07
--- /dev/null
+++ b/tests/EmbeddedKitchenSinkApp/src/com/google/android/car/kitchensink/activityview/ActivityViewTestFragment.java
@@ -0,0 +1,74 @@
+/*
+ * 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.kitchensink.activityview;
+
+import android.app.ActivityView;
+import android.content.ComponentName;
+import android.content.Intent;
+import android.os.Bundle;
+import android.os.SystemClock;
+import android.support.annotation.Nullable;
+import android.support.v4.app.Fragment;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+
+import com.google.android.car.kitchensink.R;
+
+import java.util.Random;
+
+/**
+ * This fragment exercises the capabilities of virtual display.
+ */
+public class ActivityViewTestFragment extends Fragment {
+ private ActivityView mActivityView;
+ private ViewGroup mActivityViewParent;
+
+ @Override
+ public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container,
+ @Nullable Bundle savedInstanceState) {
+ View root = inflater.inflate(R.layout.activity_view_test_fragment, container, false);
+
+ root.findViewById(R.id.av_launch_activity)
+ .setOnClickListener(this::onLaunchActivityClicked);
+ root.findViewById(R.id.av_resize)
+ .setOnClickListener(this::onResizeVirtualDisplayClicked);
+
+ mActivityView = root.findViewById(R.id.av_activityview);
+ mActivityViewParent = ((ViewGroup) mActivityView.getParent());
+
+ return root;
+ }
+
+ private void onResizeVirtualDisplayClicked(View v) {
+ mActivityViewParent.setPadding(20, 20, 20,
+ new Random(SystemClock.elapsedRealtimeNanos()).nextInt(200));
+ }
+
+ private void onLaunchActivityClicked(View v) {
+ Intent intent = new Intent();
+ intent.setComponent(ComponentName.createRelative("com.android.settings", ".Settings"));
+ intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+ mActivityView.startActivity(intent);
+ }
+
+ @Override
+ public void onDestroy() {
+ super.onDestroy();
+ mActivityView.release();
+ }
+}
diff --git a/tests/EmbeddedKitchenSinkApp/src/com/google/android/car/kitchensink/alertdialog/AlertDialogTestFragment.java b/tests/EmbeddedKitchenSinkApp/src/com/google/android/car/kitchensink/alertdialog/AlertDialogTestFragment.java
new file mode 100644
index 0000000..f2f5712
--- /dev/null
+++ b/tests/EmbeddedKitchenSinkApp/src/com/google/android/car/kitchensink/alertdialog/AlertDialogTestFragment.java
@@ -0,0 +1,125 @@
+/*
+ * 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.alertdialog;
+
+import android.annotation.Nullable;
+import android.app.AlertDialog;
+import android.content.DialogInterface;
+import android.os.Bundle;
+import android.support.v4.app.Fragment;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.Button;
+
+import com.google.android.car.kitchensink.R;
+
+/**
+ * Shows alert dialogs
+ */
+public class AlertDialogTestFragment extends Fragment {
+
+ private static final String TAG = "CAR.ALERT";
+
+ private Button alertMessageBtn;
+ private Button alertBtPinConfirmBtn;
+ private Button alertBtPinEnterBtn;
+
+
+ @Nullable
+ @Override
+ public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container,
+ @Nullable Bundle savedInstanceState) {
+ View view = inflater.inflate(R.layout.alert_dialog_test, container, false);
+
+ alertMessageBtn = view.findViewById(R.id.alert_message_btn);
+ alertBtPinEnterBtn = view.findViewById(R.id.alert_bluetooth_pin_enter_view_btn);
+ alertBtPinConfirmBtn = view.findViewById(R.id.alert_bluetooth_pin_confirm_view_btn);
+
+ alertMessageBtn.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ AlertDialog.Builder builder;
+ builder = new AlertDialog.Builder(getContext());
+ builder.setTitle("Alert Title")
+ .setMessage("Message for Alert dialog window, this part is text only")
+ .setPositiveButton(
+ android.R.string.yes, new DialogInterface.OnClickListener() {
+ public void onClick(DialogInterface dialog, int which) {
+ // do nothing
+ }
+ })
+ .setNegativeButton(
+ android.R.string.no, new DialogInterface.OnClickListener() {
+ public void onClick(DialogInterface dialog, int which) {
+ // do nothing
+ }
+ })
+ .setIcon(android.R.drawable.ic_dialog_alert)
+ .show();
+ }
+ });
+
+ alertBtPinEnterBtn.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ AlertDialog.Builder builder;
+ builder = new AlertDialog.Builder(getContext());
+ builder.setTitle("Alert Title")
+ .setView(R.layout.alert_dialog_bluetooth_pin_entry)
+ .setPositiveButton(
+ android.R.string.yes, new DialogInterface.OnClickListener() {
+ public void onClick(DialogInterface dialog, int which) {
+ // do nothing
+ }
+ })
+ .setNegativeButton(
+ android.R.string.no, new DialogInterface.OnClickListener() {
+ public void onClick(DialogInterface dialog, int which) {
+ // do nothing
+ }
+ })
+ .setIcon(android.R.drawable.ic_dialog_alert)
+ .show();
+ }
+ });
+
+ alertBtPinConfirmBtn.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ AlertDialog.Builder builder;
+ builder = new AlertDialog.Builder(getContext());
+ builder.setTitle("Alert Title")
+ .setView(R.layout.alert_dialog_bluetooth_pin_confirm)
+ .setPositiveButton(
+ android.R.string.yes, new DialogInterface.OnClickListener() {
+ public void onClick(DialogInterface dialog, int which) {
+ // do nothing
+ }
+ })
+ .setNegativeButton(
+ android.R.string.no, new DialogInterface.OnClickListener() {
+ public void onClick(DialogInterface dialog, int which) {
+ // do nothing
+ }
+ })
+ .setIcon(android.R.drawable.ic_dialog_alert)
+ .show();
+ }
+ });
+ return view;
+ }
+}
diff --git a/tests/EmbeddedKitchenSinkApp/src/com/google/android/car/kitchensink/assistant/CarAssistantFragment.java b/tests/EmbeddedKitchenSinkApp/src/com/google/android/car/kitchensink/assistant/CarAssistantFragment.java
index 147b017..4bee453 100644
--- a/tests/EmbeddedKitchenSinkApp/src/com/google/android/car/kitchensink/assistant/CarAssistantFragment.java
+++ b/tests/EmbeddedKitchenSinkApp/src/com/google/android/car/kitchensink/assistant/CarAssistantFragment.java
@@ -31,15 +31,18 @@
public class CarAssistantFragment extends Fragment {
- private ImageView mMic;
+ private ImageView mMicIntent;
+ private ImageView mMicService;
@Override
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container,
@Nullable Bundle savedInstanceState) {
View v = inflater.inflate(R.layout.car_assistant, container, false);
- mMic = (ImageView) v.findViewById(R.id.voice_button);
+ mMicIntent = (ImageView) v.findViewById(R.id.voice_button_intent);
+ mMicService = (ImageView) v.findViewById(R.id.voice_button_service);
Context context = getContext();
- mMic.setOnClickListener(new View.OnClickListener() {
+
+ mMicIntent.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
v.performHapticFeedback(HapticFeedbackConstants.VIRTUAL_KEY);
@@ -54,6 +57,14 @@
}
}
});
+ mMicService.setOnClickListener(v1 -> {
+ v1.performHapticFeedback(HapticFeedbackConstants.VIRTUAL_KEY);
+ boolean success = getActivity().showAssist(null);
+ if (!success) {
+ Toast.makeText(context,
+ "Assistant app is not available.", Toast.LENGTH_SHORT).show();
+ }
+ });
return v;
}
}
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 74345aa..50a5e9e 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,8 +23,6 @@
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/audio/AudioTestFragment.java b/tests/EmbeddedKitchenSinkApp/src/com/google/android/car/kitchensink/audio/AudioTestFragment.java
index ce90651..626dc2a 100644
--- a/tests/EmbeddedKitchenSinkApp/src/com/google/android/car/kitchensink/audio/AudioTestFragment.java
+++ b/tests/EmbeddedKitchenSinkApp/src/com/google/android/car/kitchensink/audio/AudioTestFragment.java
@@ -35,11 +35,8 @@
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
-import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.widget.Button;
-import android.widget.CompoundButton;
-import android.widget.CompoundButton.OnCheckedChangeListener;
import android.widget.RadioGroup;
import android.widget.TextView;
import android.widget.Toast;
@@ -47,7 +44,6 @@
import com.google.android.car.kitchensink.CarEmulator;
import com.google.android.car.kitchensink.R;
-import com.google.android.car.kitchensink.audio.AudioPlayer.PlayStateListener;
public class AudioTestFragment extends Fragment {
private static final String TAG = "CAR.AUDIO.KS";
@@ -55,27 +51,7 @@
private AudioManager mAudioManager;
private FocusHandler mAudioFocusHandler;
- private Button mNavPlayOnce;
- private Button mVrPlayOnce;
- private Button mSystemPlayOnce;
- private Button mMediaPlay;
- private Button mMediaPlayOnce;
- private Button mMediaStop;
- private Button mWavPlay;
- private Button mWavStop;
- private Button mNavStart;
- private Button mNavEnd;
- private Button mVrStart;
- private Button mVrEnd;
- private Button mRadioStart;
- private Button mRadioEnd;
- private Button mSpeakerPhoneOn;
- private Button mSpeakerPhoneOff;
- private Button mMicrophoneOn;
- private Button mMicrophoneOff;
private ToggleButton mEnableMocking;
- private ToggleButton mRejectFocus;
- private ToggleButton mMuteMedia;
private AudioPlayer mMusicPlayer;
private AudioPlayer mMusicPlayerShort;
@@ -98,26 +74,14 @@
private AudioAttributes mSystemSoundAudioAttrib;
private CarEmulator mCarEmulator;
- private final AudioManager.OnAudioFocusChangeListener mNavFocusListener =
- new AudioManager.OnAudioFocusChangeListener() {
- @Override
- public void onAudioFocusChange(int focusChange) {
- Log.i(TAG, "Nav focus change:" + focusChange);
- }
+ private final AudioManager.OnAudioFocusChangeListener mNavFocusListener = (focusChange) -> {
+ Log.i(TAG, "Nav focus change:" + focusChange);
};
- private final AudioManager.OnAudioFocusChangeListener mVrFocusListener =
- new AudioManager.OnAudioFocusChangeListener() {
- @Override
- public void onAudioFocusChange(int focusChange) {
- Log.i(TAG, "VR focus change:" + focusChange);
- }
+ private final AudioManager.OnAudioFocusChangeListener mVrFocusListener = (focusChange) -> {
+ Log.i(TAG, "VR focus change:" + focusChange);
};
- private final AudioManager.OnAudioFocusChangeListener mRadioFocusListener =
- new AudioManager.OnAudioFocusChangeListener() {
- @Override
- public void onAudioFocusChange(int focusChange) {
- Log.i(TAG, "Radio focus change:" + focusChange);
- }
+ private final AudioManager.OnAudioFocusChangeListener mRadioFocusListener = (focusChange) -> {
+ Log.i(TAG, "Radio focus change:" + focusChange);
};
private final CarAppFocusManager.OnAppFocusOwnershipCallback mOwnershipCallbacks =
@@ -160,20 +124,21 @@
} catch (CarNotConnectedException e) {
throw new RuntimeException("Failed to create audio manager", e);
}
- try {
- mMusicAudioAttrib = mCarAudioManager.getAudioAttributesForCarUsage(
- CarAudioManager.CAR_AUDIO_USAGE_MUSIC);
- mNavAudioAttrib = mCarAudioManager.getAudioAttributesForCarUsage(
- CarAudioManager.CAR_AUDIO_USAGE_NAVIGATION_GUIDANCE);
- mVrAudioAttrib = mCarAudioManager.getAudioAttributesForCarUsage(
- CarAudioManager.CAR_AUDIO_USAGE_VOICE_COMMAND);
- mRadioAudioAttrib = mCarAudioManager.getAudioAttributesForCarUsage(
- CarAudioManager.CAR_AUDIO_USAGE_RADIO);
- mSystemSoundAudioAttrib = mCarAudioManager.getAudioAttributesForCarUsage(
- CarAudioManager.CAR_AUDIO_USAGE_SYSTEM_SOUND);
- } catch (CarNotConnectedException e) {
- //ignore for now
- }
+ mMusicAudioAttrib = new AudioAttributes.Builder()
+ .setUsage(AudioAttributes.USAGE_MEDIA)
+ .build();
+ mNavAudioAttrib = new AudioAttributes.Builder()
+ .setUsage(AudioAttributes.USAGE_ASSISTANCE_NAVIGATION_GUIDANCE)
+ .build();
+ mVrAudioAttrib = new AudioAttributes.Builder()
+ .setUsage(AudioAttributes.USAGE_ASSISTANCE_NAVIGATION_GUIDANCE)
+ .build();
+ mRadioAudioAttrib = new AudioAttributes.Builder()
+ .setUsage(AudioAttributes.USAGE_MEDIA)
+ .build();
+ mSystemSoundAudioAttrib = new AudioAttributes.Builder()
+ .setUsage(AudioAttributes.USAGE_ASSISTANCE_SONIFICATION)
+ .build();
mMusicPlayer = new AudioPlayer(mContext, R.raw.well_worth_the_wait,
mMusicAudioAttrib);
@@ -212,247 +177,102 @@
mAudioManager = (AudioManager) mContext.getSystemService(
Context.AUDIO_SERVICE);
mAudioFocusHandler = new FocusHandler(
- (RadioGroup) view.findViewById(R.id.button_focus_request_selection),
- (Button) view.findViewById(R.id.button_audio_focus_request),
- (TextView) view.findViewById(R.id.text_audio_focus_state));
- mMediaPlay = (Button) view.findViewById(R.id.button_media_play_start);
- mMediaPlay.setOnClickListener(new OnClickListener() {
- @Override
- public void onClick(View v) {
- boolean requestFocus = true;
- boolean repeat = true;
- mMusicPlayer.start(requestFocus, repeat, AudioManager.AUDIOFOCUS_GAIN);
+ view.findViewById(R.id.button_focus_request_selection),
+ view.findViewById(R.id.button_audio_focus_request),
+ view.findViewById(R.id.text_audio_focus_state));
+ view.findViewById(R.id.button_media_play_start).setOnClickListener(v -> {
+ boolean requestFocus = true;
+ boolean repeat = true;
+ mMusicPlayer.start(requestFocus, repeat, AudioManager.AUDIOFOCUS_GAIN);
+ });
+ view.findViewById(R.id.button_media_play_once).setOnClickListener(v -> {
+ mMusicPlayerShort.start(true, false, AudioManager.AUDIOFOCUS_GAIN_TRANSIENT);
+ // play only for 1 sec and stop
+ mHandler.postDelayed(() -> mMusicPlayerShort.stop(), 1000);
+ });
+ view.findViewById(R.id.button_media_play_stop).setOnClickListener(v -> mMusicPlayer.stop());
+ view.findViewById(R.id.button_wav_play_start).setOnClickListener(
+ v -> mWavPlayer.start(true, true, AudioManager.AUDIOFOCUS_GAIN));
+ view.findViewById(R.id.button_wav_play_stop).setOnClickListener(v -> mWavPlayer.stop());
+ view.findViewById(R.id.button_nav_play_once).setOnClickListener(v -> {
+ if (mAppFocusManager == null) {
+ return;
+ }
+ if (DBG) {
+ Log.i(TAG, "Nav start");
+ }
+ try {
+ mAppFocusManager.requestAppFocus(
+ CarAppFocusManager.APP_FOCUS_TYPE_NAVIGATION, mOwnershipCallbacks);
+ } catch (CarNotConnectedException e) {
+ Log.e(TAG, "Failed to set active focus", e);
+ }
+ if (!mNavGuidancePlayer.isPlaying()) {
+ mNavGuidancePlayer.start(true, false,
+ AudioManager.AUDIOFOCUS_GAIN_TRANSIENT_MAY_DUCK,
+ () -> mAppFocusManager.abandonAppFocus(mOwnershipCallbacks,
+ CarAppFocusManager.APP_FOCUS_TYPE_NAVIGATION));
}
});
- mMediaPlayOnce = (Button) view.findViewById(R.id.button_media_play_once);
- mMediaPlayOnce.setOnClickListener(new OnClickListener() {
- @Override
- public void onClick(View v) {
- mMusicPlayerShort.start(true, false, AudioManager.AUDIOFOCUS_GAIN_TRANSIENT);
- // play only for 1 sec and stop
- mHandler.postDelayed(new Runnable() {
- @Override
- public void run() {
- mMusicPlayerShort.stop();
- }
- }, 1000);
+ view.findViewById(R.id.button_vr_play_once).setOnClickListener(v -> {
+ if (mAppFocusManager == null) {
+ return;
+ }
+ if (DBG) {
+ Log.i(TAG, "VR start");
+ }
+ try {
+ mAppFocusManager.requestAppFocus(
+ CarAppFocusManager.APP_FOCUS_TYPE_VOICE_COMMAND, mOwnershipCallbacks);
+ } catch (CarNotConnectedException e) {
+ Log.e(TAG, "Failed to set active focus", e);
+ }
+ if (!mVrPlayer.isPlaying()) {
+ mVrPlayer.start(true, false,
+ AudioManager.AUDIOFOCUS_GAIN_TRANSIENT,
+ () -> mAppFocusManager.abandonAppFocus(mOwnershipCallbacks,
+ CarAppFocusManager.APP_FOCUS_TYPE_VOICE_COMMAND));
}
});
- mMediaStop = (Button) view.findViewById(R.id.button_media_play_stop);
- mMediaStop.setOnClickListener(new OnClickListener() {
- @Override
- public void onClick(View v) {
- mMusicPlayer.stop();
+ view.findViewById(R.id.button_system_play_once).setOnClickListener(v -> {
+ if (DBG) {
+ Log.i(TAG, "System start");
+ }
+ if (!mSystemPlayer.isPlaying()) {
+ // system sound played without focus
+ mSystemPlayer.start(false, false, 0);
}
});
- mWavPlay = (Button) view.findViewById(R.id.button_wav_play_start);
- mWavPlay.setOnClickListener(new OnClickListener() {
- @Override
- public void onClick(View v) {
- mWavPlayer.start(true, true, AudioManager.AUDIOFOCUS_GAIN);
- }
- });
- mWavStop = (Button) view.findViewById(R.id.button_wav_play_stop);
- mWavStop.setOnClickListener(new OnClickListener() {
- @Override
- public void onClick(View v) {
- mWavPlayer.stop();
- }
- });
- mNavPlayOnce = (Button) view.findViewById(R.id.button_nav_play_once);
- mNavPlayOnce.setOnClickListener(new OnClickListener() {
- @Override
- public void onClick(View v) {
- if (mAppFocusManager == null) {
- return;
- }
- if (DBG) {
- Log.i(TAG, "Nav start");
- }
- if (!mNavGuidancePlayer.isPlaying()) {
- try {
- mAppFocusManager.requestAppFocus(
- CarAppFocusManager.APP_FOCUS_TYPE_NAVIGATION, mOwnershipCallbacks);
- } catch (CarNotConnectedException e) {
- Log.e(TAG, "Failed to set active focus", e);
- }
- mNavGuidancePlayer.start(true, false,
- AudioManager.AUDIOFOCUS_GAIN_TRANSIENT_MAY_DUCK,
- new PlayStateListener() {
- @Override
- public void onCompletion() {
- mAppFocusManager.abandonAppFocus(mOwnershipCallbacks,
- CarAppFocusManager.APP_FOCUS_TYPE_NAVIGATION);
- }
- });
- }
- }
- });
- mVrPlayOnce = (Button) view.findViewById(R.id.button_vr_play_once);
- mVrPlayOnce.setOnClickListener(new OnClickListener() {
- @Override
- public void onClick(View v) {
- if (mAppFocusManager == null) {
- return;
- }
- if (DBG) {
- Log.i(TAG, "VR start");
- }
- try {
- mAppFocusManager.requestAppFocus(
- CarAppFocusManager.APP_FOCUS_TYPE_VOICE_COMMAND, mOwnershipCallbacks);
- } catch (CarNotConnectedException e) {
- Log.e(TAG, "Failed to set active focus", e);
- }
- if (!mVrPlayer.isPlaying()) {
- mVrPlayer.start(true, false, AudioManager.AUDIOFOCUS_GAIN_TRANSIENT,
- new PlayStateListener() {
- @Override
- public void onCompletion() {
- mAppFocusManager.abandonAppFocus(mOwnershipCallbacks,
- CarAppFocusManager.APP_FOCUS_TYPE_VOICE_COMMAND);
- }
- });
- }
- }
- });
- mSystemPlayOnce = (Button) view.findViewById(R.id.button_system_play_once);
- mSystemPlayOnce.setOnClickListener(new OnClickListener() {
- @Override
- public void onClick(View v) {
- if (DBG) {
- Log.i(TAG, "System start");
- }
- if (!mSystemPlayer.isPlaying()) {
- // system sound played without focus
- mSystemPlayer.start(false, false, 0);
- }
- }
- });
- mNavStart = (Button) view.findViewById(R.id.button_nav_start);
- mNavStart.setOnClickListener(new OnClickListener() {
- @Override
- public void onClick(View v) {
- handleNavStart();
- }
- });
- mNavEnd = (Button) view.findViewById(R.id.button_nav_end);
- mNavEnd.setOnClickListener(new OnClickListener() {
- @Override
- public void onClick(View v) {
- handleNavEnd();
- }
- });
- mVrStart = (Button) view.findViewById(R.id.button_vr_start);
- mVrStart.setOnClickListener(new OnClickListener() {
- @Override
- public void onClick(View v) {
- handleVrStart();
- }
- });
- mVrEnd = (Button) view.findViewById(R.id.button_vr_end);
- mVrEnd.setOnClickListener(new OnClickListener() {
- @Override
- public void onClick(View v) {
- handleVrEnd();
- }
- });
- mRadioStart = (Button) view.findViewById(R.id.button_radio_start);
- mRadioStart.setOnClickListener(new OnClickListener() {
- @Override
- public void onClick(View v) {
- handleRadioStart();
- }
- });
- mRadioEnd = (Button) view.findViewById(R.id.button_radio_end);
- mRadioEnd.setOnClickListener(new OnClickListener() {
- @Override
- public void onClick(View v) {
- handleRadioEnd();
- }
- });
- mSpeakerPhoneOn = (Button) view.findViewById(R.id.button_speaker_phone_on);
- mSpeakerPhoneOn.setOnClickListener(new OnClickListener() {
- @Override
- public void onClick(View v) {
- mAudioManager.setSpeakerphoneOn(true);
- }
- });
- mSpeakerPhoneOff = (Button) view.findViewById(R.id.button_speaker_phone_off);
- mSpeakerPhoneOff.setOnClickListener(new OnClickListener() {
- @Override
- public void onClick(View v) {
- mAudioManager.setSpeakerphoneOn(false);
- }
- });
- mMicrophoneOn = (Button) view.findViewById(R.id.button_microphone_on);
- mMicrophoneOn.setOnClickListener(new OnClickListener() {
- @Override
- public void onClick(View v) {
- mAudioManager.setMicrophoneMute(false); // Turn the microphone on.
- }
- });
- mMicrophoneOff = (Button) view.findViewById(R.id.button_microphone_off);
- mMicrophoneOff.setOnClickListener(new OnClickListener() {
- @Override
- public void onClick(View v) {
- mAudioManager.setMicrophoneMute(true); // Mute the microphone.
- }
- });
+ view.findViewById(R.id.button_nav_start).setOnClickListener(v -> handleNavStart());
+ view.findViewById(R.id.button_nav_end).setOnClickListener(v -> handleNavEnd());
+ view.findViewById(R.id.button_vr_start).setOnClickListener(v -> handleVrStart());
+ view.findViewById(R.id.button_vr_end).setOnClickListener(v -> handleVrEnd());
+ view.findViewById(R.id.button_radio_start).setOnClickListener(v -> handleRadioStart());
+ view.findViewById(R.id.button_radio_end).setOnClickListener(v -> handleRadioEnd());
+ view.findViewById(R.id.button_speaker_phone_on).setOnClickListener(
+ v -> mAudioManager.setSpeakerphoneOn(true));
+ view.findViewById(R.id.button_speaker_phone_off).setOnClickListener(
+ v -> mAudioManager.setSpeakerphoneOn(false));
+ view.findViewById(R.id.button_microphone_on).setOnClickListener(
+ v -> mAudioManager.setMicrophoneMute(false));
+ view.findViewById(R.id.button_microphone_off).setOnClickListener(
+ v -> mAudioManager.setMicrophoneMute(true));
- mRejectFocus = (ToggleButton) view.findViewById(R.id.button_reject_audio_focus);
- mRejectFocus.setOnCheckedChangeListener(new OnCheckedChangeListener() {
- @Override
- public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
- if (mCarEmulator == null) {
- return;
- }
- if (!mEnableMocking.isChecked()) {
- return;
- }
- if (isChecked) {
- mCarEmulator.setAudioFocusControl(true);
- } else {
- mCarEmulator.setAudioFocusControl(false);
- }
+ mEnableMocking = view.findViewById(R.id.button_mock_audio);
+ mEnableMocking.setOnCheckedChangeListener((buttonView, isChecked) -> {
+ if (mCarEmulator == null) {
+ //TODO(pavelm): need to do a full switch between emulated and normal mode
+ // all Car*Manager references should be invalidated.
+ Toast.makeText(AudioTestFragment.this.getContext(),
+ "Not supported yet :(", Toast.LENGTH_SHORT).show();
+ return;
}
- });
- mRejectFocus.setActivated(false);
- mEnableMocking = (ToggleButton) view.findViewById(R.id.button_mock_audio);
- mEnableMocking.setOnCheckedChangeListener(new OnCheckedChangeListener() {
- @Override
- public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
- if (mCarEmulator == null) {
- //TODO(pavelm): need to do a full switch between emulated and normal mode
- // all Car*Manager references should be invalidated.
- Toast.makeText(AudioTestFragment.this.getContext(),
- "Not supported yet :(", Toast.LENGTH_SHORT).show();
- return;
- }
- if (isChecked) {
- mRejectFocus.setActivated(true);
- mCarEmulator.start();
- } else {
- mRejectFocus.setActivated(false);
- mCarEmulator.stop();
- mCarEmulator = null;
- }
- }
- });
- mMuteMedia = (ToggleButton) view.findViewById(R.id.button_mute_media);
- mMuteMedia.setOnCheckedChangeListener(new OnCheckedChangeListener() {
- @Override
- public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
- try {
- if (isChecked) {
- mCarAudioManager.setMediaMute(true);
- } else {
- mCarAudioManager.setMediaMute(false);
- }
- } catch (CarNotConnectedException e) {
- //ignore
- }
+ if (isChecked) {
+ mCarEmulator.start();
+ } else {
+ mCarEmulator.stop();
+ mCarEmulator = null;
}
});
return view;
@@ -463,7 +283,6 @@
super.onDestroyView();
Log.i(TAG, "onDestroyView");
if (mCarEmulator != null) {
- mCarEmulator.setAudioFocusControl(false);
mCarEmulator.stop();
}
for (AudioPlayer p : mAllPlayers) {
@@ -482,16 +301,13 @@
if (mAppFocusManager == null) {
return;
}
- if (mCarAudioManager == null) {
- return;
- }
if (DBG) {
Log.i(TAG, "Nav start");
}
try {
mAppFocusManager.requestAppFocus(CarAppFocusManager.APP_FOCUS_TYPE_NAVIGATION,
mOwnershipCallbacks);
- mCarAudioManager.requestAudioFocus(mNavFocusListener, mNavAudioAttrib,
+ mAudioManager.requestAudioFocus(mNavFocusListener, mNavAudioAttrib,
AudioManager.AUDIOFOCUS_GAIN_TRANSIENT_MAY_DUCK, 0);
} catch (CarNotConnectedException e) {
Log.e(TAG, "Failed to set active focus", e);
@@ -502,31 +318,25 @@
if (mAppFocusManager == null) {
return;
}
- if (mCarAudioManager == null) {
- return;
- }
if (DBG) {
Log.i(TAG, "Nav end");
}
+ mAudioManager.abandonAudioFocus(mNavFocusListener, mNavAudioAttrib);
mAppFocusManager.abandonAppFocus(mOwnershipCallbacks,
CarAppFocusManager.APP_FOCUS_TYPE_NAVIGATION);
- mCarAudioManager.abandonAudioFocus(mNavFocusListener, mNavAudioAttrib);
}
private void handleVrStart() {
if (mAppFocusManager == null) {
return;
}
- if (mCarAudioManager == null) {
- return;
- }
if (DBG) {
Log.i(TAG, "VR start");
}
try {
mAppFocusManager.requestAppFocus(CarAppFocusManager.APP_FOCUS_TYPE_VOICE_COMMAND,
mOwnershipCallbacks);
- mCarAudioManager.requestAudioFocus(mVrFocusListener, mVrAudioAttrib,
+ mAudioManager.requestAudioFocus(mVrFocusListener, mVrAudioAttrib,
AudioManager.AUDIOFOCUS_GAIN_TRANSIENT, 0);
} catch (CarNotConnectedException e) {
Log.e(TAG, "Failed to set active focus", e);
@@ -537,40 +347,27 @@
if (mAppFocusManager == null) {
return;
}
- if (mCarAudioManager == null) {
- return;
- }
if (DBG) {
Log.i(TAG, "VR end");
}
+ mAudioManager.abandonAudioFocus(mVrFocusListener, mVrAudioAttrib);
mAppFocusManager.abandonAppFocus(mOwnershipCallbacks,
CarAppFocusManager.APP_FOCUS_TYPE_VOICE_COMMAND);
- mCarAudioManager.abandonAudioFocus(mVrFocusListener, mVrAudioAttrib);
}
private void handleRadioStart() {
- if (mCarAudioManager == null) {
- return;
- }
if (DBG) {
Log.i(TAG, "Radio start");
}
- try {
- mCarAudioManager.requestAudioFocus(mRadioFocusListener, mRadioAudioAttrib,
- AudioManager.AUDIOFOCUS_GAIN, 0);
- } catch (CarNotConnectedException e) {
- Log.e(TAG, "failed", e);
- }
+ mAudioManager.requestAudioFocus(mRadioFocusListener, mRadioAudioAttrib,
+ AudioManager.AUDIOFOCUS_GAIN, 0);
}
private void handleRadioEnd() {
- if (mCarAudioManager == null) {
- return;
- }
if (DBG) {
Log.i(TAG, "Radio end");
}
- mCarAudioManager.abandonAudioFocus(mRadioFocusListener, mRadioAudioAttrib);
+ mAudioManager.abandonAudioFocus(mRadioFocusListener, mRadioAudioAttrib);
}
private class FocusHandler {
@@ -587,24 +384,21 @@
mRequestSelection.check(R.id.focus_gain);
setFocusText(AUDIO_FOCUS_STATE_RELEASED_UNKNOWN);
mFocusListener = new AudioFocusListener();
- requestButton.setOnClickListener(new OnClickListener() {
- @Override
- public void onClick(View v) {
- int selectedButtonId = mRequestSelection.getCheckedRadioButtonId();
- int focusRequest = AudioManager.AUDIOFOCUS_GAIN;
- if (selectedButtonId == R.id.focus_gain_transient_duck) {
- focusRequest = AudioManager.AUDIOFOCUS_GAIN_TRANSIENT_MAY_DUCK;
- } else if (selectedButtonId == R.id.focus_release) {
- mAudioManager.abandonAudioFocus(mFocusListener);
- setFocusText(AUDIO_FOCUS_STATE_RELEASED_UNKNOWN);
- return;
- }
- int ret = mAudioManager.requestAudioFocus(mFocusListener,
- AudioManager.STREAM_MUSIC, focusRequest);
- Log.i(TAG, "requestAudioFocus returned " + ret);
- if (ret == AudioManager.AUDIOFOCUS_REQUEST_GRANTED) {
- setFocusText(AUDIO_FOCUS_STATE_GAIN);
- }
+ requestButton.setOnClickListener(v -> {
+ int selectedButtonId = mRequestSelection.getCheckedRadioButtonId();
+ int focusRequest = AudioManager.AUDIOFOCUS_GAIN;
+ if (selectedButtonId == R.id.focus_gain_transient_duck) {
+ focusRequest = AudioManager.AUDIOFOCUS_GAIN_TRANSIENT_MAY_DUCK;
+ } else if (selectedButtonId == R.id.focus_release) {
+ mAudioManager.abandonAudioFocus(mFocusListener);
+ setFocusText(AUDIO_FOCUS_STATE_RELEASED_UNKNOWN);
+ return;
+ }
+ int ret = mAudioManager.requestAudioFocus(mFocusListener,
+ AudioManager.STREAM_MUSIC, focusRequest);
+ Log.i(TAG, "requestAudioFocus returned " + ret);
+ if (ret == AudioManager.AUDIOFOCUS_REQUEST_GRANTED) {
+ setFocusText(AUDIO_FOCUS_STATE_GAIN);
}
});
}
diff --git a/tests/EmbeddedKitchenSinkApp/src/com/google/android/car/kitchensink/bluetooth/BluetoothHeadsetFragment.java b/tests/EmbeddedKitchenSinkApp/src/com/google/android/car/kitchensink/bluetooth/BluetoothHeadsetFragment.java
index cb668c4..a98d49e 100644
--- a/tests/EmbeddedKitchenSinkApp/src/com/google/android/car/kitchensink/bluetooth/BluetoothHeadsetFragment.java
+++ b/tests/EmbeddedKitchenSinkApp/src/com/google/android/car/kitchensink/bluetooth/BluetoothHeadsetFragment.java
@@ -16,18 +16,15 @@
package com.google.android.car.kitchensink.bluetooth;
-import android.app.PendingIntent;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothDevicePicker;
import android.bluetooth.BluetoothHeadsetClient;
-import android.bluetooth.BluetoothMapClient;
import android.bluetooth.BluetoothProfile;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
-import android.net.Uri;
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.v4.app.Fragment;
@@ -36,15 +33,10 @@
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
-import android.widget.CheckBox;
-import android.widget.RadioGroup;
import android.widget.TextView;
-import android.widget.Toast;
import com.google.android.car.kitchensink.R;
-import java.util.List;
-
public class BluetoothHeadsetFragment extends Fragment {
private static final String TAG = "CAR.BLUETOOTH.KS";
BluetoothAdapter mBluetoothAdapter;
@@ -58,6 +50,8 @@
Button mScoDisconnect;
Button mEnableQuietMode;
Button mHoldCall;
+ Button mEnableBVRA;
+ Button mDisableBVRA;
BluetoothHeadsetClient mHfpClientProfile;
@@ -78,6 +72,8 @@
mScoDisconnect = (Button) v.findViewById(R.id.bluetooth_sco_disconnect);
mEnableQuietMode = (Button) v.findViewById(R.id.bluetooth_quiet_mode_enable);
mHoldCall = (Button) v.findViewById(R.id.bluetooth_hold_call);
+ mEnableBVRA = (Button) v.findViewById(R.id.bluetooth_voice_recognition_enable);
+ mDisableBVRA = (Button) v.findViewById(R.id.bluetooth_voice_recognition_disable);
// Pick a bluetooth device
mDevicePicker.setOnClickListener(new View.OnClickListener() {
@@ -134,6 +130,22 @@
holdCall();
}
});
+
+ // Enable Voice Recognition
+ mEnableBVRA.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View view) {
+ startBVRA();
+ }
+ });
+
+ // Disable Voice Recognition
+ mDisableBVRA.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View view) {
+ stopBVRA();
+ }
+ });
return v;
}
@@ -217,6 +229,38 @@
mHfpClientProfile.holdCall(mPickedDevice);
}
+ void startBVRA() {
+ if (mPickedDevice == null) {
+ Log.w(TAG, "Device null when trying to start voice recognition!");
+ return;
+ }
+
+ // Check if we have the proxy and connect the device.
+ if (mHfpClientProfile == null) {
+ Log.w(TAG, "HFP Profile proxy not available, cannot start voice recognition to "
+ + mPickedDevice);
+ return;
+ }
+ mHfpClientProfile.startVoiceRecognition(mPickedDevice);
+ }
+
+ void stopBVRA() {
+ if (mPickedDevice == null) {
+ Log.w(TAG, "Device null when trying to stop voice recognition!");
+ return;
+ }
+
+ // Check if we have the proxy and connect the device.
+ if (mHfpClientProfile == null) {
+ Log.w(TAG, "HFP Profile proxy not available, cannot stop voice recognition to "
+ + mPickedDevice);
+ return;
+ }
+ mHfpClientProfile.stopVoiceRecognition(mPickedDevice);
+ }
+
+
+
private final BroadcastReceiver mPickerReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
diff --git a/tests/EmbeddedKitchenSinkApp/src/com/google/android/car/kitchensink/bluetooth/MapMceTestFragment.java b/tests/EmbeddedKitchenSinkApp/src/com/google/android/car/kitchensink/bluetooth/MapMceTestFragment.java
index ffd92a7..6a72428 100644
--- a/tests/EmbeddedKitchenSinkApp/src/com/google/android/car/kitchensink/bluetooth/MapMceTestFragment.java
+++ b/tests/EmbeddedKitchenSinkApp/src/com/google/android/car/kitchensink/bluetooth/MapMceTestFragment.java
@@ -16,6 +16,8 @@
package com.google.android.car.kitchensink.bluetooth;
+import android.Manifest;
+import android.annotation.TargetApi;
import android.app.PendingIntent;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
@@ -26,10 +28,13 @@
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
+import android.content.pm.PackageManager;
import android.net.Uri;
+import android.os.Build;
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.v4.app.Fragment;
+import android.telecom.PhoneAccount;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
@@ -38,20 +43,26 @@
import android.widget.CheckBox;
import android.widget.EditText;
import android.widget.TextView;
+import android.widget.Toast;
+import com.google.android.car.kitchensink.KitchenSinkActivity;
import com.google.android.car.kitchensink.R;
import java.util.List;
+@TargetApi(Build.VERSION_CODES.LOLLIPOP)
public class MapMceTestFragment extends Fragment {
static final String MESSAGE_TO_SEND = "Im Busy Driving";
+ static final String NEW_MESSAGE_TO_SEND = "This is new msg";
private static final String TAG = "CAR.BLUETOOTH.KS";
+ private static final int SEND_SMS_PERMISSIONS_REQUEST = 1;
BluetoothMapClient mMapProfile;
BluetoothAdapter mBluetoothAdapter;
Button mDevicePicker;
Button mDeviceDisconnect;
TextView mMessage;
EditText mOriginator;
+ EditText mSmsTelNum;
TextView mOriginatorDisplayName;
CheckBox mSent;
CheckBox mDelivered;
@@ -60,6 +71,7 @@
PendingIntent mDeliveredIntent;
NotificationReceiver mTransmissionStatusReceiver;
Object mLock = new Object();
+ private KitchenSinkActivity mActivity;
private Intent mSendIntent;
private Intent mDeliveryIntent;
@@ -67,10 +79,12 @@
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container,
@Nullable Bundle savedInstanceState) {
View v = inflater.inflate(R.layout.sms_received, container, false);
-
+ mActivity = (KitchenSinkActivity) getHost();
Button reply = (Button) v.findViewById(R.id.reply);
Button checkMessages = (Button) v.findViewById(R.id.check_messages);
mBluetoothDevice = (TextView) v.findViewById(R.id.bluetoothDevice);
+ Button sendNewMsg = (Button) v.findViewById(R.id.sms_new_message);
+ mSmsTelNum = (EditText) v.findViewById(R.id.sms_tel_num);
mOriginator = (EditText) v.findViewById(R.id.messageOriginator);
mOriginatorDisplayName = (TextView) v.findViewById(R.id.messageOriginatorDisplayName);
mSent = (CheckBox) v.findViewById(R.id.sent_checkbox);
@@ -89,6 +103,17 @@
}
});
+ sendNewMsg.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View view) {
+ String s = mSmsTelNum.getText().toString();
+ Toast.makeText(getContext(), "sending msg to " + s, Toast.LENGTH_SHORT).show();
+ Uri.Builder builder = new Uri.Builder();
+ Uri uri = builder.appendPath(s).scheme(PhoneAccount.SCHEME_TEL).build();
+ sendMessage(new Uri[]{uri}, NEW_MESSAGE_TO_SEND);
+ }
+ });
+
checkMessages.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
@@ -169,6 +194,15 @@
}
private void sendMessage(Uri[] recipients, String message) {
+ if (mActivity.checkSelfPermission(Manifest.permission.SEND_SMS)
+ != PackageManager.PERMISSION_GRANTED) {
+ Log.d(TAG,"Don't have SMS permission in kitchesink app. Requesting it");
+ mActivity.requestPermissions(new String[]{Manifest.permission.SEND_SMS},
+ SEND_SMS_PERMISSIONS_REQUEST);
+ Toast.makeText(getContext(), "Try again after granting SEND_SMS perm!",
+ Toast.LENGTH_SHORT).show();
+ return;
+ }
synchronized (mLock) {
BluetoothDevice remoteDevice;
try {
@@ -195,6 +229,7 @@
PendingIntent.FLAG_ONE_SHOT);
mDeliveredIntent = PendingIntent.getBroadcast(getContext(), 0, mDeliveryIntent,
PendingIntent.FLAG_ONE_SHOT);
+ Log.d(TAG,"Sending message in kitchesink app: " + message);
mMapProfile.sendMessage(
remoteDevice,
recipients, message, mSentIntent, mDeliveredIntent);
@@ -202,6 +237,22 @@
}
}
+ @Override
+ public void onRequestPermissionsResult(int requestCode, String[] permissions,
+ int[] grantResults) {
+ Log.d(TAG, "onRequestPermissionsResult reqCode=" + requestCode);
+ if (SEND_SMS_PERMISSIONS_REQUEST == requestCode) {
+ for (int i=0; i<permissions.length; i++) {
+ if (grantResults[i] == PackageManager.PERMISSION_GRANTED) {
+ if (permissions[i] == Manifest.permission.SEND_SMS) {
+ Log.d(TAG, "Got the SEND_SMS perm");
+ return;
+ }
+ }
+ }
+ }
+ }
+
class MapServiceListener implements BluetoothProfile.ServiceListener {
@Override
public void onServiceConnected(int profile, BluetoothProfile proxy) {
@@ -279,4 +330,4 @@
}
}
};
-}
\ No newline at end of file
+}
diff --git a/tests/EmbeddedKitchenSinkApp/src/com/google/android/car/kitchensink/cluster/InstrumentClusterFragment.java b/tests/EmbeddedKitchenSinkApp/src/com/google/android/car/kitchensink/cluster/InstrumentClusterFragment.java
index cfae45f..748ea68 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
@@ -83,7 +83,7 @@
View view = inflater.inflate(R.layout.instrument_cluster, container, false);
view.findViewById(R.id.cluster_start_button).setOnClickListener(v -> initCluster());
- view.findViewById(R.id.cluster_turn_left_button).setOnClickListener(v -> turnLeft());
+ view.findViewById(R.id.cluster_turn_left_button).setOnClickListener(v -> sendTurn());
view.findViewById(R.id.cluster_start_activity).setOnClickListener(v -> startNavActivity());
return view;
@@ -121,15 +121,14 @@
}
}
- private void turnLeft() {
+ private void sendTurn() {
+ // TODO(deanh): Make this actually meaningful.
+ Bundle bundle = new Bundle();
+ bundle.putString("someName", "someValue time=" + System.currentTimeMillis());
try {
- mCarNavigationStatusManager
- .sendNavigationTurnEvent(CarNavigationStatusManager.TURN_TURN, "Huff Ave", 90,
- -1, null, CarNavigationStatusManager.TURN_SIDE_LEFT);
- mCarNavigationStatusManager.sendNavigationTurnDistanceEvent(500, 10, 500,
- CarNavigationStatusManager.DISTANCE_METERS);
- } catch (CarNotConnectedException e) {
- e.printStackTrace();
+ mCarNavigationStatusManager.sendEvent(1, bundle);
+ } catch(CarNotConnectedException e) {
+ Log.e(TAG, "Failed to send turn information.", e);
}
}
@@ -183,12 +182,7 @@
Log.e(TAG, "Failed to get owned focus", e);
}
- try {
- mCarNavigationStatusManager
- .sendNavigationStatus(CarNavigationStatusManager.STATUS_ACTIVE);
- } catch (CarNotConnectedException e) {
- Log.e(TAG, "Failed to set navigation status, reconnecting to the car", e);
- }
+ // TODO(deanh): re-implement this using sendEvent()
}
@Override
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 b024bfd..e2b452c 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
@@ -30,8 +30,10 @@
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
+
import com.google.android.car.kitchensink.KitchenSinkActivity;
import com.google.android.car.kitchensink.R;
+
import java.util.Objects;
diff --git a/tests/EmbeddedKitchenSinkApp/src/com/google/android/car/kitchensink/displayinfo/DisplayInfoFragment.java b/tests/EmbeddedKitchenSinkApp/src/com/google/android/car/kitchensink/displayinfo/DisplayInfoFragment.java
new file mode 100644
index 0000000..bae2253
--- /dev/null
+++ b/tests/EmbeddedKitchenSinkApp/src/com/google/android/car/kitchensink/displayinfo/DisplayInfoFragment.java
@@ -0,0 +1,117 @@
+/*
+ * 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.displayinfo;
+
+import android.annotation.Nullable;
+import android.content.Context;
+import android.content.res.Resources;
+import android.graphics.Point;
+import android.os.Bundle;
+import android.support.v4.app.Fragment;
+import android.util.DisplayMetrics;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.LinearLayout;
+import android.widget.TextView;
+
+import com.google.android.car.kitchensink.R;
+
+/**
+ * Shows alert dialogs
+ */
+public class DisplayInfoFragment extends Fragment {
+
+ private LinearLayout list;
+
+ @Nullable
+ @Override
+ public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container,
+ @Nullable Bundle savedInstanceState) {
+ View view = inflater.inflate(R.layout.display_info, container, false);
+
+ list = (LinearLayout) view.findViewById(R.id.list);
+
+ return view;
+ }
+
+ @Override
+ public void onStart() {
+ super.onStart();
+ Point screenSize = new Point();
+ getActivity().getWindowManager().getDefaultDisplay().getSize(screenSize);
+ addTextView("window size(px): " + screenSize.x + " x " + screenSize.y);
+ addTextView("display density(dpi): " + getResources().getDisplayMetrics().densityDpi);
+ addTextView("display default density(dpi): "
+ + getResources().getDisplayMetrics().DENSITY_DEFAULT);
+
+ addTextView("======================================");
+ addTextView("All size are in DP.");
+ View rootView = getActivity().findViewById(android.R.id.content);
+ addTextView("view size: "
+ + convertPixelsToDp(rootView.getWidth(), getContext())
+ + " x " + convertPixelsToDp(rootView.getHeight(), getContext()));
+
+ addTextView("window size: "
+ + convertPixelsToDp(screenSize.x, getContext())
+ + " x " + convertPixelsToDp(screenSize.y, getContext()));
+
+ addDimenText("car_keyline_1");
+ addDimenText("car_keyline_2");
+ addDimenText("car_keyline_3");
+ addDimenText("car_keyline_4");
+ addDimenText("car_margin");
+ addDimenText("car_gutter_size");
+ addDimenText("car_primary_icon_size");
+ addDimenText("car_secondary_icon_size");
+ addDimenText("car_title_size");
+ addDimenText("car_title2_size");
+ addDimenText("car_headline1_size");
+ addDimenText("car_headline2_size");
+ addDimenText("car_headline3_size");
+ addDimenText("car_headline4_size");
+ addDimenText("car_body1_size");
+ addDimenText("car_body2_size");
+ addDimenText("car_body3_size");
+ addDimenText("car_body4_size");
+ addDimenText("car_body5_size");
+ addDimenText("car_action1_size");
+ addDimenText("car_touch_target_size");
+ addDimenText("car_action_bar_height");
+ }
+
+ private void addDimenText(String dimenName) {
+ addTextView(dimenName + " : " + convertPixelsToDp(
+ getResources().getDimensionPixelSize(
+ getResources().getIdentifier(
+ dimenName, "dimen", getContext().getPackageName())),
+ getContext()));
+ }
+
+ private void addTextView(String text) {
+ TextView textView = new TextView(getContext());
+ textView.setTextAppearance(R.style.TextAppearance_Car_Body2);
+ textView.setText(text);
+ list.addView(textView);
+ }
+
+ private static float convertPixelsToDp(float px, Context context){
+ Resources resources = context.getResources();
+ DisplayMetrics metrics = resources.getDisplayMetrics();
+ float dp = px / ((float) metrics.densityDpi / DisplayMetrics.DENSITY_DEFAULT);
+ return dp;
+ }
+}
diff --git a/tests/EmbeddedKitchenSinkApp/src/com/google/android/car/kitchensink/hvac/HvacTestFragment.java b/tests/EmbeddedKitchenSinkApp/src/com/google/android/car/kitchensink/hvac/HvacTestFragment.java
index 756ac0b..a1f8e1d 100644
--- a/tests/EmbeddedKitchenSinkApp/src/com/google/android/car/kitchensink/hvac/HvacTestFragment.java
+++ b/tests/EmbeddedKitchenSinkApp/src/com/google/android/car/kitchensink/hvac/HvacTestFragment.java
@@ -18,15 +18,12 @@
import static java.lang.Integer.toHexString;
-import com.google.android.car.kitchensink.KitchenSinkActivity;
-import com.google.android.car.kitchensink.R;
-
import android.car.CarNotConnectedException;
import android.car.hardware.CarPropertyConfig;
import android.car.hardware.CarPropertyValue;
import android.car.hardware.hvac.CarHvacManager;
+import android.hardware.automotive.vehicle.V2_0.VehicleAreaSeat;
import android.hardware.automotive.vehicle.V2_0.VehicleAreaWindow;
-import android.hardware.automotive.vehicle.V2_0.VehicleAreaZone;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.util.Log;
@@ -39,6 +36,9 @@
import android.widget.TextView;
import android.widget.ToggleButton;
+import com.google.android.car.kitchensink.KitchenSinkActivity;
+import com.google.android.car.kitchensink.R;
+
import java.util.ArrayList;
import java.util.List;
@@ -95,21 +95,23 @@
case CarHvacManager.ID_ZONED_AUTOMATIC_MODE_ON:
mTbAuto.setChecked((boolean)value.getValue());
break;
- case CarHvacManager.ID_ZONED_FAN_POSITION:
+ case CarHvacManager.ID_ZONED_FAN_DIRECTION:
switch((int)value.getValue()) {
- case CarHvacManager.FAN_POSITION_FACE:
+ case CarHvacManager.FAN_DIRECTION_FACE:
mRbFanPositionFace.setChecked(true);
break;
- case CarHvacManager.FAN_POSITION_FLOOR:
+ case CarHvacManager.FAN_DIRECTION_FLOOR:
mRbFanPositionFloor.setChecked(true);
break;
- case CarHvacManager.FAN_POSITION_FACE_AND_FLOOR:
+ case (CarHvacManager.FAN_DIRECTION_FACE |
+ CarHvacManager.FAN_DIRECTION_FLOOR):
mRbFanPositionFaceAndFloor.setChecked(true);
break;
- case CarHvacManager.FAN_POSITION_DEFROST:
+ case CarHvacManager.FAN_DIRECTION_DEFROST:
mRbFanPositionDefrost.setChecked(true);
break;
- case CarHvacManager.FAN_POSITION_DEFROST_AND_FLOOR:
+ case (CarHvacManager.FAN_DIRECTION_DEFROST |
+ CarHvacManager.FAN_DIRECTION_FLOOR):
mRbFanPositionDefrostAndFloor.setChecked(true);
break;
default:
@@ -126,17 +128,17 @@
mTbRecirc.setChecked((boolean)value.getValue());
break;
case CarHvacManager.ID_ZONED_FAN_SPEED_SETPOINT:
- if ((zones & mZoneForFanSpeed) != 0) {
+ if ((zones & mZoneForFanSpeed) == mZoneForFanSpeed) {
mCurFanSpeed = (int)value.getValue();
mTvFanSpeed.setText(String.valueOf(mCurFanSpeed));
}
break;
case CarHvacManager.ID_ZONED_TEMP_SETPOINT:
- if ((zones & mZoneForSetTempD) != 0) {
+ if ((zones & mZoneForSetTempD) == mZoneForSetTempD) {
mCurDTemp = (float)value.getValue();
mTvDTemp.setText(String.valueOf(mCurDTemp));
}
- if ((zones & mZoneForSetTempP) != 0) {
+ if ((zones & mZoneForSetTempP) == mZoneForSetTempP) {
mCurPTemp = (float)value.getValue();
mTvPTemp.setText(String.valueOf(mCurPTemp));
}
@@ -213,7 +215,7 @@
case CarHvacManager.ID_ZONED_AC_ON:
configureAcOn(v, prop);
break;
- case CarHvacManager.ID_ZONED_FAN_POSITION:
+ case CarHvacManager.ID_ZONED_FAN_DIRECTION:
configureFanPosition(v, prop);
break;
case CarHvacManager.ID_ZONED_FAN_SPEED_SETPOINT:
@@ -318,25 +320,27 @@
int position;
switch(checkedId) {
case R.id.rbPositionFace:
- position = CarHvacManager.FAN_POSITION_FACE;
+ position = CarHvacManager.FAN_DIRECTION_FACE;
break;
case R.id.rbPositionFloor:
- position = CarHvacManager.FAN_POSITION_FLOOR;
+ position = CarHvacManager.FAN_DIRECTION_FLOOR;
break;
case R.id.rbPositionFaceAndFloor:
- position = CarHvacManager.FAN_POSITION_FACE_AND_FLOOR;
+ position = (CarHvacManager.FAN_DIRECTION_FACE |
+ CarHvacManager.FAN_DIRECTION_FLOOR);
break;
case R.id.rbPositionDefrost:
- position = CarHvacManager.FAN_POSITION_DEFROST;
+ position = CarHvacManager.FAN_DIRECTION_DEFROST;
break;
case R.id.rbPositionDefrostAndFloor:
- position = CarHvacManager.FAN_POSITION_DEFROST_AND_FLOOR;
+ position = (CarHvacManager.FAN_DIRECTION_DEFROST |
+ CarHvacManager.FAN_DIRECTION_FLOOR);
break;
default:
throw new IllegalStateException("Unexpected fan position: " + checkedId);
}
try {
- mCarHvacManager.setIntProperty(CarHvacManager.ID_ZONED_FAN_POSITION,
+ mCarHvacManager.setIntProperty(CarHvacManager.ID_ZONED_FAN_DIRECTION,
mZoneForFanPosition,
position);
} catch (CarNotConnectedException e) {
@@ -411,12 +415,14 @@
mTempStep = 0.5f;
}
mZoneForSetTempD = 0;
- if (prop.hasArea(VehicleAreaZone.ROW_1_LEFT)) {
- mZoneForSetTempD = VehicleAreaZone.ROW_1_LEFT;
+ if (prop.hasArea(VehicleAreaSeat.ROW_1_LEFT | VehicleAreaSeat.ROW_2_LEFT
+ | VehicleAreaSeat.ROW_2_CENTER)) {
+ mZoneForSetTempD = VehicleAreaSeat.ROW_1_LEFT | VehicleAreaSeat.ROW_2_LEFT
+ | VehicleAreaSeat.ROW_2_CENTER;
}
mZoneForSetTempP = 0;
- if (prop.hasArea(VehicleAreaZone.ROW_1_RIGHT)) {
- mZoneForSetTempP = VehicleAreaZone.ROW_1_RIGHT;
+ if (prop.hasArea(VehicleAreaSeat.ROW_1_RIGHT | VehicleAreaSeat.ROW_2_RIGHT)) {
+ mZoneForSetTempP = VehicleAreaSeat.ROW_1_RIGHT | VehicleAreaSeat.ROW_2_RIGHT;
}
int[] areas = prop.getAreaIds();
if (mZoneForSetTempD == 0 && areas.length > 1) {
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 4e222c1..19ad094 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
@@ -15,26 +15,50 @@
*/
package com.google.android.car.kitchensink.input;
+import static android.hardware.automotive.vehicle.V2_0.SubscribeFlags.EVENTS_FROM_ANDROID;
+import static android.hardware.automotive.vehicle.V2_0.SubscribeFlags.EVENTS_FROM_CAR;
+import static android.hardware.automotive.vehicle.V2_0.VehicleDisplay.INSTRUMENT_CLUSTER;
+import static android.hardware.automotive.vehicle.V2_0.VehicleHwKeyInputAction.ACTION_DOWN;
+import static android.hardware.automotive.vehicle.V2_0.VehicleProperty.HW_KEY_INPUT;
+
import android.annotation.Nullable;
import android.annotation.StringRes;
-import android.hardware.automotive.vehicle.V2_0.VehicleHwKeyInputAction;
+import android.hardware.automotive.vehicle.V2_0.IVehicle;
+import android.hardware.automotive.vehicle.V2_0.IVehicleCallback;
+import android.hardware.automotive.vehicle.V2_0.IVehicleCallback.Stub;
+import android.hardware.automotive.vehicle.V2_0.SubscribeOptions;
+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;
import android.os.Bundle;
+import android.os.RemoteException;
import android.support.v4.app.Fragment;
+import android.text.method.ScrollingMovementMethod;
import android.util.Log;
import android.view.KeyEvent;
import android.view.LayoutInflater;
-import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.LinearLayout;
+import android.widget.TextView;
+import android.widget.Toast;
-import com.google.android.car.kitchensink.CarEmulator;
+import com.android.car.keventreader.EventReaderService;
+import com.android.car.keventreader.IEventCallback;
+import com.android.car.keventreader.KeypressEvent;
+
import com.google.android.car.kitchensink.R;
+import com.google.android.collect.Lists;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
+import java.util.NoSuchElementException;
/**
* Test input event handling to system.
@@ -48,7 +72,91 @@
private final List<View> mButtons = new ArrayList<>();
- private CarEmulator mCarEmulator;
+ // This is fake data generation property available only in emulated VHAL implementation.
+ private static final int sGenerateFakeDataControllingProperty =
+ 0x0666 | VehiclePropertyGroup.VENDOR | VehicleArea.GLOBAL | VehiclePropertyType.MIXED;
+ // The key press command is sent with the fake data generation property. It's matching the
+ // command defined in the emulated VHAL implementation.
+ private static final int sKeyPressCommand = 100;
+
+ private IVehicle mVehicle;
+
+ private EventReaderService mEventReaderService;
+
+ private final IEventCallback.Stub mKeypressEventHandler = new IEventCallback.Stub() {
+ private String prettyPrint(KeypressEvent event) {
+ return String.format("Event{source = %s, keycode = %s, key%s}\n",
+ event.source,
+ event.keycodeToString(),
+ event.isKeydown ? "down" : "up");
+ }
+
+ @Override
+ public void onEvent(KeypressEvent keypressEvent) throws RemoteException {
+ Log.d(TAG, "received event " + keypressEvent);
+ synchronized (mInputEventsList) {
+ mInputEventsList.append(prettyPrint(keypressEvent));
+ }
+ }
+ };
+
+ private final IVehicleCallback.Stub mHalKeyEventHandler = new Stub() {
+ private String prettyPrint(VehiclePropValue event) {
+ if (event.prop != HW_KEY_INPUT) return "";
+ if (event.value == null ||
+ event.value.int32Values == null ||
+ event.value.int32Values.size() < 2) return "";
+ return String.format("Event{source = HAL, keycode = %s, key%s}\n",
+ event.value.int32Values.get(1),
+ event.value.int32Values.get(0) == ACTION_DOWN ? "down" : "up");
+ }
+
+ @Override
+ public void onPropertyEvent(ArrayList<VehiclePropValue> propValues) throws RemoteException {
+ synchronized (mInputEventsList) {
+ propValues.forEach(vpv -> mInputEventsList.append(prettyPrint(vpv)));
+ }
+ }
+
+ @Override
+ public void onPropertySet(VehiclePropValue propValue) {}
+
+ @Override
+ public void onPropertySetError(int errorCode, int propId, int areaId) {}
+ };
+
+ private TextView mInputEventsList;
+
+ @Override
+ public void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+
+ try {
+ mVehicle = IVehicle.getService();
+ } catch (NoSuchElementException ex) {
+ throw new RuntimeException("Couldn't connect to " + IVehicle.kInterfaceName, ex);
+ } catch (RemoteException e) {
+ throw new RuntimeException("Failed to connect to IVehicle");
+ }
+ Log.d(TAG, "Connected to IVehicle service: " + mVehicle);
+
+ mEventReaderService = EventReaderService.tryGet();
+ Log.d(TAG, "Key Event Reader service: " + mEventReaderService);
+ if (mEventReaderService != null) {
+ mEventReaderService.registerCallback(mKeypressEventHandler);
+ }
+
+ SubscribeOptions subscribeOption = new SubscribeOptions();
+ subscribeOption.propId = HW_KEY_INPUT;
+ subscribeOption.flags = EVENTS_FROM_CAR | EVENTS_FROM_ANDROID;
+ ArrayList<SubscribeOptions> subscribeOptions = new ArrayList<>();
+ subscribeOptions.add(subscribeOption);
+ try {
+ mVehicle.subscribe(mHalKeyEventHandler, subscribeOptions);
+ } catch (RemoteException e) {
+ Log.e(TAG, "failed to connect to VHAL for key events", e);
+ }
+ }
@Nullable
@Override
@@ -56,6 +164,13 @@
@Nullable Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.input_test, container, false);
+ mInputEventsList = view.findViewById(R.id.events_list);
+ mInputEventsList.setMovementMethod(new ScrollingMovementMethod());
+
+ TextView steeringWheelLabel = new TextView(getActivity() /*context*/);
+ steeringWheelLabel.setText(R.string.steering_wheel);
+ steeringWheelLabel.setTextSize(getResources().getDimension(R.dimen.car_title2_size));
+
Collections.addAll(mButtons,
BREAK_LINE,
createButton(R.string.home, KeyEvent.KEYCODE_HOME),
@@ -73,49 +188,67 @@
createButton(R.string.tune_left, KeyEvent.KEYCODE_CHANNEL_DOWN),
BREAK_LINE,
createButton(R.string.call_send, KeyEvent.KEYCODE_CALL),
- createButton(R.string.call_end, KeyEvent.KEYCODE_ENDCALL)
- );
+ createButton(R.string.call_end, KeyEvent.KEYCODE_ENDCALL),
+ BREAK_LINE,
+ steeringWheelLabel,
+ BREAK_LINE,
+ createButton(R.string.sw_left, KeyEvent.KEYCODE_DPAD_LEFT, INSTRUMENT_CLUSTER),
+ createButton(R.string.sw_right, KeyEvent.KEYCODE_DPAD_RIGHT,
+ INSTRUMENT_CLUSTER),
+ createButton(R.string.sw_up, KeyEvent.KEYCODE_DPAD_UP, INSTRUMENT_CLUSTER),
+ createButton(R.string.sw_down, KeyEvent.KEYCODE_DPAD_DOWN, INSTRUMENT_CLUSTER),
+ createButton(R.string.sw_center, KeyEvent.KEYCODE_DPAD_CENTER,
+ INSTRUMENT_CLUSTER),
+ createButton(R.string.sw_back, KeyEvent.KEYCODE_BACK, INSTRUMENT_CLUSTER)
+ );
- mCarEmulator = CarEmulator.create(getContext());
- addButtonsToPanel((LinearLayout) view.findViewById(R.id.input_buttons), mButtons);
+ addButtonsToPanel(view.findViewById(R.id.input_buttons), mButtons);
return view;
}
private Button createButton(@StringRes int textResId, int keyCode) {
+ return createButton(textResId, keyCode, VehicleDisplay.MAIN);
+ }
+
+ private Button createButton(@StringRes int textResId, int keyCode, int targetDisplay) {
Button button = new Button(getContext());
button.setText(getContext().getString(textResId));
- button.setTextSize(32f);
- // Single touch + key event does not work as touch is happening in other window
- // at the same time. But long press will work.
- button.setOnTouchListener((v, event) -> {
- handleTouchEvent(event, keyCode);
- return true;
- });
-
+ button.setTextSize(getResources().getDimension(R.dimen.car_button_text_size));
+ button.setOnClickListener(v -> onButtonClick(keyCode, targetDisplay));
return button;
}
- private void handleTouchEvent(MotionEvent event, int keyCode) {
- int androidAction = event.getActionMasked();
- Log.i(TAG, "handleTouchEvent, action:" + androidAction + ",keyCode:" + keyCode);
+ private void onButtonClick(int keyCode, int targetDisplay) {
+ VehiclePropValue prop = new VehiclePropValue();
+ prop.prop = sGenerateFakeDataControllingProperty;
+ prop.value.int32Values.addAll(Lists.newArrayList(
+ sKeyPressCommand, HW_KEY_INPUT, keyCode, targetDisplay));
+ int status;
+ try {
+ status = mVehicle.set(prop);
+ } catch (RemoteException e) {
+ throw new RuntimeException("Failed to inject key press");
+ }
- switch (androidAction) {
- case MotionEvent.ACTION_DOWN:
- mCarEmulator.injectKey(keyCode, VehicleHwKeyInputAction.ACTION_DOWN);
- break;
- case MotionEvent.ACTION_UP:
- mCarEmulator.injectKey(keyCode, VehicleHwKeyInputAction.ACTION_UP);
- break;
- default:
- Log.w(TAG, "Unhandled touch action: " + androidAction);
- break;
+ if (VehiclePropertyStatus.AVAILABLE != status) {
+ Toast.makeText(getContext(), "Failed to inject key event, status:" + status,
+ Toast.LENGTH_LONG).show();
}
}
@Override
public void onDestroyView() {
super.onDestroyView();
+ mButtons.clear();
+ if (mEventReaderService != null) {
+ mEventReaderService.unregisterCallback(mKeypressEventHandler);
+ }
+ try {
+ mVehicle.unsubscribe(mHalKeyEventHandler, HW_KEY_INPUT);
+ } catch (RemoteException e) {
+ Log.e(TAG, "failed to remove HAL registration for keypress events", e);
+ }
}
private void addButtonsToPanel(LinearLayout root, List<View> buttons) {
@@ -127,6 +260,7 @@
root.addView(panel);
} else {
panel.addView(button);
+ panel.setPadding(0, 10, 10, 0);
}
}
}
diff --git a/tests/EmbeddedKitchenSinkApp/src/com/google/android/car/kitchensink/notification/NotificationFragment.java b/tests/EmbeddedKitchenSinkApp/src/com/google/android/car/kitchensink/notification/NotificationFragment.java
new file mode 100644
index 0000000..5f88259
--- /dev/null
+++ b/tests/EmbeddedKitchenSinkApp/src/com/google/android/car/kitchensink/notification/NotificationFragment.java
@@ -0,0 +1,188 @@
+package com.google.android.car.kitchensink.notification;
+
+import static android.security.KeyStore.getApplicationContext;
+
+import android.annotation.Nullable;
+import android.app.Notification;
+import android.app.NotificationChannel;
+import android.app.NotificationManager;
+import android.app.PendingIntent;
+import android.app.Person;
+import android.app.RemoteInput;
+import android.content.Context;
+import android.content.Intent;
+import android.os.Bundle;
+import android.support.v4.app.Fragment;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.Button;
+
+import com.google.android.car.kitchensink.KitchenSinkActivity;
+import com.google.android.car.kitchensink.R;
+
+/**
+ * Test fragment that can send all sorts of notifications.
+ */
+public class NotificationFragment extends Fragment {
+ private static final String CHANNEL_ID_1 = "kitchensink.channel1";
+ private static final String CHANNEL_ID_2 = "kitchensink.channel2";
+ private static final String CHANNEL_ID_3 = "kitchensink.channel3";
+ private static final String CHANNEL_ID_4 = "kitchensink.channel4";
+ private static final String CHANNEL_ID_5 = "kitchensink.channel5";
+ private static final String CHANNEL_ID_6 = "kitchensink.channel6";
+
+ @Override
+ public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container,
+ @Nullable Bundle savedInstanceState) {
+ View view = inflater.inflate(R.layout.notification_fragment, container, false);
+ Button cancelAllButton = view.findViewById(R.id.cancel_all_button);
+ Button importanceHighButton = view.findViewById(R.id.importance_high_button);
+ Button importanceHighButton2 = view.findViewById(R.id.importance_high_button_2);
+ Button importanceLowButton = view.findViewById(R.id.importance_low_button);
+ Button importanceMinButton = view.findViewById(R.id.importance_min_button);
+ Button importanceDefaultButton = view.findViewById(R.id.importance_default_button);
+ Button ongoingButton = view.findViewById(R.id.ongoing_button);
+ Button messageButton = view.findViewById(R.id.category_message_button);
+
+ NotificationManager manager =
+ (NotificationManager) getActivity().getSystemService(Context.NOTIFICATION_SERVICE);
+
+ // cancel all button
+ cancelAllButton.setOnClickListener(v -> manager.cancelAll());
+
+ // importance high notifications
+ NotificationChannel highImportanceChannel =
+ new NotificationChannel(
+ CHANNEL_ID_1, "Importance High", NotificationManager.IMPORTANCE_HIGH);
+ manager.createNotificationChannel(highImportanceChannel);
+
+ importanceHighButton.setOnClickListener(v -> {
+
+ Notification notification = new Notification.Builder(getActivity(), CHANNEL_ID_1)
+ .setContentTitle("Importance High")
+ .setContentText("blah")
+ .setSmallIcon(R.drawable.car_ic_mode)
+ .build();
+ manager.notify(1, notification);
+ });
+
+ importanceHighButton2.setOnClickListener(v -> {
+ Notification notification = new Notification.Builder(getActivity(), CHANNEL_ID_1)
+ .setContentTitle("Importance High 2")
+ .setContentText("blah blah blah")
+ .setSmallIcon(R.drawable.car_ic_mode)
+ .build();
+ manager.notify(2, notification);
+ });
+
+ // importance default
+ importanceDefaultButton.setOnClickListener(v -> {
+ NotificationChannel channel =
+ new NotificationChannel(
+ CHANNEL_ID_3,
+ "Importance Default",
+ NotificationManager.IMPORTANCE_DEFAULT);
+ manager.createNotificationChannel(channel);
+
+ Notification notification = new Notification.Builder(getActivity(), CHANNEL_ID_3)
+ .setContentTitle("Importance Default")
+ .setSmallIcon(R.drawable.car_ic_mode)
+ .build();
+ manager.notify(4, notification);
+ });
+
+ // importance low
+ importanceLowButton.setOnClickListener(v -> {
+ NotificationChannel channel =
+ new NotificationChannel(
+ CHANNEL_ID_4, "Importance Low", NotificationManager.IMPORTANCE_LOW);
+ manager.createNotificationChannel(channel);
+
+ Notification notification = new Notification.Builder(getActivity(), CHANNEL_ID_4)
+ .setContentTitle("Importance Low")
+ .setContentText("low low low")
+ .setSmallIcon(R.drawable.car_ic_mode)
+ .build();
+ manager.notify(5, notification);
+ });
+
+ // importance min
+ importanceMinButton.setOnClickListener(v -> {
+ NotificationChannel channel =
+ new NotificationChannel(
+ CHANNEL_ID_5, "Importance Min", NotificationManager.IMPORTANCE_MIN);
+ manager.createNotificationChannel(channel);
+
+ Notification notification = new Notification.Builder(getActivity(), CHANNEL_ID_5)
+ .setContentTitle("Importance Min")
+ .setContentText("min min min")
+ .setSmallIcon(R.drawable.car_ic_mode)
+ .build();
+ manager.notify(6, notification);
+ });
+
+ // ongoing
+ ongoingButton.setOnClickListener(v -> {
+ NotificationChannel channel =
+ new NotificationChannel(
+ CHANNEL_ID_6, "Ongoing", NotificationManager.IMPORTANCE_DEFAULT);
+ manager.createNotificationChannel(channel);
+
+ Notification notification = new Notification.Builder(getActivity(), CHANNEL_ID_6)
+ .setContentTitle("Playing music or something")
+ .setSmallIcon(R.drawable.car_ic_mode)
+ .setOngoing(true)
+ .build();
+ manager.notify(7, notification);
+ });
+
+ // category message
+ messageButton.setOnClickListener(v -> {
+ NotificationChannel channel =
+ new NotificationChannel(
+ CHANNEL_ID_2, "Message", NotificationManager.IMPORTANCE_HIGH);
+ manager.createNotificationChannel(channel);
+
+ Intent intent = new Intent(getActivity(), KitchenSinkActivity.class);
+ PendingIntent readIntent = PendingIntent.getActivity(getActivity(), 0, intent, 0);
+
+ RemoteInput remoteInput = new RemoteInput.Builder("voice reply").build();
+ PendingIntent replyIntent = PendingIntent.getBroadcast(getApplicationContext(),
+ 12345,
+ intent,
+ PendingIntent.FLAG_UPDATE_CURRENT);
+
+ Person personJohn = new Person.Builder().setName("John Doe").build();
+ Person personJane = new Person.Builder().setName("Jane Roe").build();
+ Notification.MessagingStyle messagingStyle =
+ new Notification.MessagingStyle(personJohn)
+ .setConversationTitle("Whassup")
+ .addHistoricMessage(
+ new Notification.MessagingStyle.Message(
+ "historic message",
+ System.currentTimeMillis() - 3600,
+ personJohn))
+ .addMessage(new Notification.MessagingStyle.Message(
+ "message", System.currentTimeMillis(), personJane));
+
+ Notification notification = new Notification.Builder(getActivity(), CHANNEL_ID_2)
+ .setContentTitle("Message from someone")
+ .setContentText("hi")
+ .setCategory(Notification.CATEGORY_MESSAGE)
+ .setSmallIcon(R.drawable.car_ic_mode)
+ .setStyle(messagingStyle)
+ .setAutoCancel(true)
+ .addAction(
+ new Notification.Action.Builder(null, "read", readIntent).build())
+ .addAction(
+ new Notification.Action.Builder(null, "reply", replyIntent)
+ .addRemoteInput(remoteInput).build())
+ .extend(new Notification.CarExtender().setColor(R.color.car_red_500))
+ .build();
+ manager.notify(3, notification);
+ });
+
+ return view;
+ }
+}
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
new file mode 100644
index 0000000..fed1fbd
--- /dev/null
+++ b/tests/EmbeddedKitchenSinkApp/src/com/google/android/car/kitchensink/power/PowerTestFragment.java
@@ -0,0 +1,140 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.google.android.car.kitchensink.power;
+
+import android.car.CarNotConnectedException;
+import android.car.hardware.power.CarPowerManager;
+import android.content.Context;
+import android.os.Bundle;
+import android.os.PowerManager;
+import android.os.SystemClock;
+import android.support.v4.app.Fragment;
+import android.util.Log;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.Button;
+import android.widget.TextView;
+
+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);
+ }
+ };
+
+ @Override
+ public void onCreate(Bundle savedInstanceState) {
+ mCarPowerManager = ((KitchenSinkActivity)getActivity()).getPowerManager();
+ mExecutor = new ThreadPerTaskExecutor();
+ super.onCreate(savedInstanceState);
+ try {
+ mCarPowerManager.setListener(mPowerListener, mExecutor);
+ } catch (CarNotConnectedException e) {
+ Log.e(TAG, "Car is not connected!");
+ } catch (IllegalStateException e) {
+ Log.e(TAG, "CarPowerManager listener was not cleared");
+ }
+ }
+
+ @Override
+ public void onDestroy() {
+ super.onDestroy();
+ mCarPowerManager.clearListener();
+ }
+
+ @Override
+ public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstance) {
+ View v = inflater.inflate(R.layout.power_test, container, false);
+
+ Button b = v.findViewById(R.id.btnPwrGetBootReason);
+ b.setOnClickListener(this::getBootReasonBtn);
+
+ b = v.findViewById(R.id.btnPwrRequestShutdown);
+ b.setOnClickListener(this::requestShutdownBtn);
+
+ b = v.findViewById(R.id.btnPwrShutdown);
+ b.setOnClickListener(this::shutdownBtn);
+
+ b = v.findViewById(R.id.btnPwrSleep);
+ b.setOnClickListener(this::sleepBtn);
+
+ mTvBootReason = v.findViewById(R.id.tvPowerBootReason);
+
+ if(DBG) {
+ Log.d(TAG, "Starting PowerTestFragment");
+ }
+
+ return v;
+ }
+
+ private void getBootReasonBtn(View v) {
+ try {
+ int bootReason = mCarPowerManager.getBootReason();
+ mTvBootReason.setText(String.valueOf(bootReason));
+ } catch (CarNotConnectedException e) {
+ Log.e(TAG, "Failed to getBootReason()", e);
+ }
+ }
+
+ private void requestShutdownBtn(View v) {
+ try {
+ mCarPowerManager.requestShutdownOnNextSuspend();
+ } catch (CarNotConnectedException e) {
+ Log.e(TAG, "Failed to set requestShutdownOnNextSuspend()", e);
+ }
+ }
+
+ private void shutdownBtn(View v) {
+ if(DBG) {
+ Log.d(TAG, "Calling shutdown method");
+ }
+ PowerManager pm = (PowerManager) getActivity().getSystemService(Context.POWER_SERVICE);
+ pm.shutdown(/* confirm */ false, /* reason */ null, /* wait */ false);
+ Log.d(TAG, "shutdown called!");
+ }
+
+ private void sleepBtn(View v) {
+ if(DBG) {
+ Log.d(TAG, "Calling sleep method");
+ }
+ // NOTE: This doesn't really work to sleep the device. Actual sleep is implemented via
+ // SystemInterface via libsuspend::force_suspend()
+ PowerManager pm = (PowerManager) getActivity().getSystemService(Context.POWER_SERVICE);
+ pm.goToSleep(SystemClock.uptimeMillis(), PowerManager.GO_TO_SLEEP_REASON_DEVICE_ADMIN,
+ PowerManager.GO_TO_SLEEP_FLAG_NO_DOZE);
+ }
+}
diff --git a/tests/EmbeddedKitchenSinkApp/src/com/google/android/car/kitchensink/property/PropertyInfo.java b/tests/EmbeddedKitchenSinkApp/src/com/google/android/car/kitchensink/property/PropertyInfo.java
new file mode 100644
index 0000000..0f0b5d4
--- /dev/null
+++ b/tests/EmbeddedKitchenSinkApp/src/com/google/android/car/kitchensink/property/PropertyInfo.java
@@ -0,0 +1,55 @@
+/*
+ * 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.kitchensink.property;
+
+import android.car.hardware.CarPropertyConfig;
+import android.hardware.automotive.vehicle.V2_0.VehicleProperty;
+
+class PropertyInfo implements Comparable<PropertyInfo> {
+ public final CarPropertyConfig mConfig;
+ public final String mName;
+ public final int mPropId;
+
+ PropertyInfo(CarPropertyConfig config) {
+ mConfig = config;
+ mPropId = config.getPropertyId();
+ mName = VehicleProperty.toString(mPropId);
+ }
+
+ @Override
+ public String toString() {
+ return mName;
+ }
+
+ @Override
+ public boolean equals(Object other) {
+ if (other instanceof PropertyInfo) {
+ return ((PropertyInfo) other).mPropId == mPropId;
+ }
+ return false;
+ }
+
+ @Override
+ public int hashCode() {
+ return mPropId;
+ }
+
+ @Override
+ public int compareTo(PropertyInfo propertyInfo) {
+ return mName.compareTo(propertyInfo.mName);
+ }
+}
diff --git a/tests/EmbeddedKitchenSinkApp/src/com/google/android/car/kitchensink/property/PropertyListAdapter.java b/tests/EmbeddedKitchenSinkApp/src/com/google/android/car/kitchensink/property/PropertyListAdapter.java
new file mode 100644
index 0000000..06ea4ee
--- /dev/null
+++ b/tests/EmbeddedKitchenSinkApp/src/com/google/android/car/kitchensink/property/PropertyListAdapter.java
@@ -0,0 +1,149 @@
+/*
+ * 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.kitchensink.property;
+
+import static java.lang.Integer.toHexString;
+
+import android.car.hardware.CarPropertyConfig;
+import android.car.hardware.CarPropertyValue;
+import android.car.hardware.property.CarPropertyManager;
+import android.content.Context;
+import android.util.Log;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.BaseAdapter;
+import android.widget.ListAdapter;
+import android.widget.ScrollView;
+import android.widget.TextView;
+import android.widget.ToggleButton;
+
+import com.google.android.car.kitchensink.R;
+
+import java.util.List;
+
+class PropertyListAdapter extends BaseAdapter implements ListAdapter {
+ private static final int DEFAULT_RATE = 1;
+ private static final String TAG = "PropertyListAdapter";
+ private final Context mContext;
+ private final PropertyListEventListener mListener;
+ private final CarPropertyManager mMgr;
+ private final List<PropertyInfo> mPropInfo;
+ private final TextView mTvEventLog;
+
+ PropertyListAdapter(List<PropertyInfo> propInfo, CarPropertyManager mgr, TextView eventLog,
+ ScrollView svEventLog, Context context) {
+ mContext = context;
+ mListener = new PropertyListEventListener(eventLog, svEventLog);
+ mMgr = mgr;
+ mPropInfo = propInfo;
+ mTvEventLog = eventLog;
+ }
+
+ @Override
+ public int getCount() {
+ return mPropInfo.size();
+ }
+
+ @Override
+ public Object getItem(int pos) {
+ return mPropInfo.get(pos);
+ }
+
+ @Override
+ public long getItemId(int pos) {
+ return mPropInfo.get(pos).mPropId;
+ }
+
+ @Override
+ public View getView(final int position, View convertView, ViewGroup parent) {
+ View view = convertView;
+ if (view == null) {
+ LayoutInflater inflater = (LayoutInflater) mContext.getSystemService(
+ Context.LAYOUT_INFLATER_SERVICE);
+ view = inflater.inflate(R.layout.property_list_item, null);
+ }
+
+ //Handle TextView and display string from your list
+ TextView listItemText = (TextView) view.findViewById(R.id.tvPropertyName);
+ listItemText.setText(mPropInfo.get(position).toString());
+
+ //Handle buttons and add onClickListeners
+ ToggleButton btn = (ToggleButton) view.findViewById(R.id.tbRegisterPropertyBtn);
+
+ btn.setOnClickListener(new View.OnClickListener(){
+ @Override
+ public void onClick(View v) {
+ CarPropertyConfig c = mPropInfo.get(position).mConfig;
+ int propId = c.getPropertyId();
+ try {
+ if (btn.isChecked()) {
+ mMgr.registerListener(mListener, propId, DEFAULT_RATE);
+ } else {
+ mMgr.unregisterListener(mListener, propId);
+ }
+ } catch (Exception e) {
+ Log.e(TAG, "Unhandled exception: ", e);
+ }
+ }
+ });
+ return view;
+ }
+
+
+ private static class PropertyListEventListener implements
+ CarPropertyManager.CarPropertyEventListener {
+ private int mNumEvents;
+ private ScrollView mScrollView;
+ private TextView mTvLogEvent;
+
+ PropertyListEventListener(TextView logEvent, ScrollView scrollView) {
+ mScrollView = scrollView;
+ mTvLogEvent = logEvent;
+ }
+
+ @Override
+ public void onChangeEvent(CarPropertyValue value) {
+ mNumEvents++;
+ mTvLogEvent.append("Event " + mNumEvents + ":"
+ + " time=" + value.getTimestamp()
+ + " propId=0x" + toHexString(value.getPropertyId())
+ + " areaId=0x" + toHexString(value.getAreaId())
+ + " status=" + value.getStatus()
+ + " value=" + value.getValue()
+ + "\n");
+ scrollToBottom();
+ }
+
+ @Override
+ public void onErrorEvent(int propId, int areaId) {
+ mTvLogEvent.append("Received error event propId=0x" + toHexString(propId)
+ + ", areaId=0x" + toHexString(areaId));
+ scrollToBottom();
+ }
+
+ private void scrollToBottom() {
+ mScrollView.post(new Runnable() {
+ public void run() {
+ mScrollView.fullScroll(View.FOCUS_DOWN);
+ //mScrollView.smoothScrollTo(0, mTextStatus.getBottom());
+ }
+ });
+ }
+
+ }
+}
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
new file mode 100644
index 0000000..fc6621a
--- /dev/null
+++ b/tests/EmbeddedKitchenSinkApp/src/com/google/android/car/kitchensink/property/PropertyTestFragment.java
@@ -0,0 +1,205 @@
+/*
+ * 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.kitchensink.property;
+
+import static java.lang.Integer.toHexString;
+
+import android.annotation.Nullable;
+import android.car.hardware.CarPropertyValue;
+import android.car.hardware.property.CarPropertyManager;
+import android.content.DialogInterface;
+import android.content.DialogInterface.OnClickListener;
+import android.hardware.automotive.vehicle.V2_0.VehicleProperty;
+import android.hardware.automotive.vehicle.V2_0.VehiclePropertyType;
+import android.os.Bundle;
+import android.support.v4.app.Fragment;
+import android.util.Log;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.AdapterView;
+import android.widget.AdapterView.OnItemSelectedListener;
+import android.widget.ArrayAdapter;
+import android.widget.Button;
+import android.widget.EditText;
+import android.widget.ListView;
+import android.widget.ScrollView;
+import android.widget.Spinner;
+import android.widget.TextView;
+import android.widget.Toast;
+
+import com.google.android.car.kitchensink.KitchenSinkActivity;
+import com.google.android.car.kitchensink.R;
+
+import java.util.LinkedList;
+import java.util.List;
+import java.util.stream.Collectors;
+
+public class PropertyTestFragment extends Fragment implements OnItemSelectedListener{
+ private static final String TAG = "PropertyTestFragment";
+
+ private KitchenSinkActivity mActivity;
+ private CarPropertyManager mMgr;
+ private List<PropertyInfo> mPropInfo = null;
+ private Spinner mAreaId;
+ private TextView mEventLog;
+ private TextView mGetValue;
+ private ListView mListView;
+ private Spinner mPropertyId;
+ private ScrollView mScrollView;
+ private EditText mSetValue;
+
+ private final OnClickListener mNopOnClickListener = new OnClickListener() {
+ @Override
+ public void onClick(DialogInterface dialog, int which) { }
+ };
+
+ @Nullable
+ @Override
+ public View onCreateView(LayoutInflater inflater,
+ @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);
+ mGetValue = view.findViewById(R.id.tvGetPropertyValue);
+ mListView = view.findViewById(R.id.lvPropertyList);
+ mPropertyId = view.findViewById(R.id.sPropertyId);
+ mScrollView = view.findViewById(R.id.svEventLog);
+ mSetValue = view.findViewById(R.id.etSetPropertyValue);
+
+ populateConfigList();
+ mListView.setAdapter(new PropertyListAdapter(mPropInfo, mMgr, mEventLog, mScrollView,
+ mActivity));
+
+ // Configure dropdown menu for propertyId spinner
+ ArrayAdapter<PropertyInfo> adapter =
+ new ArrayAdapter<PropertyInfo>(mActivity, android.R.layout.simple_spinner_item,
+ mPropInfo);
+ adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
+ mPropertyId.setAdapter(adapter);
+ mPropertyId.setOnItemSelectedListener(this);
+
+
+
+ // Configure listeners for buttons
+ Button b = view.findViewById(R.id.bGetProperty);
+ b.setOnClickListener(v -> {
+ try {
+ PropertyInfo info = (PropertyInfo) mPropertyId.getSelectedItem();
+ int propId = info.mConfig.getPropertyId();
+ int areaId = Integer.decode(mAreaId.getSelectedItem().toString());
+ CarPropertyValue value = mMgr.getProperty(propId, areaId);
+ if (propId == VehicleProperty.WHEEL_TICK) {
+ Object[] ticks = (Object[]) value.getValue();
+ mGetValue.setText("Timestamp=" + value.getTimestamp()
+ + "\nstatus=" + value.getStatus()
+ + "\n[0]=" + (Long) ticks[0]
+ + "\n[1]=" + (Long) ticks[1] + " [2]=" + (Long) ticks[2]
+ + "\n[3]=" + (Long) ticks[3] + " [4]=" + (Long) ticks[4]);
+ } else {
+ mGetValue.setText("Timestamp=" + value.getTimestamp()
+ + "\nstatus=" + value.getStatus()
+ + "\nvalue=" + value.getValue());
+ }
+ } catch (Exception e) {
+ Log.e(TAG, "Failed to get property", e);
+ }
+ });
+
+ b = view.findViewById(R.id.bSetProperty);
+ b.setOnClickListener(v -> {
+ try {
+ PropertyInfo info = (PropertyInfo) mPropertyId.getSelectedItem();
+ int propId = info.mConfig.getPropertyId();
+ int areaId = Integer.decode(mAreaId.getSelectedItem().toString());
+ String valueString = mSetValue.getText().toString();
+
+ switch (propId & VehiclePropertyType.MASK) {
+ case VehiclePropertyType.BOOLEAN:
+ Boolean boolVal = Boolean.parseBoolean(valueString);
+ mMgr.setBooleanProperty(propId, areaId, boolVal);
+ break;
+ case VehiclePropertyType.FLOAT:
+ Float floatVal = Float.parseFloat(valueString);
+ mMgr.setFloatProperty(propId, areaId, floatVal);
+ break;
+ case VehiclePropertyType.INT32:
+ Integer intVal = Integer.parseInt(valueString);
+ mMgr.setIntProperty(propId, areaId, intVal);
+ break;
+ default:
+ Toast.makeText(mActivity, "PropertyType=0x" + toHexString(propId
+ & VehiclePropertyType.MASK) + " is not handled!",
+ Toast.LENGTH_LONG).show();
+ break;
+ }
+ } catch (Exception e) {
+ Log.e(TAG, "Failed to set HVAC boolean property", e);
+ }
+ });
+
+ b = view.findViewById(R.id.bClearLog);
+ b.setOnClickListener(v -> {
+ mEventLog.setText("");
+ });
+
+ return view;
+ }
+
+ private void populateConfigList() {
+ try {
+ mPropInfo = mMgr.getPropertyList()
+ .stream()
+ .map(PropertyInfo::new)
+ .sorted()
+ .collect(Collectors.toList());
+ } catch (Exception e) {
+ Log.e(TAG, "Unhandled exception in populateConfigList: ", e);
+ }
+ }
+
+ // Spinner callbacks
+ public void onItemSelected(AdapterView<?> parent, View view, int pos, long id) {
+ // An item was selected. You can retrieve the selected item using
+ PropertyInfo info = (PropertyInfo) parent.getItemAtPosition(pos);
+ int[] areaIds = info.mConfig.getAreaIds();
+ List<String> areaString = new LinkedList<String>();
+ if (areaIds.length == 0) {
+ areaString.add("0x0");
+ } else {
+ for (int areaId : areaIds) {
+ areaString.add("0x" + toHexString(areaId));
+ }
+ }
+
+ // Configure dropdown menu for propertyId spinner
+ ArrayAdapter<String> adapter =
+ new ArrayAdapter<String>(mActivity, android.R.layout.simple_spinner_item,
+ areaString);
+ adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
+ mAreaId.setAdapter(adapter);
+ }
+
+ public void onNothingSelected(AdapterView<?> parent) {
+ // Another interface callback
+ }
+}
diff --git a/tests/EmbeddedKitchenSinkApp/src/com/google/android/car/kitchensink/radio/RadioTestFragment.java b/tests/EmbeddedKitchenSinkApp/src/com/google/android/car/kitchensink/radio/RadioTestFragment.java
deleted file mode 100644
index 0214791..0000000
--- a/tests/EmbeddedKitchenSinkApp/src/com/google/android/car/kitchensink/radio/RadioTestFragment.java
+++ /dev/null
@@ -1,542 +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.radio;
-
-import android.annotation.Nullable;
-import android.car.Car;
-import android.car.CarNotConnectedException;
-import android.car.media.CarAudioManager;
-import android.content.ComponentName;
-import android.content.Context;
-import android.content.ServiceConnection;
-import android.hardware.radio.RadioManager;
-import android.hardware.radio.RadioMetadata;
-import android.hardware.radio.RadioTuner;
-import android.media.AudioAttributes;
-import android.media.AudioManager;
-import android.os.Bundle;
-import android.os.IBinder;
-import android.os.Looper;
-import android.support.v4.app.Fragment;
-import android.text.TextUtils;
-import android.text.method.ScrollingMovementMethod;
-import android.util.Log;
-import android.view.LayoutInflater;
-import android.view.View;
-import android.view.ViewGroup;
-import android.widget.Button;
-import android.widget.CompoundButton;
-import android.widget.CompoundButton.OnCheckedChangeListener;
-import android.widget.EditText;
-import android.widget.TextView;
-import android.widget.ToggleButton;
-
-import com.google.android.car.kitchensink.R;
-
-import java.util.ArrayList;
-import java.util.LinkedList;
-import java.util.List;
-
-public class RadioTestFragment extends Fragment {
- private static final String TAG = "CAR.RADIO.KS";
- private static final boolean DBG = true;
- private static final int MAX_LOG_MESSAGES = 100;
-
- private final AudioManager.OnAudioFocusChangeListener mRadioFocusListener =
- new AudioManager.OnAudioFocusChangeListener() {
- @Override
- public void onAudioFocusChange(int focusChange) {
- addLog(Log.INFO, "Radio focus change:" + focusChange);
- }
- };
-
- private final AudioManager.OnAudioFocusChangeListener mSecondaryFocusListener =
- new AudioManager.OnAudioFocusChangeListener() {
- @Override
- public void onAudioFocusChange(int focusChange) {
- addLog(Log.INFO, "Secondary focus change:" + focusChange);
- }
- };
-
- private final RadioTuner.Callback mRadioCallback = new RadioTuner.Callback() {
- @Override
- public void onError(int status) {
- addLog(Log.WARN, "Radio tuner error " + status);
- }
-
- @Override
- public void onConfigurationChanged(RadioManager.BandConfig config) {
- addLog(Log.INFO, "Radio tuner configuration changed. config:" + config);
- }
-
- @Override
- public void onMetadataChanged(RadioMetadata metadata) {
- addLog(Log.INFO, "Radio tuner metadata changed. metadata:" + metadata);
- if (metadata == null) {
- resetMessages();
- updateMessages();
- return;
- }
- mArtist = metadata.getString(RadioMetadata.METADATA_KEY_ARTIST);
- mSong = metadata.getString(RadioMetadata.METADATA_KEY_TITLE);
- mStation = metadata.getString(RadioMetadata.METADATA_KEY_RDS_PS);
- updateMessages();
- }
-
- @Override
- public void onProgramInfoChanged(RadioManager.ProgramInfo info) {
- addLog(Log.INFO, "Radio tuner program info. info:" + info);
- mChannel = String.valueOf(info.getChannel());
- onMetadataChanged(info.getMetadata());
- updateMessages();
- }
-
- };
- private final LinkedList<String> mLogMessages = new LinkedList<>();
-
- private Button mOpenRadio;
- private Button mCloseRadio;
- private Button mGetRadioFocus;
- private Button mReleaseRadioFocus;
- private Button mGetFocus;
- private Button mReleaseFocus;
- private Button mRadioNext;
- private Button mRadioPrev;
- private Button mRadioScanCancel;
- private Button mRadioGetProgramInfo;
- private Button mRadioTuneToStation;
- private Button mRadioStepUp;
- private Button mRadioStepDown;
- private EditText mStationFrequency;
- private ToggleButton mToggleMuteRadio;
- private ToggleButton mRadioBand;
- private TextView mStationInfo;
- private TextView mChannelInfo;
- private TextView mSongInfo;
- private TextView mArtistInfo;
- private TextView mLog;
-
- private Car mCar;
- private CarAudioManager mCarAudioManager;
- private AudioAttributes mRadioAudioAttrib;
- private AudioManager mAudioManager;
- private boolean mHasRadioFocus;
- private boolean mHasSecondaryFocus;
- private RadioTuner mRadioTuner;
- private RadioManager mRadioManager;
- private RadioManager.FmBandDescriptor mFmDescriptor;
- private RadioManager.AmBandDescriptor mAmDescriptor;
- private String mStation;
- private String mChannel;
- private String mSong;
- private String mArtist;
- private String mNaString;
-
- private RadioManager.BandConfig mFmConfig;
- private RadioManager.BandConfig mAmConfig;
-
- private final List<RadioManager.ModuleProperties> mModules = new ArrayList<>();
-
- @Nullable
- @Override
- public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container,
- @Nullable Bundle savedInstanceState) {
- if (DBG) {
- Log.i(TAG, "onCreateView");
- }
-
- init();
- View view = inflater.inflate(R.layout.radio, container, false);
-
- mOpenRadio = (Button) view.findViewById(R.id.button_open_radio);
- mCloseRadio = (Button) view.findViewById(R.id.button_close_radio);
- mGetRadioFocus = (Button) view.findViewById(R.id.button_get_radio_focus);
- mReleaseRadioFocus = (Button) view.findViewById(R.id.button_release_radio_focus);
- mGetFocus = (Button) view.findViewById(R.id.button_get_focus_in_radio);
- mReleaseFocus = (Button) view.findViewById(R.id.button_release_focus_in_radio);
- mRadioNext = (Button) view.findViewById(R.id.button_radio_next);
- mRadioPrev = (Button) view.findViewById(R.id.button_radio_prev);
- mRadioScanCancel = (Button) view.findViewById(R.id.button_radio_scan_cancel);
- mRadioGetProgramInfo = (Button) view.findViewById(R.id.button_radio_get_program_info);
- mRadioTuneToStation = (Button) view.findViewById(R.id.button_radio_tune_to_station);
- mRadioStepUp = (Button) view.findViewById(R.id.button_radio_step_up);
- mRadioStepDown = (Button) view.findViewById(R.id.button_radio_step_down);
-
- mStationFrequency = (EditText) view.findViewById(R.id.edittext_station_frequency);
-
- mToggleMuteRadio = (ToggleButton) view.findViewById(R.id.togglebutton_mute_radio);
- mToggleMuteRadio.setChecked(true);
- mRadioBand = (ToggleButton) view.findViewById(R.id.button_band_selection);
-
- mStationInfo = (TextView) view.findViewById(R.id.radio_station_info);
- mChannelInfo = (TextView) view.findViewById(R.id.radio_channel_info);
- mSongInfo = (TextView) view.findViewById(R.id.radio_song_info);
- mArtistInfo = (TextView) view.findViewById(R.id.radio_artist_info);
-
- mLog = (TextView) view.findViewById(R.id.radio_log);
- mLog.setMovementMethod(new ScrollingMovementMethod());
-
- mNaString = getContext().getString(R.string.radio_na);
-
- addHandlers();
- updateStates();
-
- return view;
- }
-
- @Override
- public void onStart() {
- super.onStart();
- resetMessages();
- updateStates();
- updateMessages();
- resetLog();
- }
-
- private void init() {
- mCar = Car.createCar(getContext(), new ServiceConnection() {
- @Override
- public void onServiceConnected(ComponentName name, IBinder service) {
- try {
- mCarAudioManager = (CarAudioManager) mCar.getCarManager(Car.AUDIO_SERVICE);
- mRadioAudioAttrib = mCarAudioManager.getAudioAttributesForCarUsage(
- CarAudioManager.CAR_AUDIO_USAGE_RADIO);
- } catch (CarNotConnectedException e) {
- Log.e(TAG, "Car not connected", e);
- }
- }
-
- @Override
- public void onServiceDisconnected(ComponentName name) {
- }
- });
- mCar.connect();
- mAudioManager = (AudioManager) getContext().getSystemService(Context.AUDIO_SERVICE);
- initializeRadio();
- }
-
- private void initializeRadio() {
- mRadioManager = (RadioManager) getContext().getSystemService(Context.RADIO_SERVICE);
-
- if (mRadioManager == null) {
- throw new IllegalStateException("RadioManager could not be loaded.");
- }
-
- int status = mRadioManager.listModules(mModules);
- if (status != RadioManager.STATUS_OK) {
- throw new IllegalStateException("Load modules failed with status: " + status);
- }
-
- if (mModules.size() == 0) {
- throw new IllegalStateException("No radio modules on device.");
- }
-
- boolean isDebugLoggable = Log.isLoggable(TAG, Log.DEBUG);
-
- // Load the possible radio bands. For now, just accept FM and AM bands.
- for (RadioManager.BandDescriptor band : mModules.get(0).getBands()) {
- if (isDebugLoggable) {
- Log.d(TAG, "loading band: " + band.toString());
- }
-
- if (mFmDescriptor == null && band.isFmBand()) {
- mFmDescriptor = (RadioManager.FmBandDescriptor) band;
- }
-
- if (mAmDescriptor == null && band.isAmBand()) {
- mAmDescriptor = (RadioManager.AmBandDescriptor) band;
- }
- }
-
- if (mFmDescriptor == null && mAmDescriptor == null) {
- throw new IllegalStateException("No AM and FM radio bands could be loaded.");
- }
-
- mFmConfig = new RadioManager.FmBandConfig.Builder(mFmDescriptor)
- .setStereo(true)
- .build();
- mAmConfig = new RadioManager.AmBandConfig.Builder(mAmDescriptor)
- .setStereo(true)
- .build();
- }
-
- private void addHandlers() {
- mOpenRadio.setOnClickListener(new View.OnClickListener() {
- @Override
- public void onClick(View v) {
- handleRadioStart();
- updateStates();
- }
- });
- mCloseRadio.setOnClickListener(new View.OnClickListener() {
- @Override
- public void onClick(View v) {
- handleRadioEnd();
- mToggleMuteRadio.setChecked(true);
- updateStates();
- }
- });
- mToggleMuteRadio.setOnClickListener(new View.OnClickListener() {
- @Override
- public void onClick(View v) {
- if (DBG) {
- Log.i(TAG, "Toggle mute radio");
- }
- mRadioTuner.setMute(!mRadioTuner.getMute());
- updateStates();
- }
- });
- mGetRadioFocus.setOnClickListener(new View.OnClickListener() {
- @Override
- public void onClick(View v) {
- if (DBG) {
- Log.i(TAG, "Get radio focus");
- }
- try {
- mCarAudioManager.requestAudioFocus(mRadioFocusListener, mRadioAudioAttrib,
- AudioManager.AUDIOFOCUS_GAIN, 0);
- } catch (CarNotConnectedException e) {
- //ignore for now
- }
- mHasRadioFocus = true;
- updateStates();
- }
- });
- mReleaseRadioFocus.setOnClickListener(new View.OnClickListener() {
- @Override
- public void onClick(View v) {
- if (DBG) {
- Log.i(TAG, "Release radio focus");
- }
- mCarAudioManager.abandonAudioFocus(mRadioFocusListener, mRadioAudioAttrib);
- mHasRadioFocus = false;
- updateStates();
- }
- });
- mGetFocus.setOnClickListener(new View.OnClickListener() {
- @Override
- public void onClick(View v) {
- if (DBG) {
- Log.i(TAG, "Get secondary focus");
- }
- mAudioManager.requestAudioFocus(mSecondaryFocusListener,
- AudioManager.STREAM_MUSIC, AudioManager.AUDIOFOCUS_GAIN);
- mHasSecondaryFocus = true;
- updateStates();
- }
- });
- mReleaseFocus.setOnClickListener(new View.OnClickListener() {
- @Override
- public void onClick(View v) {
- if (DBG) {
- Log.i(TAG, "Release secondary focus");
- }
- mAudioManager.abandonAudioFocus(mSecondaryFocusListener);
- mHasSecondaryFocus = false;
- updateStates();
- }
- });
- mRadioNext.setOnClickListener(new View.OnClickListener() {
- @Override
- public void onClick(View v) {
- if (DBG) {
- Log.i(TAG, "Next radio station");
- }
- if (mRadioTuner != null) {
- mRadioTuner.scan(RadioTuner.DIRECTION_UP, true);
- }
- updateStates();
- }
- });
- mRadioPrev.setOnClickListener(new View.OnClickListener() {
- @Override
- public void onClick(View v) {
- if (DBG) {
- Log.i(TAG, "Previous radio station");
- }
- if (mRadioTuner != null) {
- mRadioTuner.scan(RadioTuner.DIRECTION_DOWN, true);
- }
- updateStates();
- }
- });
- mRadioScanCancel.setOnClickListener(new View.OnClickListener() {
- @Override
- public void onClick(View v) {
- if (DBG) {
- Log.i(TAG, "Cancel radio scan");
- }
- if (mRadioTuner != null) {
- mRadioTuner.cancel();
- }
- updateStates();
- }
- });
- mRadioTuneToStation.setOnClickListener(new View.OnClickListener() {
- @Override
- public void onClick(View v) {
- if (DBG) {
- Log.i(TAG, "Tuning to station");
- }
- String station = mStationFrequency.getText().toString().trim();
- if (mRadioTuner != null && !(station.equals(""))) {
- mRadioTuner.tune(Integer.parseInt(station), 0);
- }
- resetMessages();
- updateMessages();
- updateStates();
- }
- });
- mRadioStepUp.setOnClickListener(new View.OnClickListener() {
- @Override
- public void onClick(View v) {
- if (DBG) {
- Log.i(TAG, "Step up");
- }
- if (mRadioTuner != null) {
- mRadioTuner.step(RadioTuner.DIRECTION_UP, false);
- }
- resetMessages();
- updateMessages();
- updateStates();
- }
- });
- mRadioStepDown.setOnClickListener(new View.OnClickListener() {
- @Override
- public void onClick(View v) {
- if (DBG) {
- Log.i(TAG, "Step down");
- }
- if (mRadioTuner != null) {
- mRadioTuner.step(RadioTuner.DIRECTION_DOWN, false);
- }
- resetMessages();
- updateMessages();
- updateStates();
- }
- });
- mRadioGetProgramInfo.setOnClickListener(new View.OnClickListener() {
- @Override
- public void onClick(View v) {
- if (DBG) {
- Log.i(TAG, "getProgramInformation");
- }
- if (mRadioTuner != null) {
- RadioManager.ProgramInfo[] programInfos = new RadioManager.ProgramInfo[1];
- mRadioTuner.getProgramInformation(programInfos);
- addLog(Log.INFO, "mRadioTuner.getProgramInformation() =>" + programInfos[0]);
- }
- }
- });
- mRadioBand.setOnCheckedChangeListener(new OnCheckedChangeListener() {
- @Override
- public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
- if (DBG) {
- Log.i(TAG, "Changing radio band");
- }
- if (mRadioTuner != null) {
- mRadioTuner.setConfiguration(mRadioBand.isChecked() ? mFmConfig : mAmConfig);
- }
- resetMessages();
- updateMessages();
- updateStates();
- }
- });
- }
-
- private void updateStates() {
- mOpenRadio.setEnabled(mRadioTuner == null);
- mCloseRadio.setEnabled(mRadioTuner != null);
- mToggleMuteRadio.setEnabled(mRadioTuner != null);
- mGetRadioFocus.setEnabled(!mHasRadioFocus);
- mReleaseRadioFocus.setEnabled(mHasRadioFocus);
- mGetFocus.setEnabled(!mHasSecondaryFocus);
- mReleaseFocus.setEnabled(mHasSecondaryFocus);
- mRadioNext.setEnabled(mRadioTuner != null);
- mRadioPrev.setEnabled(mRadioTuner != null);
- mRadioBand.setEnabled(mRadioTuner != null);
- mRadioScanCancel.setEnabled(mRadioTuner != null);
- mRadioTuneToStation.setEnabled(mRadioTuner != null);
- mRadioStepUp.setEnabled(mRadioTuner != null);
- mRadioStepDown.setEnabled(mRadioTuner != null);
- mStationFrequency.setEnabled(mRadioTuner != null);
- mRadioGetProgramInfo.setEnabled(mRadioTuner != null);
- }
-
- private void updateMessages() {
- mStationInfo.setText(getContext().getString
- (R.string.radio_station_info, mStation == null ? mNaString : mStation));
- mChannelInfo.setText(getContext().getString
- (R.string.radio_channel_info, mChannel == null ? mNaString : mChannel));
- mArtistInfo.setText(getContext().getString
- (R.string.radio_artist_info, mArtist == null ? mNaString : mArtist));
- mSongInfo.setText(getContext().getString
- (R.string.radio_song_info, mSong == null ? mNaString : mSong));
- }
-
- private void resetMessages() {
- mStation = null;
- mChannel = null;
- mSong = null;
- mArtist = null;
- }
-
- private void handleRadioStart() {
- if (mCarAudioManager == null) {
- return;
- }
- if (DBG) {
- Log.i(TAG, "Radio start");
- }
- if (mRadioTuner != null) {
- Log.w(TAG, "Radio tuner already open");
- mRadioTuner.close();
- mRadioTuner = null;
- }
- mRadioTuner = mRadioManager.openTuner(mModules.get(0).getId(),
- mRadioBand.isChecked() ? mFmConfig : mAmConfig,
- true, mRadioCallback /* callback */, null /* handler */);
- }
-
- private void handleRadioEnd() {
- if (mCarAudioManager == null) {
- return;
- }
- if (DBG) {
- Log.i(TAG, "Radio end");
- }
- mRadioTuner.close();
- mRadioTuner = null;
- }
-
- private void resetLog() {
- synchronized (this) {
- mLogMessages.clear();
- }
- }
-
- private void addLog(int priority, String message) {
- Log.println(priority, TAG, message);
- synchronized (this) {
- mLogMessages.add(message);
- if (mLogMessages.size() > MAX_LOG_MESSAGES) {
- mLogMessages.poll();
- }
- mLog.setText(TextUtils.join("\n", mLogMessages));
- }
- }
-}
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 d502c75..abc2c10 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
@@ -16,17 +16,18 @@
package com.google.android.car.kitchensink.sensor;
+import static java.lang.Integer.toHexString;
+
import android.Manifest;
import android.annotation.Nullable;
import android.car.Car;
+import android.car.CarNotConnectedException;
+import android.car.hardware.CarSensorConfig;
+import android.car.hardware.CarSensorEvent;
+import android.car.hardware.CarSensorManager;
import android.content.pm.PackageManager;
-import android.location.Location;
import android.os.Bundle;
import android.os.Handler;
-import android.support.car.CarNotConnectedException;
-import android.support.car.hardware.CarSensorConfig;
-import android.support.car.hardware.CarSensorEvent;
-import android.support.car.hardware.CarSensorManager;
import android.support.v4.app.Fragment;
import android.text.TextUtils;
import android.util.Log;
@@ -51,22 +52,22 @@
public class SensorsTestFragment extends Fragment {
private static final String TAG = "CAR.SENSOR.KS";
private static final boolean DBG = true;
- private static final boolean DBG_VERBOSE = false;
+ private static final boolean DBG_VERBOSE = true;
private static final int KS_PERMISSIONS_REQUEST = 1;
private final static String[] REQUIRED_PERMISSIONS = new String[]{
Manifest.permission.ACCESS_FINE_LOCATION,
Manifest.permission.ACCESS_COARSE_LOCATION,
Car.PERMISSION_MILEAGE,
- Car.PERMISSION_FUEL,
+ Car.PERMISSION_ENERGY,
Car.PERMISSION_SPEED,
- Car.PERMISSION_VEHICLE_DYNAMICS_STATE
+ Car.PERMISSION_CAR_DYNAMICS_STATE
};
private final CarSensorManager.OnSensorChangedListener mOnSensorChangedListener =
new CarSensorManager.OnSensorChangedListener() {
@Override
- public void onSensorChanged(CarSensorManager manager, CarSensorEvent event) {
+ public void onSensorChanged(CarSensorEvent event) {
if (DBG_VERBOSE) {
Log.v(TAG, "New car sensor event: " + event);
}
@@ -88,7 +89,6 @@
private int[] supportedSensors = new int[0];
private Set<String> mActivePermissions = new HashSet<String>();
-
@Nullable
@Override
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container,
@@ -116,26 +116,23 @@
public void onPause() {
super.onPause();
if (mSensorManager != null) {
- mSensorManager.removeListener(mOnSensorChangedListener);
+ mSensorManager.unregisterListener(mOnSensorChangedListener);
}
}
private void initSensors() {
try {
- mSensorManager = (CarSensorManager)
- mActivity.getCar().getCarManager(Car.SENSOR_SERVICE);
+ mSensorManager =
+ (CarSensorManager) ((KitchenSinkActivity) getActivity()).getSensorManager();
supportedSensors = mSensorManager.getSupportedSensors();
for (Integer sensor : supportedSensors) {
- if ((sensor == CarSensorManager.SENSOR_TYPE_LOCATION
- || sensor == CarSensorManager.SENSOR_TYPE_GPS_SATELLITE)
- && !mActivePermissions.contains(Manifest.permission.ACCESS_FINE_LOCATION)) {
- continue;
- }
- mSensorManager.addListener(mOnSensorChangedListener, sensor,
+ mSensorManager.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);
}
}
@@ -189,73 +186,48 @@
for (Integer i : supportedSensors) {
CarSensorEvent event = mEventMap.get(i);
switch (i) {
- case CarSensorManager.SENSOR_TYPE_COMPASS:
- summary.add(getCompassString(event));
- break;
case CarSensorManager.SENSOR_TYPE_CAR_SPEED:
summary.add(getContext().getString(R.string.sensor_speed,
getTimestamp(event),
- event == null ? mNaString : event.getCarSpeedData().carSpeed));
+ event == null ? mNaString : event.getCarSpeedData(null).carSpeed));
break;
case CarSensorManager.SENSOR_TYPE_RPM:
summary.add(getContext().getString(R.string.sensor_rpm,
getTimestamp(event),
- event == null ? mNaString : event.getRpmData().rpm));
+ event == null ? mNaString : event.getRpmData(null).rpm));
break;
case CarSensorManager.SENSOR_TYPE_ODOMETER:
summary.add(getContext().getString(R.string.sensor_odometer,
getTimestamp(event),
- event == null ? mNaString : event.getOdometerData().kms));
+ event == null ? mNaString : event.getOdometerData(null).kms));
break;
case CarSensorManager.SENSOR_TYPE_FUEL_LEVEL:
- String level = mNaString;
- String range = mNaString;
- String lowFuelWarning = mNaString;
- if (event != null) {
- CarSensorEvent.FuelLevelData fuelData = event.getFuelLevelData();
- level = fuelData.level == -1 ? level : String.valueOf(fuelData.level);
- range = fuelData.range == -1 ? range : String.valueOf(fuelData.range);
- lowFuelWarning = String.valueOf(fuelData.lowFuelWarning);
- }
- summary.add(getContext().getString(R.string.sensor_fuel_level,
- getTimestamp(event), level, range, lowFuelWarning));
+ summary.add(getFuelLevel(event));
+ break;
+ case CarSensorManager.SENSOR_TYPE_FUEL_DOOR_OPEN:
+ summary.add(getFuelDoorOpen(event));
break;
case CarSensorManager.SENSOR_TYPE_PARKING_BRAKE:
summary.add(getContext().getString(R.string.sensor_parking_brake,
getTimestamp(event),
event == null ? mNaString :
- event.getParkingBrakeData().isEngaged));
+ event.getParkingBrakeData(null).isEngaged));
break;
case CarSensorManager.SENSOR_TYPE_GEAR:
summary.add(getContext().getString(R.string.sensor_gear,
getTimestamp(event),
- event == null ? mNaString : event.getGearData().gear));
+ event == null ? mNaString : event.getGearData(null).gear));
break;
case CarSensorManager.SENSOR_TYPE_NIGHT:
summary.add(getContext().getString(R.string.sensor_night,
getTimestamp(event),
- event == null ? mNaString : event.getNightData().isNightMode));
- break;
- case CarSensorManager.SENSOR_TYPE_LOCATION:
- summary.add(getLocationString(event));
- break;
- case CarSensorManager.SENSOR_TYPE_DRIVING_STATUS:
- String drivingStatus = mNaString;
- String binDrivingStatus = mNaString;
- if (event != null) {
- CarSensorEvent.DrivingStatusData drivingStatusData =
- event.getDrivingStatusData();
- drivingStatus = String.valueOf(drivingStatusData.status);
- binDrivingStatus = Integer.toBinaryString(drivingStatusData.status);
- }
- summary.add(getContext().getString(R.string.sensor_driving_status,
- getTimestamp(event), drivingStatus, binDrivingStatus));
+ event == null ? mNaString : event.getNightData(null).isNightMode));
break;
case CarSensorManager.SENSOR_TYPE_ENVIRONMENT:
String temperature = mNaString;
String pressure = mNaString;
if (event != null) {
- CarSensorEvent.EnvironmentData env = event.getEnvironmentData();
+ CarSensorEvent.EnvironmentData env = event.getEnvironmentData(null);
temperature = Float.isNaN(env.temperature) ? temperature :
String.valueOf(env.temperature);
pressure = Float.isNaN(env.pressure) ? pressure :
@@ -264,19 +236,10 @@
summary.add(getContext().getString(R.string.sensor_environment,
getTimestamp(event), temperature, pressure));
break;
- case CarSensorManager.SENSOR_TYPE_ACCELEROMETER:
- summary.add(getAccelerometerString(event));
- break;
- case CarSensorManager.SENSOR_TYPE_GPS_SATELLITE:
- summary.add(getGpsSatelliteString(event));
- break;
- case CarSensorManager.SENSOR_TYPE_GYROSCOPE:
- summary.add(getGyroscopeString(event));
- break;
case CarSensorManager.SENSOR_TYPE_WHEEL_TICK_DISTANCE:
if(event != null) {
CarSensorEvent.CarWheelTickDistanceData d =
- event.getCarWheelTickDistanceData();
+ event.getCarWheelTickDistanceData(null);
summary.add(getContext().getString(R.string.sensor_wheel_ticks,
getTimestamp(event), d.sensorResetCount, d.frontLeftWheelDistanceMm,
d.frontRightWheelDistanceMm, d.rearLeftWheelDistanceMm,
@@ -303,18 +266,31 @@
case CarSensorManager.SENSOR_TYPE_ABS_ACTIVE:
summary.add(getContext().getString(R.string.sensor_abs_is_active,
getTimestamp(event), event == null ? mNaString :
- event.getCarAbsActiveData().absIsActive));
+ event.getCarAbsActiveData(null).absIsActive));
break;
case CarSensorManager.SENSOR_TYPE_TRACTION_CONTROL_ACTIVE:
summary.add(
getContext().getString(R.string.sensor_traction_control_is_active,
getTimestamp(event), event == null ? mNaString :
- event.getCarTractionControlActiveData().tractionControlIsActive));
+ event.getCarTractionControlActiveData(null)
+ .tractionControlIsActive));
+ break;
+ case CarSensorManager.SENSOR_TYPE_EV_BATTERY_LEVEL:
+ summary.add(getEvBatteryLevel(event));
+ break;
+ case CarSensorManager.SENSOR_TYPE_EV_CHARGE_PORT_OPEN:
+ summary.add(getEvChargePortOpen(event));
+ break;
+ case CarSensorManager.SENSOR_TYPE_EV_CHARGE_PORT_CONNECTED:
+ summary.add(getEvChargePortConnected(event));
+ break;
+ case CarSensorManager.SENSOR_TYPE_EV_BATTERY_CHARGE_RATE:
+ summary.add(getEvChargeRate(event));
break;
default:
// Should never happen.
- Log.w(TAG, "Unrecognized event type: " + i);
+ Log.w(TAG, "Unrecognized event type: " + toHexString(i));
}
}
summaryString = TextUtils.join("\n", summary);
@@ -331,89 +307,61 @@
if (event == null) {
return mNaString;
}
- return mDateFormat.format(new Date(event.timestamp / 1000L));
+ return mDateFormat.format(new Date(event.timestamp / (1000L * 1000L)));
}
- private String getCompassString(CarSensorEvent event) {
- String bear = mNaString;
- String pitch = mNaString;
- String roll = mNaString;
- if (event != null) {
- CarSensorEvent.CompassData compass = event.getCompassData();
- bear = Float.isNaN(compass.bearing) ? bear : String.valueOf(compass.bearing);
- pitch = Float.isNaN(compass.pitch) ? pitch : String.valueOf(compass.pitch);
- roll = Float.isNaN(compass.roll) ? roll : String.valueOf(compass.roll);
+ private String getFuelLevel(CarSensorEvent event) {
+ String fuelLevel = mNaString;
+ if(event != null) {
+ fuelLevel = String.valueOf(event.getFuelLevelData(null).level);
}
- return getContext().getString(R.string.sensor_compass,
- getTimestamp(event), bear, pitch, roll);
+ return getContext().getString(R.string.sensor_fuel_level, getTimestamp(event), fuelLevel);
}
- private String getGyroscopeString(CarSensorEvent event) {
- String x = mNaString;
- String y = mNaString;
- String z = mNaString;
- if (event != null) {
- CarSensorEvent.GyroscopeData gyro = event.getGyroscopeData();
- x = Float.isNaN(gyro.x) ? x : String.valueOf(gyro.x);
- y = Float.isNaN(gyro.y) ? y : String.valueOf(gyro.y);
- z = Float.isNaN(gyro.z) ? z : String.valueOf(gyro.z);
+ private String getFuelDoorOpen(CarSensorEvent event) {
+ String fuelDoorOpen = mNaString;
+ if(event != null) {
+ fuelDoorOpen = String.valueOf(event.getCarFuelDoorOpenData(null).fuelDoorIsOpen);
}
- return getContext().getString(R.string.sensor_gyroscope,
- getTimestamp(event), x, y, z);
+ return getContext().getString(R.string.sensor_fuel_door_open, getTimestamp(event),
+ fuelDoorOpen);
}
- private String getAccelerometerString(CarSensorEvent event) {
- String x = mNaString;
- String y = mNaString;
- String z = mNaString;
- if (event != null) {
- CarSensorEvent.AccelerometerData gyro = event.getAccelerometerData();
- x = Float.isNaN(gyro.x) ? x : String.valueOf(gyro.x);
- y = Float.isNaN(gyro.y) ? y : String.valueOf(gyro.y);
- z = Float.isNaN(gyro.z) ? z : String.valueOf(gyro.z);
+ private String getEvBatteryLevel(CarSensorEvent event) {
+ String evBatteryLevel = mNaString;
+ if(event != null) {
+ evBatteryLevel = String.valueOf(event.getCarEvBatteryLevelData(null).evBatteryLevel);
}
- return getContext().getString(R.string.sensor_accelerometer,
- getTimestamp(event), x, y, z);
+ return getContext().getString(R.string.sensor_ev_battery_level, getTimestamp(event),
+ evBatteryLevel);
}
- private String getLocationString(CarSensorEvent event) {
- String lat = mNaString;
- String lon = mNaString;
- String accuracy = mNaString;
- String alt = mNaString;
- String speed = mNaString;
- String bearing = mNaString;
- if (event != null) {
- Location location = event.getLocation(null);
- lat = String.valueOf(location.getLatitude());
- lon = String.valueOf(location.getLongitude());
- accuracy = location.hasAccuracy() ? String.valueOf(location.getAccuracy()) : accuracy;
- alt = location.hasAltitude() ? String.valueOf(location.getAltitude()) : alt;
- speed = location.hasSpeed() ? String.valueOf(location.getSpeed()) : speed;
- bearing = location.hasBearing() ? String.valueOf(location.getBearing()) : bearing;
+ private String getEvChargePortOpen(CarSensorEvent event) {
+ String evChargePortOpen = mNaString;
+ if(event != null) {
+ evChargePortOpen = String.valueOf(
+ event.getCarEvChargePortOpenData(null).evChargePortIsOpen);
}
- return getContext().getString(R.string.sensor_location,
- getTimestamp(event), lat, lon, accuracy, alt, speed, bearing);
+ return getContext().getString(R.string.sensor_ev_charge_port_is_open, getTimestamp(event),
+ evChargePortOpen);
}
- private String getGpsSatelliteString(CarSensorEvent event) {
- String inUse = mNaString;
- String inView = mNaString;
- String perSattelite = "";
- if (event != null) {
- CarSensorEvent.GpsSatelliteData gpsData = event.getGpsSatelliteData(true);
- inUse = gpsData.numberInUse != -1 ? String.valueOf(gpsData.numberInUse) : inUse;
- inView = gpsData.numberInView != -1 ? String.valueOf(gpsData.numberInView) : inView;
- List<String> perSatteliteList = new ArrayList<>();
- int num = gpsData.usedInFix.length;
- for (int i=0; i<num; i++) {
- perSatteliteList.add(getContext().getString(R.string.sensor_single_gps_satellite,
- i+1, gpsData.usedInFix[i], gpsData.prn[i], gpsData.snr[i],
- gpsData.azimuth[i], gpsData.elevation[i]));
- }
- perSattelite = TextUtils.join(", ", perSatteliteList);
+ private String getEvChargePortConnected(CarSensorEvent event) {
+ String evChargePortConnected = mNaString;
+ if(event != null) {
+ evChargePortConnected = String.valueOf(
+ event.getCarEvChargePortConnectedData(null).evChargePortIsConnected);
}
- return getContext().getString(R.string.sensor_gps,
- getTimestamp(event), inView, inUse, perSattelite);
+ return getContext().getString(R.string.sensor_ev_charge_port_is_connected,
+ getTimestamp(event), evChargePortConnected);
+ }
+
+ private String getEvChargeRate(CarSensorEvent event) {
+ String evChargeRate = mNaString;
+ if(event != null) {
+ evChargeRate = String.valueOf(event.getCarEvBatteryChargeRateData(null).evChargeRate);
+ }
+ return getContext().getString(R.string.sensor_ev_charge_rate, getTimestamp(event),
+ evChargeRate);
}
}
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
index df191b8..4ace656 100644
--- a/tests/EmbeddedKitchenSinkApp/src/com/google/android/car/kitchensink/setting/GarageModeSettingsFragment.java
+++ b/tests/EmbeddedKitchenSinkApp/src/com/google/android/car/kitchensink/setting/GarageModeSettingsFragment.java
@@ -15,6 +15,13 @@
*/
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;
@@ -33,13 +40,6 @@
import java.sql.Time;
-import static android.car.settings.CarSettings.Global.KEY_GARAGE_MODE_MAINTENANCE_WINDOW;
-import static android.car.settings.CarSettings.Global.KEY_GARAGE_MODE_ENABLED;
-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_WAKE_UP_TIME_URI;
-import static android.car.settings.GarageModeSettingsObserver.GARAGE_MODE_MAINTENANCE_WINDOW_URI;
-
public class GarageModeSettingsFragment extends PreferenceFragment implements
TimePickerDialog.OnTimeSetListener, Preference.OnPreferenceChangeListener {
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
new file mode 100644
index 0000000..fc4052e
--- /dev/null
+++ b/tests/EmbeddedKitchenSinkApp/src/com/google/android/car/kitchensink/storagelifetime/StorageLifetimeFragment.java
@@ -0,0 +1,244 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.google.android.car.kitchensink.storagelifetime;
+
+import static android.system.OsConstants.O_APPEND;
+import static android.system.OsConstants.O_RDWR;
+
+import android.annotation.Nullable;
+import android.car.Car;
+import android.car.CarNotConnectedException;
+import android.car.storagemonitoring.CarStorageMonitoringManager;
+import android.car.storagemonitoring.CarStorageMonitoringManager.IoStatsListener;
+import android.car.storagemonitoring.IoStats;
+import android.car.storagemonitoring.IoStatsEntry;
+import android.os.Bundle;
+import android.os.StatFs;
+import android.support.v4.app.Fragment;
+import android.system.ErrnoException;
+import android.util.Log;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.ArrayAdapter;
+import android.widget.ListView;
+import android.widget.TextView;
+
+import com.google.android.car.kitchensink.KitchenSinkActivity;
+import com.google.android.car.kitchensink.R;
+
+import libcore.io.Libcore;
+
+import java.io.File;
+import java.io.FileDescriptor;
+import java.io.IOException;
+import java.nio.ByteBuffer;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.StandardOpenOption;
+import java.security.NoSuchAlgorithmException;
+import java.security.SecureRandom;
+import java.util.List;
+
+public class StorageLifetimeFragment extends Fragment {
+ private static final String FILE_NAME = "storage.bin";
+ private static final String TAG = "CAR.STORAGELIFETIME.KS";
+
+ private static final int KILOBYTE = 1024;
+ private static final int MEGABYTE = 1024 * 1024;
+
+ private StatFs mStatFs;
+ private KitchenSinkActivity mActivity;
+ private TextView mStorageWearInfo;
+ private ListView mStorageChangesHistory;
+ private TextView mFreeSpaceInfo;
+ private TextView mIoActivity;
+ private CarStorageMonitoringManager mStorageManager;
+
+ private final IoStatsListener mIoListener = new IoStatsListener() {
+ @Override
+ public void onSnapshot(IoStats snapshot) {
+ if (mIoActivity != null) {
+ mIoActivity.setText("");
+ snapshot.getStats().forEach(uidIoStats -> {
+ final long bytesWrittenToStorage = uidIoStats.foreground.bytesWrittenToStorage +
+ uidIoStats.background.bytesWrittenToStorage;
+ final long fsyncCalls = uidIoStats.foreground.fsyncCalls +
+ uidIoStats.background.fsyncCalls;
+ if (bytesWrittenToStorage > 0 || fsyncCalls > 0) {
+ mIoActivity.append(String.format(
+ "uid = %d, runtime = %d, bytes writen to disk = %d, fsync calls = %d\n",
+ uidIoStats.uid,
+ uidIoStats.runtimeMillis,
+ bytesWrittenToStorage,
+ fsyncCalls));
+ }
+ });
+ final List<IoStatsEntry> totals;
+ try {
+ totals = mStorageManager.getAggregateIoStats();
+ } catch (CarNotConnectedException e) {
+ Log.e(TAG, "Car not connected or not supported", e);
+ return;
+ }
+
+ final long totalBytesWrittenToStorage = totals.stream()
+ .mapToLong(stats -> stats.foreground.bytesWrittenToStorage +
+ stats.background.bytesWrittenToStorage)
+ .reduce(0L, (x,y)->x+y);
+ final long totalFsyncCalls = totals.stream()
+ .mapToLong(stats -> stats.foreground.fsyncCalls +
+ stats.background.fsyncCalls)
+ .reduce(0L, (x,y)->x+y);
+
+ mIoActivity.append(String.format(
+ "total bytes written to disk = %d, total fsync calls = %d",
+ totalBytesWrittenToStorage,
+ totalFsyncCalls));
+ }
+ }
+ };
+
+ // TODO(egranata): put this somewhere more useful than KitchenSink
+ private static String preEolToString(int preEol) {
+ switch (preEol) {
+ case 1: return "normal";
+ case 2: return "warning";
+ case 3: return "urgent";
+ default:
+ return "unknown";
+ }
+ }
+
+ private Path getFilePath() throws IOException {
+ Path filePath = new File(mActivity.getFilesDir(), FILE_NAME).toPath();
+ if (Files.notExists(filePath)) {
+ Files.createFile(filePath);
+ }
+ return filePath;
+ }
+
+ private void writeBytesToFile(int size) {
+ try {
+ final Path filePath = getFilePath();
+ byte[] data = new byte[size];
+ SecureRandom.getInstanceStrong().nextBytes(data);
+ Files.write(filePath,
+ data,
+ StandardOpenOption.APPEND);
+ } catch (NoSuchAlgorithmException | IOException e) {
+ Log.w(TAG, "could not append data", e);
+ }
+ }
+
+ private void fsyncFile() {
+ try {
+ final Path filePath = getFilePath();
+ FileDescriptor fd = Libcore.os.open(filePath.toString(), O_APPEND | O_RDWR, 0);
+ if (!fd.valid()) {
+ Log.w(TAG, "file descriptor is invalid");
+ return;
+ }
+ // fill byteBuffer with arbitrary data in order to make an fsync() meaningful
+ ByteBuffer byteBuffer = ByteBuffer.wrap(new byte[] {101, 110, 114, 105, 99, 111});
+ Libcore.os.write(fd, byteBuffer);
+ Libcore.os.fsync(fd);
+ Libcore.os.close(fd);
+ } catch (ErrnoException | IOException e) {
+ Log.w(TAG, "could not fsync data", e);
+ }
+ }
+
+ @Nullable
+ @Override
+ public View onCreateView(
+ LayoutInflater inflater,
+ @Nullable ViewGroup container,
+ @Nullable Bundle savedInstanceState) {
+ View view = inflater.inflate(R.layout.storagewear, container, false);
+ mActivity = (KitchenSinkActivity) getHost();
+ mStorageWearInfo = view.findViewById(R.id.storage_wear_info);
+ mStorageChangesHistory = view.findViewById(R.id.storage_events_list);
+ mFreeSpaceInfo = view.findViewById(R.id.free_disk_space);
+ mIoActivity = view.findViewById(R.id.last_io_snapshot);
+
+ view.findViewById(R.id.write_one_kilobyte).setOnClickListener(
+ v -> writeBytesToFile(KILOBYTE));
+
+ view.findViewById(R.id.write_one_megabyte).setOnClickListener(
+ v -> writeBytesToFile(MEGABYTE));
+
+ view.findViewById(R.id.perform_fsync).setOnClickListener(
+ v -> fsyncFile());
+
+ return view;
+ }
+
+ private void reloadInfo() {
+ try {
+ mStatFs = new StatFs(mActivity.getFilesDir().getAbsolutePath());
+
+ mStorageManager =
+ (CarStorageMonitoringManager) mActivity.getCar().getCarManager(
+ Car.STORAGE_MONITORING_SERVICE);
+
+ mStorageWearInfo.setText("Wear estimate: " +
+ mStorageManager.getWearEstimate() + "\nPre EOL indicator: " +
+ preEolToString(mStorageManager.getPreEolIndicatorStatus()));
+
+ mStorageChangesHistory.setAdapter(new ArrayAdapter(mActivity,
+ R.layout.wear_estimate_change_textview,
+ mStorageManager.getWearEstimateHistory().toArray()));
+
+ mFreeSpaceInfo.setText("Available blocks: " + mStatFs.getAvailableBlocksLong() +
+ "\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) {
+ Log.e(TAG, "Car not connected or not supported", e);
+ }
+ }
+
+ private void registerListener() {
+ try {
+ mStorageManager.registerListener(mIoListener);
+ } catch (CarNotConnectedException e) {
+ Log.e(TAG, "Car not connected or not supported", e);
+ }
+ }
+
+ private void unregisterListener() {
+ try {
+ mStorageManager.unregisterListener(mIoListener);
+ } catch (CarNotConnectedException e) {
+ Log.e(TAG, "Car not connected or not supported", e);
+ }
+ }
+
+ @Override
+ public void onResume() {
+ super.onResume();
+ reloadInfo();
+ registerListener();
+ }
+
+ @Override
+ public void onPause() {
+ unregisterListener();
+ super.onPause();
+ }
+}
diff --git a/tests/EmbeddedKitchenSinkApp/src/com/google/android/car/kitchensink/touchsound/DisableTouchSoundOnBoot.java b/tests/EmbeddedKitchenSinkApp/src/com/google/android/car/kitchensink/touchsound/DisableTouchSoundOnBoot.java
new file mode 100644
index 0000000..2c81bda
--- /dev/null
+++ b/tests/EmbeddedKitchenSinkApp/src/com/google/android/car/kitchensink/touchsound/DisableTouchSoundOnBoot.java
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.google.android.car.kitchensink.touchsound;
+
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.provider.Settings;
+import android.util.Log;
+
+/**
+ * Temp solution until b/68882625 is fixed
+ */
+public class DisableTouchSoundOnBoot extends BroadcastReceiver {
+
+ private static final String KEY_TOUCH_SOUNDS = "sound_effects_enabled";
+
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ Log.w("DisableTouchSoundOnBoot", "disabling touch sound");
+ Settings.System.putInt(context.getContentResolver(), KEY_TOUCH_SOUNDS, 0);
+ }
+}
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
new file mode 100644
index 0000000..ac62505
--- /dev/null
+++ b/tests/EmbeddedKitchenSinkApp/src/com/google/android/car/kitchensink/vhal/VehicleHalFragment.java
@@ -0,0 +1,144 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.google.android.car.kitchensink.vhal;
+
+import android.annotation.Nullable;
+import android.app.AlertDialog;
+import android.content.DialogInterface;
+import android.content.DialogInterface.OnClickListener;
+import android.hardware.automotive.vehicle.V2_0.IVehicle;
+import android.hardware.automotive.vehicle.V2_0.VehiclePropConfig;
+import android.hardware.automotive.vehicle.V2_0.VehicleProperty;
+import android.os.Bundle;
+import android.os.RemoteException;
+import android.support.v4.app.Fragment;
+import android.util.Log;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.AdapterView;
+import android.widget.AdapterView.OnItemClickListener;
+import android.widget.ArrayAdapter;
+import android.widget.ListView;
+
+import com.google.android.car.kitchensink.KitchenSinkActivity;
+import com.google.android.car.kitchensink.R;
+
+import java.util.List;
+import java.util.Objects;
+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,
+ @Nullable ViewGroup container,
+ @Nullable Bundle savedInstanceState) {
+ 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;
+ }
+
+ @Override
+ public void onResume() {
+ super.onResume();
+
+ final IVehicle vehicle;
+ try {
+ vehicle = Objects.requireNonNull(IVehicle.getService());
+ } catch (NullPointerException | RemoteException e) {
+ Log.e(TAG, "unable to retrieve Vehicle HAL service", e);
+ return;
+ }
+
+ final List<VehiclePropConfig> propConfigList;
+ try {
+ propConfigList = Objects.requireNonNull(vehicle.getAllPropConfigs());
+ } catch (NullPointerException | RemoteException e) {
+ Log.e(TAG, "unable to retrieve prop configs", e);
+ return;
+ }
+
+ final List<HalPropertyInfo> supportedProperties = propConfigList.stream()
+ .map(HalPropertyInfo::new)
+ .sorted()
+ .collect(Collectors.toList());
+
+ mListView.setAdapter(new ArrayAdapter<HalPropertyInfo>(mActivity,
+ android.R.layout.simple_list_item_1,
+ supportedProperties));
+ }
+
+ private static class HalPropertyInfo implements Comparable<HalPropertyInfo> {
+ public final int id;
+ public final String name;
+ public final VehiclePropConfig config;
+
+ HalPropertyInfo(VehiclePropConfig config) {
+ this.config = config;
+ id = config.prop;
+ name = VehicleProperty.toString(id);
+ }
+
+ @Override
+ public String toString() {
+ return name;
+ }
+
+ @Override
+ public boolean equals(Object other) {
+ if (other instanceof HalPropertyInfo) {
+ return ((HalPropertyInfo)other).id == id;
+ }
+ return false;
+ }
+
+ @Override
+ public int hashCode() {
+ return id;
+ }
+
+ @Override
+ public int compareTo(HalPropertyInfo halPropertyInfo) {
+ return name.compareTo(halPropertyInfo.name);
+ }
+ }
+}
diff --git a/tests/EmbeddedKitchenSinkApp/src/com/google/android/car/kitchensink/volume/VolumeAdapter.java b/tests/EmbeddedKitchenSinkApp/src/com/google/android/car/kitchensink/volume/VolumeAdapter.java
index c66d242..ec071dc 100644
--- a/tests/EmbeddedKitchenSinkApp/src/com/google/android/car/kitchensink/volume/VolumeAdapter.java
+++ b/tests/EmbeddedKitchenSinkApp/src/com/google/android/car/kitchensink/volume/VolumeAdapter.java
@@ -36,13 +36,13 @@
private VolumeTestFragment mFragment;
- public VolumeAdapter(Context c, int layoutResourceId, VolumeInfo[] locations,
+ public VolumeAdapter(Context c, int layoutResourceId, VolumeInfo[] volumeList,
VolumeTestFragment fragment) {
- super(c, layoutResourceId, locations);
+ super(c, layoutResourceId, volumeList);
mFragment = fragment;
mContext = c;
this.mLayoutResourceId = layoutResourceId;
- this.mVolumeList = locations;
+ this.mVolumeList = volumeList;
}
@Override
@@ -51,14 +51,12 @@
if (convertView == null) {
LayoutInflater inflater = LayoutInflater.from(mContext);
convertView = inflater.inflate(mLayoutResourceId, parent, false);
- vh.id = (TextView) convertView.findViewById(R.id.stream_id);
- vh.maxVolume = (TextView) convertView.findViewById(R.id.volume_limit);
- vh.currentVolume = (TextView) convertView.findViewById(R.id.current_volume);
- vh.logicalVolume = (TextView) convertView.findViewById(R.id.logical_volume);
- vh.logicalMax = (TextView) convertView.findViewById(R.id.logical_max);
- vh.upButton = (Button) convertView.findViewById(R.id.volume_up);
- vh.downButton = (Button) convertView.findViewById(R.id.volume_down);
- vh.requestButton = (Button) convertView.findViewById(R.id.request);
+ vh.id = convertView.findViewById(R.id.stream_id);
+ vh.maxVolume = convertView.findViewById(R.id.volume_limit);
+ vh.currentVolume = convertView.findViewById(R.id.current_volume);
+ vh.upButton = convertView.findViewById(R.id.volume_up);
+ vh.downButton = convertView.findViewById(R.id.volume_down);
+ vh.requestButton = convertView.findViewById(R.id.request);
convertView.setTag(vh);
} else {
vh = (ViewHolder) convertView.getTag();
@@ -67,8 +65,6 @@
vh.id.setText(mVolumeList[position].mId);
vh.maxVolume.setText(String.valueOf(mVolumeList[position].mMax));
vh.currentVolume.setText(String.valueOf(mVolumeList[position].mCurrent));
- vh.logicalVolume.setText(String.valueOf(mVolumeList[position].mLogicalCurrent));
- vh.logicalMax.setText(String.valueOf(mVolumeList[position].mLogicalMax));
int color = mVolumeList[position].mHasFocus ? Color.GREEN : Color.GRAY;
vh.requestButton.setBackgroundColor(color);
if (position == 0) {
@@ -79,25 +75,15 @@
vh.upButton.setVisibility(View.VISIBLE);
vh.downButton.setVisibility(View.VISIBLE);
vh.requestButton.setVisibility(View.VISIBLE);
- vh.upButton.setOnClickListener(new View.OnClickListener() {
- @Override
- public void onClick(View view) {
- mFragment.adjustVolumeByOne(mVolumeList[position].logicalStream, true);
- }
+ vh.upButton.setOnClickListener((view) -> {
+ mFragment.adjustVolumeByOne(mVolumeList[position].mGroupId, true);
+ });
+ vh.downButton.setOnClickListener((view) -> {
+ mFragment.adjustVolumeByOne(mVolumeList[position].mGroupId, false);
});
- vh.downButton.setOnClickListener(new View.OnClickListener() {
- @Override
- public void onClick(View view) {
- mFragment.adjustVolumeByOne(mVolumeList[position].logicalStream, false);
- }
- });
-
- vh.requestButton.setOnClickListener(new View.OnClickListener() {
- @Override
- public void onClick(View view) {
- mFragment.requestFocus(mVolumeList[position].logicalStream);
- }
+ vh.requestButton.setOnClickListener((view) -> {
+ mFragment.requestFocus(mVolumeList[position].mGroupId);
});
}
}
@@ -119,8 +105,6 @@
TextView id;
TextView maxVolume;
TextView currentVolume;
- TextView logicalMax;
- TextView logicalVolume;
Button upButton;
Button downButton;
Button requestButton;
diff --git a/tests/EmbeddedKitchenSinkApp/src/com/google/android/car/kitchensink/volume/VolumeTestFragment.java b/tests/EmbeddedKitchenSinkApp/src/com/google/android/car/kitchensink/volume/VolumeTestFragment.java
index 0d65500..800d650 100644
--- a/tests/EmbeddedKitchenSinkApp/src/com/google/android/car/kitchensink/volume/VolumeTestFragment.java
+++ b/tests/EmbeddedKitchenSinkApp/src/com/google/android/car/kitchensink/volume/VolumeTestFragment.java
@@ -18,46 +18,41 @@
import android.car.Car;
import android.car.CarNotConnectedException;
import android.car.media.CarAudioManager;
+import android.content.ComponentName;
import android.content.Context;
+import android.content.ServiceConnection;
import android.media.AudioManager;
-import android.media.IVolumeController;
import android.os.Bundle;
import android.os.Handler;
+import android.os.IBinder;
import android.os.Message;
-import android.os.RemoteException;
import android.support.annotation.Nullable;
import android.support.v4.app.Fragment;
import android.util.Log;
import android.util.SparseIntArray;
-import android.view.KeyEvent;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
-import android.widget.Button;
import android.widget.ListView;
+import android.widget.SeekBar;
-import com.google.android.car.kitchensink.CarEmulator;
import com.google.android.car.kitchensink.R;
-public class VolumeTestFragment extends Fragment{
+public class VolumeTestFragment extends Fragment {
private static final String TAG = "CarVolumeTest";
private static final int MSG_VOLUME_CHANGED = 0;
private static final int MSG_REQUEST_FOCUS = 1;
private static final int MSG_FOCUS_CHANGED= 2;
- private ListView mVolumeList;
- private Button mRefreshButton;
private AudioManager mAudioManager;
private VolumeAdapter mAdapter;
private CarAudioManager mCarAudioManager;
private Car mCar;
- private CarEmulator mCarEmulator;
- private Button mVolumeUp;
- private Button mVolumeDown;
+ private SeekBar mFader;
+ private SeekBar mBalance;
- private final VolumeController mVolumeController = new VolumeController();
private final Handler mHandler = new VolumeHandler();
private class VolumeHandler extends Handler {
@@ -70,20 +65,20 @@
initVolumeInfo();
break;
case MSG_REQUEST_FOCUS:
- int stream = msg.arg1;
+ int groupId = msg.arg1;
if (mFocusListener != null) {
mAudioManager.abandonAudioFocus(mFocusListener);
- mVolumeInfos[mStreamIndexMap.get(stream)].mHasFocus = false;
+ mVolumeInfos[mGroupIdIndexMap.get(groupId)].mHasFocus = false;
mAdapter.notifyDataSetChanged();
}
- mFocusListener = new AudioFocusListener(stream);
- mAudioManager.requestAudioFocus(mFocusListener, stream,
+ mFocusListener = new AudioFocusListener(groupId);
+ mAudioManager.requestAudioFocus(mFocusListener, groupId,
AudioManager.AUDIOFOCUS_GAIN);
break;
case MSG_FOCUS_CHANGED:
- int focusStream = msg.arg1;
- mVolumeInfos[mStreamIndexMap.get(focusStream)].mHasFocus = true;
+ int focusGroupId = msg.arg1;
+ mVolumeInfos[mGroupIdIndexMap.get(focusGroupId)].mHasFocus = true;
mAdapter.refreshVolumes(mVolumeInfos);
break;
@@ -91,18 +86,18 @@
}
}
- private VolumeInfo[] mVolumeInfos = new VolumeInfo[LOGICAL_STREAMS.length + 1];
- private SparseIntArray mStreamIndexMap = new SparseIntArray(LOGICAL_STREAMS.length);
+ private VolumeInfo[] mVolumeInfos = new VolumeInfo[0];
+ private SparseIntArray mGroupIdIndexMap = new SparseIntArray();
private class AudioFocusListener implements AudioManager.OnAudioFocusChangeListener {
- private final int mStream;
- public AudioFocusListener(int stream) {
- mStream = stream;
+ private final int mGroupId;
+ public AudioFocusListener(int groupId) {
+ mGroupId = groupId;
}
@Override
public void onAudioFocusChange(int focusChange) {
if (focusChange == AudioManager.AUDIOFOCUS_GAIN) {
- mHandler.sendMessage(mHandler.obtainMessage(MSG_FOCUS_CHANGED, mStream, 0));
+ mHandler.sendMessage(mHandler.obtainMessage(MSG_FOCUS_CHANGED, mGroupId, 0));
} else {
Log.e(TAG, "Audio focus request failed");
}
@@ -110,158 +105,127 @@
}
public static class VolumeInfo {
- public int logicalStream;
+ public int mGroupId;
public String mId;
public String mMax;
public String mCurrent;
- public String mLogicalMax;
- public String mLogicalCurrent;
public boolean mHasFocus;
}
- private static final int LOGICAL_STREAMS[] = {
- AudioManager.STREAM_MUSIC,
- AudioManager.STREAM_ALARM,
- AudioManager.STREAM_NOTIFICATION,
- AudioManager.STREAM_RING,
- AudioManager.STREAM_VOICE_CALL,
- AudioManager.STREAM_SYSTEM
- // AudioManager.STREAM_DTMF,
- };
+ private final ServiceConnection mCarConnectionCallback =
+ new ServiceConnection() {
+ @Override
+ public void onServiceConnected(ComponentName name, IBinder binder) {
+ Log.d(TAG, "Connected to Car Service");
+ try {
+ mCarAudioManager = (CarAudioManager) mCar.getCarManager(Car.AUDIO_SERVICE);
+ initVolumeInfo();
+ } catch (CarNotConnectedException e) {
+ Log.e(TAG, "Car is not connected!", e);
+ }
+ }
- private static String streamToName (int stream) {
- switch (stream) {
- case AudioManager.STREAM_ALARM: return "Alarm";
- case AudioManager.STREAM_MUSIC: return "Music";
- case AudioManager.STREAM_NOTIFICATION: return "Notification";
- case AudioManager.STREAM_RING: return "Ring";
- case AudioManager.STREAM_VOICE_CALL: return "Call";
- case AudioManager.STREAM_SYSTEM: return "System";
- default: return "Unknown";
- }
- }
+ @Override
+ public void onServiceDisconnected(ComponentName name) {
+ Log.d(TAG, "Disconnect from Car Service");
+ }
+ };
@Override
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container,
@Nullable Bundle savedInstanceState) {
View v = inflater.inflate(R.layout.volume_test, container, false);
- mVolumeList = (ListView) v.findViewById(R.id.volume_list);
+ ListView volumeListView = v.findViewById(R.id.volume_list);
mAudioManager = (AudioManager) getContext().getSystemService(Context.AUDIO_SERVICE);
- mRefreshButton = (Button) v.findViewById(R.id.refresh);
mAdapter = new VolumeAdapter(getContext(), R.layout.volume_item, mVolumeInfos, this);
- mVolumeList.setAdapter(mAdapter);
+ volumeListView.setAdapter(mAdapter);
- mRefreshButton.setOnClickListener(new View.OnClickListener() {
- @Override
- public void onClick(View view) {
- initVolumeInfo();
+ v.findViewById(R.id.refresh).setOnClickListener((view) -> initVolumeInfo());
+
+ final SeekBar.OnSeekBarChangeListener seekListener = new SeekBar.OnSeekBarChangeListener() {
+ public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
+ final float percent = (progress - 100) / 100.0f;
+ try {
+ if (seekBar.getId() == R.id.fade_bar) {
+ mCarAudioManager.setFadeTowardFront(percent);
+ } else {
+ mCarAudioManager.setBalanceTowardRight(percent);
+ }
+ } catch (CarNotConnectedException e) {
+ Log.e(TAG, "Can't adjust fade or balance when car not connected", e);
+ }
}
- });
- mCarEmulator = CarEmulator.create(getContext());
- mCar = mCarEmulator.getCar();
- try {
- mCarAudioManager = (CarAudioManager) mCar.getCarManager(Car.AUDIO_SERVICE);
- initVolumeInfo();
- mCarAudioManager.setVolumeController(mVolumeController);
- } catch (CarNotConnectedException e) {
- throw new RuntimeException(e); // Should never occur in car emulator.
- }
+ public void onStartTrackingTouch(SeekBar seekBar) {}
- mVolumeUp = (Button) v.findViewById(R.id.volume_up);
- mVolumeDown = (Button) v.findViewById(R.id.volume_down);
+ public void onStopTrackingTouch(SeekBar seekBar) {}
+ };
- mVolumeUp.setOnClickListener(new View.OnClickListener() {
- @Override
- public void onClick(View view) {
- mCarEmulator.injectKey(KeyEvent.KEYCODE_VOLUME_UP);
- }
- });
+ mFader = v.findViewById(R.id.fade_bar);
+ mFader.setOnSeekBarChangeListener(seekListener);
- mVolumeDown.setOnClickListener(new View.OnClickListener() {
- @Override
- public void onClick(View view) {
- mCarEmulator.injectKey(KeyEvent.KEYCODE_VOLUME_DOWN);
- }
- });
+ mBalance = v.findViewById(R.id.balance_bar);
+ mBalance.setOnSeekBarChangeListener(seekListener);
+ mCar = Car.createCar(getActivity(), mCarConnectionCallback);
+ mCar.connect();
return v;
}
- public void adjustVolumeByOne(int logicalStream, boolean up) {
+ public void adjustVolumeByOne(int groupId, boolean up) {
if (mCarAudioManager == null) {
Log.e(TAG, "CarAudioManager is null");
return;
}
int current = 0;
try {
- current = mCarAudioManager.getStreamVolume(logicalStream);
+ current = mCarAudioManager.getGroupVolume(groupId);
+ int volume = current + (up ? 1 : -1);
+ mCarAudioManager.setGroupVolume(groupId, volume,
+ AudioManager.FLAG_SHOW_UI | AudioManager.FLAG_PLAY_SOUND);
+ Log.d(TAG, "Set group " + groupId + " volume " + volume);
} catch (CarNotConnectedException e) {
Log.e(TAG, "car not connected", e);
}
- setStreamVolume(logicalStream, current + (up ? 1 : -1));
}
- public void requestFocus(int logicalStream) {
- mHandler.sendMessage(mHandler.obtainMessage(MSG_REQUEST_FOCUS, logicalStream));
+ public void requestFocus(int groupId) {
+ mHandler.sendMessage(mHandler.obtainMessage(MSG_REQUEST_FOCUS, groupId));
}
- public void setStreamVolume(int logicalStream, int volume) {
- if (mCarAudioManager == null) {
- Log.e(TAG, "CarAudioManager is null");
- return;
- }
- try {
- mCarAudioManager.setStreamVolume(logicalStream, volume, 0);
- } catch (CarNotConnectedException e) {
- Log.e(TAG, "car not connected", e);
- }
-
- Log.d(TAG, "Set stream " + logicalStream + " volume " + volume);
- }
-
-
private void initVolumeInfo() {
- if (mVolumeInfos[0] == null) {
+ try {
+ int volumeGroupCount = mCarAudioManager.getVolumeGroupCount();
+ mVolumeInfos = new VolumeInfo[volumeGroupCount + 1];
+ mGroupIdIndexMap.clear();
mVolumeInfos[0] = new VolumeInfo();
- mVolumeInfos[0].mId = "Stream";
+ mVolumeInfos[0].mId = "Group id";
mVolumeInfos[0].mCurrent = "Current";
mVolumeInfos[0].mMax = "Max";
- mVolumeInfos[0].mLogicalMax = "Android_Max";
- mVolumeInfos[0].mLogicalCurrent = "Android_Current";
- }
- int i = 1;
- for (int stream : LOGICAL_STREAMS) {
- if (mVolumeInfos[i] == null) {
+ int i = 1;
+ for (int groupId = 0; groupId < volumeGroupCount; groupId++) {
mVolumeInfos[i] = new VolumeInfo();
+ mVolumeInfos[i].mGroupId = groupId;
+ mGroupIdIndexMap.put(groupId, i);
+ mVolumeInfos[i].mId = String.valueOf(groupId);
+
+
+ int current = mCarAudioManager.getGroupVolume(groupId);
+ int max = mCarAudioManager.getGroupMaxVolume(groupId);
+ mVolumeInfos[i].mCurrent = String.valueOf(current);
+ mVolumeInfos[i].mMax = String.valueOf(max);
+
+ Log.d(TAG, groupId + " max: " + mVolumeInfos[i].mMax + " current: "
+ + mVolumeInfos[i].mCurrent);
+ i++;
}
- mVolumeInfos[i].logicalStream = stream;
- mStreamIndexMap.put(stream, i);
- mVolumeInfos[i].mId = streamToName(stream);
-
- int current = 0;
- int max = 0;
- try {
- current = mCarAudioManager.getStreamVolume(stream);
- max = mCarAudioManager.getStreamMaxVolume(stream);
- } catch (CarNotConnectedException e) {
- Log.e(TAG, "car not connected", e);
- }
-
- mVolumeInfos[i].mCurrent = String.valueOf(current);
- mVolumeInfos[i].mMax = String.valueOf(max);
-
- mVolumeInfos[i].mLogicalMax = String.valueOf(mAudioManager.getStreamMaxVolume(stream));
- mVolumeInfos[i].mLogicalCurrent = String.valueOf(mAudioManager.getStreamVolume(stream));
-
- Log.d(TAG, stream + " max: " + mVolumeInfos[i].mMax + " current: "
- + mVolumeInfos[i].mCurrent);
- i++;
+ mAdapter.refreshVolumes(mVolumeInfos);
+ } catch (CarNotConnectedException e) {
+ Log.e(TAG, "car not connected", e);
}
- mAdapter.refreshVolumes(mVolumeInfos);
}
@Override
@@ -271,30 +235,4 @@
}
super.onDestroy();
}
-
- private class VolumeController extends IVolumeController.Stub {
-
- @Override
- public void displaySafeVolumeWarning(int flags) throws RemoteException {}
-
- @Override
- public void volumeChanged(int streamType, int flags) throws RemoteException {
- mHandler.sendMessage(mHandler.obtainMessage(MSG_VOLUME_CHANGED, streamType));
- }
-
- @Override
- public void masterMuteChanged(int flags) throws RemoteException {}
-
- @Override
- public void setLayoutDirection(int layoutDirection) throws RemoteException {
- }
-
- @Override
- public void dismiss() throws RemoteException {
- }
-
- @Override
- public void setA11yMode(int mode) throws RemoteException {
- }
- }
}
diff --git a/tests/InstrumentClusterRendererSample/Android.mk b/tests/InstrumentClusterRendererSample/Android.mk
index 4d26ba3..fc00dfa 100644
--- a/tests/InstrumentClusterRendererSample/Android.mk
+++ b/tests/InstrumentClusterRendererSample/Android.mk
@@ -32,6 +32,9 @@
LOCAL_JAVA_LIBRARIES += android.car
-LOCAL_STATIC_JAVA_LIBRARIES += android-support-v4
+LOCAL_USE_AAPT2 := true
+LOCAL_RESOURCE_DIR := $(LOCAL_PATH)/res
+
+LOCAL_STATIC_ANDROID_LIBRARIES += androidx.legacy_legacy-support-v4
include $(BUILD_PACKAGE)
diff --git a/tests/InstrumentClusterRendererSample/src/com/android/car/cluster/sample/InstrumentClusterController.java b/tests/InstrumentClusterRendererSample/src/com/android/car/cluster/sample/InstrumentClusterController.java
index 0120f5b..fbfa8de 100644
--- a/tests/InstrumentClusterRendererSample/src/com/android/car/cluster/sample/InstrumentClusterController.java
+++ b/tests/InstrumentClusterRendererSample/src/com/android/car/cluster/sample/InstrumentClusterController.java
@@ -34,6 +34,7 @@
import android.media.MediaDescription;
import android.media.MediaMetadata;
import android.media.session.PlaybackState;
+import android.os.Bundle;
import android.os.Handler;
import android.os.IBinder;
import android.os.Looper;
@@ -68,7 +69,6 @@
private final Context mContext;
private final NavigationRenderer mNavigationRenderer;
- private final SparseArray<String> mDistanceUnitNames = new SparseArray<>();
private ClusterView mClusterView;
private MediaStateMonitor mMediaStateMonitor;
@@ -97,8 +97,6 @@
return;
}
- initDistanceUnitNames(mContext);
-
mClusterView = new ClusterView(mContext);
Presentation presentation = new InstrumentClusterPresentation(mContext, display);
presentation.setContentView(mClusterView);
@@ -212,19 +210,6 @@
return number;
}
- private void initDistanceUnitNames(Context context) {
- mDistanceUnitNames.put(CarNavigationStatusManager.DISTANCE_METERS,
- context.getString(R.string.nav_distance_units_meters));
- mDistanceUnitNames.put(CarNavigationStatusManager.DISTANCE_KILOMETERS,
- context.getString(R.string.nav_distance_units_kilometers));
- mDistanceUnitNames.put(CarNavigationStatusManager.DISTANCE_FEET,
- context.getString(R.string.nav_distance_units_ft));
- mDistanceUnitNames.put(CarNavigationStatusManager.DISTANCE_MILES,
- context.getString(R.string.nav_distance_units_miles));
- mDistanceUnitNames.put(CarNavigationStatusManager.DISTANCE_YARDS,
- context.getString(R.string.nav_distance_units_yards));
- }
-
private void onCallStateChanged(Call call, int state) {
if (DEBUG) {
Log.d(TAG, "onCallStateChanged, call: " + call + ", state: " + state);
@@ -556,66 +541,11 @@
}
@Override
- public void onStartNavigation() {
+ public void onEvent(int eventType, Bundle bundle) {
if (DEBUG) {
- Log.d(TAG, "onStartNavigation");
+ Log.d(TAG, "onEvent");
}
- mClusterView = mController.mClusterView;
- mResources = mController.mContext.getResources();
- mNavCard = mClusterView.createNavCard();
- }
-
- @Override
- public void onStopNavigation() {
- if (DEBUG) {
- Log.d(TAG, "onStopNavigation");
- }
-
- if (mNavCard != null) {
- mNavCard.removeGracefully();
- mNavCard = null;
- }
- }
-
- @Override
- public void onNextTurnChanged(int event, CharSequence eventName, int turnAngle,
- int turnNumber, Bitmap image, int turnSide) {
- if (DEBUG) {
- Log.d(TAG, "onNextTurnChanged, eventName: " + eventName + ", image: " + image +
- (image == null ? "" : ", size: "
- + image.getWidth() + "x" + image.getHeight()));
- }
- mNavCard.setManeuverImage(BitmapUtils.generateNavManeuverIcon(
- (int) mResources.getDimension(R.dimen.card_icon_size),
- mResources.getColor(R.color.maps_background, null),
- image));
- mNavCard.setStreet(eventName);
- if (!mClusterView.cardExists(mNavCard)) {
- mClusterView.enqueueCard(mNavCard);
- }
- }
-
- @Override
- public void onNextTurnDistanceChanged(int meters, int timeSeconds,
- int displayDistanceMillis, int distanceUnit) {
- if (DEBUG) {
- Log.d(TAG, "onNextTurnDistanceChanged, distanceMeters: " + meters
- + ", timeSeconds: " + timeSeconds
- + ", displayDistanceMillis: " + displayDistanceMillis
- + ", DistanceUnit: " + distanceUnit);
- }
-
- int remainder = displayDistanceMillis % 1000;
- String decimalPart = (remainder != 0)
- ? String.format("%c%d",
- DecimalFormatSymbols.getInstance().getDecimalSeparator(),
- remainder)
- : "";
-
- String distanceToDisplay = (displayDistanceMillis / 1000) + decimalPart;
- String unitsToDisplay = mController.mDistanceUnitNames.get(distanceUnit);
-
- mNavCard.setDistanceToNextManeuver(distanceToDisplay, unitsToDisplay);
+ // Implement this.
}
}
diff --git a/tests/InstrumentClusterRendererSample/src/com/android/car/cluster/sample/MessagingConverter.java b/tests/InstrumentClusterRendererSample/src/com/android/car/cluster/sample/MessagingConverter.java
index 2c88b95..eddeec7 100644
--- a/tests/InstrumentClusterRendererSample/src/com/android/car/cluster/sample/MessagingConverter.java
+++ b/tests/InstrumentClusterRendererSample/src/com/android/car/cluster/sample/MessagingConverter.java
@@ -19,11 +19,12 @@
import android.app.Notification;
import android.graphics.Bitmap;
import android.service.notification.StatusBarNotification;
-import android.support.v4.app.NotificationCompat.CarExtender;
-import android.support.v4.app.NotificationCompat.CarExtender.UnreadConversation;
import android.text.TextUtils;
import android.util.Log;
+import androidx.core.app.NotificationCompat.CarExtender;
+import androidx.core.app.NotificationCompat.CarExtender.UnreadConversation;
+
/**
* Convert a {@link CarExtender} notification into a {@link MessageContactDetails}
*/
diff --git a/libvehiclemonitor/native/Android.mk b/tests/PowerTestService/Android.mk
similarity index 61%
copy from libvehiclemonitor/native/Android.mk
copy to tests/PowerTestService/Android.mk
index 880fcae..6ea33f2 100644
--- a/libvehiclemonitor/native/Android.mk
+++ b/tests/PowerTestService/Android.mk
@@ -1,4 +1,4 @@
-# Copyright (C) 2016 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.
@@ -11,32 +11,36 @@
# 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.
-#
-#
+
LOCAL_PATH:= $(call my-dir)
include $(CLEAR_VARS)
-LOCAL_SRC_FILES := $(patsubst ./%,%, $(shell cd $(LOCAL_PATH); \
- find . -name "*.cpp" -and -not -name ".*"))
+LOCAL_MODULE := com.android.car.powertestservice
+
+LOCAL_SRC_FILES := \
+ src/main.cpp
+
+LOCAL_CFLAGS += \
+ -Wall \
+ -Wextra \
+ -Werror \
+ -Wno-unused-parameter
LOCAL_C_INCLUDES += \
frameworks/base/include \
- packages/services/Car/libvehiclemonitor/include
+ packages/services/Car/car-lib/native/include
LOCAL_SHARED_LIBRARIES := \
+ libbinder \
+ libcarpowermanager \
liblog \
- libutils \
- libhardware \
- libbinder
+ libutils
-LOCAL_EXPORT_SHARED_LIBRARY_HEADERS := libbinder
+LOCAL_MODULE_CLASS := EXECUTABLES
-LOCAL_STRIP_MODULE := keep_symbols
-
-LOCAL_MODULE := libvehiclemonitor-native
+LOCAL_INIT_RC := com.android.car.powertestservice.rc
LOCAL_MODULE_TAGS := optional
-LOCAL_CFLAGS += -Werror
+include $(BUILD_EXECUTABLE)
-include $(BUILD_SHARED_LIBRARY)
diff --git a/libvehiclemonitor/Android.mk b/tests/PowerTestService/com.android.car.powertestservice.rc
similarity index 65%
rename from libvehiclemonitor/Android.mk
rename to tests/PowerTestService/com.android.car.powertestservice.rc
index 23bc789..db27237 100644
--- a/libvehiclemonitor/Android.mk
+++ b/tests/PowerTestService/com.android.car.powertestservice.rc
@@ -1,4 +1,4 @@
-# Copyright (C) 2016 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.
@@ -11,10 +11,11 @@
# 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.
-#
-#
-LOCAL_PATH := $(call my-dir)
-include $(CLEAR_VARS)
-# Include the sub-makefiles
-include $(call all-makefiles-under,$(LOCAL_PATH))
+service com.android.car.powertestservice /system/bin/com.android.car.powertestservice
+ class core
+ user system
+ group system
+
+on boot && property:boot.car_service_created=1
+ start com.android.car.powertestservice
diff --git a/tests/PowerTestService/src/main.cpp b/tests/PowerTestService/src/main.cpp
new file mode 100644
index 0000000..acd14ed
--- /dev/null
+++ b/tests/PowerTestService/src/main.cpp
@@ -0,0 +1,81 @@
+/*
+ * 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.
+ */
+
+#define LOG_TAG "PowerTestService"
+
+#include <signal.h>
+#include <utils/Log.h>
+
+#include <binder/IPCThreadState.h>
+#include <binder/ProcessState.h>
+#include <binder/IServiceManager.h>
+#include <binder/IBinder.h>
+#include <binder/IInterface.h>
+
+#include "android/car/ICar.h"
+#include "android/car/hardware/power/ICarPower.h"
+#include "CarPowerManager.h"
+
+using namespace android;
+using namespace android::binder;
+using namespace android::car;
+using namespace android::car::hardware::power;
+
+static std::atomic_bool run(true);
+
+void onStateChanged(CarPowerManager::State state) {
+ ALOGE("onStateChanged callback = %d", state);
+ // Stop the loop
+ run = false;
+}
+
+int main(int, char**)
+{
+ int retVal;
+
+ sp<ProcessState> processSelf(ProcessState::self());
+ processSelf->startThreadPool();
+ ALOGE(LOG_TAG " started");
+
+ std::unique_ptr<CarPowerManager> carPowerManager(new CarPowerManager());
+
+ do {
+ retVal = carPowerManager->setListener(onStateChanged);
+ } while (retVal != 0);
+
+ do {
+ CarPowerManager::BootReason bootReason;
+ // Test code
+ retVal = carPowerManager->getBootReason(&bootReason);
+
+ if (retVal == 0) {
+ ALOGE("bootreason = %d", bootReason);
+ } else {
+ ALOGE("ERROR: Could not read bootReason!!");
+ }
+
+ sleep(5);
+ } while (run);
+
+ // Unregister the listener
+ carPowerManager->clearListener();
+
+ // Wait for threads to finish, and then exit.
+ IPCThreadState::self()->joinThreadPool();
+ ALOGE(LOG_TAG " joined and going down");
+ return 0;
+}
+
diff --git a/tests/UxRestrictionsSample/Android.mk b/tests/UxRestrictionsSample/Android.mk
new file mode 100644
index 0000000..50419f4
--- /dev/null
+++ b/tests/UxRestrictionsSample/Android.mk
@@ -0,0 +1,54 @@
+# 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.
+#
+#
+
+LOCAL_PATH := $(call my-dir)
+
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES := $(call all-java-files-under, src)
+
+LOCAL_RESOURCE_DIR := $(LOCAL_PATH)/res
+
+LOCAL_PACKAGE_NAME := UxRestrictionsSample
+LOCAL_PRIVATE_PLATFORM_APIS := true
+
+LOCAL_MODULE_TAGS := optional
+
+LOCAL_JAVA_VERSION := 1.8
+
+LOCAL_PROGUARD_ENABLED := disabled
+
+LOCAL_DEX_PREOPT := false
+
+LOCAL_USE_AAPT2 := true
+
+LOCAL_PRIVILEGED_MODULE := true
+
+LOCAL_CERTIFICATE := platform
+
+LOCAL_STATIC_JAVA_LIBRARIES += vehicle-hal-support-lib
+
+LOCAL_STATIC_ANDROID_LIBRARIES += \
+ androidx.car_car \
+ androidx.legacy_legacy-support-v4 \
+ androidx.appcompat_appcompat
+
+LOCAL_JAVA_LIBRARIES += android.car
+
+include $(BUILD_PACKAGE)
+
+# Use the following include to make our test apk.
+include $(call all-makefiles-under,$(LOCAL_PATH))
diff --git a/tests/UxRestrictionsSample/AndroidManifest.xml b/tests/UxRestrictionsSample/AndroidManifest.xml
new file mode 100644
index 0000000..4c702ca
--- /dev/null
+++ b/tests/UxRestrictionsSample/AndroidManifest.xml
@@ -0,0 +1,30 @@
+<?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.uxr.sample" android:sharedUserId="android.uid.system">
+
+ <uses-permission android:name="android.car.permission.CAR_DRIVING_STATE" />
+
+ <application android:label="UxRestrictions Sample">
+ <activity android:name=".MainActivity">
+ <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>
+ </application>
+</manifest>
diff --git a/tests/UxRestrictionsSample/res/layout/main_activity.xml b/tests/UxRestrictionsSample/res/layout/main_activity.xml
new file mode 100644
index 0000000..ec0d226
--- /dev/null
+++ b/tests/UxRestrictionsSample/res/layout/main_activity.xml
@@ -0,0 +1,67 @@
+<?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.
+-->
+<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:orientation="horizontal"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent">
+
+ <LinearLayout
+ android:layout_height="match_parent"
+ android:layout_width="0dp"
+ android:layout_weight="1"
+ android:orientation="vertical"
+ android:gravity="center">
+ <TextView
+ android:id="@+id/driving_state"
+ android:layout_gravity="center"
+ 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:layout_width="match_parent"
+ android:textAppearance="?android:textAppearanceLarge"
+ android:layout_height="wrap_content" />
+ <TextView
+ android:id="@+id/uxr_status"
+ android:layout_gravity="center"
+ android:layout_width="match_parent"
+ android:textAppearance="?android:textAppearanceLarge"
+ android:layout_height="wrap_content" />
+ <Button
+ android:id="@+id/toggle_status"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:text="Disable Ux Restrictions"
+ android:textSize="32sp"/>
+ </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/UxRestrictionsSample/src/com/google/android/car/uxr/sample/MainActivity.java b/tests/UxRestrictionsSample/src/com/google/android/car/uxr/sample/MainActivity.java
new file mode 100644
index 0000000..ba82e6f
--- /dev/null
+++ b/tests/UxRestrictionsSample/src/com/google/android/car/uxr/sample/MainActivity.java
@@ -0,0 +1,246 @@
+/*
+ * 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.car.Car;
+import android.car.CarNotConnectedException;
+import android.car.content.pm.CarPackageManager;
+import android.car.drivingstate.CarDrivingStateEvent;
+import android.car.drivingstate.CarDrivingStateManager;
+import android.car.drivingstate.CarUxRestrictions;
+import android.car.drivingstate.CarUxRestrictionsManager;
+import android.content.ComponentName;
+import android.content.ServiceConnection;
+import android.os.Bundle;
+import android.os.IBinder;
+import android.util.Log;
+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;
+ private CarPackageManager mCarPackageManager;
+ private TextView mDrvStatus;
+ private TextView mDistractionOptStatus;
+ private TextView mUxrStatus;
+ private Button mToggleButton;
+ private boolean mEnableUxR;
+ private PagedListView mPagedListView;
+
+ private final ServiceConnection mCarConnectionListener =
+ new ServiceConnection() {
+ @Override
+ public void onServiceConnected(ComponentName name, IBinder iBinder) {
+ Log.d(TAG, "Connected to " + name.flattenToString());
+ // Get Driving State & UXR manager
+ try {
+ mCarDrivingStateManager = (CarDrivingStateManager) mCar.getCarManager(
+ Car.CAR_DRIVING_STATE_SERVICE);
+ mCarUxRestrictionsManager = (CarUxRestrictionsManager) mCar.getCarManager(
+ Car.CAR_UX_RESTRICTION_SERVICE);
+ mCarPackageManager = (CarPackageManager) mCar.getCarManager(
+ Car.PACKAGE_SERVICE);
+
+ if (mCarDrivingStateManager != null) {
+ mCarDrivingStateManager.registerListener(mDrvStateChangeListener);
+ updateDrivingStateText(
+ mCarDrivingStateManager.getCurrentCarDrivingState());
+ }
+ if (mCarUxRestrictionsManager != null) {
+ mCarUxRestrictionsManager.registerListener(mUxRChangeListener);
+ updateUxRText(mCarUxRestrictionsManager.getCurrentCarUxRestrictions());
+ }
+
+ } 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());
+ mCarDrivingStateManager = null;
+ mCarUxRestrictionsManager = null;
+ mCarPackageManager = null;
+ }
+ };
+
+ private void updateUxRText(CarUxRestrictions restrictions) {
+ mDistractionOptStatus.setText(
+ restrictions.isRequiresDistractionOptimization()
+ ? "Requires Distraction Optimization"
+ : "No Distraction Optimization required");
+
+ mUxrStatus.setText("Active Restrictions : 0x"
+ + Integer.toHexString(restrictions.getActiveRestrictions()));
+
+ mDistractionOptStatus.requestLayout();
+ mUxrStatus.requestLayout();
+ }
+
+ private void updateToggleUxREnable() {
+ if (mCarPackageManager == null) {
+ return;
+ }
+ mCarPackageManager.setEnableActivityBlocking(mEnableUxR);
+ if (mEnableUxR) {
+ mToggleButton.setText("Disable UX Restrictions");
+ } else {
+ mToggleButton.setText("Enable UX Restrictions");
+ }
+ mEnableUxR = !mEnableUxR;
+ mToggleButton.requestLayout();
+
+ }
+
+ private void updateDrivingStateText(CarDrivingStateEvent state) {
+ if (state == null) {
+ return;
+ }
+ String displayText;
+ switch (state.eventValue) {
+ case CarDrivingStateEvent.DRIVING_STATE_PARKED:
+ displayText = "Parked";
+ break;
+ case CarDrivingStateEvent.DRIVING_STATE_IDLING:
+ displayText = "Idling";
+ break;
+ case CarDrivingStateEvent.DRIVING_STATE_MOVING:
+ displayText = "Moving";
+ break;
+ default:
+ displayText = "Unknown";
+ }
+ mDrvStatus.setText("Driving State: " + displayText);
+ mDrvStatus.requestLayout();
+ }
+
+ private CarUxRestrictionsManager.OnUxRestrictionsChangedListener mUxRChangeListener =
+ this::updateUxRText;
+
+
+ private CarDrivingStateManager.CarDrivingStateEventListener mDrvStateChangeListener =
+ this::updateDrivingStateText;
+
+ @Override
+ public void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.main_activity);
+
+ mDrvStatus = findViewById(R.id.driving_state);
+ 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();
+ });
+
+ // Connect to car service
+ mCar = Car.createCar(this, mCarConnectionListener);
+ mCar.connect();
+ }
+
+ private void setUpPagedListView() {
+ ListItemAdapter adapter = new ListItemAdapter(this, populateData());
+ mPagedListView.setAdapter(adapter);
+ }
+
+ 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() {
+ try {
+ if (mCarUxRestrictionsManager != null) {
+ mCarUxRestrictionsManager.unregisterListener();
+ }
+ if (mCarDrivingStateManager != null) {
+ mCarDrivingStateManager.unregisterListener();
+ }
+ } catch (CarNotConnectedException e) {
+ Log.e(TAG, "Error unregistering listeners", e);
+ }
+ if (mCar != null) {
+ mCar.disconnect();
+ }
+ }
+}
+
diff --git a/tests/VmsSubscriberClientSample/AndroidManifest.xml b/tests/VmsSubscriberClientSample/AndroidManifest.xml
index bc798d7..a035d05 100644
--- a/tests/VmsSubscriberClientSample/AndroidManifest.xml
+++ b/tests/VmsSubscriberClientSample/AndroidManifest.xml
@@ -16,10 +16,12 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:androidprv="http://schemas.android.com/apk/prv/res/android"
- package="com.google.android.car.vms.subscriber"
- android:sharedUserId="android.uid.system">
+ package="com.google.android.car.vms.subscriber">
+ <!--android:sharedUserId="android.uid.system">-->
<uses-sdk android:minSdkVersion="25" android:targetSdkVersion='25'/>
+ <uses-permission android:name="android.car.permission.VMS_SUBSCRIBER"/>
+
<application android:label="@string/app_name"
android:icon="@mipmap/ic_launcher">
<meta-data
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 3ac0707..a82350b 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,6 +17,7 @@
package com.google.android.car.vms.subscriber;
import android.app.Activity;
+import android.car.vms.VmsAvailableLayers;
import android.car.vms.VmsLayer;
import android.car.vms.VmsSubscriberManager;
import android.content.pm.PackageManager;
@@ -25,8 +26,7 @@
import android.support.car.CarConnectionCallback;
import android.util.Log;
import android.widget.TextView;
-
-import java.util.List;
+import java.util.concurrent.Executor;
/**
* Connects to the Car service during onCreate. CarConnectionCallback.onConnected is invoked when
@@ -42,9 +42,17 @@
private Car mCarApi;
private TextView mTextView;
private VmsSubscriberManager mVmsSubscriberManager;
+ private Executor mExecutor;
+
+ private class ThreadPerTaskExecutor implements Executor {
+ public void execute(Runnable r) {
+ new Thread(r).start();
+ }
+ }
@Override
protected void onCreate(Bundle savedInstanceState) {
+ mExecutor = new ThreadPerTaskExecutor();
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mTextView = (TextView) findViewById(R.id.textview);
@@ -90,24 +98,25 @@
private void configureSubscriptions(VmsSubscriberManager vmsSubscriberManager) {
try {
- vmsSubscriberManager.registerClientCallback(mClientCallback);
+ vmsSubscriberManager.setVmsSubscriberClientCallback(mExecutor, mClientCallback);
vmsSubscriberManager.subscribe(TEST_LAYER);
} catch (android.car.CarNotConnectedException e) {
Log.e(TAG, "Car is not connected!", e);
}
}
+
};
private final VmsSubscriberManager.VmsSubscriberClientCallback mClientCallback =
- new VmsSubscriberManager.VmsSubscriberClientCallback() {
- @Override
- public void onVmsMessageReceived(VmsLayer layer, byte[] payload) {
- mTextView.setText(String.valueOf(payload[0]));
- }
+ new VmsSubscriberManager.VmsSubscriberClientCallback() {
+ @Override
+ public void onVmsMessageReceived(VmsLayer layer, byte[] payload) {
+ mTextView.setText(String.valueOf(payload[0]));
+ }
- @Override
- public void onLayersAvailabilityChanged(List<VmsLayer> availableLayers) {
- mTextView.setText(String.valueOf(availableLayers));
- }
- };
+ @Override
+ public void onLayersAvailabilityChanged(VmsAvailableLayers availableLayers) {
+ mTextView.setText(String.valueOf(availableLayers));
+ }
+ };
}
diff --git a/tests/android_car_api_test/Android.mk b/tests/android_car_api_test/Android.mk
index 3196b4f..b1c2728 100644
--- a/tests/android_car_api_test/Android.mk
+++ b/tests/android_car_api_test/Android.mk
@@ -33,12 +33,12 @@
LOCAL_PROGUARD_ENABLED := disabled
-LOCAL_STATIC_JAVA_LIBRARIES := junit legacy-android-test
+LOCAL_STATIC_JAVA_LIBRARIES := junit
LOCAL_STATIC_JAVA_LIBRARIES += \
android-support-test \
android.hidl.base-V1.0-java \
android.hardware.automotive.vehicle-V2.0-java \
-LOCAL_JAVA_LIBRARIES := android.car android.test.runner
+LOCAL_JAVA_LIBRARIES := android.car android.test.runner android.test.base
include $(BUILD_PACKAGE)
diff --git a/tests/android_car_api_test/src/android/car/apitest/CarAppFocusManagerTest.java b/tests/android_car_api_test/src/android/car/apitest/CarAppFocusManagerTest.java
index 5f23a6c..a067fe3 100644
--- a/tests/android_car_api_test/src/android/car/apitest/CarAppFocusManagerTest.java
+++ b/tests/android_car_api_test/src/android/car/apitest/CarAppFocusManagerTest.java
@@ -48,11 +48,15 @@
// Request all application focuses and abandon them to ensure no active context is present
// when test starts.
+ int[] activeTypes = mManager.getActiveAppTypes();
FocusOwnershipCallback owner = new FocusOwnershipCallback();
- mManager.requestAppFocus(APP_FOCUS_TYPE_NAVIGATION, owner);
- mManager.requestAppFocus(APP_FOCUS_TYPE_VOICE_COMMAND, owner);
- mManager.abandonAppFocus(owner);
-
+ for (int i = 0; i < activeTypes.length; i++) {
+ mManager.requestAppFocus(activeTypes[i], owner);
+ owner.waitForOwnershipGrantAndAssert(DEFAULT_WAIT_TIMEOUT_MS, activeTypes[i]);
+ mManager.abandonAppFocus(owner, activeTypes[i]);
+ owner.waitForOwnershipLossAndAssert(
+ DEFAULT_WAIT_TIMEOUT_MS, activeTypes[i]);
+ }
mEventThread.start();
mEventThread.waitForReadyState();
}
diff --git a/tests/android_car_api_test/src/android/car/apitest/CarCabinManagerTest.java b/tests/android_car_api_test/src/android/car/apitest/CarCabinManagerTest.java
index 3a14624..2526ecf 100644
--- a/tests/android_car_api_test/src/android/car/apitest/CarCabinManagerTest.java
+++ b/tests/android_car_api_test/src/android/car/apitest/CarCabinManagerTest.java
@@ -16,8 +16,8 @@
package android.car.apitest;
import android.car.Car;
-import android.car.hardware.cabin.CarCabinManager;
import android.car.hardware.CarPropertyConfig;
+import android.car.hardware.cabin.CarCabinManager;
import android.test.suitebuilder.annotation.MediumTest;
import android.util.Log;
@@ -101,8 +101,6 @@
case CarCabinManager.ID_SEAT_HEADREST_FORE_AFT_MOVE:
case CarCabinManager.ID_WINDOW_POS:
case CarCabinManager.ID_WINDOW_MOVE:
- case CarCabinManager.ID_WINDOW_VENT_POS:
- case CarCabinManager.ID_WINDOW_VENT_MOVE:
assertEquals(Integer.class, property.getPropertyType());
assertFalse(property.isGlobalProperty());
checkIntMinMax(property);
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 4fb72a1..7196d14 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
@@ -16,8 +16,8 @@
package android.car.apitest;
import android.car.Car;
-import android.car.hardware.hvac.CarHvacManager;
import android.car.hardware.CarPropertyConfig;
+import android.car.hardware.hvac.CarHvacManager;
import android.hardware.automotive.vehicle.V2_0.VehicleHvacFanDirection;
import android.test.suitebuilder.annotation.MediumTest;
import android.util.Log;
@@ -55,13 +55,9 @@
}
public void testHvacPosition() {
- assertEquals(CarHvacManager.FAN_POSITION_FACE, VehicleHvacFanDirection.FACE);
- assertEquals(CarHvacManager.FAN_POSITION_FLOOR, VehicleHvacFanDirection.FLOOR);
- assertEquals(CarHvacManager.FAN_POSITION_FACE_AND_FLOOR,
- VehicleHvacFanDirection.FACE_AND_FLOOR);
- assertEquals(CarHvacManager.FAN_POSITION_DEFROST, VehicleHvacFanDirection.DEFROST);
- assertEquals(CarHvacManager.FAN_POSITION_DEFROST_AND_FLOOR,
- VehicleHvacFanDirection.DEFROST_AND_FLOOR);
+ assertEquals(CarHvacManager.FAN_DIRECTION_FACE, VehicleHvacFanDirection.FACE);
+ assertEquals(CarHvacManager.FAN_DIRECTION_FLOOR, VehicleHvacFanDirection.FLOOR);
+ assertEquals(CarHvacManager.FAN_DIRECTION_DEFROST, VehicleHvacFanDirection.DEFROST);
}
private void assertTypeAndZone(CarPropertyConfig property) {
@@ -69,8 +65,8 @@
case CarHvacManager.ID_MIRROR_DEFROSTER_ON: // non-zoned bool
checkTypeAndGlobal(Boolean.class, true, property);
break;
- case CarHvacManager.ID_STEERING_WHEEL_TEMP: // non-zoned int
- case CarHvacManager.ID_TEMPERATURE_UNITS:
+ case CarHvacManager.ID_STEERING_WHEEL_HEAT: // non-zoned int
+ case CarHvacManager.ID_TEMPERATURE_DISPLAY_UNITS:
checkTypeAndGlobal(Integer.class, true, property);
checkIntMinMax(property);
break;
@@ -84,12 +80,12 @@
break;
case CarHvacManager.ID_ZONED_FAN_SPEED_SETPOINT: // zoned int
case CarHvacManager.ID_ZONED_FAN_SPEED_RPM:
- case CarHvacManager.ID_ZONED_FAN_POSITION_AVAILABLE:
+ case CarHvacManager.ID_ZONED_FAN_DIRECTION_AVAILABLE:
case CarHvacManager.ID_ZONED_SEAT_TEMP:
checkTypeAndGlobal(Integer.class, false, property);
checkIntMinMax(property);
break;
- case CarHvacManager.ID_ZONED_FAN_POSITION:
+ case CarHvacManager.ID_ZONED_FAN_DIRECTION:
checkTypeAndGlobal(Integer.class, false, property);
break;
case CarHvacManager.ID_ZONED_AC_ON: // zoned boolean
@@ -120,10 +116,10 @@
assertTrue(areaIds.length > 0);
assertEquals(areaIds.length, property.getAreaCount());
- for (int areId : areaIds) {
- assertTrue(property.hasArea(areId));
- int min = property.getMinValue(areId);
- int max = property.getMaxValue(areId);
+ for (int areaId : areaIds) {
+ assertTrue(property.hasArea(areaId));
+ int min = property.getMinValue(areaId);
+ int max = property.getMaxValue(areaId);
assertTrue(min <= max);
}
} else {
diff --git a/tests/android_car_api_test/src/android/car/apitest/CarNavigationManagerTest.java b/tests/android_car_api_test/src/android/car/apitest/CarNavigationManagerTest.java
index 31543bd..6d53471 100644
--- a/tests/android_car_api_test/src/android/car/apitest/CarNavigationManagerTest.java
+++ b/tests/android_car_api_test/src/android/car/apitest/CarNavigationManagerTest.java
@@ -45,15 +45,21 @@
assertNotNull(mCarAppFocusManager);
}
- public void testStart() throws Exception {
+ public void testSendEvent() throws Exception {
if (mCarNavigationManager == null) {
Log.w(TAG, "Unable to run the test: "
+ "car navigation manager was not created succesfully.");
return;
}
+ Bundle bundle = new Bundle();
+ bundle.putInt("BUNDLE_INTEGER_VALUE", 1234);
+ bundle.putFloat("BUNDLE_FLOAT_VALUE", 12.3456f);
+ bundle.putStringArrayList("BUNDLE_ARRAY_OF_STRINGS",
+ Lists.newArrayList("Value A", "Value B", "Value Z"));
+
try {
- mCarNavigationManager.sendNavigationStatus(1);
+ mCarNavigationManager.sendEvent(1, bundle);
fail();
} catch (IllegalStateException expected) {
// Expected. Client should acquire focus ownership for APP_FOCUS_TYPE_NAVIGATION.
@@ -85,15 +91,6 @@
// TODO: we should use mocked HAL to be able to verify this, right now just make sure that
// it is not crashing and logcat has appropriate traces.
- mCarNavigationManager.sendNavigationStatus(1);
-
- Bundle bundle = new Bundle();
- bundle.putInt("BUNDLE_INTEGER_VALUE", 1234);
- bundle.putFloat("BUNDLE_FLOAT_VALUE", 12.3456f);
- bundle.putStringArrayList("BUNDLE_ARRAY_OF_STRINGS",
- Lists.newArrayList("Value A", "Value B", "Value Z"));
-
- mCarNavigationManager.sendEvent
- (CarNavigationStatusManager.EVENT_TYPE_NEXT_MANEUVER_INFO, bundle);
+ mCarNavigationManager.sendEvent(1, bundle);
}
}
diff --git a/tests/android_car_api_test/src/android/car/apitest/CarSensorManagerTest.java b/tests/android_car_api_test/src/android/car/apitest/CarSensorManagerTest.java
index 21da64f..f19f33d 100644
--- a/tests/android_car_api_test/src/android/car/apitest/CarSensorManagerTest.java
+++ b/tests/android_car_api_test/src/android/car/apitest/CarSensorManagerTest.java
@@ -16,13 +16,12 @@
package android.car.apitest;
+import android.car.Car;
+import android.car.hardware.CarSensorManager;
import android.content.ComponentName;
import android.content.ServiceConnection;
import android.os.IBinder;
import android.os.Looper;
-import android.car.Car;
-import android.car.hardware.CarSensorEvent;
-import android.car.hardware.CarSensorManager;
import android.test.AndroidTestCase;
import android.test.suitebuilder.annotation.MediumTest;
@@ -74,24 +73,4 @@
super.tearDown();
mCar.disconnect();
}
-
- public void testDrivingPolicy() throws Exception {
- int[] supportedSensors = mCarSensorManager.getSupportedSensors();
- assertNotNull(supportedSensors);
- boolean found = false;
- for (int sensor: supportedSensors) {
- if (sensor == CarSensorManager.SENSOR_TYPE_DRIVING_STATUS) {
- found = true;
- break;
- }
- }
- assertTrue(found);
- assertTrue(mCarSensorManager.isSensorSupported(
- CarSensorManager.SENSOR_TYPE_DRIVING_STATUS));
- assertTrue(CarSensorManager.isSensorSupported(supportedSensors,
- CarSensorManager.SENSOR_TYPE_DRIVING_STATUS));
- CarSensorEvent lastEvent = mCarSensorManager.getLatestSensorEvent(
- CarSensorManager.SENSOR_TYPE_DRIVING_STATUS);
- assertNotNull(lastEvent);
- }
}
diff --git a/tests/android_car_api_test/src/android/car/apitest/VehicleAreaMirrorTest.java b/tests/android_car_api_test/src/android/car/apitest/VehicleAreaMirrorTest.java
new file mode 100644
index 0000000..7eb7eb8
--- /dev/null
+++ b/tests/android_car_api_test/src/android/car/apitest/VehicleAreaMirrorTest.java
@@ -0,0 +1,33 @@
+/*
+ * 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.apitest;
+
+import android.car.VehicleAreaMirror;
+import android.test.AndroidTestCase;
+import android.test.suitebuilder.annotation.SmallTest;
+
+@SmallTest
+public class VehicleAreaMirrorTest extends AndroidTestCase{
+
+ public void testMatchWithVehicleHal() {
+ assertEquals(android.hardware.automotive.vehicle.V2_0.VehicleAreaMirror.DRIVER_CENTER,
+ VehicleAreaMirror.MIRROR_DRIVER_CENTER);
+ assertEquals(android.hardware.automotive.vehicle.V2_0.VehicleAreaMirror.DRIVER_LEFT,
+ VehicleAreaMirror.MIRROR_DRIVER_LEFT);
+ assertEquals(android.hardware.automotive.vehicle.V2_0.VehicleAreaMirror.DRIVER_RIGHT,
+ VehicleAreaMirror.MIRROR_DRIVER_RIGHT);
+ }
+}
diff --git a/tests/android_car_api_test/src/android/car/apitest/VehicleDoorTest.java b/tests/android_car_api_test/src/android/car/apitest/VehicleDoorTest.java
index 1e265fd..d1b35c0 100644
--- a/tests/android_car_api_test/src/android/car/apitest/VehicleDoorTest.java
+++ b/tests/android_car_api_test/src/android/car/apitest/VehicleDoorTest.java
@@ -15,8 +15,7 @@
*/
package android.car.apitest;
-import android.car.VehicleDoor;
-import android.hardware.automotive.vehicle.V2_0.VehicleAreaDoor;
+import android.car.VehicleAreaDoor;
import android.test.AndroidTestCase;
import android.test.suitebuilder.annotation.SmallTest;
@@ -24,13 +23,21 @@
public class VehicleDoorTest extends AndroidTestCase {
public void testMatchWithVehicleHal() {
- assertEquals(VehicleAreaDoor.HOOD, VehicleDoor.DOOR_HOOD);
- assertEquals(VehicleAreaDoor.REAR, VehicleDoor.DOOR_REAR);
- assertEquals(VehicleAreaDoor.ROW_1_LEFT, VehicleDoor.DOOR_ROW_1_LEFT);
- assertEquals(VehicleAreaDoor.ROW_1_RIGHT, VehicleDoor.DOOR_ROW_1_RIGHT);
- assertEquals(VehicleAreaDoor.ROW_2_LEFT, VehicleDoor.DOOR_ROW_2_LEFT);
- assertEquals(VehicleAreaDoor.ROW_2_RIGHT, VehicleDoor.DOOR_ROW_2_RIGHT);
- assertEquals(VehicleAreaDoor.ROW_3_LEFT, VehicleDoor.DOOR_ROW_3_LEFT);
- assertEquals(VehicleAreaDoor.ROW_3_RIGHT, VehicleDoor.DOOR_ROW_3_RIGHT);
+ assertEquals(android.hardware.automotive.vehicle.V2_0.VehicleAreaDoor.HOOD,
+ VehicleAreaDoor.DOOR_HOOD);
+ assertEquals(android.hardware.automotive.vehicle.V2_0.VehicleAreaDoor.REAR,
+ VehicleAreaDoor.DOOR_REAR);
+ assertEquals(android.hardware.automotive.vehicle.V2_0.VehicleAreaDoor.ROW_1_LEFT,
+ VehicleAreaDoor.DOOR_ROW_1_LEFT);
+ assertEquals(android.hardware.automotive.vehicle.V2_0.VehicleAreaDoor.ROW_1_RIGHT,
+ VehicleAreaDoor.DOOR_ROW_1_RIGHT);
+ assertEquals(android.hardware.automotive.vehicle.V2_0.VehicleAreaDoor.ROW_2_LEFT,
+ VehicleAreaDoor.DOOR_ROW_2_LEFT);
+ assertEquals(android.hardware.automotive.vehicle.V2_0.VehicleAreaDoor.ROW_2_RIGHT,
+ VehicleAreaDoor.DOOR_ROW_2_RIGHT);
+ assertEquals(android.hardware.automotive.vehicle.V2_0.VehicleAreaDoor.ROW_3_LEFT,
+ VehicleAreaDoor.DOOR_ROW_3_LEFT);
+ assertEquals(android.hardware.automotive.vehicle.V2_0.VehicleAreaDoor.ROW_3_RIGHT,
+ VehicleAreaDoor.DOOR_ROW_3_RIGHT);
}
}
diff --git a/tests/android_car_api_test/src/android/car/apitest/VehicleSeatTest.java b/tests/android_car_api_test/src/android/car/apitest/VehicleSeatTest.java
index 4452d3d..841c66e 100644
--- a/tests/android_car_api_test/src/android/car/apitest/VehicleSeatTest.java
+++ b/tests/android_car_api_test/src/android/car/apitest/VehicleSeatTest.java
@@ -15,8 +15,7 @@
*/
package android.car.apitest;
-import android.car.VehicleSeat;
-import android.hardware.automotive.vehicle.V2_0.VehicleAreaSeat;
+import android.car.VehicleAreaSeat;
import android.test.AndroidTestCase;
import android.test.suitebuilder.annotation.SmallTest;
@@ -24,14 +23,23 @@
public class VehicleSeatTest extends AndroidTestCase {
public void testMatchWithVehicleHal() {
- assertEquals(VehicleAreaSeat.ROW_1_LEFT, VehicleSeat.SEAT_ROW_1_LEFT);
- assertEquals(VehicleAreaSeat.ROW_1_CENTER, VehicleSeat.SEAT_ROW_1_CENTER);
- assertEquals(VehicleAreaSeat.ROW_1_RIGHT, VehicleSeat.SEAT_ROW_1_RIGHT);
- assertEquals(VehicleAreaSeat.ROW_2_LEFT, VehicleSeat.SEAT_ROW_2_LEFT);
- assertEquals(VehicleAreaSeat.ROW_2_CENTER, VehicleSeat.SEAT_ROW_2_CENTER);
- assertEquals(VehicleAreaSeat.ROW_2_RIGHT, VehicleSeat.SEAT_ROW_2_RIGHT);
- assertEquals(VehicleAreaSeat.ROW_3_LEFT, VehicleSeat.SEAT_ROW_3_LEFT);
- assertEquals(VehicleAreaSeat.ROW_3_CENTER, VehicleSeat.SEAT_ROW_3_CENTER);
- assertEquals(VehicleAreaSeat.ROW_3_RIGHT, VehicleSeat.SEAT_ROW_3_RIGHT);
+ assertEquals(android.hardware.automotive.vehicle.V2_0.VehicleAreaSeat.ROW_1_LEFT,
+ VehicleAreaSeat.SEAT_ROW_1_LEFT);
+ assertEquals(android.hardware.automotive.vehicle.V2_0.VehicleAreaSeat.ROW_1_CENTER,
+ VehicleAreaSeat.SEAT_ROW_1_CENTER);
+ assertEquals(android.hardware.automotive.vehicle.V2_0.VehicleAreaSeat.ROW_1_RIGHT,
+ VehicleAreaSeat.SEAT_ROW_1_RIGHT);
+ assertEquals(android.hardware.automotive.vehicle.V2_0.VehicleAreaSeat.ROW_2_LEFT,
+ VehicleAreaSeat.SEAT_ROW_2_LEFT);
+ assertEquals(android.hardware.automotive.vehicle.V2_0.VehicleAreaSeat.ROW_2_CENTER,
+ VehicleAreaSeat.SEAT_ROW_2_CENTER);
+ assertEquals(android.hardware.automotive.vehicle.V2_0.VehicleAreaSeat.ROW_2_RIGHT,
+ VehicleAreaSeat.SEAT_ROW_2_RIGHT);
+ assertEquals(android.hardware.automotive.vehicle.V2_0.VehicleAreaSeat.ROW_3_LEFT,
+ VehicleAreaSeat.SEAT_ROW_3_LEFT);
+ assertEquals(android.hardware.automotive.vehicle.V2_0.VehicleAreaSeat.ROW_3_CENTER,
+ VehicleAreaSeat.SEAT_ROW_3_CENTER);
+ assertEquals(android.hardware.automotive.vehicle.V2_0.VehicleAreaSeat.ROW_3_RIGHT,
+ VehicleAreaSeat.SEAT_ROW_3_RIGHT);
}
}
diff --git a/tests/android_car_api_test/src/android/car/apitest/VehicleWindowTest.java b/tests/android_car_api_test/src/android/car/apitest/VehicleWindowTest.java
index f87bd38..331d3ef 100644
--- a/tests/android_car_api_test/src/android/car/apitest/VehicleWindowTest.java
+++ b/tests/android_car_api_test/src/android/car/apitest/VehicleWindowTest.java
@@ -15,8 +15,7 @@
*/
package android.car.apitest;
-import android.car.VehicleWindow;
-import android.hardware.automotive.vehicle.V2_0.VehicleAreaWindow;
+import android.car.VehicleAreaWindow;
import android.test.AndroidTestCase;
import android.test.suitebuilder.annotation.SmallTest;
@@ -24,14 +23,25 @@
public class VehicleWindowTest extends AndroidTestCase {
public void testMatchWithVehicleHal() {
- assertEquals(VehicleAreaWindow.FRONT_WINDSHIELD, VehicleWindow.WINDOW_FRONT_WINDSHIELD);
- assertEquals(VehicleAreaWindow.REAR_WINDSHIELD, VehicleWindow.WINDOW_REAR_WINDSHIELD);
- assertEquals(VehicleAreaWindow.ROOF_TOP, VehicleWindow.WINDOW_ROOF_TOP);
- assertEquals(VehicleAreaWindow.ROW_1_LEFT, VehicleWindow.WINDOW_ROW_1_LEFT);
- assertEquals(VehicleAreaWindow.ROW_1_RIGHT, VehicleWindow.WINDOW_ROW_1_RIGHT);
- assertEquals(VehicleAreaWindow.ROW_2_LEFT, VehicleWindow.WINDOW_ROW_2_LEFT);
- assertEquals(VehicleAreaWindow.ROW_2_RIGHT, VehicleWindow.WINDOW_ROW_2_RIGHT);
- assertEquals(VehicleAreaWindow.ROW_3_LEFT, VehicleWindow.WINDOW_ROW_3_LEFT);
- assertEquals(VehicleAreaWindow.ROW_3_RIGHT, VehicleWindow.WINDOW_ROW_3_RIGHT);
+ assertEquals(android.hardware.automotive.vehicle.V2_0.VehicleAreaWindow.FRONT_WINDSHIELD,
+ VehicleAreaWindow.WINDOW_FRONT_WINDSHIELD);
+ assertEquals(android.hardware.automotive.vehicle.V2_0.VehicleAreaWindow.REAR_WINDSHIELD,
+ VehicleAreaWindow.WINDOW_REAR_WINDSHIELD);
+ assertEquals(android.hardware.automotive.vehicle.V2_0.VehicleAreaWindow.ROW_1_LEFT,
+ VehicleAreaWindow.WINDOW_ROW_1_LEFT);
+ assertEquals(android.hardware.automotive.vehicle.V2_0.VehicleAreaWindow.ROW_1_RIGHT,
+ VehicleAreaWindow.WINDOW_ROW_1_RIGHT);
+ assertEquals(android.hardware.automotive.vehicle.V2_0.VehicleAreaWindow.ROW_2_LEFT,
+ VehicleAreaWindow.WINDOW_ROW_2_LEFT);
+ assertEquals(android.hardware.automotive.vehicle.V2_0.VehicleAreaWindow.ROW_2_RIGHT,
+ VehicleAreaWindow.WINDOW_ROW_2_RIGHT);
+ assertEquals(android.hardware.automotive.vehicle.V2_0.VehicleAreaWindow.ROW_3_LEFT,
+ VehicleAreaWindow.WINDOW_ROW_3_LEFT);
+ assertEquals(android.hardware.automotive.vehicle.V2_0.VehicleAreaWindow.ROW_3_RIGHT,
+ VehicleAreaWindow.WINDOW_ROW_3_RIGHT);
+ assertEquals(android.hardware.automotive.vehicle.V2_0.VehicleAreaWindow.ROOF_TOP_1,
+ VehicleAreaWindow.WINDOW_ROOF_TOP_1);
+ assertEquals(android.hardware.automotive.vehicle.V2_0.VehicleAreaWindow.ROOF_TOP_2,
+ VehicleAreaWindow.WINDOW_ROOF_TOP_2);
}
}
diff --git a/tests/android_car_api_test/src/android/car/apitest/VehicleZoneTest.java b/tests/android_car_api_test/src/android/car/apitest/VehicleZoneTest.java
deleted file mode 100644
index 27c328f..0000000
--- a/tests/android_car_api_test/src/android/car/apitest/VehicleZoneTest.java
+++ /dev/null
@@ -1,45 +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.apitest;
-
-import android.car.VehicleZone;
-import android.hardware.automotive.vehicle.V2_0.VehicleAreaZone;
-import android.test.AndroidTestCase;
-import android.test.suitebuilder.annotation.SmallTest;
-
-@SmallTest
-public class VehicleZoneTest extends AndroidTestCase {
-
- public void testMatchWithVehicleHal() {
- assertEquals(VehicleAreaZone.WHOLE_CABIN, VehicleZone.ZONE_ALL);
- assertEquals(VehicleAreaZone.ROW_1, VehicleZone.ZONE_ROW_1_ALL);
- assertEquals(VehicleAreaZone.ROW_1_CENTER, VehicleZone.ZONE_ROW_1_CENTER);
- assertEquals(VehicleAreaZone.ROW_1_LEFT, VehicleZone.ZONE_ROW_1_LEFT);
- assertEquals(VehicleAreaZone.ROW_1_RIGHT, VehicleZone.ZONE_ROW_1_RIGHT);
- assertEquals(VehicleAreaZone.ROW_2, VehicleZone.ZONE_ROW_2_ALL);
- assertEquals(VehicleAreaZone.ROW_2_CENTER, VehicleZone.ZONE_ROW_2_CENTER);
- assertEquals(VehicleAreaZone.ROW_2_LEFT, VehicleZone.ZONE_ROW_2_LEFT);
- assertEquals(VehicleAreaZone.ROW_2_RIGHT, VehicleZone.ZONE_ROW_2_RIGHT);
- assertEquals(VehicleAreaZone.ROW_3, VehicleZone.ZONE_ROW_3_ALL);
- assertEquals(VehicleAreaZone.ROW_3_CENTER, VehicleZone.ZONE_ROW_3_CENTER);
- assertEquals(VehicleAreaZone.ROW_3_LEFT, VehicleZone.ZONE_ROW_3_LEFT);
- assertEquals(VehicleAreaZone.ROW_3_RIGHT, VehicleZone.ZONE_ROW_3_RIGHT);
- assertEquals(VehicleAreaZone.ROW_4, VehicleZone.ZONE_ROW_4_ALL);
- assertEquals(VehicleAreaZone.ROW_4_CENTER, VehicleZone.ZONE_ROW_4_CENTER);
- assertEquals(VehicleAreaZone.ROW_4_LEFT, VehicleZone.ZONE_ROW_4_LEFT);
- assertEquals(VehicleAreaZone.ROW_4_RIGHT, VehicleZone.ZONE_ROW_4_RIGHT);
- }
-}
diff --git a/tests/android_car_api_test/src/android/car/apitest/VehicleZoneUtilTest.java b/tests/android_car_api_test/src/android/car/apitest/VehicleZoneUtilTest.java
deleted file mode 100644
index 8ce2e5a..0000000
--- a/tests/android_car_api_test/src/android/car/apitest/VehicleZoneUtilTest.java
+++ /dev/null
@@ -1,107 +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.apitest;
-
-import android.car.VehicleZoneUtil;
-import android.test.AndroidTestCase;
-import android.test.suitebuilder.annotation.SmallTest;
-
-@SmallTest
-public class VehicleZoneUtilTest extends AndroidTestCase {
-
- public void testZoneToIndex() {
- int[] zones = {0, 0, 1, 0xf0, 0xf};
- int[] zone = {0, 1, 0, 0x1, 0x6};
-
- // Test failure cases
- for (int i = 0; i < zones.length; i++) {
- try {
- int r = VehicleZoneUtil.zoneToIndex(zones[i], zone[i]);
- fail();
- } catch (IllegalArgumentException e) {
- // expected
- }
- }
-
- zones = new int[] {0xffffffff, 0xffffffff, 0x1002, 0x1002};
- zone = new int[] { 0x1, 0x80000000, 0x2, 0x1000};
- int[] result = { 0, 31, 0, 1};
-
- // Test passing cases
- for (int i = 0; i < zones.length; i++) {
- assertEquals(result[i], VehicleZoneUtil.zoneToIndex(zones[i], zone[i]));
- }
- }
-
- public void testGetNumberOfZones() {
- int[] zones = {0, 0x1, 0x7, 0xffffffff};
- int[] result = {0, 1, 3, 32};
-
- for (int i = 0; i < zones.length; i++) {
- assertEquals(result[i], VehicleZoneUtil.getNumberOfZones(zones[i]));
- }
- }
-
- public void testGetFirstZone() {
- int[] zones = {0, 1, 0xffff00};
- int[] result = {0, 1, 0x100};
-
- for (int i = 0; i < zones.length; i++) {
- assertEquals(result[i], VehicleZoneUtil.getFirstZone(zones[i]));
- }
- }
-
- public void testGetNextZone() {
- int[] zones = {0, 1, 0x7};
- int[] startingZone = {0, 0, 0x3};
-
- // Test failure cases
- for (int i = 0; i < zones.length; i++) {
- try {
- int r = VehicleZoneUtil.getNextZone(zones[i], startingZone[i]);
- fail();
- } catch (IllegalArgumentException e) {
- // expected
- }
- }
-
- zones = new int[] {0, 1, 0xff00, 0xff00, 0xf, 0xf0000000};
- startingZone = new int[] {1, 1, 1, 0x100, 0x2, 0x40000000};
- int[] result = {0, 0, 0x100, 0x200, 0x4, 0x80000000};
-
- // Test passing cases
- for (int i = 0; i < zones.length; i++) {
- assertEquals(result[i], VehicleZoneUtil.getNextZone(zones[i], startingZone[i]));
- }
- }
-
- public void testGetAllZones() {
- int zones = 0;
- int[] list = VehicleZoneUtil.listAllZones(zones);
- assertEquals(0, list.length);
- zones = 0xffffffff;
- list = VehicleZoneUtil.listAllZones(zones);
- assertEquals(32, list.length);
- for (int i = 0; i < 32; i++) {
- assertEquals(0x1<<i, list[i]);
- }
- zones = 0x1001;
- list = VehicleZoneUtil.listAllZones(zones);
- assertEquals(2, list.length);
- assertEquals(0x1, list[0]);
- assertEquals(0x1000, list[1]);
- }
-}
diff --git a/tests/android_support_car_api_test/Android.mk b/tests/android_support_car_api_test/Android.mk
index 767401f..90aa767 100644
--- a/tests/android_support_car_api_test/Android.mk
+++ b/tests/android_support_car_api_test/Android.mk
@@ -33,9 +33,9 @@
LOCAL_PROGUARD_ENABLED := disabled
-LOCAL_STATIC_JAVA_LIBRARIES := junit legacy-android-test
+LOCAL_STATIC_JAVA_LIBRARIES := junit
LOCAL_STATIC_JAVA_LIBRARIES += android.support.car android-support-test
-LOCAL_JAVA_LIBRARIES := android.car android.test.runner
+LOCAL_JAVA_LIBRARIES := android.car android.test.runner android.test.base
include $(BUILD_PACKAGE)
diff --git a/tests/android_support_car_api_test/src/com/android/support/car/apitest/CarAppFocusManagerTest.java b/tests/android_support_car_api_test/src/com/android/support/car/apitest/CarAppFocusManagerTest.java
index 31670a0..2d58e56 100644
--- a/tests/android_support_car_api_test/src/com/android/support/car/apitest/CarAppFocusManagerTest.java
+++ b/tests/android_support_car_api_test/src/com/android/support/car/apitest/CarAppFocusManagerTest.java
@@ -36,10 +36,16 @@
// Request all application focuses and abandon them to ensure no active context is present
// when test starts.
+ int[] activeTypes = {CarAppFocusManager.APP_FOCUS_TYPE_NAVIGATION,
+ CarAppFocusManager.APP_FOCUS_TYPE_VOICE_COMMAND};
FocusOwnershipCallback owner = new FocusOwnershipCallback();
- mManager.requestAppFocus(CarAppFocusManager.APP_FOCUS_TYPE_NAVIGATION, owner);
- mManager.requestAppFocus(CarAppFocusManager.APP_FOCUS_TYPE_VOICE_COMMAND, owner);
- mManager.abandonAppFocus(owner);
+ for (int i = 0; i < activeTypes.length; i++) {
+ mManager.requestAppFocus(activeTypes[i], owner);
+ owner.waitForOwnershipGrantAndAssert(DEFAULT_WAIT_TIMEOUT_MS, activeTypes[i]);
+ mManager.abandonAppFocus(owner, activeTypes[i]);
+ owner.waitForOwnershipLossAndAssert(
+ DEFAULT_WAIT_TIMEOUT_MS, activeTypes[i]);
+ }
}
public void testSetActiveNullListener() throws Exception {
diff --git a/tests/android_support_car_api_test/src/com/android/support/car/apitest/CarNavigationStatusManagerTest.java b/tests/android_support_car_api_test/src/com/android/support/car/apitest/CarNavigationStatusManagerTest.java
index 1972c48..d57d9ee 100644
--- a/tests/android_support_car_api_test/src/com/android/support/car/apitest/CarNavigationStatusManagerTest.java
+++ b/tests/android_support_car_api_test/src/com/android/support/car/apitest/CarNavigationStatusManagerTest.java
@@ -17,6 +17,7 @@
import static android.support.car.CarAppFocusManager.APP_FOCUS_TYPE_NAVIGATION;
+import android.os.Bundle;
import android.support.car.Car;
import android.support.car.CarAppFocusManager;
import android.support.car.CarAppFocusManager.OnAppFocusChangedListener;
@@ -71,8 +72,7 @@
assertTrue(onStartLatch.await(DEFAULT_WAIT_TIMEOUT_MS, TimeUnit.MILLISECONDS));
try {
- mCarNavigationStatusManager.sendNavigationStatus(CarNavigationStatusManager
- .STATUS_ACTIVE);
+ mCarNavigationStatusManager.sendEvent(1, new Bundle());
fail();
} catch (IllegalStateException expected) {
// Expected. Client should acquire focus ownership for APP_FOCUS_TYPE_NAVIGATION.
@@ -103,6 +103,6 @@
// TODO: we should use mocked HAL to be able to verify this, right now just make sure that
// it is not crashing and logcat has appropriate traces.
- mCarNavigationStatusManager.sendNavigationStatus(CarNavigationStatusManager.STATUS_ACTIVE);
+ mCarNavigationStatusManager.sendEvent(1, new Bundle());
}
}
diff --git a/tests/android_support_car_api_test/src/com/android/support/car/apitest/CarSensorManagerTest.java b/tests/android_support_car_api_test/src/com/android/support/car/apitest/CarSensorManagerTest.java
index c60496b..bc97d67 100644
--- a/tests/android_support_car_api_test/src/com/android/support/car/apitest/CarSensorManagerTest.java
+++ b/tests/android_support_car_api_test/src/com/android/support/car/apitest/CarSensorManagerTest.java
@@ -16,6 +16,8 @@
package com.android.support.car.apitest;
+import static android.content.pm.PackageManager.FEATURE_AUTOMOTIVE;
+
import android.os.Looper;
import android.support.car.Car;
import android.support.car.CarConnectionCallback;
@@ -79,6 +81,12 @@
}
public void testDrivingPolicy() throws Exception {
+ // Embedded does not support SENSOR_TYPE_DRIVING_STATUS. Hence this test is not run in
+ // Android Auto Embedded.
+ if (getContext().getPackageManager().hasSystemFeature(FEATURE_AUTOMOTIVE)) {
+ return;
+ }
+
int[] supportedSensors = mCarSensorManager.getSupportedSensors();
assertNotNull(supportedSensors);
boolean found = false;
diff --git a/tests/carservice_test/Android.mk b/tests/carservice_test/Android.mk
index 95e1404..d4c327c 100644
--- a/tests/carservice_test/Android.mk
+++ b/tests/carservice_test/Android.mk
@@ -37,13 +37,18 @@
LOCAL_PROGUARD_ENABLED := disabled
-LOCAL_STATIC_JAVA_LIBRARIES := junit legacy-android-test
+LOCAL_STATIC_JAVA_LIBRARIES := junit
LOCAL_STATIC_JAVA_LIBRARIES += car-service-lib-for-test \
vehicle-hal-support-lib \
car-systemtest \
+ mockito-target-inline \
android-support-test \
- android.hardware.automotive.vehicle-V2.0-java-static
+ android.hardware.automotive.vehicle-V2.0-java \
+ com.android.car.test.utils \
+ truth-prebuilt
-LOCAL_JAVA_LIBRARIES := android.car android.test.runner
+LOCAL_JAVA_LIBRARIES := android.car android.test.runner android.test.base
+
+LOCAL_JNI_SHARED_LIBRARIES := libdexmakerjvmtiagent
include $(BUILD_PACKAGE)
diff --git a/tests/carservice_test/AndroidManifest.xml b/tests/carservice_test/AndroidManifest.xml
index 6f7ba34..2be5a83 100644
--- a/tests/carservice_test/AndroidManifest.xml
+++ b/tests/carservice_test/AndroidManifest.xml
@@ -15,37 +15,48 @@
-->
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
- package="com.android.car.test"
- android:sharedUserId="android.uid.system" >
+ package="com.android.car.test" android:sharedUserId="android.uid.system">
<uses-permission android:name="android.Manifest.permission.MODIFY_AUDIO_ROUTING" />
- <uses-permission android:name="android.car.permission.CAR_HVAC" />
- <uses-permission android:name="android.car.permission.CAR_RADIO" />
+ <uses-permission android:name="android.car.permission.CONTROL_CAR_CLIMATE" />
+ <uses-permission android:name="android.car.permission.ADJUST_CAR_CABIN" />
+ <uses-permission android:name="android.car.permission.CAR_ENERGY" />
<uses-permission android:name="android.car.permission.CONTROL_APP_BLOCKING" />
<uses-permission android:name="android.car.permission.CAR_CONTROL_AUDIO_VOLUME" />
<uses-permission android:name="android.car.permission.CAR_CONTROL_AUDIO_SETTINGS" />
- <instrumentation android:name="android.test.InstrumentationTestRunner"
+ <uses-permission android:name="android.car.permission.STORAGE_MONITORING" />
+
+ <instrumentation android:name="android.support.test.runner.AndroidJUnitRunner"
android:targetPackage="com.android.car.test"
android:label="Tests for Car APIs"/>
- <application android:label="CarServiceTest">
+ <application android:label="CarServiceTest" android:name=".CarServiceTestApp"
+ android:debuggable="true">
<uses-library android:name="android.test.runner" />
- <service android:name="com.android.car.test.TestAppBlockingPolicyService"
+ <service android:name="com.android.car.TestAppBlockingPolicyService"
android:permission="android.car.permission.CONTROL_APP_BLOCKING">
<intent-filter>
<action android:name="android.car.content.pm.CarAppBlockingPolicyService"/>
</intent-filter>
</service>
- <activity android:name="com.android.car.test.SystemActivityMonitoringServiceTest$ActivityA" />
- <activity android:name="com.android.car.test.SystemActivityMonitoringServiceTest$ActivityB"
- android:taskAffinity="com.android.car.carservicetest.activity"/>
- <activity android:name="com.android.car.test.SystemActivityMonitoringServiceTest$ActivityC"
- android:process="com.android.car.carservicetest.activityC"/>
- <activity android:name="com.android.car.test.SystemActivityMonitoringServiceTest$BlockingActivity"
- android:taskAffinity="com.android.car.carservicetest.block"/>
- <service android:name=".SimpleVmsPublisherClientService"
- android:exported="true"
- />
- <service android:name=".VmsPublisherClientMockService" android:exported="true" />
+ <service android:name="com.android.car.SimpleVmsPublisherClientService"
+ android:exported="true" />
+ <service android:name="com.android.car.VmsPublisherClientMockService"
+ android:exported="true" />
+
+ <activity android:name="com.android.car.SystemActivityMonitoringServiceTest$ActivityA"/>
+ <activity android:name="com.android.car.SystemActivityMonitoringServiceTest$ActivityB"/>
+ <activity android:name="com.android.car.SystemActivityMonitoringServiceTest$ActivityC"/>
+ <activity android:name="com.android.car.SystemActivityMonitoringServiceTest$BlockingActivity"
+ android:taskAffinity="com.android.car.carservicetest.block"/>
+
+ <receiver android:name="com.android.car.CarStorageMonitoringBroadcastReceiver"
+ android:exported="true"
+ android:permission="android.car.permission.STORAGE_MONITORING">
+ <intent-filter>
+ <action android:name="android.car.storagemonitoring.EXCESSIVE_IO"/>
+ </intent-filter>
+ </receiver>
+
</application>
</manifest>
diff --git a/tests/carservice_test/src/android/media/tests/AudioPolicyTest.java b/tests/carservice_test/src/android/media/tests/AudioPolicyTest.java
index 3fc51f1..9fcf449 100644
--- a/tests/carservice_test/src/android/media/tests/AudioPolicyTest.java
+++ b/tests/carservice_test/src/android/media/tests/AudioPolicyTest.java
@@ -16,6 +16,9 @@
package android.media.tests;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+
import android.content.Context;
import android.media.AudioAttributes;
import android.media.AudioFormat;
@@ -27,43 +30,47 @@
import android.media.audiopolicy.AudioPolicy;
import android.os.Handler;
import android.os.Looper;
-import android.test.AndroidTestCase;
-import android.test.suitebuilder.annotation.MediumTest;
+import android.support.test.InstrumentationRegistry;
+import android.support.test.filters.MediumTest;
+import android.support.test.runner.AndroidJUnit4;
import android.util.Log;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
import java.util.ArrayList;
import java.util.concurrent.Semaphore;
import java.util.concurrent.TimeUnit;
+@RunWith(AndroidJUnit4.class)
@MediumTest
-public class AudioPolicyTest extends AndroidTestCase {
+public class AudioPolicyTest {
private static final String TAG = AudioPolicyTest.class.getSimpleName();
private static final long WAIT_TIMEOUT_MS = 1000;
private AudioManager mAudioManager;
private Handler mHandler;
+ private Context mContext = InstrumentationRegistry.getContext();
- @Override
- protected void setUp() throws Exception {
- super.setUp();
+ @Before
+ public void setUp() throws Exception {
mHandler = new Handler(Looper.getMainLooper());
final Semaphore mWaitSemaphore = new Semaphore(0);
- mHandler.post(new Runnable() {
- @Override
- public void run() {
- mAudioManager = (AudioManager) mContext.getSystemService(Context.AUDIO_SERVICE);
- mWaitSemaphore.release();
- }
+ mHandler.post(() -> {
+ mAudioManager = (AudioManager) mContext.getSystemService(Context.AUDIO_SERVICE);
+ mWaitSemaphore.release();
});
assertTrue(mWaitSemaphore.tryAcquire(WAIT_TIMEOUT_MS, TimeUnit.MILLISECONDS));
}
+ @Test
public void testAudioPorts() throws Exception {
AudioPortUpdateListener listener = new AudioPortUpdateListener();
mAudioManager.registerAudioPortUpdateListener(listener);
ArrayList<AudioPort> initialPorts = dumpAudioPorts("initial state");
AudioMix mediaMix = createAudioMix(AudioAttributes.CONTENT_TYPE_UNKNOWN,
AudioAttributes.CONTENT_TYPE_MUSIC);
- AudioPolicy audioPolicy = new AudioPolicy.Builder(getContext())
+ AudioPolicy audioPolicy = new AudioPolicy.Builder(mContext)
.addMix(mediaMix)
.setLooper(Looper.getMainLooper())
.build();
diff --git a/tests/carservice_test/src/com/android/car/test/AppFocusTest.java b/tests/carservice_test/src/com/android/car/AppFocusTest.java
similarity index 94%
rename from tests/carservice_test/src/com/android/car/test/AppFocusTest.java
rename to tests/carservice_test/src/com/android/car/AppFocusTest.java
index b63383e..630717f 100644
--- a/tests/carservice_test/src/com/android/car/test/AppFocusTest.java
+++ b/tests/carservice_test/src/com/android/car/AppFocusTest.java
@@ -13,21 +13,29 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package com.android.car.test;
+package com.android.car;
+
+import static org.junit.Assert.assertEquals;
import android.car.Car;
import android.car.CarAppFocusManager;
-import android.test.suitebuilder.annotation.MediumTest;
+import android.support.test.filters.MediumTest;
+import android.support.test.runner.AndroidJUnit4;
import android.util.Log;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
import java.util.concurrent.Semaphore;
import java.util.concurrent.TimeUnit;
+@RunWith(AndroidJUnit4.class)
@MediumTest
public class AppFocusTest extends MockedCarTestBase {
private static final String TAG = AppFocusTest.class.getSimpleName();
private static final long DEFAULT_WAIT_TIMEOUT_MS = 1000;
+ @Test
public void testFocusChange() throws Exception {
CarAppFocusManager manager = (CarAppFocusManager) getCar().getCarManager(
Car.APP_FOCUS_SERVICE);
diff --git a/tests/carservice_test/src/com/android/car/CarAudioManagerTest.java b/tests/carservice_test/src/com/android/car/CarAudioManagerTest.java
new file mode 100644
index 0000000..1eb641f
--- /dev/null
+++ b/tests/carservice_test/src/com/android/car/CarAudioManagerTest.java
@@ -0,0 +1,51 @@
+/*
+ * 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;
+
+import android.car.Car;
+import android.car.media.CarAudioManager;
+import android.support.test.filters.MediumTest;
+import android.support.test.runner.AndroidJUnit4;
+import android.util.Log;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+@RunWith(AndroidJUnit4.class)
+@MediumTest
+public class CarAudioManagerTest extends MockedCarTestBase {
+
+ private static final String TAG = CarAudioManagerTest.class.getSimpleName();
+
+ private CarAudioManager mCarAudioManager;
+
+
+ @Override
+ public void setUp() throws Exception {
+ super.setUp();
+ mCarAudioManager = (CarAudioManager) getCar().getCarManager(Car.AUDIO_SERVICE);
+ }
+
+ @Test
+ public void testGetExternalSources() throws Exception {
+ String[] sources = mCarAudioManager.getExternalSources();
+ // Log the sources we found. No other real error check as long as the query doesn't crash
+ // unless/until we have a known set of audio devices available.
+ for (String s: sources) {
+ Log.i(TAG, " Available ext source: " + s);
+ }
+ }
+}
diff --git a/tests/carservice_test/src/com/android/car/test/CarCabinManagerTest.java b/tests/carservice_test/src/com/android/car/CarCabinManagerTest.java
similarity index 86%
rename from tests/carservice_test/src/com/android/car/test/CarCabinManagerTest.java
rename to tests/carservice_test/src/com/android/car/CarCabinManagerTest.java
index cef163e..67725b9 100644
--- a/tests/carservice_test/src/com/android/car/test/CarCabinManagerTest.java
+++ b/tests/carservice_test/src/com/android/car/CarCabinManagerTest.java
@@ -14,7 +14,11 @@
* limitations under the License.
*/
-package com.android.car.test;
+package com.android.car;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
import android.car.Car;
import android.car.hardware.CarPropertyValue;
@@ -26,18 +30,23 @@
import android.hardware.automotive.vehicle.V2_0.VehiclePropValue;
import android.hardware.automotive.vehicle.V2_0.VehicleProperty;
import android.os.SystemClock;
-import android.test.suitebuilder.annotation.MediumTest;
+import android.support.test.filters.MediumTest;
+import android.support.test.runner.AndroidJUnit4;
import android.util.Log;
import android.util.MutableInt;
import com.android.car.vehiclehal.VehiclePropValueBuilder;
import com.android.car.vehiclehal.test.MockedVehicleHal.VehicleHalPropertyHandler;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
import java.util.HashMap;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.Semaphore;
import java.util.concurrent.TimeUnit;
+@RunWith(AndroidJUnit4.class)
@MediumTest
public class CarCabinManagerTest extends MockedCarTestBase {
private static final String TAG = CarCabinManagerTest.class.getSimpleName();
@@ -54,19 +63,20 @@
protected synchronized void configureMockedHal() {
CabinPropertyHandler handler = new CabinPropertyHandler();
addProperty(VehicleProperty.DOOR_LOCK, handler)
- .setSupportedAreas(VehicleAreaDoor.ROW_1_LEFT);
+ .addAreaConfig(VehicleAreaDoor.ROW_1_LEFT, 0, 0);
addProperty(VehicleProperty.WINDOW_POS, handler)
- .setSupportedAreas(VehicleAreaWindow.ROW_1_LEFT);
+ .addAreaConfig(VehicleAreaWindow.ROW_1_LEFT, 0, 0);
}
@Override
- protected void setUp() throws Exception {
+ public void setUp() throws Exception {
super.setUp();
mAvailable = new Semaphore(0);
mCarCabinManager = (CarCabinManager) getCar().getCarManager(Car.CABIN_SERVICE);
}
// Test a boolean property
+ @Test
public void testCabinDoorLockOn() throws Exception {
mCarCabinManager.setBooleanProperty(CarCabinManager.ID_DOOR_LOCK,
VehicleAreaDoor.ROW_1_LEFT, true);
@@ -82,6 +92,7 @@
}
// Test an integer property
+ @Test
public void testCabinWindowPos() throws Exception {
mCarCabinManager.setIntProperty(CarCabinManager.ID_WINDOW_POS,
VehicleAreaWindow.ROW_1_LEFT, 50);
@@ -96,6 +107,7 @@
assertEquals(25, windowPos);
}
+ @Test
public void testError() throws Exception {
final int PROP = VehicleProperty.DOOR_LOCK;
final int AREA = VehicleAreaWindow.ROW_1_LEFT;
@@ -127,9 +139,12 @@
// Test an event
+ @Test
public void testEvent() throws Exception {
mCarCabinManager.registerCallback(new EventListener());
-
+ // Wait for two events generated on registration
+ assertTrue(mAvailable.tryAcquire(2L, TimeUnit.SECONDS));
+ assertTrue(mAvailable.tryAcquire(2L, TimeUnit.SECONDS));
// Inject a boolean event and wait for its callback in onPropertySet.
VehiclePropValue v = VehiclePropValueBuilder.newBuilder(VehicleProperty.DOOR_LOCK)
.setAreaId(VehicleAreaDoor.ROW_1_LEFT)
@@ -150,7 +165,6 @@
.setTimestamp(SystemClock.elapsedRealtimeNanos())
.addIntValue(75)
.build();
-
assertEquals(0, mAvailable.availablePermits());
getMockedVehicleHal().injectEvent(v);
@@ -176,8 +190,17 @@
}
@Override
- public synchronized void onPropertySubscribe(int property, int zones, float sampleRate) {
+ public synchronized void onPropertySubscribe(int property, float sampleRate) {
Log.d(TAG, "onPropertySubscribe property " + property + " sampleRate " + sampleRate);
+ if (mMap.get(property) == null) {
+ Log.d(TAG, "onPropertySubscribe add dummy property: " + property);
+ VehiclePropValue dummyValue = VehiclePropValueBuilder.newBuilder(property)
+ .setAreaId(VehicleAreaDoor.ROW_1_LEFT)
+ .setTimestamp(SystemClock.elapsedRealtimeNanos())
+ .addIntValue(1)
+ .build();
+ mMap.put(property, dummyValue);
+ }
}
@Override
diff --git a/tests/carservice_test/src/com/android/car/test/CarDiagnosticConstantsTest.java b/tests/carservice_test/src/com/android/car/CarDiagnosticConstantsTest.java
similarity index 94%
rename from tests/carservice_test/src/com/android/car/test/CarDiagnosticConstantsTest.java
rename to tests/carservice_test/src/com/android/car/CarDiagnosticConstantsTest.java
index 2ed2658..4d08e2d 100644
--- a/tests/carservice_test/src/com/android/car/test/CarDiagnosticConstantsTest.java
+++ b/tests/carservice_test/src/com/android/car/CarDiagnosticConstantsTest.java
@@ -14,24 +14,29 @@
* limitations under the License.
*/
-package com.android.car.test;
+package com.android.car;
-import android.test.suitebuilder.annotation.MediumTest;
+import android.support.test.filters.MediumTest;
+import android.support.test.runner.AndroidJUnit4;
import android.util.Log;
+import junit.framework.TestCase;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
-import junit.framework.TestCase;
-
/**
* Validates that diagnostic constants in CarService and Vehicle HAL have the same value
* This is an important assumption to validate because we do not perform any mapping between
* the two layers, instead relying on the constants on both sides having identical values.
*/
+@RunWith(AndroidJUnit4.class)
@MediumTest
public class CarDiagnosticConstantsTest extends TestCase {
static final String TAG = CarDiagnosticConstantsTest.class.getSimpleName();
@@ -137,22 +142,23 @@
}
}
+ @Test
public void testFuelSystemStatus() throws Exception {
validateMatch(android.hardware.automotive.vehicle.V2_0.Obd2FuelSystemStatus.class,
android.car.diagnostic.CarDiagnosticEvent.FuelSystemStatus.class);
}
- public void testFuelType() throws Exception {
+ @Test public void testFuelType() throws Exception {
validateMatch(android.hardware.automotive.vehicle.V2_0.Obd2FuelType.class,
android.car.diagnostic.CarDiagnosticEvent.FuelType.class);
}
- public void testSecondaryAirStatus() throws Exception {
+ @Test public void testSecondaryAirStatus() throws Exception {
validateMatch(android.hardware.automotive.vehicle.V2_0.Obd2SecondaryAirStatus.class,
android.car.diagnostic.CarDiagnosticEvent.SecondaryAirStatus.class);
}
- public void testIgnitionMonitors() throws Exception {
+ @Test public void testIgnitionMonitors() throws Exception {
validateMatch(android.hardware.automotive.vehicle.V2_0.Obd2CommonIgnitionMonitors.class,
android.car.diagnostic.CarDiagnosticEvent.CommonIgnitionMonitors.class);
diff --git a/tests/carservice_test/src/com/android/car/test/CarDiagnosticManagerTest.java b/tests/carservice_test/src/com/android/car/CarDiagnosticManagerTest.java
similarity index 94%
rename from tests/carservice_test/src/com/android/car/test/CarDiagnosticManagerTest.java
rename to tests/carservice_test/src/com/android/car/CarDiagnosticManagerTest.java
index b77a844..ac07d0e 100644
--- a/tests/carservice_test/src/com/android/car/test/CarDiagnosticManagerTest.java
+++ b/tests/carservice_test/src/com/android/car/CarDiagnosticManagerTest.java
@@ -14,40 +14,53 @@
* limitations under the License.
*/
-package com.android.car.test;
+package com.android.car;
import static java.lang.Integer.toHexString;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
import android.car.Car;
import android.car.diagnostic.CarDiagnosticEvent;
-import android.car.diagnostic.CarDiagnosticEvent.FuelSystemStatus;
-import android.car.diagnostic.CarDiagnosticEvent.FuelType;
import android.car.diagnostic.CarDiagnosticEvent.CommonIgnitionMonitors;
import android.car.diagnostic.CarDiagnosticEvent.CompressionIgnitionMonitors;
-import android.car.diagnostic.CarDiagnosticEvent.SparkIgnitionMonitors;
+import android.car.diagnostic.CarDiagnosticEvent.FuelSystemStatus;
+import android.car.diagnostic.CarDiagnosticEvent.FuelType;
import android.car.diagnostic.CarDiagnosticEvent.SecondaryAirStatus;
+import android.car.diagnostic.CarDiagnosticEvent.SparkIgnitionMonitors;
import android.car.diagnostic.CarDiagnosticManager;
import android.car.diagnostic.FloatSensorIndex;
import android.car.diagnostic.IntegerSensorIndex;
import android.hardware.automotive.vehicle.V2_0.VehiclePropValue;
import android.hardware.automotive.vehicle.V2_0.VehicleProperty;
import android.os.SystemClock;
-import android.test.suitebuilder.annotation.MediumTest;
+import android.support.test.filters.MediumTest;
+import android.support.test.runner.AndroidJUnit4;
import android.util.JsonReader;
import android.util.JsonWriter;
import android.util.Log;
+
import com.android.car.vehiclehal.DiagnosticEventBuilder;
import com.android.car.vehiclehal.DiagnosticJson;
import com.android.car.vehiclehal.VehiclePropValueBuilder;
import com.android.car.vehiclehal.test.MockedVehicleHal.VehicleHalPropertyHandler;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
import java.io.StringReader;
import java.io.StringWriter;
import java.util.Arrays;
+import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Set;
/** Test the public entry points for the CarDiagnosticManager */
+@RunWith(AndroidJUnit4.class)
@MediumTest
public class CarDiagnosticManagerTest extends MockedCarTestBase {
private static final String TAG = CarDiagnosticManagerTest.class.getSimpleName();
@@ -61,6 +74,7 @@
private CarDiagnosticManager mCarDiagnosticManager;
private static final String DTC = "P1010";
+ private static final float EPS = 1e-9f;
/**
* This class is a central repository for freeze frame data. It ensures that timestamps and
@@ -123,8 +137,7 @@
}
@Override
- public synchronized void onPropertySubscribe(
- int property, int zones, float sampleRate) {
+ public synchronized void onPropertySubscribe(int property, float sampleRate) {
assertEquals(VEHICLE_PROPERTY, property);
mSubscribed = true;
}
@@ -190,6 +203,7 @@
@Override
protected synchronized void configureMockedHal() {
java.util.Collection<Integer> numVendorSensors = Arrays.asList(0, 0);
+ java.util.Collection<Integer> selectiveClear = Collections.singletonList(1);
addProperty(VehicleProperty.OBD2_LIVE_FRAME, mLiveFrameEventBuilder.build())
.setConfigArray(numVendorSensors);
addProperty(
@@ -199,11 +213,12 @@
.setConfigArray(numVendorSensors);
addProperty(
VehicleProperty.OBD2_FREEZE_FRAME_CLEAR,
- mFreezeFrameProperties.mFreezeFrameClearHandler);
+ mFreezeFrameProperties.mFreezeFrameClearHandler)
+ .setConfigArray(selectiveClear);
}
@Override
- protected void setUp() throws Exception {
+ public void setUp() throws Exception {
mLiveFrameEventBuilder.addIntSensor(IntegerSensorIndex.AMBIENT_AIR_TEMPERATURE, 30);
mLiveFrameEventBuilder.addIntSensor(
IntegerSensorIndex.FUEL_SYSTEM_STATUS,
@@ -230,7 +245,7 @@
(CarDiagnosticManager) getCar().getCarManager(Car.DIAGNOSTIC_SERVICE);
}
- public void testLiveFrameRead() throws Exception {
+ @Test public void testLiveFrameRead() throws Exception {
CarDiagnosticEvent liveFrame = mCarDiagnosticManager.getLatestLiveFrame();
assertNotNull(liveFrame);
@@ -255,15 +270,15 @@
.intValue());
assertEquals(
0.125f,
- liveFrame
- .getSystemFloatSensor(FloatSensorIndex.CALCULATED_ENGINE_LOAD)
- .floatValue());
+ liveFrame.getSystemFloatSensor(FloatSensorIndex.CALCULATED_ENGINE_LOAD),
+ EPS);
assertEquals(
12.5f,
- liveFrame.getSystemFloatSensor(FloatSensorIndex.VEHICLE_SPEED).floatValue());
+ liveFrame.getSystemFloatSensor(FloatSensorIndex.VEHICLE_SPEED),
+ EPS);
}
- public void testLiveFrameEvent() throws Exception {
+ @Test public void testLiveFrameEvent() throws Exception {
Listener listener = new Listener();
mCarDiagnosticManager.registerListener(
listener,
@@ -287,7 +302,7 @@
.intValue());
}
- public void testMissingSensorRead() throws Exception {
+ @Test public void testMissingSensorRead() throws Exception {
Listener listener = new Listener();
mCarDiagnosticManager.registerListener(
listener,
@@ -311,17 +326,17 @@
assertNull(liveFrame.getSystemFloatSensor(FloatSensorIndex.OXYGEN_SENSOR6_VOLTAGE));
assertEquals(
0.25f,
- liveFrame.getSystemFloatSensor(FloatSensorIndex.OXYGEN_SENSOR5_VOLTAGE, 0.25f));
+ liveFrame.getSystemFloatSensor(FloatSensorIndex.OXYGEN_SENSOR5_VOLTAGE, 0.25f), EPS);
assertNull(liveFrame.getVendorIntegerSensor(IntegerSensorIndex.VENDOR_START));
assertEquals(-1, liveFrame.getVendorIntegerSensor(IntegerSensorIndex.VENDOR_START, -1));
assertNull(liveFrame.getVendorFloatSensor(FloatSensorIndex.VENDOR_START));
assertEquals(
- 0.25f, liveFrame.getVendorFloatSensor(FloatSensorIndex.VENDOR_START, 0.25f));
+ 0.25f, liveFrame.getVendorFloatSensor(FloatSensorIndex.VENDOR_START, 0.25f), EPS);
}
- public void testFuelSystemStatus() throws Exception {
+ @Test public void testFuelSystemStatus() throws Exception {
Listener listener = new Listener();
mCarDiagnosticManager.registerListener(
listener,
@@ -344,7 +359,7 @@
liveFrame.getFuelSystemStatus().intValue());
}
- public void testSecondaryAirStatus() throws Exception {
+ @Test public void testSecondaryAirStatus() throws Exception {
Listener listener = new Listener();
mCarDiagnosticManager.registerListener(
listener,
@@ -373,7 +388,7 @@
liveFrame.getSecondaryAirStatus().intValue());
}
- public void testIgnitionMonitors() throws Exception {
+ @Test public void testIgnitionMonitors() throws Exception {
Listener listener = new Listener();
mCarDiagnosticManager.registerListener(
listener,
@@ -470,7 +485,7 @@
assertFalse(compressionIgnitionMonitors.NMHCCatalyst.incomplete);
}
- public void testFuelType() throws Exception {
+ @Test public void testFuelType() throws Exception {
Listener listener = new Listener();
mCarDiagnosticManager.registerListener(
listener,
@@ -493,7 +508,7 @@
assertEquals(FuelType.BIFUEL_RUNNING_LPG, liveFrame.getFuelType().intValue());
}
- public void testDiagnosticJson() throws Exception {
+ @Test public void testDiagnosticJson() throws Exception {
Listener listener = new Listener();
mCarDiagnosticManager.registerListener(
listener,
@@ -518,7 +533,8 @@
.intValue());
assertEquals(
0.125f,
- liveFrame.getSystemFloatSensor(FloatSensorIndex.OXYGEN_SENSOR1_VOLTAGE));
+ liveFrame.getSystemFloatSensor(FloatSensorIndex.OXYGEN_SENSOR1_VOLTAGE),
+ EPS);
StringWriter stringWriter = new StringWriter();
JsonWriter jsonWriter = new JsonWriter(stringWriter);
@@ -538,9 +554,11 @@
.intValue());
assertEquals(
0.125f,
- diagnosticJson.floatValues.get(FloatSensorIndex.OXYGEN_SENSOR1_VOLTAGE));
+ diagnosticJson.floatValues.get(FloatSensorIndex.OXYGEN_SENSOR1_VOLTAGE),
+ EPS);
}
+ @Test
public void testMultipleListeners() throws Exception {
Listener listener1 = new Listener();
Listener listener2 = new Listener();
@@ -605,6 +623,7 @@
.intValue());
}
+ @Test
public void testFreezeFrameEvent() throws Exception {
Listener listener = new Listener();
mCarDiagnosticManager.registerListener(
@@ -643,6 +662,7 @@
.intValue());
}
+ @Test
public void testFreezeFrameTimestamps() throws Exception {
Listener listener = new Listener();
mCarDiagnosticManager.registerListener(
@@ -672,6 +692,7 @@
}
}
+ @Test
public void testClearFreezeFrameTimestamps() throws Exception {
Listener listener = new Listener();
mCarDiagnosticManager.registerListener(
@@ -689,6 +710,7 @@
assertNull(mCarDiagnosticManager.getFreezeFrame(injectedEvent.timestamp));
}
+ @Test
public void testListenerUnregister() throws Exception {
Listener listener1 = new Listener();
Listener listener2 = new Listener();
@@ -727,11 +749,13 @@
assertTrue(listener2.waitForEvent(time));
}
+ @Test
public void testIsSupportedApiCalls() throws Exception {
assertTrue(mCarDiagnosticManager.isLiveFrameSupported());
assertTrue(mCarDiagnosticManager.isFreezeFrameNotificationSupported());
assertTrue(mCarDiagnosticManager.isGetFreezeFrameSupported());
assertTrue(mCarDiagnosticManager.isClearFreezeFramesSupported());
+ assertTrue(mCarDiagnosticManager.isSelectiveClearFreezeFramesSupported());
}
class Listener implements CarDiagnosticManager.OnDiagnosticEventListener {
diff --git a/tests/carservice_test/src/com/android/car/CarDrivingRestrictionsTest.java b/tests/carservice_test/src/com/android/car/CarDrivingRestrictionsTest.java
new file mode 100644
index 0000000..31ed4b2
--- /dev/null
+++ b/tests/carservice_test/src/com/android/car/CarDrivingRestrictionsTest.java
@@ -0,0 +1,292 @@
+/*
+ * 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;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
+
+import android.car.Car;
+import android.car.CarNotConnectedException;
+import android.car.drivingstate.CarDrivingStateEvent;
+import android.car.drivingstate.CarDrivingStateManager;
+import android.car.drivingstate.CarUxRestrictions;
+import android.car.drivingstate.CarUxRestrictionsManager;
+import android.hardware.automotive.vehicle.V2_0.VehicleGear;
+import android.hardware.automotive.vehicle.V2_0.VehicleProperty;
+import android.os.SystemClock;
+import android.support.test.filters.SmallTest;
+import android.support.test.runner.AndroidJUnit4;
+import android.util.Log;
+
+import com.android.car.vehiclehal.VehiclePropValueBuilder;
+import com.android.internal.annotations.GuardedBy;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+@RunWith(AndroidJUnit4.class)
+@SmallTest
+public class CarDrivingRestrictionsTest extends MockedCarTestBase {
+ private static final String TAG = CarDrivingRestrictionsTest.class
+ .getSimpleName();
+ private CarDrivingStateManager mCarDrivingStateManager;
+ private CarUxRestrictionsManager mCarUxRManager;
+
+ @Override
+ protected synchronized void configureMockedHal() {
+ addProperty(VehicleProperty.PERF_VEHICLE_SPEED, VehiclePropValueBuilder
+ .newBuilder(VehicleProperty.PERF_VEHICLE_SPEED)
+ .addFloatValue(0f)
+ .build());
+ addProperty(VehicleProperty.PARKING_BRAKE_ON, VehiclePropValueBuilder
+ .newBuilder(VehicleProperty.PARKING_BRAKE_ON)
+ .setBooleanValue(false)
+ .build());
+ addProperty(VehicleProperty.GEAR_SELECTION, VehiclePropValueBuilder
+ .newBuilder(VehicleProperty.GEAR_SELECTION)
+ .addIntValue(0)
+ .build());
+ }
+
+ @Override
+ public void setUp() throws Exception {
+ super.setUp();
+ mCarDrivingStateManager = (CarDrivingStateManager) getCar()
+ .getCarManager(Car.CAR_DRIVING_STATE_SERVICE);
+ mCarUxRManager = (CarUxRestrictionsManager) getCar()
+ .getCarManager(Car.CAR_UX_RESTRICTION_SERVICE);
+ }
+
+ @Test
+ public void testDrivingStateChange() throws CarNotConnectedException, InterruptedException {
+ CarDrivingStateEvent drivingEvent;
+ CarUxRestrictions restrictions;
+ DrivingStateListener listener = new DrivingStateListener();
+ mCarDrivingStateManager.registerListener(listener);
+ mCarUxRManager.registerListener(listener);
+ // With no gear value available, driving state should be unknown
+ listener.reset();
+ // Test Parked state and corresponding restrictions based on car_ux_restrictions_map.xml
+ Log.d(TAG, "Injecting gear park");
+ getMockedVehicleHal().injectEvent(
+ VehiclePropValueBuilder.newBuilder(VehicleProperty.GEAR_SELECTION)
+ .addIntValue(VehicleGear.GEAR_PARK)
+ .setTimestamp(SystemClock.elapsedRealtimeNanos())
+ .build());
+ drivingEvent = listener.waitForDrivingStateChange();
+ assertNotNull(drivingEvent);
+ assertThat(drivingEvent.eventValue).isEqualTo(CarDrivingStateEvent.DRIVING_STATE_PARKED);
+
+ Log.d(TAG, "Injecting speed 0");
+ getMockedVehicleHal().injectEvent(
+ VehiclePropValueBuilder.newBuilder(VehicleProperty.PERF_VEHICLE_SPEED)
+ .addFloatValue(0.0f)
+ .setTimestamp(SystemClock.elapsedRealtimeNanos())
+ .build());
+
+ // Switch gear to drive. Driving state changes to Idling but the UX restrictions don't
+ // change between parked and idling.
+ listener.reset();
+ Log.d(TAG, "Injecting gear drive");
+ getMockedVehicleHal().injectEvent(
+ VehiclePropValueBuilder.newBuilder(VehicleProperty.GEAR_SELECTION)
+ .addIntValue(VehicleGear.GEAR_DRIVE)
+ .setTimestamp(SystemClock.elapsedRealtimeNanos())
+ .build());
+ drivingEvent = listener.waitForDrivingStateChange();
+ assertNotNull(drivingEvent);
+ assertThat(drivingEvent.eventValue).isEqualTo(CarDrivingStateEvent.DRIVING_STATE_IDLING);
+
+ // Test Moving state and corresponding restrictions based on car_ux_restrictions_map.xml
+ listener.reset();
+ Log.d(TAG, "Injecting speed 30");
+ getMockedVehicleHal().injectEvent(
+ VehiclePropValueBuilder.newBuilder(VehicleProperty.PERF_VEHICLE_SPEED)
+ .addFloatValue(30.0f)
+ .setTimestamp(SystemClock.elapsedRealtimeNanos())
+ .build());
+ drivingEvent = listener.waitForDrivingStateChange();
+ assertNotNull(drivingEvent);
+ assertThat(drivingEvent.eventValue).isEqualTo(CarDrivingStateEvent.DRIVING_STATE_MOVING);
+ restrictions = listener.waitForUxRestrictionsChange();
+ assertNotNull(restrictions);
+ assertTrue(restrictions.isRequiresDistractionOptimization());
+ assertThat(restrictions.getActiveRestrictions())
+ .isEqualTo(CarUxRestrictions.UX_RESTRICTIONS_FULLY_RESTRICTED);
+
+ // Test Idling state and corresponding restrictions based on car_ux_restrictions_map.xml
+ listener.reset();
+ Log.d(TAG, "Injecting speed 0");
+ getMockedVehicleHal().injectEvent(
+ VehiclePropValueBuilder.newBuilder(VehicleProperty.PERF_VEHICLE_SPEED)
+ .addFloatValue(0.0f)
+ .setTimestamp(SystemClock.elapsedRealtimeNanos())
+ .build());
+ drivingEvent = listener.waitForDrivingStateChange();
+ assertNotNull(drivingEvent);
+ assertThat(drivingEvent.eventValue).isEqualTo(CarDrivingStateEvent.DRIVING_STATE_IDLING);
+ restrictions = listener.waitForUxRestrictionsChange();
+ assertNotNull(restrictions);
+ assertFalse(restrictions.isRequiresDistractionOptimization());
+ assertThat(restrictions.getActiveRestrictions())
+ .isEqualTo(CarUxRestrictions.UX_RESTRICTIONS_BASELINE);
+
+ // Apply Parking brake. Supported gears is not provided in this test and hence
+ // Automatic transmission should be assumed and hence parking brake state should not
+ // make a difference to the driving state.
+ listener.reset();
+ Log.d(TAG, "Injecting parking brake on");
+ getMockedVehicleHal().injectEvent(
+ VehiclePropValueBuilder.newBuilder(VehicleProperty.PARKING_BRAKE_ON)
+ .setBooleanValue(true)
+ .setTimestamp(SystemClock.elapsedRealtimeNanos())
+ .build());
+ drivingEvent = listener.waitForDrivingStateChange();
+ assertNull(drivingEvent);
+
+ mCarDrivingStateManager.unregisterListener();
+ mCarUxRManager.unregisterListener();
+ }
+
+ @Test
+ public void testDrivingStateChangeForMalformedInputs()
+ throws CarNotConnectedException, InterruptedException {
+ CarDrivingStateEvent drivingEvent;
+ CarUxRestrictions restrictions;
+ DrivingStateListener listener = new DrivingStateListener();
+ mCarDrivingStateManager.registerListener(listener);
+ mCarUxRManager.registerListener(listener);
+
+ // Start with gear = park and speed = 0 to begin with a known state.
+ listener.reset();
+ Log.d(TAG, "Injecting gear park");
+ getMockedVehicleHal().injectEvent(
+ VehiclePropValueBuilder.newBuilder(VehicleProperty.GEAR_SELECTION)
+ .addIntValue(VehicleGear.GEAR_PARK)
+ .setTimestamp(SystemClock.elapsedRealtimeNanos())
+ .build());
+ drivingEvent = listener.waitForDrivingStateChange();
+ assertNotNull(drivingEvent);
+ assertThat(drivingEvent.eventValue).isEqualTo(CarDrivingStateEvent.DRIVING_STATE_PARKED);
+
+ Log.d(TAG, "Injecting speed 0");
+ getMockedVehicleHal().injectEvent(
+ VehiclePropValueBuilder.newBuilder(VehicleProperty.PERF_VEHICLE_SPEED)
+ .addFloatValue(0.0f)
+ .setTimestamp(SystemClock.elapsedRealtimeNanos())
+ .build());
+
+ // Inject an invalid gear. Since speed is still valid, idling will be the expected
+ // driving state
+ listener.reset();
+ Log.d(TAG, "Injecting gear -1");
+ getMockedVehicleHal().injectEvent(
+ VehiclePropValueBuilder.newBuilder(VehicleProperty.GEAR_SELECTION)
+ .addIntValue(-1)
+ .setTimestamp(SystemClock.elapsedRealtimeNanos())
+ .build());
+ drivingEvent = listener.waitForDrivingStateChange();
+ assertNotNull(drivingEvent);
+ assertThat(drivingEvent.eventValue).isEqualTo(CarDrivingStateEvent.DRIVING_STATE_IDLING);
+
+ // Now, send in an invalid speed value as well, now the driving state will be unknown and
+ // the UX restrictions will change to fully restricted.
+ listener.reset();
+ Log.d(TAG, "Injecting speed -1");
+ getMockedVehicleHal().injectEvent(
+ VehiclePropValueBuilder.newBuilder(VehicleProperty.PERF_VEHICLE_SPEED)
+ .addFloatValue(-1.0f)
+ .setTimestamp(SystemClock.elapsedRealtimeNanos())
+ .build());
+ drivingEvent = listener.waitForDrivingStateChange();
+ assertNotNull(drivingEvent);
+ assertThat(drivingEvent.eventValue).isEqualTo(CarDrivingStateEvent.DRIVING_STATE_UNKNOWN);
+ restrictions = listener.waitForUxRestrictionsChange();
+ assertNotNull(restrictions);
+ assertTrue(restrictions.isRequiresDistractionOptimization());
+ assertThat(restrictions.getActiveRestrictions())
+ .isEqualTo(CarUxRestrictions.UX_RESTRICTIONS_FULLY_RESTRICTED);
+ mCarDrivingStateManager.unregisterListener();
+ mCarUxRManager.unregisterListener();
+ }
+
+ /**
+ * Callback function we register for driving state update notifications.
+ */
+ private class DrivingStateListener implements
+ CarDrivingStateManager.CarDrivingStateEventListener,
+ CarUxRestrictionsManager.OnUxRestrictionsChangedListener {
+ private final Object mDrivingStateLock = new Object();
+ @GuardedBy("mDrivingStateLock")
+ private CarDrivingStateEvent mLastEvent = null;
+ private final Object mUxRLock = new Object();
+ @GuardedBy("mUxRLock")
+ private CarUxRestrictions mLastRestrictions = null;
+
+ void reset() {
+ mLastEvent = null;
+ mLastRestrictions = null;
+ }
+
+ // Returns True to indicate receipt of a driving state event. False indicates a timeout.
+ CarDrivingStateEvent waitForDrivingStateChange() throws InterruptedException {
+ long start = SystemClock.elapsedRealtime();
+
+ synchronized (mDrivingStateLock) {
+ while (mLastEvent == null
+ && (start + DEFAULT_WAIT_TIMEOUT_MS > SystemClock.elapsedRealtime())) {
+ mDrivingStateLock.wait(100L);
+ }
+ return mLastEvent;
+ }
+ }
+
+ @Override
+ public void onDrivingStateChanged(CarDrivingStateEvent event) {
+ Log.d(TAG, "onDrivingStateChanged, event: " + event.eventValue);
+ synchronized (mDrivingStateLock) {
+ // We're going to hold a reference to this object
+ mLastEvent = event;
+ mDrivingStateLock.notify();
+ }
+ }
+
+ CarUxRestrictions waitForUxRestrictionsChange() throws InterruptedException {
+ long start = SystemClock.elapsedRealtime();
+ synchronized (mUxRLock) {
+ while (mLastRestrictions == null
+ && (start + DEFAULT_WAIT_TIMEOUT_MS > SystemClock.elapsedRealtime())) {
+ mUxRLock.wait(100L);
+ }
+ }
+ return mLastRestrictions;
+ }
+
+ @Override
+ public void onUxRestrictionsChanged(CarUxRestrictions restrictions) {
+ Log.d(TAG, "onUxRestrictionsChanged, restrictions: "
+ + restrictions.getActiveRestrictions());
+ synchronized (mUxRLock) {
+ mLastRestrictions = restrictions;
+ mUxRLock.notify();
+ }
+ }
+ }
+}
diff --git a/tests/carservice_test/src/com/android/car/test/CarHvacManagerTest.java b/tests/carservice_test/src/com/android/car/CarHvacManagerTest.java
similarity index 79%
rename from tests/carservice_test/src/com/android/car/test/CarHvacManagerTest.java
rename to tests/carservice_test/src/com/android/car/CarHvacManagerTest.java
index 07f879e..1493fe9 100644
--- a/tests/carservice_test/src/com/android/car/test/CarHvacManagerTest.java
+++ b/tests/carservice_test/src/com/android/car/CarHvacManagerTest.java
@@ -14,32 +14,41 @@
* limitations under the License.
*/
-package com.android.car.test;
+package com.android.car;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
import android.car.Car;
import android.car.hardware.CarPropertyValue;
import android.car.hardware.hvac.CarHvacManager;
import android.car.hardware.hvac.CarHvacManager.CarHvacEventCallback;
import android.car.hardware.hvac.CarHvacManager.PropertyId;
+import android.hardware.automotive.vehicle.V2_0.VehicleAreaSeat;
import android.hardware.automotive.vehicle.V2_0.VehicleAreaWindow;
-import android.hardware.automotive.vehicle.V2_0.VehicleAreaZone;
import android.hardware.automotive.vehicle.V2_0.VehiclePropValue;
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.os.SystemClock;
-import android.test.suitebuilder.annotation.MediumTest;
+import android.support.test.filters.MediumTest;
+import android.support.test.runner.AndroidJUnit4;
import android.util.Log;
import android.util.MutableInt;
import com.android.car.vehiclehal.VehiclePropValueBuilder;
import com.android.car.vehiclehal.test.MockedVehicleHal.VehicleHalPropertyHandler;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
import java.util.HashMap;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.Semaphore;
import java.util.concurrent.TimeUnit;
+@RunWith(AndroidJUnit4.class)
@MediumTest
public class CarHvacManagerTest extends MockedCarTestBase {
private static final String TAG = CarHvacManagerTest.class.getSimpleName();
@@ -57,25 +66,26 @@
protected synchronized void configureMockedHal() {
HvacPropertyHandler handler = new HvacPropertyHandler();
addProperty(VehicleProperty.HVAC_DEFROSTER, handler)
- .setSupportedAreas(VehicleAreaWindow.FRONT_WINDSHIELD);
+ .addAreaConfig(VehicleAreaWindow.FRONT_WINDSHIELD, 0, 0);
addProperty(VehicleProperty.HVAC_FAN_SPEED, handler)
- .setSupportedAreas(VehicleAreaZone.ROW_1_LEFT);
+ .addAreaConfig(VehicleAreaSeat.ROW_1_LEFT, 0, 0);
addProperty(VehicleProperty.HVAC_TEMPERATURE_SET, handler)
- .setSupportedAreas(VehicleAreaZone.ROW_1_LEFT);
+ .addAreaConfig(VehicleAreaSeat.ROW_1_LEFT, 0, 0);
addProperty(VehicleProperty.HVAC_TEMPERATURE_CURRENT, handler)
.setChangeMode(VehiclePropertyChangeMode.CONTINUOUS)
.setAccess(VehiclePropertyAccess.READ)
- .setSupportedAreas(VehicleAreaZone.ROW_1);
+ .addAreaConfig(VehicleAreaSeat.ROW_1_LEFT | VehicleAreaSeat.ROW_1_RIGHT, 0, 0);
}
@Override
- protected void setUp() throws Exception {
+ public void setUp() throws Exception {
super.setUp();
mAvailable = new Semaphore(0);
mCarHvacManager = (CarHvacManager) getCar().getCarManager(Car.HVAC_SERVICE);
}
// Test a boolean property
+ @Test
public void testHvacRearDefrosterOn() throws Exception {
mCarHvacManager.setBooleanProperty(CarHvacManager.ID_WINDOW_DEFROSTER_ON,
VehicleAreaWindow.FRONT_WINDSHIELD, true);
@@ -91,35 +101,38 @@
}
// Test an integer property
+ @Test
public void testHvacFanSpeed() throws Exception {
mCarHvacManager.setIntProperty(CarHvacManager.ID_ZONED_FAN_SPEED_SETPOINT,
- VehicleAreaZone.ROW_1_LEFT, 15);
+ VehicleAreaSeat.ROW_1_LEFT, 15);
int speed = mCarHvacManager.getIntProperty(CarHvacManager.ID_ZONED_FAN_SPEED_SETPOINT,
- VehicleAreaZone.ROW_1_LEFT);
+ VehicleAreaSeat.ROW_1_LEFT);
assertEquals(15, speed);
mCarHvacManager.setIntProperty(CarHvacManager.ID_ZONED_FAN_SPEED_SETPOINT,
- VehicleAreaZone.ROW_1_LEFT, 23);
+ VehicleAreaSeat.ROW_1_LEFT, 23);
speed = mCarHvacManager.getIntProperty(CarHvacManager.ID_ZONED_FAN_SPEED_SETPOINT,
- VehicleAreaZone.ROW_1_LEFT);
+ VehicleAreaSeat.ROW_1_LEFT);
assertEquals(23, speed);
}
// Test an float property
+ @Test
public void testHvacTempSetpoint() throws Exception {
mCarHvacManager.setFloatProperty(CarHvacManager.ID_ZONED_TEMP_SETPOINT,
- VehicleAreaZone.ROW_1_LEFT, 70);
+ VehicleAreaSeat.ROW_1_LEFT, 70);
float temp = mCarHvacManager.getFloatProperty(CarHvacManager.ID_ZONED_TEMP_SETPOINT,
- VehicleAreaZone.ROW_1_LEFT);
+ VehicleAreaSeat.ROW_1_LEFT);
assertEquals(70.0, temp, 0);
mCarHvacManager.setFloatProperty(CarHvacManager.ID_ZONED_TEMP_SETPOINT,
- VehicleAreaZone.ROW_1_LEFT, (float) 65.5);
+ VehicleAreaSeat.ROW_1_LEFT, (float) 65.5);
temp = mCarHvacManager.getFloatProperty(CarHvacManager.ID_ZONED_TEMP_SETPOINT,
- VehicleAreaZone.ROW_1_LEFT);
+ VehicleAreaSeat.ROW_1_LEFT);
assertEquals(65.5, temp, 0);
}
+ @Test
public void testError() throws Exception {
final int PROP = VehicleProperty.HVAC_DEFROSTER;
final int AREA = VehicleAreaWindow.FRONT_WINDSHIELD;
@@ -129,7 +142,7 @@
MutableInt propertyIdReceived = new MutableInt(0);
MutableInt areaIdReceived = new MutableInt(0);
- mCarHvacManager.registerCallback(new CarHvacEventCallback() {
+ mCarHvacManager.registerCallback(new CarHvacEventCallback() {
@Override
public void onChangeEvent(CarPropertyValue value) {
@@ -150,8 +163,14 @@
}
// Test an event
+ @Test
public void testEvent() throws Exception {
mCarHvacManager.registerCallback(new EventListener());
+ // Wait for events generated on registration
+ assertTrue(mAvailable.tryAcquire(2L, TimeUnit.SECONDS));
+ assertTrue(mAvailable.tryAcquire(2L, TimeUnit.SECONDS));
+ assertTrue(mAvailable.tryAcquire(2L, TimeUnit.SECONDS));
+ assertTrue(mAvailable.tryAcquire(2L, TimeUnit.SECONDS));
// Inject a boolean event and wait for its callback in onPropertySet.
VehiclePropValue v = VehiclePropValueBuilder.newBuilder(VehicleProperty.HVAC_DEFROSTER)
@@ -168,7 +187,7 @@
// Inject a float event and wait for its callback in onPropertySet.
v = VehiclePropValueBuilder.newBuilder(VehicleProperty.HVAC_TEMPERATURE_CURRENT)
- .setAreaId(VehicleAreaZone.ROW_1)
+ .setAreaId(VehicleAreaSeat.ROW_1_LEFT | VehicleAreaSeat.ROW_1_RIGHT)
.setTimestamp(SystemClock.elapsedRealtimeNanos())
.addFloatValue(67f)
.build();
@@ -177,11 +196,11 @@
assertTrue(mAvailable.tryAcquire(2L, TimeUnit.SECONDS));
assertEquals(67, mEventFloatVal, 0);
- assertEquals(VehicleAreaZone.ROW_1, mEventZoneVal);
+ assertEquals(VehicleAreaSeat.ROW_1_LEFT | VehicleAreaSeat.ROW_1_RIGHT, mEventZoneVal);
// Inject an integer event and wait for its callback in onPropertySet.
v = VehiclePropValueBuilder.newBuilder(VehicleProperty.HVAC_FAN_SPEED)
- .setAreaId(VehicleAreaZone.ROW_1_LEFT)
+ .setAreaId(VehicleAreaSeat.ROW_1_LEFT)
.setTimestamp(SystemClock.elapsedRealtimeNanos())
.addIntValue(4)
.build();
@@ -190,7 +209,7 @@
assertTrue(mAvailable.tryAcquire(2L, TimeUnit.SECONDS));
assertEquals(4, mEventIntVal);
- assertEquals(VehicleAreaZone.ROW_1_LEFT, mEventZoneVal);
+ assertEquals(VehicleAreaSeat.ROW_1_LEFT, mEventZoneVal);
}
private class HvacPropertyHandler implements VehicleHalPropertyHandler {
@@ -209,8 +228,18 @@
}
@Override
- public synchronized void onPropertySubscribe(int property, int zones, float sampleRate) {
+ public synchronized void onPropertySubscribe(int property, float sampleRate) {
Log.d(TAG, "onPropertySubscribe property " + property + " sampleRate " + sampleRate);
+ if (mMap.get(property) == null) {
+ Log.d(TAG, "onPropertySubscribe add dummy property: " + property);
+ VehiclePropValue dummyValue = VehiclePropValueBuilder.newBuilder(property)
+ .setAreaId(0)
+ .setTimestamp(SystemClock.elapsedRealtimeNanos())
+ .addIntValue(1)
+ .addFloatValue(1)
+ .build();
+ mMap.put(property, dummyValue);
+ }
}
@Override
diff --git a/tests/carservice_test/src/com/android/car/test/CarInfoManagerTest.java b/tests/carservice_test/src/com/android/car/CarInfoManagerTest.java
similarity index 81%
rename from tests/carservice_test/src/com/android/car/test/CarInfoManagerTest.java
rename to tests/carservice_test/src/com/android/car/CarInfoManagerTest.java
index 2cdbbb0..9f5aa3a 100644
--- a/tests/carservice_test/src/com/android/car/test/CarInfoManagerTest.java
+++ b/tests/carservice_test/src/com/android/car/CarInfoManagerTest.java
@@ -13,15 +13,24 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package com.android.car.test;
+package com.android.car;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
import android.car.Car;
import android.car.CarInfoManager;
import android.hardware.automotive.vehicle.V2_0.VehicleProperty;
-import android.test.suitebuilder.annotation.MediumTest;
+import android.support.test.filters.MediumTest;
+import android.support.test.runner.AndroidJUnit4;
import com.android.car.vehiclehal.VehiclePropValueBuilder;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+@RunWith(AndroidJUnit4.class)
@MediumTest
public class CarInfoManagerTest extends MockedCarTestBase {
private static final String MAKE_NAME = "ANDROID";
@@ -38,19 +47,22 @@
}
@Override
- protected void setUp() throws Exception {
+ public void setUp() throws Exception {
super.setUp();
mCarInfoManager = (CarInfoManager) getCar().getCarManager(Car.INFO_SERVICE);
}
+ @Test
public void testVehicleId() throws Exception {
assertNotNull(mCarInfoManager.getVehicleId());
}
+ @Test
public void testManufacturer() throws Exception {
assertEquals(MAKE_NAME, mCarInfoManager.getManufacturer());
}
+ @Test
public void testNullItems() throws Exception {
assertNull(mCarInfoManager.getModel());
assertNull(mCarInfoManager.getModelYear());
diff --git a/tests/carservice_test/src/com/android/car/test/CarPackageManagerTest.java b/tests/carservice_test/src/com/android/car/CarPackageManagerTest.java
similarity index 72%
rename from tests/carservice_test/src/com/android/car/test/CarPackageManagerTest.java
rename to tests/carservice_test/src/com/android/car/CarPackageManagerTest.java
index c455bc4..9c65555 100644
--- a/tests/carservice_test/src/com/android/car/test/CarPackageManagerTest.java
+++ b/tests/carservice_test/src/com/android/car/CarPackageManagerTest.java
@@ -13,16 +13,27 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package com.android.car.test;
+package com.android.car;
+
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
import android.car.Car;
import android.car.CarNotConnectedException;
import android.car.content.pm.AppBlockingPackageInfo;
import android.car.content.pm.CarAppBlockingPolicy;
import android.car.content.pm.CarPackageManager;
-import android.test.suitebuilder.annotation.SmallTest;
+import android.support.test.filters.SmallTest;
+import android.support.test.runner.AndroidJUnit4;
import android.util.Log;
+import com.android.car.pm.CarPackageManagerService;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+@RunWith(AndroidJUnit4.class)
@SmallTest
public class CarPackageManagerTest extends MockedCarTestBase {
private static final String TAG = CarPackageManagerTest.class.getSimpleName();
@@ -31,23 +42,26 @@
private static final long POLLING_SLEEP = 100;
private CarPackageManager mCarPm;
-
- @Override
- protected void setUp() throws Exception {
- super.setUp();
- }
+ private CarPackageManagerService mCarPmService;
private void init(boolean policyFromService) throws Exception {
+ Log.i(TAG, "init started");
TestAppBlockingPolicyService.controlPolicySettingFromService(policyFromService);
mCarPm = (CarPackageManager) getCar().getCarManager(Car.PACKAGE_SERVICE);
assertNotNull(mCarPm);
+ mCarPmService = getPackageManagerService();
+ assertNotNull(mCarPmService);
+ mCarPmService.startAppBlockingPolicies();
}
+ @Test
public void testServiceLaunched() throws Exception {
init(true);
+ Log.i(TAG, "testServiceLaunched, init called");
assertTrue(pollingCheck(new PollingChecker() {
@Override
public boolean check() {
+ Log.i(TAG, "checking instance ...");
return TestAppBlockingPolicyService.getInstance() != null;
}
}, POLLING_MAX_RETRY, POLLING_SLEEP));
@@ -57,17 +71,18 @@
@Override
public boolean check() {
try {
- return mCarPm.isServiceAllowedWhileDriving(thisPackage, serviceClassName);
+ return mCarPm.isServiceDistractionOptimized(thisPackage, serviceClassName);
} catch (CarNotConnectedException e) {
return false;
}
}
}, POLLING_MAX_RETRY, POLLING_SLEEP));
- assertTrue(mCarPm.isServiceAllowedWhileDriving(thisPackage, null));
- assertFalse(mCarPm.isServiceAllowedWhileDriving(serviceClassName, serviceClassName));
- assertFalse(mCarPm.isServiceAllowedWhileDriving(serviceClassName, null));
+ assertTrue(mCarPm.isServiceDistractionOptimized(thisPackage, null));
+ assertFalse(mCarPm.isServiceDistractionOptimized(serviceClassName, serviceClassName));
+ assertFalse(mCarPm.isServiceDistractionOptimized(serviceClassName, null));
}
+ @Test
public void testSettingWhitelist() throws Exception {
init(false);
final String carServicePackageName = "com.android.car";
@@ -84,8 +99,8 @@
mCarPm.setAppBlockingPolicy(thisPackage, policy,
CarPackageManager.FLAG_SET_POLICY_WAIT_FOR_CHANGE);
Log.i(TAG, "setting policy done");
- assertTrue(mCarPm.isActivityAllowedWhileDriving(carServicePackageName, activityAllowed));
- assertFalse(mCarPm.isActivityAllowedWhileDriving(carServicePackageName,
+ assertTrue(mCarPm.isActivityDistractionOptimized(carServicePackageName, activityAllowed));
+ assertFalse(mCarPm.isActivityDistractionOptimized(carServicePackageName,
activityNotAllowed));
// replace policy
@@ -95,9 +110,9 @@
, null);
mCarPm.setAppBlockingPolicy(thisPackage, policy,
CarPackageManager.FLAG_SET_POLICY_WAIT_FOR_CHANGE);
- assertFalse(mCarPm.isActivityAllowedWhileDriving(carServicePackageName, activityAllowed));
- assertTrue(mCarPm.isActivityAllowedWhileDriving(carServicePackageName, acticityAllowed2));
- assertFalse(mCarPm.isActivityAllowedWhileDriving(carServicePackageName,
+ assertFalse(mCarPm.isActivityDistractionOptimized(carServicePackageName, activityAllowed));
+ assertTrue(mCarPm.isActivityDistractionOptimized(carServicePackageName, acticityAllowed2));
+ assertFalse(mCarPm.isActivityDistractionOptimized(carServicePackageName,
activityNotAllowed));
//add, it replace the whole package policy. So activities are not added.
@@ -108,9 +123,9 @@
mCarPm.setAppBlockingPolicy(thisPackage, policy,
CarPackageManager.FLAG_SET_POLICY_WAIT_FOR_CHANGE |
CarPackageManager.FLAG_SET_POLICY_ADD);
- assertTrue(mCarPm.isActivityAllowedWhileDriving(carServicePackageName, activityAllowed));
- assertFalse(mCarPm.isActivityAllowedWhileDriving(carServicePackageName, acticityAllowed2));
- assertFalse(mCarPm.isActivityAllowedWhileDriving(carServicePackageName,
+ assertTrue(mCarPm.isActivityDistractionOptimized(carServicePackageName, activityAllowed));
+ assertFalse(mCarPm.isActivityDistractionOptimized(carServicePackageName, acticityAllowed2));
+ assertFalse(mCarPm.isActivityDistractionOptimized(carServicePackageName,
activityNotAllowed));
//remove
@@ -121,9 +136,9 @@
mCarPm.setAppBlockingPolicy(thisPackage, policy,
CarPackageManager.FLAG_SET_POLICY_WAIT_FOR_CHANGE |
CarPackageManager.FLAG_SET_POLICY_REMOVE);
- assertFalse(mCarPm.isActivityAllowedWhileDriving(carServicePackageName, activityAllowed));
- assertFalse(mCarPm.isActivityAllowedWhileDriving(carServicePackageName, acticityAllowed2));
- assertFalse(mCarPm.isActivityAllowedWhileDriving(carServicePackageName,
+ assertFalse(mCarPm.isActivityDistractionOptimized(carServicePackageName, activityAllowed));
+ assertFalse(mCarPm.isActivityDistractionOptimized(carServicePackageName, acticityAllowed2));
+ assertFalse(mCarPm.isActivityDistractionOptimized(carServicePackageName,
activityNotAllowed));
}
diff --git a/tests/carservice_test/src/com/android/car/test/CarPowerManagementTest.java b/tests/carservice_test/src/com/android/car/CarPowerManagementTest.java
similarity index 69%
rename from tests/carservice_test/src/com/android/car/test/CarPowerManagementTest.java
rename to tests/carservice_test/src/com/android/car/CarPowerManagementTest.java
index d5e5bf8..c449302 100644
--- a/tests/carservice_test/src/com/android/car/test/CarPowerManagementTest.java
+++ b/tests/carservice_test/src/com/android/car/CarPowerManagementTest.java
@@ -13,38 +13,57 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package com.android.car.test;
+package com.android.car;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.fail;
import android.hardware.automotive.vehicle.V2_0.VehicleApPowerBootupReason;
-import android.hardware.automotive.vehicle.V2_0.VehicleApPowerSetState;
-import android.hardware.automotive.vehicle.V2_0.VehicleApPowerState;
import android.hardware.automotive.vehicle.V2_0.VehicleApPowerStateConfigFlag;
-import android.hardware.automotive.vehicle.V2_0.VehicleApPowerStateIndex;
+import android.hardware.automotive.vehicle.V2_0.VehicleApPowerStateReport;
+import android.hardware.automotive.vehicle.V2_0.VehicleApPowerStateReq;
+import android.hardware.automotive.vehicle.V2_0.VehicleApPowerStateReqIndex;
import android.hardware.automotive.vehicle.V2_0.VehicleApPowerStateShutdownParam;
import android.hardware.automotive.vehicle.V2_0.VehiclePropValue;
import android.hardware.automotive.vehicle.V2_0.VehicleProperty;
import android.os.SystemClock;
-import android.test.suitebuilder.annotation.MediumTest;
+import android.support.test.annotation.UiThreadTest;
+import android.support.test.filters.MediumTest;
+import android.support.test.runner.AndroidJUnit4;
+
+import com.android.car.systeminterface.DisplayInterface;
+import com.android.car.systeminterface.SystemInterface;
+import com.android.car.vehiclehal.VehiclePropValueBuilder;
+import com.android.car.vehiclehal.test.MockedVehicleHal.VehicleHalPropertyHandler;
import com.google.android.collect.Lists;
-import com.android.car.vehiclehal.VehiclePropValueBuilder;
-import com.android.car.vehiclehal.test.MockedVehicleHal.VehicleHalPropertyHandler;
+import org.junit.Test;
+import org.junit.runner.RunWith;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.concurrent.Semaphore;
import java.util.concurrent.TimeUnit;
+@RunWith(AndroidJUnit4.class)
@MediumTest
public class CarPowerManagementTest extends MockedCarTestBase {
private final PowerStatePropertyHandler mPowerStateHandler = new PowerStatePropertyHandler();
+ private final MockDisplayInterface mMockDisplayInterface = new MockDisplayInterface();
- private void setupPowerPropertyAndStart(boolean allowSleep) {
- addProperty(VehicleProperty.AP_POWER_STATE, mPowerStateHandler)
+ @Override
+ protected synchronized SystemInterface.Builder getSystemInterfaceBuilder() {
+ SystemInterface.Builder builder = super.getSystemInterfaceBuilder();
+ return builder.withDisplayInterface(mMockDisplayInterface);
+ }
+
+ private void setupPowerPropertyAndStart(boolean allowSleep) throws Exception {
+ addProperty(VehicleProperty.AP_POWER_STATE_REQ, mPowerStateHandler)
.setConfigArray(Lists.newArrayList(
allowSleep ? VehicleApPowerStateConfigFlag.ENABLE_DEEP_SLEEP_FLAG : 0));
+ addProperty(VehicleProperty.AP_POWER_STATE_REPORT, mPowerStateHandler);
addStaticProperty(VehicleProperty.AP_POWER_BOOTUP_REASON,
VehiclePropValueBuilder.newBuilder(VehicleProperty.AP_POWER_BOOTUP_REASON)
@@ -54,30 +73,34 @@
reinitializeMockedHal();
}
+ @Test
+ @UiThreadTest
public void testImmediateShutdown() throws Exception {
setupPowerPropertyAndStart(true);
assertBootComplete();
mPowerStateHandler.sendPowerState(
- VehicleApPowerState.SHUTDOWN_PREPARE,
+ VehicleApPowerStateReq.SHUTDOWN_PREPARE,
VehicleApPowerStateShutdownParam.SHUTDOWN_IMMEDIATELY);
mPowerStateHandler.waitForStateSetAndGetAll(DEFAULT_WAIT_TIMEOUT_MS,
- VehicleApPowerSetState.SHUTDOWN_START);
- mPowerStateHandler.sendPowerState(VehicleApPowerState.ON_FULL, 0);
+ VehicleApPowerStateReport.SHUTDOWN_START);
+ mPowerStateHandler.sendPowerState(VehicleApPowerStateReq.ON_FULL, 0);
}
+ @Test
+ @UiThreadTest
public void testDisplayOnOff() throws Exception {
setupPowerPropertyAndStart(true);
assertBootComplete();
for (int i = 0; i < 2; i++) {
- mPowerStateHandler.sendPowerState(VehicleApPowerState.ON_DISP_OFF, 0);
- waitForFakeDisplayState(false);
- mPowerStateHandler.sendPowerState(VehicleApPowerState.ON_FULL, 0);
- waitForFakeDisplayState(true);
+ mPowerStateHandler.sendPowerState(VehicleApPowerStateReq.ON_DISP_OFF, 0);
+ mMockDisplayInterface.waitForDisplayState(false);
+ mPowerStateHandler.sendPowerState(VehicleApPowerStateReq.ON_FULL, 0);
+ mMockDisplayInterface.waitForDisplayState(true);
}
}
/* TODO make deep sleep work to test this
- public void testSleepEntry() throws Exception {
+ @Test public void testSleepEntry() throws Exception {
assertBootComplete();
mPowerStateHandler.sendPowerState(
VehicleApPowerState.SHUTDOWN_PREPARE,
@@ -101,15 +124,45 @@
private void assertBootComplete() throws Exception {
mPowerStateHandler.waitForSubscription(DEFAULT_WAIT_TIMEOUT_MS);
LinkedList<int[]> setEvents = mPowerStateHandler.waitForStateSetAndGetAll(
- DEFAULT_WAIT_TIMEOUT_MS, VehicleApPowerSetState.BOOT_COMPLETE);
+ DEFAULT_WAIT_TIMEOUT_MS, VehicleApPowerStateReport.BOOT_COMPLETE);
int[] first = setEvents.getFirst();
- assertEquals(VehicleApPowerSetState.BOOT_COMPLETE, first[0]);
+ assertEquals(VehicleApPowerStateReport.BOOT_COMPLETE, first[0]);
assertEquals(0, first[1]);
}
+ private final class MockDisplayInterface implements DisplayInterface {
+ private boolean mDisplayOn = true;
+ private final Semaphore mDisplayStateWait = new Semaphore(0);
+
+ @Override
+ public void setDisplayBrightness(int brightness) {}
+
+ @Override
+ public synchronized void setDisplayState(boolean on) {
+ mDisplayOn = on;
+ mDisplayStateWait.release();
+ }
+
+ boolean waitForDisplayState(boolean expectedState)
+ throws Exception {
+ if (expectedState == mDisplayOn) {
+ return true;
+ }
+ mDisplayStateWait.tryAcquire(MockedCarTestBase.SHORT_WAIT_TIMEOUT_MS,
+ TimeUnit.MILLISECONDS);
+ return expectedState == mDisplayOn;
+ }
+
+ @Override
+ public void startDisplayStateMonitoring(CarPowerManagementService service) {}
+
+ @Override
+ public void stopDisplayStateMonitoring() {}
+ }
+
private class PowerStatePropertyHandler implements VehicleHalPropertyHandler {
- private int mPowerState = VehicleApPowerState.ON_FULL;
+ private int mPowerState = VehicleApPowerStateReq.ON_FULL;
private int mPowerParam = 0;
private final Semaphore mSubscriptionWaitSemaphore = new Semaphore(0);
@@ -121,8 +174,8 @@
ArrayList<Integer> v = value.value.int32Values;
synchronized (this) {
mSetStates.add(new int[] {
- v.get(VehicleApPowerStateIndex.STATE),
- v.get(VehicleApPowerStateIndex.ADDITIONAL)
+ v.get(VehicleApPowerStateReqIndex.STATE),
+ v.get(VehicleApPowerStateReqIndex.ADDITIONAL)
});
}
mSetWaitSemaphore.release();
@@ -130,14 +183,14 @@
@Override
public synchronized VehiclePropValue onPropertyGet(VehiclePropValue value) {
- return VehiclePropValueBuilder.newBuilder(VehicleProperty.AP_POWER_STATE)
+ return VehiclePropValueBuilder.newBuilder(VehicleProperty.AP_POWER_STATE_REQ)
.setTimestamp(SystemClock.elapsedRealtimeNanos())
.addIntValue(mPowerState, mPowerParam)
.build();
}
@Override
- public void onPropertySubscribe(int property, int zones, float sampleRate) {
+ public void onPropertySubscribe(int property, float sampleRate) {
mSubscriptionWaitSemaphore.release();
}
@@ -181,7 +234,7 @@
private void sendPowerState(int state, int param) {
getMockedVehicleHal().injectEvent(
- VehiclePropValueBuilder.newBuilder(VehicleProperty.AP_POWER_STATE)
+ VehiclePropValueBuilder.newBuilder(VehicleProperty.AP_POWER_STATE_REQ)
.setTimestamp(SystemClock.elapsedRealtimeNanos())
.addIntValue(state, param)
.build());
diff --git a/tests/carservice_test/src/com/android/car/test/CarProjectionManagerTest.java b/tests/carservice_test/src/com/android/car/CarProjectionManagerTest.java
similarity index 93%
rename from tests/carservice_test/src/com/android/car/test/CarProjectionManagerTest.java
rename to tests/carservice_test/src/com/android/car/CarProjectionManagerTest.java
index adf288c..8b108df 100644
--- a/tests/carservice_test/src/com/android/car/test/CarProjectionManagerTest.java
+++ b/tests/carservice_test/src/com/android/car/CarProjectionManagerTest.java
@@ -14,7 +14,10 @@
* limitations under the License.
*/
-package com.android.car.test;
+package com.android.car;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
import android.car.Car;
import android.car.CarProjectionManager;
@@ -23,17 +26,22 @@
import android.hardware.automotive.vehicle.V2_0.VehicleProperty;
import android.hardware.automotive.vehicle.V2_0.VehiclePropertyAccess;
import android.os.SystemClock;
-import android.test.suitebuilder.annotation.MediumTest;
+import android.support.test.filters.MediumTest;
+import android.support.test.runner.AndroidJUnit4;
import android.util.Log;
import android.view.KeyEvent;
import com.android.car.vehiclehal.VehiclePropValueBuilder;
import com.android.car.vehiclehal.test.MockedVehicleHal.VehicleHalPropertyHandler;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
import java.util.HashMap;
import java.util.concurrent.Semaphore;
import java.util.concurrent.TimeUnit;
+@RunWith(AndroidJUnit4.class)
@MediumTest
public class CarProjectionManagerTest extends MockedCarTestBase {
private static final String TAG = CarProjectionManagerTest.class.getSimpleName();
@@ -62,11 +70,12 @@
}
@Override
- protected void setUp() throws Exception {
+ public void setUp() throws Exception {
super.setUp();
mManager = (CarProjectionManager) getCar().getCarManager(Car.PROJECTION_SERVICE);
}
+ @Test
public void testShortPressListener() throws Exception {
mManager.registerProjectionListener(
mListener,
@@ -78,6 +87,7 @@
assertEquals(0, mLongAvailable.availablePermits());
}
+ @Test
public void testLongPressListener() throws Exception {
mManager.registerProjectionListener(
mListener,
@@ -89,6 +99,7 @@
assertEquals(0, mAvailable.availablePermits());
}
+ @Test
public void testMixedPressListener() throws Exception {
mManager.registerProjectionListener(
mListener,
@@ -151,7 +162,7 @@
}
@Override
- public synchronized void onPropertySubscribe(int property, int zones, float sampleRate) {
+ public synchronized void onPropertySubscribe(int property, float sampleRate) {
Log.d(TAG, "onPropertySubscribe property " + property + " sampleRate " + sampleRate);
}
diff --git a/tests/carservice_test/src/com/android/car/test/CarSensorManagerTest.java b/tests/carservice_test/src/com/android/car/CarSensorManagerTest.java
similarity index 87%
rename from tests/carservice_test/src/com/android/car/test/CarSensorManagerTest.java
rename to tests/carservice_test/src/com/android/car/CarSensorManagerTest.java
index daddfdb..e5b3566 100644
--- a/tests/carservice_test/src/com/android/car/test/CarSensorManagerTest.java
+++ b/tests/carservice_test/src/com/android/car/CarSensorManagerTest.java
@@ -14,7 +14,12 @@
* limitations under the License.
*/
-package com.android.car.test;
+package com.android.car;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
import android.car.Car;
import android.car.CarNotConnectedException;
@@ -30,6 +35,8 @@
import com.android.car.vehiclehal.VehiclePropValueBuilder;
+import org.junit.Test;
+
/**
* Test the public entry points for the CarSensorManager
*/
@@ -49,9 +56,9 @@
VehiclePropValueBuilder.newBuilder(VehicleProperty.PERF_VEHICLE_SPEED)
.addFloatValue(0f)
.build());
- addProperty(VehicleProperty.FUEL_LEVEL_LOW,
- VehiclePropValueBuilder.newBuilder(VehicleProperty.FUEL_LEVEL_LOW)
- .setBooleanValue(false)
+ addProperty(VehicleProperty.FUEL_LEVEL,
+ VehiclePropValueBuilder.newBuilder(VehicleProperty.FUEL_LEVEL)
+ .addFloatValue(20000) // ml
.build());
addProperty(VehicleProperty.PARKING_BRAKE_ON,
VehiclePropValueBuilder.newBuilder(VehicleProperty.PARKING_BRAKE_ON)
@@ -65,10 +72,6 @@
VehiclePropValueBuilder.newBuilder(VehicleProperty.GEAR_SELECTION)
.addIntValue(0)
.build());
- addProperty(VehicleProperty.DRIVING_STATUS,
- VehiclePropValueBuilder.newBuilder(VehicleProperty.DRIVING_STATUS)
- .addIntValue(0)
- .build());
addProperty(VehicleProperty.IGNITION_STATE,
VehiclePropValueBuilder.newBuilder(VehicleProperty.IGNITION_STATE)
.addIntValue(CarSensorEvent.IGNITION_STATE_ACC)
@@ -76,7 +79,7 @@
}
@Override
- protected void setUp() throws Exception {
+ public void setUp() throws Exception {
super.setUp();
// Start the HAL layer and set up the sensor manager service
mCarSensorManager = (CarSensorManager) getCar().getCarManager(Car.SENSOR_SERVICE);
@@ -86,6 +89,7 @@
* Test single sensor availability entry point
* @throws Exception
*/
+ @Test
public void testSensorAvailability() throws Exception {
// NOTE: Update this test if/when the reserved values put into use. For now, we
// expect them to never be supported.
@@ -100,8 +104,6 @@
assertTrue(mCarSensorManager.isSensorSupported(CarSensorManager.SENSOR_TYPE_GEAR));
assertTrue(mCarSensorManager.isSensorSupported(CarSensorManager.SENSOR_TYPE_NIGHT));
assertTrue(mCarSensorManager.isSensorSupported(
- CarSensorManager.SENSOR_TYPE_DRIVING_STATUS));
- assertTrue(mCarSensorManager.isSensorSupported(
CarSensorManager.SENSOR_TYPE_IGNITION_STATE));
}
@@ -109,6 +111,7 @@
* Test sensor enumeration entry point
* @throws Exception
*/
+ @Test
public void testSensorEnumeration() throws Exception {
int[] supportedSensors = mCarSensorManager.getSupportedSensors();
assertNotNull(supportedSensors);
@@ -133,23 +136,13 @@
// Make sure the individual query on a sensor type is consistent
assertEquals(found, supported);
}
-
- // Here we simply ensure that one specific expected sensor is always available to help
- // ensure we don't have a trivially broken test finding nothing.
- boolean found = false;
- for (int sensor : supportedSensors) {
- if (sensor == CarSensorManager.SENSOR_TYPE_DRIVING_STATUS) {
- found = true;
- break;
- }
- }
- assertTrue("We expect at least DRIVING_STATUS to be available", found);
}
/**
* Test senor notification registration, delivery, and unregistration
* @throws Exception
*/
+ @Test
public void testEvents() throws Exception {
// Set up our listener callback
SensorListener listener = new SensorListener();
@@ -161,6 +154,8 @@
CarSensorEvent event;
CarSensorEvent.NightData data = null;
+ // Clear event generated by registerListener()
+ listener.waitForSensorChange();
listener.reset();
// Set the value TRUE and wait for the event to arrive
@@ -168,7 +163,7 @@
VehiclePropValueBuilder.newBuilder(VehicleProperty.NIGHT_MODE)
.setBooleanValue(true)
.setTimestamp(1L)
- .build());
+ .build(), true);
assertTrue(listener.waitForSensorChange(1L));
// Ensure we got the expected event
@@ -192,7 +187,7 @@
VehiclePropValueBuilder.newBuilder(VehicleProperty.NIGHT_MODE)
.setTimestamp(1001)
.setBooleanValue(false)
- .build());
+ .build(), true);
assertTrue(listener.waitForSensorChange(1001));
// Ensure we got the expected event
@@ -218,7 +213,7 @@
.setTimestamp(2001)
.setBooleanValue(true)
.build();
- getMockedVehicleHal().injectEvent(value);
+ getMockedVehicleHal().injectEvent(value, true);
// Ensure we did not get a callback (should timeout)
Log.i(TAG, "waiting for unexpected callback -- should timeout.");
@@ -232,6 +227,7 @@
assertTrue("Unexpected value", data.isNightMode);
}
+ @Test
public void testIgnitionState() throws CarNotConnectedException {
CarSensorEvent event = mCarSensorManager.getLatestSensorEvent(
CarSensorManager.SENSOR_TYPE_IGNITION_STATE);
@@ -239,11 +235,13 @@
assertEquals(CarSensorEvent.IGNITION_STATE_ACC, event.intValues[0]);
}
+ @Test
public void testIgnitionEvents() throws Exception {
SensorListener listener = new SensorListener();
mCarSensorManager.registerListener(listener, CarSensorManager.SENSOR_TYPE_IGNITION_STATE,
CarSensorManager.SENSOR_RATE_NORMAL);
-
+ // Clear event generated by registerListener()
+ listener.waitForSensorChange();
// Mapping of HAL -> Manager ignition states.
int[] ignitionStates = new int[] {
@@ -270,7 +268,7 @@
VehiclePropValueBuilder.newBuilder(VehicleProperty.IGNITION_STATE)
.addIntValue(halIgnitionState)
.setTimestamp(time)
- .build());
+ .build(), true);
assertTrue(listener.waitForSensorChange(time));
CarSensorEvent eventReceived = listener.getLastEvent();
@@ -278,35 +276,22 @@
assertEquals(mgrIgnitionState, eventReceived.intValues[0]);
}
- public void testIgnitionEvents_Bad() throws Exception {
- SensorListener listener = new SensorListener();
- mCarSensorManager.registerListener(listener, CarSensorManager.SENSOR_TYPE_IGNITION_STATE,
- CarSensorManager.SENSOR_RATE_NORMAL);
-
- listener.reset();
- long time = SystemClock.elapsedRealtimeNanos();
- getMockedVehicleHal().injectEvent(
- VehiclePropValueBuilder.newBuilder(VehicleProperty.IGNITION_STATE)
- .addIntValue(0xdeadbeef)
- .setTimestamp(time)
- .build());
-
- // Make sure invalid events are never propagated to clients.
- assertFalse(listener.waitForSensorChange(time));
- }
-
+ @Test
public void testGear() throws Exception {
SensorListener listener = new SensorListener();
+
mCarSensorManager.registerListener(listener, CarSensorManager.SENSOR_TYPE_GEAR,
CarSensorManager.SENSOR_RATE_NORMAL);
+ // Clear event generated by registerListener()
+ listener.waitForSensorChange();
+
// Mapping of HAL -> Manager gear selection states.
int[] gears = new int[] {
VehicleGear.GEAR_PARK, CarSensorEvent.GEAR_PARK,
VehicleGear.GEAR_DRIVE, CarSensorEvent.GEAR_DRIVE,
VehicleGear.GEAR_NEUTRAL, CarSensorEvent.GEAR_NEUTRAL,
VehicleGear.GEAR_REVERSE, CarSensorEvent.GEAR_REVERSE,
- VehicleGear.GEAR_LOW, CarSensorEvent.GEAR_FIRST,
VehicleGear.GEAR_1, CarSensorEvent.GEAR_FIRST,
VehicleGear.GEAR_2, CarSensorEvent.GEAR_SECOND,
VehicleGear.GEAR_3, CarSensorEvent.GEAR_THIRD,
@@ -321,19 +306,6 @@
for (int i = 0; i < gears.length; i += 2) {
injectGearEventAndAssert(listener, gears[i], gears[i + 1]);
}
-
- // invalid input should not be forwarded
- long time = SystemClock.elapsedRealtimeNanos();
- getMockedVehicleHal().injectEvent(
- VehiclePropValueBuilder.newBuilder(VehicleProperty.GEAR_SELECTION)
- .addIntValue(0xdeadbeef)
- .setTimestamp(time)
- .build());
- assertFalse(listener.waitForSensorChange(time));
- CarSensorEvent event = mCarSensorManager.getLatestSensorEvent(
- CarSensorManager.SENSOR_TYPE_GEAR);
- assertNotNull(event); // Still holds an old event.
- assertEquals(CarSensorEvent.GEAR_NINTH, event.intValues[0]);
}
private void injectGearEventAndAssert(SensorListener listener, int halValue,
@@ -344,7 +316,7 @@
VehiclePropValueBuilder.newBuilder(VehicleProperty.GEAR_SELECTION)
.addIntValue(halValue)
.setTimestamp(time)
- .build());
+ .build(), true);
assertTrue(listener.waitForSensorChange(time));
CarSensorEvent event = mCarSensorManager.getLatestSensorEvent(
CarSensorManager.SENSOR_TYPE_GEAR);
@@ -356,6 +328,7 @@
* Test senor multiple liseners notification registration, delivery and unregistration.
* @throws Exception
*/
+ @Test
public void testEventsWithMultipleListeners() throws Exception {
// Set up our listeners callback
SensorListener listener1 = new SensorListener();
@@ -378,17 +351,20 @@
VehiclePropValue value;
CarSensorEvent event;
+ // Clear event generated by registerListener()
+ listener1.waitForSensorChange();
+ listener2.waitForSensorChange();
+ listener3.waitForSensorChange();
listener1.reset();
listener2.reset();
listener3.reset();
// Set the value TRUE and wait for the event to arrive
value = VehiclePropValueBuilder.newBuilder(VehicleProperty.NIGHT_MODE)
- .setTimestamp(42L)
- .setBooleanValue(true)
- .build();
-
- getMockedVehicleHal().injectEvent(value);
+ .setTimestamp(42L)
+ .setBooleanValue(true)
+ .build();
+ getMockedVehicleHal().injectEvent(value, true);
assertTrue(listener1.waitForSensorChange(42L));
assertTrue(listener2.waitForSensorChange(42L));
@@ -426,7 +402,7 @@
.setTimestamp(1001)
.setBooleanValue(false)
.build();
- getMockedVehicleHal().injectEvent(value);
+ getMockedVehicleHal().injectEvent(value, true);
assertTrue(listener1.waitForSensorChange(1001));
assertTrue(listener2.waitForSensorChange(1001));
assertTrue(listener3.waitForSensorChange(1001));
@@ -446,7 +422,6 @@
assertFalse("Unexpected value", data.isNightMode);
data = listener3.getLastEvent().getNightData(data);
- listener3.reset();
assertEquals("Unexpected event timestamp", 1001, data.timestamp);
assertFalse("Unexpected value", data.isNightMode);
@@ -456,13 +431,19 @@
assertFalse(data.isNightMode);
Log.d(TAG, "Unregistering listener3");
+ listener1.reset();
+ listener2.reset();
+ listener3.reset();
mCarSensorManager.unregisterListener(listener3);
-
Log.d(TAG, "Rate changed - expect sensor restart and change event sent.");
+ value = VehiclePropValueBuilder.newBuilder(VehicleProperty.NIGHT_MODE)
+ .setTimestamp(1002)
+ .setBooleanValue(false)
+ .build();
+ getMockedVehicleHal().injectEvent(value, true);
assertTrue(listener1.waitForSensorChange());
assertTrue(listener2.waitForSensorChange());
assertFalse(listener3.waitForSensorChange());
-
listener1.reset();
listener2.reset();
listener3.reset();
@@ -471,11 +452,10 @@
.setTimestamp()
.setBooleanValue(true)
.build();
- getMockedVehicleHal().injectEvent(value);
+ getMockedVehicleHal().injectEvent(value, true);
assertTrue(listener1.waitForSensorChange());
assertTrue(listener2.waitForSensorChange());
-
listener1.reset();
listener2.reset();
@@ -484,7 +464,7 @@
assertFalse(listener3.waitForSensorChange());
Log.d(TAG, "Unregistering listener2");
- mCarSensorManager.unregisterListener(listener3);
+ mCarSensorManager.unregisterListener(listener2);
Log.d(TAG, "Rate did nor change - dont expect sensor restart and change event sent.");
assertFalse(listener1.waitForSensorChange());
diff --git a/tests/carservice_test/src/com/android/car/CarStorageMonitoringBroadcastReceiver.java b/tests/carservice_test/src/com/android/car/CarStorageMonitoringBroadcastReceiver.java
new file mode 100644
index 0000000..d418174
--- /dev/null
+++ b/tests/carservice_test/src/com/android/car/CarStorageMonitoringBroadcastReceiver.java
@@ -0,0 +1,73 @@
+/*
+ * 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.android.car;
+
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.os.SystemClock;
+import android.util.Log;
+
+import java.time.Duration;
+
+public class CarStorageMonitoringBroadcastReceiver extends BroadcastReceiver {
+ private static final String TAG = CarStorageMonitoringBroadcastReceiver.class.getSimpleName();
+ private static Intent mLastIntent;
+ private static final Object mSync = new Object();
+
+ static void deliver(Intent intent) {
+ Log.i(TAG, "onReceive, intent: " + intent);
+ synchronized (mSync) {
+ mLastIntent = intent;
+ mSync.notify();
+ }
+ }
+
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ Log.i(TAG, "onReceive, intent: " + intent);
+ synchronized (mSync) {
+ mLastIntent = intent;
+ mSync.notify();
+ }
+ }
+
+ static Intent reset() {
+ Log.i(TAG, "reset");
+ synchronized (mSync) {
+ Intent lastIntent = mLastIntent;
+ mLastIntent = null;
+ return lastIntent;
+ }
+ }
+
+ static boolean waitForIntent(Duration duration) {
+ long start = SystemClock.elapsedRealtime();
+ long end = start + duration.toMillis();
+ synchronized (mSync) {
+ while (mLastIntent == null && SystemClock.elapsedRealtime() < end) {
+ try {
+ mSync.wait(10L);
+ } catch (InterruptedException e) {
+ // ignore
+ }
+ }
+ }
+
+ return (mLastIntent != null);
+ }
+}
diff --git a/tests/carservice_test/src/com/android/car/CarStorageMonitoringTest.java b/tests/carservice_test/src/com/android/car/CarStorageMonitoringTest.java
new file mode 100644
index 0000000..1157007
--- /dev/null
+++ b/tests/carservice_test/src/com/android/car/CarStorageMonitoringTest.java
@@ -0,0 +1,933 @@
+/*
+ * 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.android.car;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.car.Car;
+import android.car.storagemonitoring.CarStorageMonitoringManager;
+import android.car.storagemonitoring.IoStatsEntry;
+import android.car.storagemonitoring.IoStats;
+import android.car.storagemonitoring.LifetimeWriteInfo;
+import android.car.storagemonitoring.UidIoRecord;
+import android.car.storagemonitoring.WearEstimate;
+import android.car.storagemonitoring.WearEstimateChange;
+import android.content.Intent;
+import android.content.pm.PackageManager.NameNotFoundException;
+import android.content.pm.ResolveInfo;
+import android.os.SystemClock;
+import android.support.test.filters.MediumTest;
+import android.support.test.runner.AndroidJUnit4;
+import android.util.JsonWriter;
+import android.util.Log;
+import android.util.Pair;
+import android.util.SparseArray;
+
+import com.android.car.storagemonitoring.LifetimeWriteInfoProvider;
+import com.android.car.storagemonitoring.UidIoStatsProvider;
+import com.android.car.storagemonitoring.WearEstimateRecord;
+import com.android.car.storagemonitoring.WearHistory;
+import com.android.car.storagemonitoring.WearInformation;
+import com.android.car.storagemonitoring.WearInformationProvider;
+import com.android.car.systeminterface.StorageMonitoringInterface;
+import com.android.car.systeminterface.SystemInterface;
+import com.android.car.systeminterface.SystemStateInterface;
+import com.android.car.systeminterface.TimeInterface;
+
+import com.android.car.test.utils.TemporaryFile;
+import java.util.ArrayDeque;
+import java.util.Collection;
+import java.util.Objects;
+import java.util.Queue;
+import org.json.JSONArray;
+import org.json.JSONObject;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.TestName;
+import org.junit.runner.RunWith;
+
+import java.io.File;
+import java.io.FileWriter;
+import java.io.IOException;
+import java.time.Duration;
+import java.time.Instant;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Comparator;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+/** Test the public entry points for the CarStorageMonitoringManager */
+@RunWith(AndroidJUnit4.class)
+@MediumTest
+public class CarStorageMonitoringTest extends MockedCarTestBase {
+ private static final String TAG = CarStorageMonitoringTest.class.getSimpleName();
+
+ @Rule public TestName mTestName = new TestName();
+
+ private static final WearInformation DEFAULT_WEAR_INFORMATION =
+ new WearInformation(30, 0, WearInformation.PRE_EOL_INFO_NORMAL);
+
+ final class TestContext extends MockContext {
+ TestContext(MockContext context) {
+ super(context.getBaseContext());
+ }
+
+ @Override
+ public void sendBroadcast(Intent intent, String receiverPermission) {
+ Log.d(TAG, "test context broadcasting " + intent);
+ if (CarStorageMonitoringManager.INTENT_EXCESSIVE_IO.equals(intent.getAction())) {
+ assertEquals(Car.PERMISSION_STORAGE_MONITORING, receiverPermission);
+
+ List<ResolveInfo> resolveInfoList = mContext.getPackageManager().
+ queryBroadcastReceivers(intent, 0);
+
+ assertEquals(1,
+ resolveInfoList.stream().map(ri -> ri.activityInfo)
+ .filter(Objects::nonNull)
+ .map(ai -> ai.name)
+ .filter(CarStorageMonitoringBroadcastReceiver.class
+ .getCanonicalName()::equals)
+ .count());
+
+ CarStorageMonitoringBroadcastReceiver.deliver(intent);
+ } else {
+ super.sendBroadcast(intent, receiverPermission);
+ }
+ }
+ }
+
+ static class ResourceOverrides {
+ private final HashMap<Integer, Integer> mIntegerOverrides = new HashMap<>();
+ private final HashMap<Integer, String> mStringOverrides = new HashMap<>();
+
+ void override(int id, int value) {
+ mIntegerOverrides.put(id, value);
+ }
+ void override(int id, String value) {
+ mStringOverrides.put(id, value);
+ }
+
+ void overrideResources(MockResources resources) {
+ mIntegerOverrides.forEach(resources::overrideResource);
+ mStringOverrides.forEach(resources::overrideResource);
+ }
+ }
+
+ private final Map<String, ResourceOverrides> PER_TEST_RESOURCES =
+ new HashMap<String, ResourceOverrides>() {
+ {
+ put("testAggregateIoStats",
+ new ResourceOverrides() {{
+ override(R.integer.ioStatsNumSamplesToStore, 5);
+ }});
+ put("testIoStatsDeltas",
+ new ResourceOverrides() {{
+ override(R.integer.ioStatsNumSamplesToStore, 5);
+ }});
+ put("testEventDelivery",
+ new ResourceOverrides() {{
+ override(R.integer.ioStatsNumSamplesToStore, 5);
+ }});
+ put("testIntentOnExcessiveWrite",
+ new ResourceOverrides() {{
+ override(R.integer.ioStatsNumSamplesToStore, 5);
+ override(R.integer.maxExcessiveIoSamplesInWindow, 0);
+ override(R.integer.acceptableWrittenKBytesPerSample, 10);
+ override(R.integer.acceptableFsyncCallsPerSample, 1000);
+ override(R.string.intentReceiverForUnacceptableIoMetrics,
+ getFlattenComponent(
+ CarStorageMonitoringBroadcastReceiver.class));
+ }});
+
+ put("testIntentOnExcessiveFsync",
+ new ResourceOverrides() {{
+ override(R.integer.ioStatsNumSamplesToStore, 5);
+ override(R.integer.maxExcessiveIoSamplesInWindow, 0);
+ override(R.integer.acceptableWrittenKBytesPerSample, 1000);
+ override(R.integer.acceptableFsyncCallsPerSample, 2);
+ override(R.string.intentReceiverForUnacceptableIoMetrics,
+ getFlattenComponent(
+ CarStorageMonitoringBroadcastReceiver.class));
+ }});
+
+ put("testZeroWindowDisablesCollection",
+ new ResourceOverrides() {{
+ override(R.integer.ioStatsNumSamplesToStore, 0);
+ }});
+
+ }
+ };
+
+ private static final class TestData {
+ static final TestData DEFAULT = new TestData(0, DEFAULT_WEAR_INFORMATION, null, null);
+
+ final long uptime;
+ @NonNull
+ final WearInformation wearInformation;
+ @Nullable
+ final WearHistory wearHistory;
+ @NonNull
+ final UidIoRecord[] ioStats;
+ @NonNull
+ final LifetimeWriteInfo[] previousLifetimeWriteInfo;
+ @NonNull
+ final LifetimeWriteInfo[] currentLifetimeWriteInfo;
+
+ TestData(long uptime,
+ @Nullable WearInformation wearInformation,
+ @Nullable WearHistory wearHistory,
+ @Nullable UidIoRecord[] ioStats) {
+ this(uptime, wearInformation, wearHistory, ioStats, null, null);
+ }
+
+ TestData(long uptime,
+ @Nullable WearInformation wearInformation,
+ @Nullable WearHistory wearHistory,
+ @Nullable UidIoRecord[] ioStats,
+ @Nullable LifetimeWriteInfo[] previousLifetimeWriteInfo,
+ @Nullable LifetimeWriteInfo[] currentLifetimeWriteInfo) {
+ if (wearInformation == null) wearInformation = DEFAULT_WEAR_INFORMATION;
+ if (ioStats == null) ioStats = new UidIoRecord[0];
+ if (previousLifetimeWriteInfo == null) {
+ previousLifetimeWriteInfo = new LifetimeWriteInfo[0];
+ }
+ if (currentLifetimeWriteInfo == null) {
+ currentLifetimeWriteInfo = new LifetimeWriteInfo[0];
+ }
+ this.uptime = uptime;
+ this.wearInformation = wearInformation;
+ this.wearHistory = wearHistory;
+ this.ioStats = ioStats;
+ this.previousLifetimeWriteInfo = previousLifetimeWriteInfo;
+ this.currentLifetimeWriteInfo = currentLifetimeWriteInfo;
+ }
+ }
+
+ private static final Map<String, TestData> PER_TEST_DATA =
+ new HashMap<String, TestData>() {
+ {
+ put("testReadWearHistory",
+ new TestData(6500, DEFAULT_WEAR_INFORMATION,
+ WearHistory.fromRecords(
+ WearEstimateRecord.Builder.newBuilder()
+ .fromWearEstimate(WearEstimate.UNKNOWN_ESTIMATE)
+ .toWearEstimate(new WearEstimate(10, 0))
+ .atUptime(1000)
+ .atTimestamp(Instant.ofEpochMilli(5000)).build(),
+ WearEstimateRecord.Builder.newBuilder()
+ .fromWearEstimate(new WearEstimate(10, 0))
+ .toWearEstimate(new WearEstimate(20, 0))
+ .atUptime(4000)
+ .atTimestamp(Instant.ofEpochMilli(12000)).build(),
+ WearEstimateRecord.Builder.newBuilder()
+ .fromWearEstimate(new WearEstimate(20, 0))
+ .toWearEstimate(new WearEstimate(30, 0))
+ .atUptime(6500)
+ .atTimestamp(Instant.ofEpochMilli(17000)).build()), null));
+
+ put("testNotAcceptableWearEvent",
+ new TestData(2520006499L,
+ new WearInformation(40, 0, WearInformation.PRE_EOL_INFO_NORMAL),
+ WearHistory.fromRecords(
+ WearEstimateRecord.Builder.newBuilder()
+ .fromWearEstimate(WearEstimate.UNKNOWN_ESTIMATE)
+ .toWearEstimate(new WearEstimate(10, 0))
+ .atUptime(1000)
+ .atTimestamp(Instant.ofEpochMilli(5000)).build(),
+ WearEstimateRecord.Builder.newBuilder()
+ .fromWearEstimate(new WearEstimate(10, 0))
+ .toWearEstimate(new WearEstimate(20, 0))
+ .atUptime(4000)
+ .atTimestamp(Instant.ofEpochMilli(12000)).build(),
+ WearEstimateRecord.Builder.newBuilder()
+ .fromWearEstimate(new WearEstimate(20, 0))
+ .toWearEstimate(new WearEstimate(30, 0))
+ .atUptime(6500)
+ .atTimestamp(Instant.ofEpochMilli(17000)).build()), null));
+
+ put("testAcceptableWearEvent",
+ new TestData(2520006501L,
+ new WearInformation(40, 0, WearInformation.PRE_EOL_INFO_NORMAL),
+ WearHistory.fromRecords(
+ WearEstimateRecord.Builder.newBuilder()
+ .fromWearEstimate(WearEstimate.UNKNOWN_ESTIMATE)
+ .toWearEstimate(new WearEstimate(10, 0))
+ .atUptime(1000)
+ .atTimestamp(Instant.ofEpochMilli(5000)).build(),
+ WearEstimateRecord.Builder.newBuilder()
+ .fromWearEstimate(new WearEstimate(10, 0))
+ .toWearEstimate(new WearEstimate(20, 0))
+ .atUptime(4000)
+ .atTimestamp(Instant.ofEpochMilli(12000)).build(),
+ WearEstimateRecord.Builder.newBuilder()
+ .fromWearEstimate(new WearEstimate(20, 0))
+ .toWearEstimate(new WearEstimate(30, 0))
+ .atUptime(6500)
+ .atTimestamp(Instant.ofEpochMilli(17000)).build()), null));
+
+ put("testBootIoStats",
+ new TestData(1000L,
+ new WearInformation(0, 0, WearInformation.PRE_EOL_INFO_NORMAL),
+ null,
+ new UidIoRecord[]{
+ new UidIoRecord(0, 5000, 6000, 3000, 1000, 1,
+ 0, 0, 0, 0, 0),
+ new UidIoRecord(1000, 200, 5000, 0, 4000, 0,
+ 1000, 0, 500, 0, 0)}));
+
+ put("testAggregateIoStats",
+ new TestData(1000L,
+ new WearInformation(0, 0, WearInformation.PRE_EOL_INFO_NORMAL),
+ null,
+ new UidIoRecord[]{
+ new UidIoRecord(0, 5000, 6000, 3000, 1000, 1,
+ 0, 0, 0, 0, 0),
+ new UidIoRecord(1000, 200, 5000, 0, 4000, 0,
+ 1000, 0, 500, 0, 0)}));
+
+ put("testIoStatsDeltas",
+ new TestData(1000L,
+ new WearInformation(0, 0, WearInformation.PRE_EOL_INFO_NORMAL),
+ null,
+ new UidIoRecord[]{
+ new UidIoRecord(0, 5000, 6000, 3000, 1000, 1,
+ 0, 0, 0, 0, 0)}));
+
+ put("testComputeShutdownCost",
+ new TestData(1000L,
+ new WearInformation(0, 0, WearInformation.PRE_EOL_INFO_NORMAL),
+ null,
+ null,
+ new LifetimeWriteInfo[] { new LifetimeWriteInfo("p1", "ext4", 120),
+ new LifetimeWriteInfo("p2", "ext4", 100),
+ new LifetimeWriteInfo("p3", "f2fs", 100)},
+ new LifetimeWriteInfo[] { new LifetimeWriteInfo("p1", "ext4", 200),
+ new LifetimeWriteInfo("p2", "ext4", 300),
+ new LifetimeWriteInfo("p3", "f2fs", 100)}));
+
+ put("testNegativeShutdownCost",
+ new TestData(1000L,
+ new WearInformation(0, 0, WearInformation.PRE_EOL_INFO_NORMAL),
+ null,
+ null,
+ new LifetimeWriteInfo[] { new LifetimeWriteInfo("p1", "ext4", 120),
+ new LifetimeWriteInfo("p2", "ext4", 100),
+ new LifetimeWriteInfo("p3", "f2fs", 200)},
+ new LifetimeWriteInfo[] { new LifetimeWriteInfo("p1", "ext4", 200),
+ new LifetimeWriteInfo("p2", "ext4", 300),
+ new LifetimeWriteInfo("p3", "f2fs", 100)}));
+ }};
+
+ private final MockSystemStateInterface mMockSystemStateInterface =
+ new MockSystemStateInterface();
+ private final MockStorageMonitoringInterface mMockStorageMonitoringInterface =
+ new MockStorageMonitoringInterface();
+ private final MockTimeInterface mMockTimeInterface =
+ new MockTimeInterface();
+ private TestContext mContext;
+
+ private CarStorageMonitoringManager mCarStorageMonitoringManager;
+
+ @Override
+ protected MockContext getCarServiceContext() throws NameNotFoundException {
+ if (mContext == null) {
+ mContext = new TestContext(super.getCarServiceContext());
+ }
+ return mContext;
+ }
+
+ @Override
+ protected synchronized SystemInterface.Builder getSystemInterfaceBuilder() {
+ SystemInterface.Builder builder = super.getSystemInterfaceBuilder();
+ return builder.withSystemStateInterface(mMockSystemStateInterface)
+ .withStorageMonitoringInterface(mMockStorageMonitoringInterface)
+ .withTimeInterface(mMockTimeInterface);
+ }
+
+ @Override
+ protected synchronized void configureFakeSystemInterface() {
+ try {
+ final TestData wearData = PER_TEST_DATA.getOrDefault(getName(), TestData.DEFAULT);
+ final WearHistory wearHistory = wearData.wearHistory;
+
+ mMockStorageMonitoringInterface.setWearInformation(wearData.wearInformation);
+ mMockStorageMonitoringInterface.setWriteInfo(wearData.currentLifetimeWriteInfo);
+
+ if (wearHistory != null) {
+ File wearHistoryFile = new File(getFakeSystemInterface().getFilesDir(),
+ CarStorageMonitoringService.WEAR_INFO_FILENAME);
+ try (JsonWriter jsonWriter = new JsonWriter(new FileWriter(wearHistoryFile))) {
+ wearHistory.writeToJson(jsonWriter);
+ }
+ }
+
+ if (wearData.uptime > 0) {
+ File uptimeFile = new File(getFakeSystemInterface().getFilesDir(),
+ CarStorageMonitoringService.UPTIME_TRACKER_FILENAME);
+ try (JsonWriter jsonWriter = new JsonWriter(new FileWriter(uptimeFile))) {
+ jsonWriter.beginObject();
+ jsonWriter.name("uptime").value(wearData.uptime);
+ jsonWriter.endObject();
+ }
+ }
+
+ if (wearData.previousLifetimeWriteInfo.length > 0) {
+ File previousLifetimeFile = new File(getFakeSystemInterface().getFilesDir(),
+ CarStorageMonitoringService.LIFETIME_WRITES_FILENAME);
+ try (JsonWriter jsonWriter = new JsonWriter(new FileWriter(previousLifetimeFile))) {
+ jsonWriter.beginObject();
+ jsonWriter.name("lifetimeWriteInfo").beginArray();
+ for (LifetimeWriteInfo writeInfo : wearData.previousLifetimeWriteInfo) {
+ writeInfo.writeToJson(jsonWriter);
+ }
+ jsonWriter.endArray().endObject();
+ }
+ }
+
+ Arrays.stream(wearData.ioStats).forEach(
+ mMockStorageMonitoringInterface::addIoStatsRecord);
+
+ } catch (IOException e) {
+ Log.e(TAG, "failed to configure fake system interface", e);
+ fail("failed to configure fake system interface instance");
+ }
+ }
+
+ @Override
+ protected synchronized void configureResourceOverrides(MockResources resources) {
+ final ResourceOverrides overrides = PER_TEST_RESOURCES.getOrDefault(getName(), null);
+ if (overrides != null) {
+ overrides.overrideResources(resources);
+ }
+ }
+
+ @Override
+ public void setUp() throws Exception {
+ super.setUp();
+ mMockSystemStateInterface.executeBootCompletedActions();
+
+ mCarStorageMonitoringManager =
+ (CarStorageMonitoringManager) getCar().getCarManager(Car.STORAGE_MONITORING_SERVICE);
+ }
+
+ @Test
+ public void testReadPreEolInformation() throws Exception {
+ assertEquals(DEFAULT_WEAR_INFORMATION.preEolInfo,
+ mCarStorageMonitoringManager.getPreEolIndicatorStatus());
+ }
+
+ @Test
+ public void testReadWearEstimate() throws Exception {
+ final WearEstimate wearEstimate = mCarStorageMonitoringManager.getWearEstimate();
+
+ assertNotNull(wearEstimate);
+ assertEquals(DEFAULT_WEAR_INFORMATION.lifetimeEstimateA, wearEstimate.typeA);
+ assertEquals(DEFAULT_WEAR_INFORMATION.lifetimeEstimateB, wearEstimate.typeB);
+ }
+
+ @Test
+ public void testReadWearHistory() throws Exception {
+ final List<WearEstimateChange> wearEstimateChanges =
+ mCarStorageMonitoringManager.getWearEstimateHistory();
+
+ assertNotNull(wearEstimateChanges);
+ assertFalse(wearEstimateChanges.isEmpty());
+
+ final WearHistory expectedWearHistory = PER_TEST_DATA.get(getName()).wearHistory;
+
+ assertEquals(expectedWearHistory.size(), wearEstimateChanges.size());
+ for (int i = 0; i < wearEstimateChanges.size(); ++i) {
+ final WearEstimateRecord expected = expectedWearHistory.get(i);
+ final WearEstimateChange actual = wearEstimateChanges.get(i);
+
+ assertTrue(expected.isSameAs(actual));
+ }
+ }
+
+ private void checkLastWearEvent(boolean isAcceptable) throws Exception {
+ final List<WearEstimateChange> wearEstimateChanges =
+ mCarStorageMonitoringManager.getWearEstimateHistory();
+
+ assertNotNull(wearEstimateChanges);
+ assertFalse(wearEstimateChanges.isEmpty());
+
+ final TestData wearData = PER_TEST_DATA.get(getName());
+
+ final WearInformation expectedCurrentWear = wearData.wearInformation;
+ final WearEstimate expectedPreviousWear = wearData.wearHistory.getLast().getNewWearEstimate();
+
+ final WearEstimateChange actualCurrentWear =
+ wearEstimateChanges.get(wearEstimateChanges.size() - 1);
+
+ assertEquals(isAcceptable, actualCurrentWear.isAcceptableDegradation);
+ assertEquals(expectedCurrentWear.toWearEstimate(), actualCurrentWear.newEstimate);
+ assertEquals(expectedPreviousWear, actualCurrentWear.oldEstimate);
+ }
+
+ @Test
+ public void testNotAcceptableWearEvent() throws Exception {
+ checkLastWearEvent(false);
+ }
+
+ @Test
+ public void testAcceptableWearEvent() throws Exception {
+ checkLastWearEvent(true);
+ }
+
+ @Test
+ public void testBootIoStats() throws Exception {
+ final List<IoStatsEntry> bootIoStats =
+ mCarStorageMonitoringManager.getBootIoStats();
+
+ assertNotNull(bootIoStats);
+ assertFalse(bootIoStats.isEmpty());
+
+ final UidIoRecord[] bootIoRecords = PER_TEST_DATA.get(getName()).ioStats;
+
+ bootIoStats.forEach(uidIoStats -> assertTrue(Arrays.stream(bootIoRecords).anyMatch(
+ ioRecord -> uidIoStats.representsSameMetrics(ioRecord))));
+ }
+
+ @Test
+ public void testAggregateIoStats() throws Exception {
+ UidIoRecord oldRecord1000 = mMockStorageMonitoringInterface.getIoStatsRecord(1000);
+
+ UidIoRecord newRecord1000 = new UidIoRecord(1000,
+ oldRecord1000.foreground_rchar,
+ oldRecord1000.foreground_wchar + 50,
+ oldRecord1000.foreground_read_bytes,
+ oldRecord1000.foreground_write_bytes + 100,
+ oldRecord1000.foreground_fsync + 1,
+ oldRecord1000.background_rchar,
+ oldRecord1000.background_wchar,
+ oldRecord1000.background_read_bytes,
+ oldRecord1000.background_write_bytes,
+ oldRecord1000.background_fsync);
+
+ mMockStorageMonitoringInterface.addIoStatsRecord(newRecord1000);
+
+ UidIoRecord record2000 = new UidIoRecord(2000,
+ 1024,
+ 2048,
+ 0,
+ 1024,
+ 1,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0);
+
+ mMockStorageMonitoringInterface.addIoStatsRecord(record2000);
+
+ mMockTimeInterface.tick();
+
+ List<IoStatsEntry> aggregateIoStats = mCarStorageMonitoringManager.getAggregateIoStats();
+
+ assertNotNull(aggregateIoStats);
+ assertFalse(aggregateIoStats.isEmpty());
+
+ aggregateIoStats.forEach(serviceIoStat -> {
+ UidIoRecord mockIoStat = mMockStorageMonitoringInterface.getIoStatsRecord(
+ serviceIoStat.uid);
+
+ assertNotNull(mockIoStat);
+
+ assertTrue(serviceIoStat.representsSameMetrics(mockIoStat));
+ });
+ }
+
+ @Test
+ public void testIoStatsDeltas() throws Exception {
+ UidIoRecord oldRecord0 = mMockStorageMonitoringInterface.getIoStatsRecord(0);
+
+ UidIoRecord newRecord0 = new UidIoRecord(0,
+ oldRecord0.foreground_rchar,
+ oldRecord0.foreground_wchar + 100,
+ oldRecord0.foreground_read_bytes,
+ oldRecord0.foreground_write_bytes + 50,
+ oldRecord0.foreground_fsync,
+ oldRecord0.background_rchar,
+ oldRecord0.background_wchar,
+ oldRecord0.background_read_bytes + 100,
+ oldRecord0.background_write_bytes,
+ oldRecord0.background_fsync);
+
+ mMockStorageMonitoringInterface.addIoStatsRecord(newRecord0);
+ mMockTimeInterface.setUptime(500).tick();
+
+ List<IoStats> deltas = mCarStorageMonitoringManager.getIoStatsDeltas();
+ assertNotNull(deltas);
+ assertEquals(1, deltas.size());
+
+ IoStats delta0 = deltas.get(0);
+ assertNotNull(delta0);
+ assertEquals(500, delta0.getTimestamp());
+
+ List<IoStatsEntry> delta0Stats = delta0.getStats();
+ assertNotNull(delta0Stats);
+ assertEquals(1, delta0Stats.size());
+
+ IoStatsEntry deltaRecord0 = delta0Stats.get(0);
+
+ assertTrue(deltaRecord0.representsSameMetrics(newRecord0.delta(oldRecord0)));
+
+ UidIoRecord newerRecord0 = new UidIoRecord(0,
+ newRecord0.foreground_rchar + 200,
+ newRecord0.foreground_wchar + 10,
+ newRecord0.foreground_read_bytes,
+ newRecord0.foreground_write_bytes,
+ newRecord0.foreground_fsync,
+ newRecord0.background_rchar,
+ newRecord0.background_wchar + 100,
+ newRecord0.background_read_bytes,
+ newRecord0.background_write_bytes + 30,
+ newRecord0.background_fsync + 2);
+
+ mMockStorageMonitoringInterface.addIoStatsRecord(newerRecord0);
+ mMockTimeInterface.setUptime(1000).tick();
+
+ deltas = mCarStorageMonitoringManager.getIoStatsDeltas();
+ assertNotNull(deltas);
+ assertEquals(2, deltas.size());
+
+ delta0 = deltas.get(0);
+ assertNotNull(delta0);
+ assertEquals(500, delta0.getTimestamp());
+
+ delta0Stats = delta0.getStats();
+ assertNotNull(delta0Stats);
+ assertEquals(1, delta0Stats.size());
+
+ deltaRecord0 = delta0Stats.get(0);
+
+ assertTrue(deltaRecord0.representsSameMetrics(newRecord0.delta(oldRecord0)));
+
+ IoStats delta1 = deltas.get(1);
+ assertNotNull(delta1);
+ assertEquals(1000, delta1.getTimestamp());
+
+ List<IoStatsEntry> delta1Stats = delta1.getStats();
+ assertNotNull(delta1Stats);
+ assertEquals(1, delta1Stats.size());
+
+ deltaRecord0 = delta1Stats.get(0);
+
+ assertTrue(deltaRecord0.representsSameMetrics(newerRecord0.delta(newRecord0)));
+ }
+
+ @Test
+ public void testEventDelivery() throws Exception {
+ final Duration eventDeliveryDeadline = Duration.ofSeconds(5);
+
+ UidIoRecord record = new UidIoRecord(0,
+ 0,
+ 100,
+ 0,
+ 75,
+ 1,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0);
+
+ Listener listener1 = new Listener("listener1");
+ Listener listener2 = new Listener("listener2");
+
+ mCarStorageMonitoringManager.registerListener(listener1);
+ mCarStorageMonitoringManager.registerListener(listener2);
+
+ mMockStorageMonitoringInterface.addIoStatsRecord(record);
+ mMockTimeInterface.setUptime(500).tick();
+
+ assertTrue(listener1.waitForEvent(eventDeliveryDeadline));
+ assertTrue(listener2.waitForEvent(eventDeliveryDeadline));
+
+ IoStats event1 = listener1.reset();
+ IoStats event2 = listener2.reset();
+
+ assertEquals(event1, event2);
+ event1.getStats().forEach(stats -> assertTrue(stats.representsSameMetrics(record)));
+
+ mCarStorageMonitoringManager.unregisterListener(listener1);
+
+ mMockTimeInterface.setUptime(600).tick();
+ assertFalse(listener1.waitForEvent(eventDeliveryDeadline));
+ assertTrue(listener2.waitForEvent(eventDeliveryDeadline));
+ }
+
+ @Test
+ public void testIntentOnExcessiveWrite() throws Exception {
+ assertNull(CarStorageMonitoringBroadcastReceiver.reset());
+
+ final Duration intentDeliveryDeadline = Duration.ofSeconds(5);
+
+ UidIoRecord record = new UidIoRecord(0,
+ 0,
+ 5120,
+ 0,
+ 5000,
+ 1,
+ 0,
+ 7168,
+ 0,
+ 7000,
+ 0);
+
+ mMockStorageMonitoringInterface.addIoStatsRecord(record);
+ mMockTimeInterface.setUptime(500).tick();
+
+ assertTrue(CarStorageMonitoringBroadcastReceiver.waitForIntent(intentDeliveryDeadline));
+ Intent deliveredIntent = CarStorageMonitoringBroadcastReceiver.reset();
+ assertNotNull(deliveredIntent);
+ assertEquals(CarStorageMonitoringManager.INTENT_EXCESSIVE_IO, deliveredIntent.getAction());
+ }
+
+ @Test
+ public void testIntentOnExcessiveFsync() throws Exception {
+ assertNull(CarStorageMonitoringBroadcastReceiver.reset());
+
+ final Duration intentDeliveryDeadline = Duration.ofSeconds(5);
+
+ UidIoRecord record = new UidIoRecord(0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 2,
+ 0,
+ 0,
+ 0,
+ 0,
+ 3);
+
+ mMockStorageMonitoringInterface.addIoStatsRecord(record);
+ mMockTimeInterface.setUptime(500).tick();
+
+ assertTrue(CarStorageMonitoringBroadcastReceiver.waitForIntent(intentDeliveryDeadline));
+ Intent deliveredIntent = CarStorageMonitoringBroadcastReceiver.reset();
+ assertNotNull(deliveredIntent);
+ assertEquals(CarStorageMonitoringManager.INTENT_EXCESSIVE_IO, deliveredIntent.getAction());
+ }
+
+ @Test
+ public void testZeroWindowDisablesCollection() throws Exception {
+ final Duration eventDeliveryDeadline = Duration.ofSeconds(5);
+
+ UidIoRecord record = new UidIoRecord(0,
+ 0,
+ 100,
+ 0,
+ 75,
+ 1,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0);
+
+ Listener listener = new Listener("listener");
+
+ mMockStorageMonitoringInterface.addIoStatsRecord(record);
+ mMockTimeInterface.setUptime(500).tick();
+
+ assertFalse(listener.waitForEvent(eventDeliveryDeadline));
+
+ assertEquals(0, mCarStorageMonitoringManager.getIoStatsDeltas().size());
+ }
+
+ @Test
+ public void testComputeShutdownCost() throws Exception {
+ assertEquals(280, mCarStorageMonitoringManager.getShutdownDiskWriteAmount());
+ }
+
+ @Test
+ public void testNegativeShutdownCost() throws Exception {
+ assertEquals(CarStorageMonitoringManager.SHUTDOWN_COST_INFO_MISSING,
+ mCarStorageMonitoringManager.getShutdownDiskWriteAmount());
+ }
+
+ private String getName() {
+ return mTestName.getMethodName();
+ }
+
+ static final class Listener implements CarStorageMonitoringManager.IoStatsListener {
+ private final String mName;
+ private final Object mSync = new Object();
+
+ private IoStats mLastEvent = null;
+
+ Listener(String name) {
+ mName = name;
+ }
+
+ IoStats reset() {
+ synchronized (mSync) {
+ IoStats lastEvent = mLastEvent;
+ mLastEvent = null;
+ return lastEvent;
+ }
+ }
+
+ boolean waitForEvent(Duration duration) {
+ long start = SystemClock.elapsedRealtime();
+ long end = start + duration.toMillis();
+ synchronized (mSync) {
+ while (mLastEvent == null && SystemClock.elapsedRealtime() < end) {
+ try {
+ mSync.wait(10L);
+ } catch (InterruptedException e) {
+ // ignore
+ }
+ }
+ }
+
+ return (mLastEvent != null);
+ }
+
+ @Override
+ public void onSnapshot(IoStats event) {
+ synchronized (mSync) {
+ Log.d(TAG, "listener " + mName + " received event " + event);
+ // We're going to hold a reference to this object
+ mLastEvent = event;
+ mSync.notify();
+ }
+ }
+
+ }
+
+ static final class MockStorageMonitoringInterface implements StorageMonitoringInterface,
+ WearInformationProvider {
+ private WearInformation mWearInformation = null;
+ private SparseArray<UidIoRecord> mIoStats = new SparseArray<>();
+ private UidIoStatsProvider mIoStatsProvider = () -> mIoStats;
+ private LifetimeWriteInfo[] mWriteInfo = new LifetimeWriteInfo[0];
+
+ void setWearInformation(WearInformation wearInformation) {
+ mWearInformation = wearInformation;
+ }
+
+ void setWriteInfo(LifetimeWriteInfo[] writeInfo) {
+ mWriteInfo = writeInfo;
+ }
+
+ void addIoStatsRecord(UidIoRecord record) {
+ mIoStats.append(record.uid, record);
+ }
+
+ UidIoRecord getIoStatsRecord(int uid) {
+ return mIoStats.get(uid);
+ }
+
+ void deleteIoStatsRecord(int uid) {
+ mIoStats.delete(uid);
+ }
+
+ @Override
+ public WearInformation load() {
+ return mWearInformation;
+ }
+
+ @Override
+ public LifetimeWriteInfoProvider getLifetimeWriteInfoProvider() {
+ // cannot make this directly implement because Java does not allow
+ // overloading based on return type and there already is a method named
+ // load() in WearInformationProvider
+ return new LifetimeWriteInfoProvider() {
+ @Override
+ public LifetimeWriteInfo[] load() {
+ return mWriteInfo;
+ }
+ };
+ }
+
+ @Override
+ public WearInformationProvider[] getFlashWearInformationProviders() {
+ return new WearInformationProvider[] {this};
+ }
+
+ @Override
+ public UidIoStatsProvider getUidIoStatsProvider() {
+ return mIoStatsProvider;
+ }
+ }
+
+ static final class MockTimeInterface implements TimeInterface {
+ private final List<Pair<Runnable, Long>> mActionsList = new ArrayList<>();
+ private long mUptime = 0;
+
+ @Override
+ public long getUptime(boolean includeDeepSleepTime) {
+ return mUptime;
+ }
+
+ @Override
+ public void scheduleAction(Runnable r, long delayMs) {
+ mActionsList.add(Pair.create(r, delayMs));
+ mActionsList.sort(Comparator.comparing(d -> d.second));
+ }
+
+ @Override
+ public void cancelAllActions() {
+ mActionsList.clear();
+ }
+
+ void tick() {
+ mActionsList.forEach(pair -> pair.first.run());
+ }
+
+ MockTimeInterface setUptime(long time) {
+ mUptime = time;
+ return this;
+ }
+ }
+
+ static final class MockSystemStateInterface implements SystemStateInterface {
+ private final List<Pair<Runnable, Duration>> mActionsList = new ArrayList<>();
+
+ @Override
+ public void shutdown() {}
+
+ @Override
+ public boolean enterDeepSleep(int wakeupTimeSec) {
+ return true;
+ }
+
+ @Override
+ public void scheduleActionForBootCompleted(Runnable action, Duration delay) {
+ mActionsList.add(Pair.create(action, delay));
+ mActionsList.sort(Comparator.comparing(d -> d.second));
+ }
+
+ void executeBootCompletedActions() {
+ for (Pair<Runnable, Duration> action : mActionsList) {
+ action.first.run();
+ }
+ }
+ }
+}
diff --git a/tests/carservice_test/src/com/android/car/test/CarVendorExtensionManagerTest.java b/tests/carservice_test/src/com/android/car/CarVendorExtensionManagerTest.java
similarity index 90%
rename from tests/carservice_test/src/com/android/car/test/CarVendorExtensionManagerTest.java
rename to tests/carservice_test/src/com/android/car/CarVendorExtensionManagerTest.java
index fa33e56..1f6bb10 100644
--- a/tests/carservice_test/src/com/android/car/test/CarVendorExtensionManagerTest.java
+++ b/tests/carservice_test/src/com/android/car/CarVendorExtensionManagerTest.java
@@ -14,22 +14,26 @@
* limitations under the License.
*/
-package com.android.car.test;
+package com.android.car;
import static com.android.car.CarServiceUtils.toByteArray;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+
import android.car.Car;
import android.car.hardware.CarPropertyConfig;
import android.car.hardware.CarVendorExtensionManager;
import android.hardware.automotive.vehicle.V2_0.StatusCode;
import android.hardware.automotive.vehicle.V2_0.VehicleArea;
-import android.hardware.automotive.vehicle.V2_0.VehicleAreaZone;
+import android.hardware.automotive.vehicle.V2_0.VehicleAreaSeat;
import android.hardware.automotive.vehicle.V2_0.VehiclePropConfig;
import android.hardware.automotive.vehicle.V2_0.VehiclePropValue;
import android.hardware.automotive.vehicle.V2_0.VehiclePropertyGroup;
import android.hardware.automotive.vehicle.V2_0.VehiclePropertyType;
import android.os.SystemClock;
-import android.test.suitebuilder.annotation.MediumTest;
+import android.support.test.filters.MediumTest;
+import android.support.test.runner.AndroidJUnit4;
import android.util.Log;
import android.util.SparseArray;
@@ -37,6 +41,8 @@
import com.android.car.vehiclehal.test.VehiclePropConfigBuilder;
import org.junit.Assert;
+import org.junit.Test;
+import org.junit.runner.RunWith;
import java.util.Arrays;
import java.util.List;
@@ -45,6 +51,7 @@
/**
* Tests for {@link CarVendorExtensionManager}
*/
+@RunWith(AndroidJUnit4.class)
@MediumTest
public class CarVendorExtensionManagerTest extends MockedCarTestBase {
@@ -54,10 +61,10 @@
0x1 | VehiclePropertyGroup.VENDOR | VehiclePropertyType.INT32 | VehicleArea.GLOBAL;
private static final int CUSTOM_ZONED_FLOAT_PROP_ID =
- 0x2 | VehiclePropertyGroup.VENDOR | VehiclePropertyType.FLOAT | VehicleArea.ZONE;
+ 0x2 | VehiclePropertyGroup.VENDOR | VehiclePropertyType.FLOAT | VehicleArea.SEAT;
private static final int CUSTOM_BYTES_PROP_ID_1 =
- 0x3 | VehiclePropertyGroup.VENDOR | VehiclePropertyType.BYTES | VehicleArea.ZONE;
+ 0x3 | VehiclePropertyGroup.VENDOR | VehiclePropertyType.BYTES | VehicleArea.SEAT;
private static final int CUSTOM_BYTES_PROP_ID_2 =
0x4 | VehiclePropertyGroup.VENDOR | VehiclePropertyType.BYTES | VehicleArea.GLOBAL;
@@ -81,12 +88,12 @@
.addAreaConfig(0, MIN_PROP_INT32, MAX_PROP_INT32)
.build(),
VehiclePropConfigBuilder.newBuilder(CUSTOM_ZONED_FLOAT_PROP_ID)
- .setSupportedAreas(VehicleAreaZone.ROW_1_LEFT | VehicleAreaZone.ROW_1_RIGHT)
- .addAreaConfig(VehicleAreaZone.ROW_1_LEFT, MIN_PROP_FLOAT, MAX_PROP_FLOAT)
- .addAreaConfig(VehicleAreaZone.ROW_2_RIGHT, MIN_PROP_FLOAT, MAX_PROP_FLOAT)
+ .addAreaConfig(VehicleAreaSeat.ROW_1_LEFT | VehicleAreaSeat.ROW_1_RIGHT, 0, 0)
+ .addAreaConfig(VehicleAreaSeat.ROW_1_LEFT, MIN_PROP_FLOAT, MAX_PROP_FLOAT)
+ .addAreaConfig(VehicleAreaSeat.ROW_2_RIGHT, MIN_PROP_FLOAT, MAX_PROP_FLOAT)
.build(),
VehiclePropConfigBuilder.newBuilder(CUSTOM_BYTES_PROP_ID_1)
- .setSupportedAreas(VehicleAreaZone.ROW_1_LEFT | VehicleAreaZone.ROW_1_RIGHT)
+ .addAreaConfig(VehicleAreaSeat.ROW_1_LEFT | VehicleAreaSeat.ROW_1_RIGHT, 0, 0)
.build(),
VehiclePropConfigBuilder.newBuilder(CUSTOM_BYTES_PROP_ID_2).build(),
VehiclePropConfigBuilder.newBuilder(CUSTOM_STRING_PROP_ID).build(),
@@ -95,18 +102,14 @@
private CarVendorExtensionManager mManager;
@Override
- protected void setUp() throws Exception {
+ public void setUp() throws Exception {
super.setUp();
mManager = (CarVendorExtensionManager) getCar().getCarManager(Car.VENDOR_EXTENSION_SERVICE);
assertNotNull(mManager);
}
- @Override
- protected void tearDown() throws Exception {
- super.tearDown();
- }
-
+ @Test
public void testPropertyList() throws Exception {
List<CarPropertyConfig> configs = mManager.getProperties();
assertEquals(mConfigs.length, configs.size());
@@ -123,6 +126,7 @@
assertEquals(MAX_PROP_INT32, prop1.getMaxValue());
}
+ @Test
public void testIntGlobalProperty() throws Exception {
final int value = 0xbeef;
mManager.setGlobalProperty(Integer.class, CUSTOM_GLOBAL_INT_PROP_ID, value);
@@ -130,19 +134,21 @@
assertEquals(value, actualValue);
}
+ @Test
public void testFloatZonedProperty() throws Exception {
final float value = MIN_PROP_FLOAT + 1;
mManager.setProperty(
Float.class,
CUSTOM_ZONED_FLOAT_PROP_ID,
- VehicleAreaZone.ROW_1_RIGHT,
+ VehicleAreaSeat.ROW_1_RIGHT,
value);
float actualValue = mManager.getProperty(
- Float.class, CUSTOM_ZONED_FLOAT_PROP_ID, VehicleAreaZone.ROW_1_RIGHT);
+ Float.class, CUSTOM_ZONED_FLOAT_PROP_ID, VehicleAreaSeat.ROW_1_RIGHT);
assertEquals(value, actualValue, EPS);
}
+ @Test
public void testByteArrayProperty() throws Exception {
final byte[] expectedData = new byte[] { 1, 2, 3, 4, -1, 127, -127, 0 };
@@ -159,6 +165,7 @@
assertEquals(Arrays.toString(expectedData), Arrays.toString(actualData));
}
+ @Test
public void testLargeByteArrayProperty() throws Exception {
// Allocate array of byte which is greater than binder transaction buffer limitation.
byte[] expectedData = new byte[2 * MILLION];
@@ -179,6 +186,7 @@
Assert.assertArrayEquals(expectedData, actualData);
}
+ @Test
public void testLargeStringProperty() throws Exception {
// Allocate string which is greater than binder transaction buffer limitation.
String expectedString = generateRandomString(2 * MILLION,
@@ -196,6 +204,7 @@
assertEquals(expectedString, actualString);
}
+ @Test
public void testStringProperty() throws Exception {
final String expectedString = "εὕρηκα!"; // Test some utf as well.
@@ -246,7 +255,7 @@
@Override
public synchronized void get(VehiclePropValue requestedPropValue, getCallback cb) {
if (!isVendorProperty(requestedPropValue.prop)) {
- cb.onValues(StatusCode.INVALID_ARG, null);
+ super.get(requestedPropValue, cb);
return;
}
VehiclePropValue result = new VehiclePropValue();
diff --git a/tests/carservice_test/src/com/android/car/FastPairProviderTest.java b/tests/carservice_test/src/com/android/car/FastPairProviderTest.java
new file mode 100644
index 0000000..02c4cf1
--- /dev/null
+++ b/tests/carservice_test/src/com/android/car/FastPairProviderTest.java
@@ -0,0 +1,102 @@
+/*
+ * 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;
+
+import static org.mockito.Mockito.any;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import android.bluetooth.BluetoothAdapter;
+import android.bluetooth.BluetoothManager;
+import android.bluetooth.le.AdvertiseData;
+import android.bluetooth.le.BluetoothLeAdvertiser;
+import android.content.Context;
+import android.content.res.Resources;
+import android.os.ParcelUuid;
+import android.support.test.filters.SmallTest;
+import android.support.test.runner.AndroidJUnit4;
+
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.ArgumentCaptor;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+
+import java.util.Arrays;
+
+@SmallTest
+@RunWith(AndroidJUnit4.class)
+public class FastPairProviderTest {
+ // Service ID assigned for FastPair.
+ private static final ParcelUuid FastPairServiceUuid = ParcelUuid
+ .fromString("0000FE2C-0000-1000-8000-00805f9b34fb");
+
+ @Mock
+ private BluetoothLeAdvertiser mBluetoothLeAdvertiser;
+ @Mock
+ private BluetoothManager mMockBluetoothManager;
+ @Mock
+ private BluetoothAdapter mMockBluetoothAdapter;
+ @Mock
+ private Context mMockContext;
+ @Mock
+ Resources mMockResources;
+
+ @Before
+ public void setUp() {
+ MockitoAnnotations.initMocks(this);
+ when(mMockContext.getSystemService(Context.BLUETOOTH_SERVICE)).thenReturn(
+ mMockBluetoothManager);
+ when(mMockBluetoothManager.getAdapter()).thenReturn(mMockBluetoothAdapter);
+ when(mMockContext.getResources()).thenReturn(mMockResources);
+ when(mMockResources.getInteger(R.integer.fastPairModelId)).thenReturn(0);
+ when(mMockBluetoothAdapter.getBluetoothLeAdvertiser()).thenReturn(mBluetoothLeAdvertiser);
+ }
+
+ /**
+ * Verify that when a model id is set it gets serialized correctly.
+ */
+ @Test
+ public void enabledViaModelIdTest() {
+ int modelId = 0xABCDEF;
+ byte[] modelIdBytes = new byte[]{(byte) 0xEF, (byte) 0xCD, (byte) 0xAB};
+ when(mMockResources.getInteger(R.integer.fastPairModelId)).thenReturn(modelId);
+ ArgumentCaptor<AdvertiseData> advertiseDataCaptor = ArgumentCaptor.forClass(
+ AdvertiseData.class);
+
+ FastPairProvider fastPairProvider = new FastPairProvider(mMockContext);
+ fastPairProvider.startAdvertising();
+
+ verify(mBluetoothLeAdvertiser).startAdvertising(any(), advertiseDataCaptor.capture(),
+ any());
+ Assert.assertTrue(Arrays.equals(modelIdBytes,
+ advertiseDataCaptor.getValue().getServiceData().get(FastPairServiceUuid)));
+ }
+
+ /**
+ * Verify that when the model id is 0 Fast Pair is disabled.
+ */
+ @Test
+ public void disabledViaModelIdTest() {
+ FastPairProvider fastPairProvider = new FastPairProvider(mMockContext);
+ fastPairProvider.startAdvertising();
+ verify(mBluetoothLeAdvertiser, never()).startAdvertising(any(), any(), any());
+ }
+}
diff --git a/tests/carservice_test/src/com/android/car/GarageModeTest.java b/tests/carservice_test/src/com/android/car/GarageModeTest.java
new file mode 100644
index 0000000..23153fc
--- /dev/null
+++ b/tests/carservice_test/src/com/android/car/GarageModeTest.java
@@ -0,0 +1,306 @@
+/*
+ * 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 static org.junit.Assert.assertArrayEquals;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
+
+import android.car.settings.CarSettings;
+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.runner.AndroidJUnit4;
+
+import com.android.car.GarageModeService.GarageModePolicy;
+import com.android.car.GarageModeService.WakeupTime;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+@RunWith(AndroidJUnit4.class)
+@MediumTest
+public class GarageModeTest {
+ private static final int WAIT_FOR_COMPLETION_TIME = 3000;//ms
+
+ @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());
+
+ controller.setMaintenanceActivity(false);
+ assertEquals(false, garageMode.isInGarageMode());
+ assertEquals(false, garageMode.isMaintenanceActive());
+ final int index2 = garageMode.getGarageModeIndex();
+
+ assertEquals(1, index2 - index1);
+ }
+
+ @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());
+ }
+
+ @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());
+ String[] policy = {
+ "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);
+ 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);
+ assertEquals(9, prefs.getInt("garage_mode_index", 0));
+ }
+
+ @Test
+ public void testPolicyParserValid() throws Exception {
+ WakeupTime expected[] = new WakeupTime[]{
+ new WakeupTime(15 * 60, 1),
+ new WakeupTime(6 * 60 * 60, 8),
+ new WakeupTime(24 * 60 * 60, 5),
+ };
+ WakeupTime received[] = new GarageModePolicy(new String[] {
+ "15m,1",
+ "6h,8",
+ "1d,5",
+ }).mWakeupTime;
+
+ assertEquals(expected.length, received.length);
+ for (int i = 0; i < expected.length; i++) {
+ assertEquals(expected[i].mWakeupTime, received[i].mWakeupTime);
+ assertEquals(expected[i].mNumAttempts, received[i].mNumAttempts);
+ }
+ }
+
+ @Test(expected=RuntimeException.class)
+ public void testPolicyParserNull() {
+ new GarageModePolicy(null);
+ }
+ @Test(expected=RuntimeException.class)
+ public void testPolicyParserEmptyArray() {
+ new GarageModePolicy(new String[] {});
+ }
+ @Test(expected=RuntimeException.class)
+ public void testPolicyParserEmptyString() {
+ new GarageModePolicy(new String[] {""});
+ }
+ @Test(expected=RuntimeException.class)
+ public void testPolicyParserMissingUnits() {
+ new GarageModePolicy(new String[] {"15,1"});
+ }
+ @Test(expected=RuntimeException.class)
+ public void testPolicyParserInvalidUnits() {
+ new GarageModePolicy(new String[] {"15y,1"});
+ }
+ @Test(expected=RuntimeException.class)
+ public void testPolicyParserNoCount() {
+ new GarageModePolicy(new String[] {"15m"});
+ }
+ @Test(expected=RuntimeException.class)
+ public void testPolicyParserBadCount() {
+ new GarageModePolicy(new String[] {"15m,Q"});
+ }
+ @Test(expected=RuntimeException.class)
+ public void testPolicyParserNegativeCount() {
+ new GarageModePolicy(new String[] {"15m,-1"});
+ }
+ @Test(expected=RuntimeException.class)
+ public void testPolicyParserNoTime() {
+ new GarageModePolicy(new String[] {",1"});
+ }
+ @Test(expected=RuntimeException.class)
+ public void testPolicyParserNoTimeValue() {
+ new GarageModePolicy(new String[] {"m,1"});
+ }
+ @Test(expected=RuntimeException.class)
+ public void testPolicyParserBadTime() {
+ new GarageModePolicy(new String[] {"Qm,1"});
+ }
+ @Test(expected=RuntimeException.class)
+ public void testPolicyParserNegativeTime() {
+ new GarageModePolicy(new String[] {"-10m,1"});
+ }
+
+ @Test
+ public void testPolicyInResource() throws Exception {
+ // Test that the policy in the resource file parses fine.
+ assertNotNull(new GarageModePolicy(getContext().getResources().getStringArray(
+ R.array.config_garageModeCadence)).mWakeupTime);
+ }
+
+ 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 {
+ public GarageModeServiceForTest(Context context,
+ CarPowerManagementService powerManagementService,
+ DeviceIdleControllerWrapper controllerWrapper,
+ Looper looper) {
+ super(context, powerManagementService, controllerWrapper, looper);
+ }
+
+ public 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);
+ }
+ }
+}
diff --git a/tests/carservice_test/src/com/android/car/MockedCarTestBase.java b/tests/carservice_test/src/com/android/car/MockedCarTestBase.java
new file mode 100644
index 0000000..a57d800
--- /dev/null
+++ b/tests/carservice_test/src/com/android/car/MockedCarTestBase.java
@@ -0,0 +1,443 @@
+/*
+ * 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;
+
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.fail;
+
+import android.car.Car;
+import android.car.test.CarTestManager;
+import android.car.test.CarTestManagerBinderWrapper;
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.ContextWrapper;
+import android.content.ServiceConnection;
+import android.content.pm.PackageManager.NameNotFoundException;
+import android.content.res.Resources;
+import android.hardware.automotive.vehicle.V2_0.VehiclePropValue;
+import android.hardware.automotive.vehicle.V2_0.VehiclePropertyAccess;
+import android.hardware.automotive.vehicle.V2_0.VehiclePropertyChangeMode;
+import android.os.Binder;
+import android.os.Handler;
+import android.os.IBinder;
+import android.os.Looper;
+import android.support.test.InstrumentationRegistry;
+import android.support.test.annotation.UiThreadTest;
+import android.util.Log;
+import android.util.SparseArray;
+
+import com.android.car.pm.CarPackageManagerService;
+import com.android.car.systeminterface.DisplayInterface;
+import com.android.car.systeminterface.IOInterface;
+import com.android.car.systeminterface.StorageMonitoringInterface;
+import com.android.car.systeminterface.SystemInterface;
+import com.android.car.systeminterface.SystemInterface.Builder;
+import com.android.car.systeminterface.SystemStateInterface;
+import com.android.car.systeminterface.TimeInterface;
+import com.android.car.systeminterface.WakeLockInterface;
+import com.android.car.test.CarServiceTestApp;
+import com.android.car.test.utils.TemporaryDirectory;
+import com.android.car.vehiclehal.test.MockedVehicleHal;
+import com.android.car.vehiclehal.test.MockedVehicleHal.DefaultPropertyHandler;
+import com.android.car.vehiclehal.test.MockedVehicleHal.StaticPropertyHandler;
+import com.android.car.vehiclehal.test.MockedVehicleHal.VehicleHalPropertyHandler;
+import com.android.car.vehiclehal.test.VehiclePropConfigBuilder;
+
+import org.junit.After;
+import org.junit.Before;
+
+import java.io.File;
+import java.io.IOException;
+import java.time.Duration;
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * Base class for testing with mocked vehicle HAL (=car).
+ * It is up to each app to start emulation by getMockedVehicleHal().start() as there will be
+ * per test set up that should be done before starting.
+ */
+public class MockedCarTestBase {
+ private static final String TAG = MockedCarTestBase.class.getSimpleName();
+ static final long DEFAULT_WAIT_TIMEOUT_MS = 3000;
+ static final long SHORT_WAIT_TIMEOUT_MS = 500;
+
+ private Car mCar;
+ private ICarImpl mCarImpl;
+ private MockedVehicleHal mMockedVehicleHal;
+ private SystemInterface mFakeSystemInterface;
+ private MockContext mMockContext;
+ private final MockIOInterface mMockIOInterface = new MockIOInterface();
+
+ private final Handler mMainHandler = new Handler(Looper.getMainLooper());
+
+ private final Map<VehiclePropConfigBuilder, VehicleHalPropertyHandler> mHalConfig =
+ new HashMap<>();
+ private final SparseArray<VehiclePropConfigBuilder> mPropToConfigBuilder = new SparseArray<>();
+
+ private static final IBinder mCarServiceToken = new Binder();
+ private static boolean mRealCarServiceReleased = false;
+
+ protected synchronized MockedVehicleHal createMockedVehicleHal() {
+ return new MockedVehicleHal();
+ }
+
+ protected synchronized MockedVehicleHal getMockedVehicleHal() {
+ return mMockedVehicleHal;
+ }
+
+ protected synchronized SystemInterface getFakeSystemInterface() {
+ return mFakeSystemInterface;
+ }
+
+ protected synchronized void configureMockedHal() {
+ }
+
+ protected synchronized SystemInterface.Builder getSystemInterfaceBuilder() {
+ return Builder.newSystemInterface()
+ .withSystemStateInterface(new MockSystemStateInterface())
+ .withDisplayInterface(new MockDisplayInterface())
+ .withIOInterface(mMockIOInterface)
+ .withStorageMonitoringInterface(new MockStorageMonitoringInterface())
+ .withTimeInterface(new MockTimeInterface())
+ .withWakeLockInterface(new MockWakeLockInterface());
+ }
+
+ protected synchronized void configureFakeSystemInterface() {}
+
+ protected synchronized void configureResourceOverrides(MockResources resources) {
+ resources.overrideResource(com.android.car.R.string.instrumentClusterRendererService, "");
+ }
+
+ protected Context getContext() {
+ return InstrumentationRegistry.getTargetContext();
+ }
+
+ protected Context getTestContext() {
+ return InstrumentationRegistry.getContext();
+ }
+
+ protected String getFlattenComponent(Class cls) {
+ ComponentName cn = new ComponentName(getTestContext(), cls);
+ return cn.flattenToString();
+ }
+
+ @Before
+ @UiThreadTest
+ public void setUp() throws Exception {
+ Log.i(TAG, "setUp");
+ releaseRealCarService(getContext());
+
+ mMockedVehicleHal = createMockedVehicleHal();
+ configureMockedHal();
+
+ mFakeSystemInterface = getSystemInterfaceBuilder().build();
+ configureFakeSystemInterface();
+
+ MockContext context = getCarServiceContext();
+ configureResourceOverrides(context.getResources());
+
+ mCarImpl = new ICarImpl(context, mMockedVehicleHal, mFakeSystemInterface,
+ null /* error notifier */, "MockedCar");
+
+ initMockedHal(false /* no need to release */);
+
+ mCar = new Car(context, mCarImpl, null /* handler */);
+ }
+
+ @After
+ public void tearDown() throws Exception {
+ mCar.disconnect();
+ mCarImpl.release();
+
+ mMockIOInterface.tearDown();
+ }
+
+ public CarPackageManagerService getPackageManagerService() {
+ return (CarPackageManagerService) mCarImpl.getCarService(Car.PACKAGE_SERVICE);
+ }
+
+ protected MockContext getCarServiceContext() throws NameNotFoundException {
+ if (mMockContext == null) {
+ mMockContext = new MockContext(getContext()
+ .createPackageContext("com.android.car", Context.CONTEXT_IGNORE_SECURITY));
+ }
+ return mMockContext;
+ }
+
+ protected synchronized void reinitializeMockedHal() throws Exception {
+ initMockedHal(true /* release */);
+ }
+
+ private synchronized void initMockedHal(boolean release) throws Exception {
+ if (release) {
+ mCarImpl.release();
+ }
+
+ for (Map.Entry<VehiclePropConfigBuilder, VehicleHalPropertyHandler> entry
+ : mHalConfig.entrySet()) {
+ mMockedVehicleHal.addProperty(entry.getKey().build(), entry.getValue());
+ }
+ mHalConfig.clear();
+ mCarImpl.init();
+ }
+
+ protected synchronized VehiclePropConfigBuilder addProperty(int propertyId,
+ VehicleHalPropertyHandler propertyHandler) {
+ VehiclePropConfigBuilder builder = VehiclePropConfigBuilder.newBuilder(propertyId);
+ setConfigBuilder(builder, propertyHandler);
+ return builder;
+ }
+
+ protected synchronized VehiclePropConfigBuilder addProperty(int propertyId) {
+ VehiclePropConfigBuilder builder = VehiclePropConfigBuilder.newBuilder(propertyId);
+ setConfigBuilder(builder, new DefaultPropertyHandler(builder.build(), null));
+ return builder;
+ }
+
+ protected synchronized VehiclePropConfigBuilder addProperty(int propertyId,
+ VehiclePropValue value) {
+ VehiclePropConfigBuilder builder = VehiclePropConfigBuilder.newBuilder(propertyId);
+ setConfigBuilder(builder, new DefaultPropertyHandler(builder.build(), value));
+ return builder;
+ }
+
+ protected synchronized VehiclePropConfigBuilder addStaticProperty(int propertyId,
+ VehiclePropValue value) {
+ VehiclePropConfigBuilder builder = VehiclePropConfigBuilder.newBuilder(propertyId)
+ .setChangeMode(VehiclePropertyChangeMode.STATIC)
+ .setAccess(VehiclePropertyAccess.READ);
+
+ setConfigBuilder(builder, new StaticPropertyHandler(value));
+ return builder;
+ }
+
+ private void setConfigBuilder(VehiclePropConfigBuilder builder,
+ VehicleHalPropertyHandler propertyHandler) {
+ int propId = builder.build().prop;
+
+ // Override previous property config if exists.
+ VehiclePropConfigBuilder prevBuilder = mPropToConfigBuilder.get(propId);
+ if (prevBuilder != null) {
+ mHalConfig.remove(prevBuilder);
+ }
+ mPropToConfigBuilder.put(propId, builder);
+ mHalConfig.put(builder, propertyHandler);
+ }
+
+ protected synchronized android.car.Car getCar() {
+ return mCar;
+ }
+
+ /*
+ * In order to eliminate interfering with real car service we will disable it. It will be
+ * enabled back in CarTestService when mCarServiceToken will go away (tests finish).
+ */
+ private synchronized static void releaseRealCarService(Context context) throws Exception {
+ if (mRealCarServiceReleased) {
+ return; // We just want to release it once.
+ }
+
+ mRealCarServiceReleased = true; // To make sure it was called once.
+
+ Object waitForConnection = new Object();
+ android.car.Car car = android.car.Car.createCar(context, new ServiceConnection() {
+ @Override
+ public void onServiceConnected(ComponentName name, IBinder service) {
+ synchronized (waitForConnection) {
+ waitForConnection.notify();
+ }
+ }
+
+ @Override
+ public void onServiceDisconnected(ComponentName name) { }
+ });
+
+ car.connect();
+ synchronized (waitForConnection) {
+ if (!car.isConnected()) {
+ waitForConnection.wait(DEFAULT_WAIT_TIMEOUT_MS);
+ }
+ }
+
+ if (car.isConnected()) {
+ Log.i(TAG, "Connected to real car service");
+ CarTestManagerBinderWrapper binderWrapper =
+ (CarTestManagerBinderWrapper) car.getCarManager(android.car.Car.TEST_SERVICE);
+ assertNotNull(binderWrapper);
+
+ CarTestManager mgr = new CarTestManager(binderWrapper.binder);
+ mgr.stopCarService(mCarServiceToken);
+ }
+ }
+
+ static final class MockDisplayInterface implements DisplayInterface {
+
+ @Override
+ public void setDisplayBrightness(int brightness) {}
+
+ @Override
+ public void setDisplayState(boolean on) {}
+
+ @Override
+ public void startDisplayStateMonitoring(CarPowerManagementService service) {}
+
+ @Override
+ public void stopDisplayStateMonitoring() {}
+ }
+
+ static final class MockIOInterface implements IOInterface {
+ private TemporaryDirectory mFilesDir = null;
+
+ @Override
+ public File getFilesDir() {
+ if (mFilesDir == null) {
+ try {
+ mFilesDir = new TemporaryDirectory(TAG);
+ } catch (IOException e) {
+ Log.e(TAG, "failed to create temporary directory", e);
+ fail("failed to create temporary directory. exception was: " + e);
+ }
+ }
+ return mFilesDir.getDirectory();
+ }
+
+ public void tearDown() {
+ if (mFilesDir != null) {
+ try {
+ mFilesDir.close();
+ } catch (Exception e) {
+ Log.w(TAG, "could not remove temporary directory", e);
+ }
+ }
+ }
+ }
+
+ static final class MockResources extends Resources {
+ private final HashMap<Integer, Integer> mIntegerOverrides = new HashMap<>();
+ private final HashMap<Integer, String> mStringOverrides = new HashMap<>();
+ private final HashMap<Integer, String[]> mStringArrayOverrides = new HashMap<>();
+
+ MockResources(Resources resources) {
+ super(resources.getAssets(),
+ resources.getDisplayMetrics(),
+ resources.getConfiguration());
+ }
+
+ @Override
+ public int getInteger(int id) {
+ return mIntegerOverrides.getOrDefault(id,
+ super.getInteger(id));
+ }
+
+ @Override
+ public String getString(int id) {
+ return mStringOverrides.getOrDefault(id,
+ super.getString(id));
+ }
+
+ @Override
+ public String[] getStringArray(int id) {
+ return mStringArrayOverrides.getOrDefault(id,
+ super.getStringArray(id));
+ }
+
+ MockResources overrideResource(int id, int value) {
+ mIntegerOverrides.put(id, value);
+ return this;
+ }
+
+ MockResources overrideResource(int id, String value) {
+ mStringOverrides.put(id, value);
+ return this;
+ }
+
+ MockResources overrideResource(int id, String[] value) {
+ mStringArrayOverrides.put(id, value);
+ return this;
+ }
+ }
+
+ static class MockContext extends ContextWrapper {
+ private final MockResources mResources;
+
+ MockContext(Context base) {
+ super(base);
+ mResources = new MockResources(super.getResources());
+ }
+
+ @Override
+ public MockResources getResources() {
+ return mResources;
+ }
+
+ // BLUETOOTH_SERVICE needs to be retrieved with an Application context, which neither
+ // this MockContext, nor its base Context are. In order to make this work, we save
+ // an Application context at startup and use it when necessary. Add other services
+ // here as needed.
+ @Override
+ public Object getSystemService(String name) {
+ switch (name) {
+ case BLUETOOTH_SERVICE:
+ return CarServiceTestApp.getAppContext().getSystemService(name);
+ default:
+ return super.getSystemService(name);
+ }
+ }
+
+ @Override
+ public Context getApplicationContext() {
+ return this;
+ }
+ }
+
+ static final class MockStorageMonitoringInterface implements StorageMonitoringInterface {}
+
+ static final class MockSystemStateInterface implements SystemStateInterface {
+ @Override
+ public void shutdown() {}
+
+ @Override
+ public boolean enterDeepSleep(int wakeupTimeSec) {
+ return true;
+ }
+
+ @Override
+ public void scheduleActionForBootCompleted(Runnable action, Duration delay) {}
+ }
+
+ static final class MockTimeInterface implements TimeInterface {
+
+ @Override
+ public void scheduleAction(Runnable r, long delayMs) {}
+
+ @Override
+ public void cancelAllActions() {}
+ }
+
+ static final class MockWakeLockInterface implements WakeLockInterface {
+
+ @Override
+ public void releaseAllWakeLocks() {}
+
+ @Override
+ public void switchToPartialWakeLock() {}
+
+ @Override
+ public void switchToFullWakeLock() {}
+ }
+
+}
diff --git a/tests/carservice_test/src/com/android/car/test/SimpleVmsPublisherClientService.java b/tests/carservice_test/src/com/android/car/SimpleVmsPublisherClientService.java
similarity index 93%
rename from tests/carservice_test/src/com/android/car/test/SimpleVmsPublisherClientService.java
rename to tests/carservice_test/src/com/android/car/SimpleVmsPublisherClientService.java
index c3c15f5..53491b1 100644
--- a/tests/carservice_test/src/com/android/car/test/SimpleVmsPublisherClientService.java
+++ b/tests/carservice_test/src/com/android/car/SimpleVmsPublisherClientService.java
@@ -14,16 +14,14 @@
* limitations under the License.
*/
-package com.android.car.test;
+package com.android.car;
-import android.car.annotation.FutureFeature;
import android.car.vms.VmsPublisherClientService;
import android.car.vms.VmsSubscriptionState;
/**
* This service is launched during the tests in VmsPublisherClientServiceTest.
*/
-@FutureFeature
public class SimpleVmsPublisherClientService extends VmsPublisherClientService {
@Override
public void onVmsSubscriptionChange(VmsSubscriptionState subscriptionState) {
diff --git a/tests/carservice_test/src/com/android/car/SystemActivityMonitoringServiceTest.java b/tests/carservice_test/src/com/android/car/SystemActivityMonitoringServiceTest.java
new file mode 100644
index 0000000..6c546fc
--- /dev/null
+++ b/tests/carservice_test/src/com/android/car/SystemActivityMonitoringServiceTest.java
@@ -0,0 +1,135 @@
+/*
+ * 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 static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+
+import android.app.Activity;
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.Intent;
+import android.support.test.InstrumentationRegistry;
+import android.support.test.filters.MediumTest;
+import android.support.test.runner.AndroidJUnit4;
+
+import com.android.car.SystemActivityMonitoringService.TopTaskInfoContainer;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.util.concurrent.Semaphore;
+import java.util.concurrent.TimeUnit;
+
+@RunWith(AndroidJUnit4.class)
+@MediumTest
+public class SystemActivityMonitoringServiceTest {
+ private static final long ACTIVITY_TIME_OUT = 5000;
+
+ private SystemActivityMonitoringService mService;
+ private Semaphore mSemaphore = new Semaphore(0);
+
+ private final TopTaskInfoContainer[] mTopTaskInfo = new TopTaskInfoContainer[1];
+
+ @Before
+ public void setUp() throws Exception {
+ mService = new SystemActivityMonitoringService(getContext());
+ mService.registerActivityLaunchListener(topTask -> {
+ if (!getTestContext().getPackageName().equals(topTask.topActivity.getPackageName())) {
+ return; // Ignore activities outside of this test case.
+ }
+ synchronized (mTopTaskInfo) {
+ mTopTaskInfo[0] = topTask;
+ }
+ mSemaphore.release();
+ });
+ }
+
+ @After
+ public void tearDown() throws Exception {
+ mService.registerActivityLaunchListener(null);
+ mService = null;
+ }
+
+ @Test
+ public void testActivityLaunch() throws Exception {
+ ComponentName activityA = toComponentName(getTestContext(), ActivityA.class);
+ startActivity(getContext(), activityA);
+ assertTopTaskActivity(activityA);
+
+ ComponentName activityB = toComponentName(getTestContext(), ActivityB.class);
+ startActivity(getContext(), activityB);
+ assertTopTaskActivity(activityB);
+ }
+
+ @Test
+ public void testActivityBlocking() throws Exception {
+ ComponentName blackListedActivity = toComponentName(getTestContext(), ActivityC.class);
+ ComponentName blockingActivity = toComponentName(getTestContext(), BlockingActivity.class);
+ Intent blockingIntent = new Intent();
+ blockingIntent.setComponent(blockingActivity);
+
+ // start a black listed activity
+ startActivity(getContext(), blackListedActivity);
+ assertTopTaskActivity(blackListedActivity);
+
+ // Instead of start activity, invoke blockActivity.
+ mService.blockActivity(mTopTaskInfo[0], blockingIntent);
+ assertTopTaskActivity(blockingActivity);
+ }
+
+ /** Activity that closes itself after some timeout to clean up the screen. */
+ public static class TempActivity extends Activity {
+ @Override
+ protected void onResume() {
+ super.onResume();
+ getMainThreadHandler().postDelayed(this::finish, ACTIVITY_TIME_OUT);
+ }
+ }
+
+ public static class ActivityA extends TempActivity {}
+ public static class ActivityB extends TempActivity {}
+ public static class ActivityC extends TempActivity {}
+ public static class BlockingActivity extends TempActivity {}
+
+ private void assertTopTaskActivity(ComponentName activity) throws Exception{
+ assertTrue(mSemaphore.tryAcquire(2, TimeUnit.SECONDS));
+ synchronized (mTopTaskInfo) {
+ assertEquals(activity, mTopTaskInfo[0].topActivity);
+ }
+ }
+
+ private Context getContext() {
+ return InstrumentationRegistry.getTargetContext();
+ }
+
+ private Context getTestContext() {
+ return InstrumentationRegistry.getContext();
+ }
+
+ private static ComponentName toComponentName(Context ctx, Class<?> cls) {
+ return ComponentName.createRelative(ctx, cls.getName());
+ }
+
+ private static void startActivity(Context ctx, ComponentName name) {
+ Intent intent = new Intent();
+ intent.setComponent(name);
+ intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+ ctx.startActivity(intent);
+ }
+}
diff --git a/tests/carservice_test/src/com/android/car/test/TestAppBlockingPolicyService.java b/tests/carservice_test/src/com/android/car/TestAppBlockingPolicyService.java
similarity index 96%
rename from tests/carservice_test/src/com/android/car/test/TestAppBlockingPolicyService.java
rename to tests/carservice_test/src/com/android/car/TestAppBlockingPolicyService.java
index dc1ad8a..41bc612 100644
--- a/tests/carservice_test/src/com/android/car/test/TestAppBlockingPolicyService.java
+++ b/tests/carservice_test/src/com/android/car/TestAppBlockingPolicyService.java
@@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package com.android.car.test;
+package com.android.car;
import android.car.content.pm.AppBlockingPackageInfo;
import android.car.content.pm.CarAppBlockingPolicy;
@@ -40,7 +40,7 @@
@Override
protected CarAppBlockingPolicy getAppBlockingPolicy() {
- synchronized (TestAppBlockingPolicyService.class) {
+ synchronized (this) {
sInstance = this;
if (sSetPolicy == false) {
Log.i(TAG, "getAppBlockingPolicy returning null");
@@ -56,6 +56,7 @@
} catch (NameNotFoundException e) {
return null;
}
+
AppBlockingPackageInfo selfInfo = new AppBlockingPackageInfo(packageName, 0, 0, 0,
signatures, null);
AppBlockingPackageInfo[] whitelists = new AppBlockingPackageInfo[] { selfInfo };
diff --git a/tests/carservice_test/src/com/android/car/test/VmsHalServiceSubscriptionEventTest.java b/tests/carservice_test/src/com/android/car/VmsHalServiceSubscriptionEventTest.java
similarity index 89%
rename from tests/carservice_test/src/com/android/car/test/VmsHalServiceSubscriptionEventTest.java
rename to tests/carservice_test/src/com/android/car/VmsHalServiceSubscriptionEventTest.java
index cad3086..82c9361 100644
--- a/tests/carservice_test/src/com/android/car/test/VmsHalServiceSubscriptionEventTest.java
+++ b/tests/carservice_test/src/com/android/car/VmsHalServiceSubscriptionEventTest.java
@@ -14,26 +14,30 @@
* limitations under the License.
*/
-package com.android.car.test;
+package com.android.car;
-import static org.junit.Assume.assumeTrue;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
import android.car.VehicleAreaType;
-import android.car.annotation.FutureFeature;
import android.car.vms.VmsLayer;
import android.hardware.automotive.vehicle.V2_0.VehiclePropValue;
+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.VehicleProperty;
-import android.hardware.automotive.vehicle.V2_0.VmsMessageWithLayerIntegerValuesIndex;
import android.hardware.automotive.vehicle.V2_0.VmsMessageType;
+import android.hardware.automotive.vehicle.V2_0.VmsMessageWithLayerIntegerValuesIndex;
import android.hardware.automotive.vehicle.V2_0.VmsSubscriptionsStateIntegerValuesIndex;
-import android.test.suitebuilder.annotation.MediumTest;
+import android.support.test.filters.MediumTest;
+import android.support.test.runner.AndroidJUnit4;
import com.android.car.vehiclehal.VehiclePropValueBuilder;
import com.android.car.vehiclehal.test.MockedVehicleHal;
import com.android.car.vehiclehal.test.MockedVehicleHal.VehicleHalPropertyHandler;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashSet;
@@ -41,7 +45,7 @@
import java.util.concurrent.Semaphore;
import java.util.concurrent.TimeUnit;
-@FutureFeature
+@RunWith(AndroidJUnit4.class)
@MediumTest
public class VmsHalServiceSubscriptionEventTest extends MockedCarTestBase {
private static final String TAG = "VmsHalServiceTest";
@@ -57,37 +61,30 @@
addProperty(VehicleProperty.VEHICLE_MAP_SERVICE, mHalHandler)
.setChangeMode(VehiclePropertyChangeMode.ON_CHANGE)
.setAccess(VehiclePropertyAccess.READ_WRITE)
- .setSupportedAreas(VehicleAreaType.VEHICLE_AREA_TYPE_NONE);
+ .addAreaConfig(VehicleAreaType.VEHICLE_AREA_TYPE_GLOBAL, 0, 0);
}
@Override
- protected void setUp() throws Exception {
- if (!VmsTestUtils.canRunTest(TAG)) return;
+ public void setUp() throws Exception {
super.setUp();
mHal = getMockedVehicleHal();
mHalHandlerSemaphore = new Semaphore(0);
}
- @Override
- protected synchronized void tearDown() throws Exception {
- if (!VmsTestUtils.canRunTest(TAG)) return;
- super.tearDown();
- }
-
+ @Test
public void testEmptySubscriptions() throws Exception {
- if (!VmsTestUtils.canRunTest(TAG)) return;
List<VmsLayer> layers = new ArrayList<>();
subscriptionTestLogic(layers);
}
+ @Test
public void testOneSubscription() throws Exception {
- if (!VmsTestUtils.canRunTest(TAG)) return;
List<VmsLayer> layers = Arrays.asList(new VmsLayer(8, 0, 3));
subscriptionTestLogic(layers);
}
+ @Test
public void testManySubscriptions() throws Exception {
- if (!VmsTestUtils.canRunTest(TAG)) return;
List<VmsLayer> layers = Arrays.asList(
new VmsLayer(8, 1, 3),
new VmsLayer(5, 2, 1),
@@ -115,8 +112,6 @@
int sequenceNumber = v.get(VmsSubscriptionsStateIntegerValuesIndex.SEQUENCE_NUMBER);
int numberLayers = v.get(VmsSubscriptionsStateIntegerValuesIndex.NUMBER_OF_LAYERS);
assertEquals(VmsMessageType.SUBSCRIPTIONS_RESPONSE, messageType);
- //TODO(asafro): This assertion makes no sense. need to fix.
- //assertEquals(layers.size(), sequenceNumber);
assertEquals(layers.size(), numberLayers);
List<VmsLayer> receivedLayers = new ArrayList<>();
int start = VmsSubscriptionsStateIntegerValuesIndex.SUBSCRIPTIONS_START;
diff --git a/tests/carservice_test/src/com/android/car/test/VmsOperationRecorderTest.java b/tests/carservice_test/src/com/android/car/VmsOperationRecorderTest.java
similarity index 93%
rename from tests/carservice_test/src/com/android/car/test/VmsOperationRecorderTest.java
rename to tests/carservice_test/src/com/android/car/VmsOperationRecorderTest.java
index 179a194..7820936 100644
--- a/tests/carservice_test/src/com/android/car/test/VmsOperationRecorderTest.java
+++ b/tests/carservice_test/src/com/android/car/VmsOperationRecorderTest.java
@@ -14,13 +14,16 @@
* limitations under the License.
*/
-package com.android.car.test;
+package com.android.car;
+
+import static org.junit.Assert.assertTrue;
import android.car.vms.VmsLayer;
import android.car.vms.VmsLayerDependency;
import android.car.vms.VmsLayersOffering;
import android.car.vms.VmsOperationRecorder;
-import android.test.suitebuilder.annotation.MediumTest;
+import android.support.test.filters.MediumTest;
+import android.support.test.runner.AndroidJUnit4;
import android.util.Log;
import junit.framework.TestCase;
@@ -28,13 +31,16 @@
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
-import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashSet;
+@RunWith(AndroidJUnit4.class)
@MediumTest
-public class VmsOperationRecorderTest extends TestCase {
+public class VmsOperationRecorderTest {
/**
* Capture messages that VmsOperationRecorder.Writer would normally pass to Log.d(...).
@@ -73,36 +79,43 @@
private static final VmsLayersOffering layersOffering2 = new VmsLayersOffering(
new HashSet<>(Arrays.asList(layerDependency1, layerDependency2)), 66);
+ @Before
public void setUp() {
mWriter = new TestWriter();
mRecorder = new VmsOperationRecorder(mWriter);
}
+ @Test
public void testSubscribe() throws Exception {
mRecorder.subscribe(layer1);
assertJsonMsgEquals("{'subscribe':{'layer':{'subtype':3,'type':1,'version':2}}}");
}
+ @Test
public void testUnsubscribe() throws Exception {
mRecorder.unsubscribe(layer1);
assertJsonMsgEquals("{'unsubscribe':{'layer':{'type':1,'subtype':3,'version':2}}}");
}
+ @Test
public void testStartMonitoring() throws Exception {
mRecorder.startMonitoring();
assertJsonMsgEquals("{'startMonitoring':{}}");
}
+ @Test
public void testStopMonitoring() throws Exception {
mRecorder.stopMonitoring();
assertJsonMsgEquals("{'stopMonitoring':{}}");
}
+ @Test
public void testSetLayersOffering0() throws Exception {
mRecorder.setLayersOffering(layersOffering0);
assertJsonMsgEquals("{'setLayersOffering':{}}");
}
+ @Test
public void testSetLayersOffering2() throws Exception {
mRecorder.setLayersOffering(layersOffering2);
assertJsonMsgEquals("{'setLayersOffering':{'layerDependency':["
@@ -112,11 +125,13 @@
+ "]}}");
}
+ @Test
public void testGetPublisherId() throws Exception {
mRecorder.getPublisherId(9);
assertJsonMsgEquals("{'getPublisherId':{'publisherId':9}}");
}
+ @Test
public void testAddSubscription() throws Exception {
mRecorder.addSubscription(42, layer1);
assertJsonMsgEquals(
@@ -124,52 +139,60 @@
);
}
+ @Test
public void testRemoveSubscription() throws Exception {
mRecorder.removeSubscription(42, layer1);
assertJsonMsgEquals("{'removeSubscription':"
+ "{'sequenceNumber':42,'layer':{'type':1,'subtype':3,'version':2}}}");
}
+ @Test
public void testAddPromiscuousSubscription() throws Exception {
mRecorder.addPromiscuousSubscription(42);
assertJsonMsgEquals("{'addPromiscuousSubscription':{'sequenceNumber':42}}");
}
+ @Test
public void testRemovePromiscuousSubscription() throws Exception {
mRecorder.removePromiscuousSubscription(42);
assertJsonMsgEquals("{'removePromiscuousSubscription':{'sequenceNumber':42}}");
}
+ @Test
public void testAddHalSubscription() throws Exception {
mRecorder.addHalSubscription(42, layer1);
assertJsonMsgEquals("{'addHalSubscription':"
+ "{'sequenceNumber':42,'layer':{'type':1,'subtype':3,'version':2}}}");
}
+ @Test
public void testRemoveHalSubscription() throws Exception {
mRecorder.removeHalSubscription(42, layer1);
assertJsonMsgEquals("{'removeHalSubscription':"
+ "{'sequenceNumber':42,'layer':{'type':1,'subtype':3,'version':2}}}");
}
+ @Test
public void testSetPublisherLayersOffering() throws Exception {
mRecorder.setPublisherLayersOffering(layersOffering1);
assertJsonMsgEquals("{'setPublisherLayersOffering':{'layerDependency':["
+ "{'layer':{'type':3,'subtype':5,'version':4}}]}}");
}
- public void testSetHalPublisherLayersOffering() throws Exception {
+ @Test public void testSetHalPublisherLayersOffering() throws Exception {
mRecorder.setHalPublisherLayersOffering(layersOffering1);
assertJsonMsgEquals("{'setHalPublisherLayersOffering':{'layerDependency':["
+ "{'layer':{'type':3,'subtype':5,'version':4}}]}}");
}
+ @Test
public void testSubscribeToPublisher() throws Exception {
mRecorder.subscribe(layer1, 99);
assertJsonMsgEquals(
"{'subscribe':{'publisherId':99, 'layer':{'type':1,'subtype':3,'version':2}}}");
}
+ @Test
public void testUnsubscribeToPublisher() throws Exception {
mRecorder.unsubscribe(layer1, 99);
assertJsonMsgEquals(
diff --git a/tests/carservice_test/src/com/android/car/test/VmsPublisherClientMockService.java b/tests/carservice_test/src/com/android/car/VmsPublisherClientMockService.java
similarity index 96%
rename from tests/carservice_test/src/com/android/car/test/VmsPublisherClientMockService.java
rename to tests/carservice_test/src/com/android/car/VmsPublisherClientMockService.java
index 0d5c427..32d224b 100644
--- a/tests/carservice_test/src/com/android/car/test/VmsPublisherClientMockService.java
+++ b/tests/carservice_test/src/com/android/car/VmsPublisherClientMockService.java
@@ -14,18 +14,16 @@
* limitations under the License.
*/
-package com.android.car.test;
+package com.android.car;
-import android.car.annotation.FutureFeature;
import android.car.vms.VmsLayer;
import android.car.vms.VmsLayerDependency;
import android.car.vms.VmsLayersOffering;
import android.car.vms.VmsPublisherClientService;
import android.car.vms.VmsSubscriptionState;
import android.util.Log;
-import java.util.ArrayList;
+
import java.util.HashSet;
-import java.util.List;
import java.util.Set;
/**
@@ -43,7 +41,6 @@
* both potential scenarios, this service publishes the test message in onVmsSubscriptionChange
* and in onVmsPublisherServiceReady. See comments below.
*/
-@FutureFeature
public class VmsPublisherClientMockService extends VmsPublisherClientService {
private static final String TAG = "VmsPublisherClientMockService";
diff --git a/tests/carservice_test/src/com/android/car/test/VmsPublisherClientServiceTest.java b/tests/carservice_test/src/com/android/car/VmsPublisherClientServiceTest.java
similarity index 76%
rename from tests/carservice_test/src/com/android/car/test/VmsPublisherClientServiceTest.java
rename to tests/carservice_test/src/com/android/car/VmsPublisherClientServiceTest.java
index 053bab7..d8cbe7b 100644
--- a/tests/carservice_test/src/com/android/car/test/VmsPublisherClientServiceTest.java
+++ b/tests/carservice_test/src/com/android/car/VmsPublisherClientServiceTest.java
@@ -14,37 +14,37 @@
* limitations under the License.
*/
-package com.android.car.test;
+package com.android.car;
-import android.annotation.ArrayRes;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+
import android.car.VehicleAreaType;
-import android.car.annotation.FutureFeature;
import android.car.vms.VmsLayer;
-import android.content.Context;
-import android.content.ContextWrapper;
-import android.content.pm.PackageManager;
-import android.content.res.Resources;
import android.hardware.automotive.vehicle.V2_0.VehiclePropValue;
+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.VehicleProperty;
import android.hardware.automotive.vehicle.V2_0.VmsBaseMessageIntegerValuesIndex;
-import android.hardware.automotive.vehicle.V2_0.VmsMessageWithLayerIntegerValuesIndex;
import android.hardware.automotive.vehicle.V2_0.VmsMessageType;
-import android.test.suitebuilder.annotation.MediumTest;
+import android.hardware.automotive.vehicle.V2_0.VmsMessageWithLayerIntegerValuesIndex;
+import android.support.test.filters.MediumTest;
+import android.support.test.runner.AndroidJUnit4;
import android.util.Log;
-import com.android.car.R;
import com.android.car.vehiclehal.VehiclePropValueBuilder;
import com.android.car.vehiclehal.test.MockedVehicleHal;
import com.android.car.vehiclehal.test.MockedVehicleHal.VehicleHalPropertyHandler;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
import java.util.ArrayList;
import java.util.Arrays;
import java.util.concurrent.Semaphore;
import java.util.concurrent.TimeUnit;
-@FutureFeature
+@RunWith(AndroidJUnit4.class)
@MediumTest
public class VmsPublisherClientServiceTest extends MockedCarTestBase {
private static final String TAG = "VmsPublisherTest";
@@ -68,35 +68,13 @@
addProperty(VehicleProperty.VEHICLE_MAP_SERVICE, mHalHandler)
.setChangeMode(VehiclePropertyChangeMode.ON_CHANGE)
.setAccess(VehiclePropertyAccess.READ_WRITE)
- .setSupportedAreas(VehicleAreaType.VEHICLE_AREA_TYPE_NONE);
+ .addAreaConfig(VehicleAreaType.VEHICLE_AREA_TYPE_GLOBAL, 0, 0);
}
- /**
- * Creates a context with the resource vmsPublisherClients overridden. The overridden value
- * contains the name of the test service defined also in this test package.
- */
@Override
- protected Context getCarServiceContext() throws PackageManager.NameNotFoundException {
- Context context = getContext()
- .createPackageContext("com.android.car", Context.CONTEXT_IGNORE_SECURITY);
- Resources resources = new Resources(context.getAssets(),
- context.getResources().getDisplayMetrics(),
- context.getResources().getConfiguration()) {
- @Override
- public String[] getStringArray(@ArrayRes int id) throws NotFoundException {
- if (id == R.array.vmsPublisherClients) {
- return new String[]{"com.android.car.test/.SimpleVmsPublisherClientService"};
- }
- return super.getStringArray(id);
- }
- };
- ContextWrapper wrapper = new ContextWrapper(context) {
- @Override
- public Resources getResources() {
- return resources;
- }
- };
- return wrapper;
+ protected synchronized void configureResourceOverrides(MockResources resources) {
+ resources.overrideResource(R.array.vmsPublisherClients,
+ new String[]{ getFlattenComponent(SimpleVmsPublisherClientService.class) });
}
private VehiclePropValue getHalSubscriptionRequest() {
@@ -109,8 +87,7 @@
}
@Override
- protected void setUp() throws Exception {
- if (!VmsTestUtils.canRunTest(TAG)) return;
+ public void setUp() throws Exception {
/**
* First init the semaphore, setUp will start a series of events that will ultimately
* update the HAL layer and release this semaphore.
@@ -123,12 +100,6 @@
mHal.injectEvent(getHalSubscriptionRequest());
}
- @Override
- protected synchronized void tearDown() throws Exception {
- if (!VmsTestUtils.canRunTest(TAG)) return;
- super.tearDown();
- }
-
/**
* The method setUp initializes all the Car services, including the VmsPublisherService.
* The VmsPublisherService will start and configure its list of clients. This list was
@@ -137,8 +108,8 @@
* The service SimpleVmsPublisherClientService will publish one message, which is validated in
* this test.
*/
+ @Test
public void testPublish() throws Exception {
- if (!VmsTestUtils.canRunTest(TAG)) return;
//TODO: This test is using minial synchronisation between clients.
// If more complexity is added this may result in publisher
// publishing before the subscriber subscribed, in which case
@@ -165,7 +136,7 @@
public synchronized void onPropertySet(VehiclePropValue value) {
mValue = value;
- // If this is the data message release the semaphone so the test can continue.
+ // If this is the data message release the semaphore so the test can continue.
ArrayList<Integer> int32Values = value.value.int32Values;
if (int32Values.get(VmsBaseMessageIntegerValuesIndex.MESSAGE_TYPE) ==
VmsMessageType.DATA) {
@@ -179,7 +150,7 @@
}
@Override
- public synchronized void onPropertySubscribe(int property, int zones, float sampleRate) {
+ public synchronized void onPropertySubscribe(int property, float sampleRate) {
Log.d(TAG, "onPropertySubscribe property " + property + " sampleRate " + sampleRate);
}
diff --git a/tests/carservice_test/src/com/android/car/test/VmsPublisherPermissionsTest.java b/tests/carservice_test/src/com/android/car/VmsPublisherPermissionsTest.java
similarity index 65%
rename from tests/carservice_test/src/com/android/car/test/VmsPublisherPermissionsTest.java
rename to tests/carservice_test/src/com/android/car/VmsPublisherPermissionsTest.java
index 1d14c57..a4d094a 100644
--- a/tests/carservice_test/src/com/android/car/test/VmsPublisherPermissionsTest.java
+++ b/tests/carservice_test/src/com/android/car/VmsPublisherPermissionsTest.java
@@ -14,33 +14,33 @@
* limitations under the License.
*/
-package com.android.car.test;
+package com.android.car;
-import android.annotation.ArrayRes;
+import static org.junit.Assert.assertTrue;
+
import android.car.VehicleAreaType;
-import android.car.annotation.FutureFeature;
-import android.content.Context;
-import android.content.ContextWrapper;
import android.content.pm.PackageManager;
-import android.content.res.Resources;
import android.hardware.automotive.vehicle.V2_0.VehiclePropValue;
+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.VehicleProperty;
import android.hardware.automotive.vehicle.V2_0.VmsBaseMessageIntegerValuesIndex;
import android.hardware.automotive.vehicle.V2_0.VmsMessageType;
-import android.test.suitebuilder.annotation.MediumTest;
+import android.support.test.filters.MediumTest;
+import android.support.test.runner.AndroidJUnit4;
-import com.android.car.R;
import com.android.car.vehiclehal.VehiclePropValueBuilder;
import com.android.car.vehiclehal.test.MockedVehicleHal;
import com.android.car.vehiclehal.test.MockedVehicleHal.VehicleHalPropertyHandler;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
import java.util.ArrayList;
import java.util.concurrent.Semaphore;
import java.util.concurrent.TimeUnit;
-@FutureFeature
+@RunWith(AndroidJUnit4.class)
@MediumTest
public class VmsPublisherPermissionsTest extends MockedCarTestBase {
private static final String TAG = "VmsPublisherTest";
@@ -58,39 +58,15 @@
addProperty(VehicleProperty.VEHICLE_MAP_SERVICE, mHalHandler)
.setChangeMode(VehiclePropertyChangeMode.ON_CHANGE)
.setAccess(VehiclePropertyAccess.READ_WRITE)
- .setSupportedAreas(VehicleAreaType.VEHICLE_AREA_TYPE_NONE);
+ .addAreaConfig(VehicleAreaType.VEHICLE_AREA_TYPE_GLOBAL, 0, 0);
}
- /**
- * Creates a context with the resource vmsPublisherClients overridden. The overridden value
- * contains the name of the test service defined also in this test package.
- */
@Override
- protected Context getCarServiceContext() throws PackageManager.NameNotFoundException {
- Context context = getContext()
- .createPackageContext("com.android.car", Context.CONTEXT_IGNORE_SECURITY);
- Resources resources = new Resources(context.getAssets(),
- context.getResources().getDisplayMetrics(),
- context.getResources().getConfiguration()) {
- @Override
- public String[] getStringArray(@ArrayRes int id) throws NotFoundException {
- if (id == R.array.vmsPublisherClients) {
- return new String[]{
- "com.google.android.car.vms.publisher/"
- + ".VmsPublisherClientSampleService"};
- } else if (id == R.array.vmsSafePermissions) {
- return new String[]{"android.permission.ACCESS_FINE_LOCATION"};
- }
- return super.getStringArray(id);
- }
- };
- ContextWrapper wrapper = new ContextWrapper(context) {
- @Override
- public Resources getResources() {
- return resources;
- }
- };
- return wrapper;
+ protected synchronized void configureResourceOverrides(MockResources resources) {
+ resources.overrideResource(R.array.vmsPublisherClients, new String[]{
+ "com.google.android.car.vms.publisher/.VmsPublisherClientSampleService"})
+ .overrideResource(R.array.vmsSafePermissions,
+ new String[]{"android.permission.ACCESS_FINE_LOCATION"});
}
private VehiclePropValue getHalSubscriptionRequest() {
@@ -103,8 +79,7 @@
}
@Override
- protected void setUp() throws Exception {
- if (!VmsTestUtils.canRunTest(TAG)) return;
+ public void setUp() throws Exception {
/**
* First init the semaphore, setUp will start a series of events that will ultimately
* update the HAL layer and release this semaphore.
@@ -117,12 +92,6 @@
mHal.injectEvent(getHalSubscriptionRequest());
}
- @Override
- protected synchronized void tearDown() throws Exception {
- if (!VmsTestUtils.canRunTest(TAG)) return;
- super.tearDown();
- }
-
/**
* The method setUp initializes all the Car services, including the VmsPublisherService.
* The VmsPublisherService will start and configure its list of clients. This list was
@@ -131,19 +100,16 @@
* The service VmsPublisherClientSampleService will publish one message, which is validated in
* this test.
*/
+ @Test
public void testPermissions() throws Exception {
- if (!VmsTestUtils.canRunTest(TAG)) return;
assertTrue(mHalHandlerSemaphore.tryAcquire(2L, TimeUnit.SECONDS));
// At this point the client initialization finished. Let's validate the permissions.
- // The VMS service is only allowed to grant ACCESS_FINE_LOCATION but not CAMERA.
+ // The VMS service should be allowed to grant ACCESS_FINE_LOCATION.
assertTrue(
getContext().getPackageManager().checkPermission(
"android.permission.ACCESS_FINE_LOCATION",
"com.google.android.car.vms.publisher")
== PackageManager.PERMISSION_GRANTED);
- assertFalse(getContext().getPackageManager().checkPermission(
- "android.permission.CAMERA", "com.google.android.car.vms.publisher")
- == PackageManager.PERMISSION_GRANTED);
}
private class HalHandler implements VehicleHalPropertyHandler {
diff --git a/tests/carservice_test/src/com/android/car/VmsPublisherSubscriberTest.java b/tests/carservice_test/src/com/android/car/VmsPublisherSubscriberTest.java
new file mode 100644
index 0000000..1ef35f7
--- /dev/null
+++ b/tests/carservice_test/src/com/android/car/VmsPublisherSubscriberTest.java
@@ -0,0 +1,227 @@
+/*
+ * 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.android.car;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+
+import android.car.Car;
+import android.car.VehicleAreaType;
+import android.car.vms.VmsAssociatedLayer;
+import android.car.vms.VmsAvailableLayers;
+import android.car.vms.VmsLayer;
+import android.car.vms.VmsSubscriberManager;
+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.support.test.filters.MediumTest;
+import android.support.test.runner.AndroidJUnit4;
+
+import com.android.car.vehiclehal.test.MockedVehicleHal;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+import java.util.concurrent.Executor;
+import java.util.concurrent.Semaphore;
+import java.util.concurrent.TimeUnit;
+
+@RunWith(AndroidJUnit4.class)
+@MediumTest
+public class VmsPublisherSubscriberTest extends MockedCarTestBase {
+ private static final int LAYER_ID = 88;
+ private static final int LAYER_VERSION = 19;
+ private static final int LAYER_SUBTYPE = 55;
+ private static final String TAG = "VmsPubSubTest";
+
+ // The expected publisher ID is 0 since it the expected assigned ID from the VMS core.
+ public static final int EXPECTED_PUBLISHER_ID = 0;
+ public static final VmsLayer LAYER = new VmsLayer(LAYER_ID, LAYER_SUBTYPE, LAYER_VERSION);
+ public static final VmsAssociatedLayer ASSOCIATED_LAYER =
+ new VmsAssociatedLayer(LAYER, new HashSet<>(Arrays.asList(EXPECTED_PUBLISHER_ID)));
+ public static final byte[] PAYLOAD = new byte[]{2, 3, 5, 7, 11, 13, 17};
+
+ private static final List<VmsAssociatedLayer> AVAILABLE_ASSOCIATED_LAYERS =
+ new ArrayList<>(Arrays.asList(ASSOCIATED_LAYER));
+ private static final VmsAvailableLayers AVAILABLE_LAYERS_WITH_SEQ =
+ new VmsAvailableLayers(
+ new HashSet(AVAILABLE_ASSOCIATED_LAYERS), 1);
+
+
+ private static final int SUBSCRIBED_LAYER_ID = 89;
+ public static final VmsLayer SUBSCRIBED_LAYER =
+ new VmsLayer(SUBSCRIBED_LAYER_ID, LAYER_SUBTYPE, LAYER_VERSION);
+ public static final VmsAssociatedLayer ASSOCIATED_SUBSCRIBED_LAYER =
+ new VmsAssociatedLayer(SUBSCRIBED_LAYER,
+ new HashSet<>(Arrays.asList(EXPECTED_PUBLISHER_ID)));
+ private static final List<VmsAssociatedLayer>
+ AVAILABLE_ASSOCIATED_LAYERS_WITH_SUBSCRIBED_LAYER =
+ new ArrayList<>(Arrays.asList(ASSOCIATED_LAYER, ASSOCIATED_SUBSCRIBED_LAYER));
+ private static final VmsAvailableLayers AVAILABLE_LAYERS_WITH_SUBSCRIBED_LAYER_WITH_SEQ =
+ new VmsAvailableLayers(
+ new HashSet(AVAILABLE_ASSOCIATED_LAYERS_WITH_SUBSCRIBED_LAYER), 1);
+ VmsSubscriberManager mVmsSubscriberManager;
+ TestClientCallback mClientCallback;
+ private HalHandler mHalHandler;
+ // Used to block until a value is propagated to the TestClientCallback.onVmsMessageReceived.
+ private Semaphore mSubscriberSemaphore;
+ private Semaphore mAvailabilitySemaphore;
+ private Executor mExecutor;
+
+ private class ThreadPerTaskExecutor implements Executor {
+ public void execute(Runnable r) {
+ new Thread(r).start();
+ }
+ }
+
+
+ @Override
+ protected synchronized void configureMockedHal() {
+ mHalHandler = new HalHandler();
+ addProperty(VehicleProperty.VEHICLE_MAP_SERVICE, mHalHandler)
+ .setChangeMode(VehiclePropertyChangeMode.ON_CHANGE)
+ .setAccess(VehiclePropertyAccess.READ_WRITE)
+ .addAreaConfig(VehicleAreaType.VEHICLE_AREA_TYPE_GLOBAL, 0, 0);
+ }
+
+ @Override
+ protected synchronized void configureResourceOverrides(MockResources resources) {
+ resources.overrideResource(com.android.car.R.array.vmsPublisherClients,
+ new String[]{getFlattenComponent(VmsPublisherClientMockService.class)});
+ }
+
+ /*
+ * The method setUp initializes all the Car services, including the VmsPublisherService.
+ * The VmsPublisherService will start and configure its list of clients. This list was
+ * overridden in the method getCarServiceContext. Therefore, only VmsPublisherClientMockService
+ * will be started. Method setUp() subscribes to a layer and triggers
+ * VmsPublisherClientMockService.onVmsSubscriptionChange.
+ * There is a race condition between publisher and subscriber starting time.
+ * So we wanted to make sure that the tests start only after the publisher is up. We achieve
+ * this by subscribing in setUp() and waiting on the semaphore at the beginning of each test
+ * case.
+ */
+
+ @Override
+ public void setUp() throws Exception {
+ mExecutor = new ThreadPerTaskExecutor();
+ super.setUp();
+ mSubscriberSemaphore = new Semaphore(0);
+ mAvailabilitySemaphore = new Semaphore(0);
+
+ mVmsSubscriberManager = (VmsSubscriberManager) getCar().getCarManager(
+ Car.VMS_SUBSCRIBER_SERVICE);
+ mClientCallback = new TestClientCallback();
+ mVmsSubscriberManager.setVmsSubscriberClientCallback(mExecutor, mClientCallback);
+ mVmsSubscriberManager.subscribe(LAYER);
+ }
+
+ public void postSetup() throws Exception {
+ assertTrue(mAvailabilitySemaphore.tryAcquire(2L, TimeUnit.SECONDS));
+ }
+
+ /*
+ * This test method subscribes to a layer and triggers
+ * VmsPublisherClientMockService.onVmsSubscriptionChange. In turn, the mock service will publish
+ * a message, which is validated in this test.
+ */
+
+ @Test
+ public void testPublisherToSubscriber() throws Exception {
+ postSetup();
+ assertEquals(LAYER, mClientCallback.getLayer());
+ assertTrue(Arrays.equals(PAYLOAD, mClientCallback.getPayload()));
+ }
+
+ /**
+ * The Mock service will get a publisher ID by sending its information when it will get
+ * ServiceReady as well as on SubscriptionChange. Since clients are not notified when
+ * publishers are assigned IDs, this test waits until the availability is changed which
+ * indicates
+ * that the Mock service has gotten its ServiceReady and publisherId.
+ */
+
+
+ @Test
+ public void testPublisherInfo() throws Exception {
+ postSetup();
+
+ // Inject a value and wait for its callback in TestClientCallback.onVmsMessageReceived.
+ byte[] info = mVmsSubscriberManager.getPublisherInfo(EXPECTED_PUBLISHER_ID);
+ assertTrue(Arrays.equals(PAYLOAD, info));
+ }
+
+ /*
+ * The Mock service offers all the subscribed layers as available layers.
+ * In this test the client subscribes to a layer and verifies that it gets the
+ * notification that it is available.
+ */
+
+ @Test
+ public void testAvailabilityWithSubscription() throws Exception {
+ postSetup();
+ mVmsSubscriberManager.subscribe(SUBSCRIBED_LAYER);
+ assertTrue(mAvailabilitySemaphore.tryAcquire(2L, TimeUnit.SECONDS));
+
+ final Set<VmsAssociatedLayer> associatedLayers =
+ AVAILABLE_LAYERS_WITH_SUBSCRIBED_LAYER_WITH_SEQ.getAssociatedLayers();
+ assertEquals(associatedLayers, mClientCallback.getAvailableLayers().getAssociatedLayers());
+ assertEquals(associatedLayers,
+ mVmsSubscriberManager.getAvailableLayers().getAssociatedLayers());
+ }
+
+ private class HalHandler implements MockedVehicleHal.VehicleHalPropertyHandler {
+ }
+
+ private class TestClientCallback implements VmsSubscriberManager.VmsSubscriberClientCallback {
+ private VmsLayer mLayer;
+ private byte[] mPayload;
+ private VmsAvailableLayers mAvailableLayers;
+
+ @Override
+ public void onVmsMessageReceived(VmsLayer layer, byte[] payload) {
+ assertEquals(LAYER, layer);
+ assertTrue(Arrays.equals(PAYLOAD, payload));
+ mLayer = layer;
+ mPayload = payload;
+ mSubscriberSemaphore.release();
+ }
+
+ @Override
+ public void onLayersAvailabilityChanged(VmsAvailableLayers availableLayers) {
+ mAvailableLayers = availableLayers;
+ mAvailabilitySemaphore.release();
+ }
+
+ public VmsLayer getLayer() {
+ return mLayer;
+ }
+
+ public byte[] getPayload() {
+ return mPayload;
+ }
+
+ public VmsAvailableLayers getAvailableLayers() {
+ return mAvailableLayers;
+ }
+ }
+}
diff --git a/tests/carservice_test/src/com/android/car/test/VmsSubscriberManagerTest.java b/tests/carservice_test/src/com/android/car/VmsSubscriberManagerTest.java
similarity index 67%
rename from tests/carservice_test/src/com/android/car/test/VmsSubscriberManagerTest.java
rename to tests/carservice_test/src/com/android/car/VmsSubscriberManagerTest.java
index 201e58f..643ffff 100644
--- a/tests/carservice_test/src/com/android/car/test/VmsSubscriberManagerTest.java
+++ b/tests/carservice_test/src/com/android/car/VmsSubscriberManagerTest.java
@@ -14,37 +14,45 @@
* limitations under the License.
*/
-package com.android.car.test;
+package com.android.car;
-import static org.junit.Assume.assumeTrue;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
import android.car.Car;
import android.car.VehicleAreaType;
-import android.car.annotation.FutureFeature;
import android.car.vms.VmsAssociatedLayer;
+import android.car.vms.VmsAvailableLayers;
import android.car.vms.VmsLayer;
import android.car.vms.VmsSubscriberManager;
import android.car.vms.VmsSubscriberManager.VmsSubscriberClientCallback;
import android.hardware.automotive.vehicle.V2_0.VehiclePropValue;
+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.VehicleProperty;
+import android.hardware.automotive.vehicle.V2_0.VmsAvailabilityStateIntegerValuesIndex;
import android.hardware.automotive.vehicle.V2_0.VmsMessageType;
import android.os.SystemClock;
-import android.test.suitebuilder.annotation.MediumTest;
+import android.support.test.filters.MediumTest;
+import android.support.test.runner.AndroidJUnit4;
import android.util.Log;
+
import com.android.car.vehiclehal.VehiclePropValueBuilder;
import com.android.car.vehiclehal.test.MockedVehicleHal.VehicleHalPropertyHandler;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashSet;
-import java.util.List;
import java.util.Set;
+import java.util.concurrent.Executor;
import java.util.concurrent.Semaphore;
import java.util.concurrent.TimeUnit;
-@FutureFeature
+@RunWith(AndroidJUnit4.class)
@MediumTest
public class VmsSubscriberManagerTest extends MockedCarTestBase {
private static final String TAG = "VmsSubscriberManagerTest";
@@ -90,6 +98,14 @@
private Semaphore mHalHandlerSemaphore;
// Used to block until a value is propagated to the TestClientCallback.onVmsMessageReceived.
private Semaphore mSubscriberSemaphore;
+ private Executor mExecutor;
+
+ private class ThreadPerTaskExecutor implements Executor {
+ public void execute(Runnable r) {
+ new Thread(r).start();
+ }
+ }
+
@Override
protected synchronized void configureMockedHal() {
@@ -97,35 +113,29 @@
addProperty(VehicleProperty.VEHICLE_MAP_SERVICE, mHalHandler)
.setChangeMode(VehiclePropertyChangeMode.ON_CHANGE)
.setAccess(VehiclePropertyAccess.READ_WRITE)
- .setSupportedAreas(VehicleAreaType.VEHICLE_AREA_TYPE_NONE);
+ .addAreaConfig(VehicleAreaType.VEHICLE_AREA_TYPE_GLOBAL, 0, 0);
}
@Override
- protected void setUp() throws Exception {
- if (!VmsTestUtils.canRunTest(TAG)) return;
+ public void setUp() throws Exception {
+ mExecutor = new ThreadPerTaskExecutor();
super.setUp();
mSubscriberSemaphore = new Semaphore(0);
mHalHandlerSemaphore = new Semaphore(0);
}
- @Override
- protected synchronized void tearDown() throws Exception {
- if (!VmsTestUtils.canRunTest(TAG)) return;
- super.tearDown();
- }
-
// Test injecting a value in the HAL and verifying it propagates to a subscriber.
+ @Test
public void testSubscribe() throws Exception {
- if (!VmsTestUtils.canRunTest(TAG)) return;
VmsSubscriberManager vmsSubscriberManager = (VmsSubscriberManager) getCar().getCarManager(
Car.VMS_SUBSCRIBER_SERVICE);
TestClientCallback clientCallback = new TestClientCallback();
- vmsSubscriberManager.registerClientCallback(clientCallback);
+ vmsSubscriberManager.setVmsSubscriberClientCallback(mExecutor, clientCallback);
vmsSubscriberManager.subscribe(SUBSCRIPTION_LAYER);
// Inject a value and wait for its callback in TestClientCallback.onVmsMessageReceived.
VehiclePropValue v = VehiclePropValueBuilder.newBuilder(VehicleProperty.VEHICLE_MAP_SERVICE)
- .setAreaId(VehicleAreaType.VEHICLE_AREA_TYPE_NONE)
+ .setAreaId(VehicleAreaType.VEHICLE_AREA_TYPE_GLOBAL)
.setTimestamp(SystemClock.elapsedRealtimeNanos())
.build();
v.value.int32Values.add(VmsMessageType.DATA); // MessageType
@@ -144,19 +154,18 @@
assertTrue(Arrays.equals(expectedPayload, clientCallback.getPayload()));
}
-
// Test injecting a value in the HAL and verifying it propagates to a subscriber.
+ @Test
public void testSubscribeToPublisher() throws Exception {
- if (!VmsTestUtils.canRunTest(TAG)) return;
VmsSubscriberManager vmsSubscriberManager = (VmsSubscriberManager) getCar().getCarManager(
Car.VMS_SUBSCRIBER_SERVICE);
TestClientCallback clientCallback = new TestClientCallback();
- vmsSubscriberManager.registerClientCallback(clientCallback);
+ vmsSubscriberManager.setVmsSubscriberClientCallback(mExecutor, clientCallback);
vmsSubscriberManager.subscribe(SUBSCRIPTION_LAYER, PUBLISHER_ID);
// Inject a value and wait for its callback in TestClientCallback.onVmsMessageReceived.
VehiclePropValue v = VehiclePropValueBuilder.newBuilder(VehicleProperty.VEHICLE_MAP_SERVICE)
- .setAreaId(VehicleAreaType.VEHICLE_AREA_TYPE_NONE)
+ .setAreaId(VehicleAreaType.VEHICLE_AREA_TYPE_GLOBAL)
.setTimestamp(SystemClock.elapsedRealtimeNanos())
.build();
v.value.int32Values.add(VmsMessageType.DATA); // MessageType
@@ -174,17 +183,17 @@
}
// Test injecting a value in the HAL and verifying it propagates to a subscriber.
+ @Test
public void testSubscribeFromPublisher() throws Exception {
- if (!VmsTestUtils.canRunTest(TAG)) return;
VmsSubscriberManager vmsSubscriberManager = (VmsSubscriberManager) getCar().getCarManager(
Car.VMS_SUBSCRIBER_SERVICE);
TestClientCallback clientCallback = new TestClientCallback();
- vmsSubscriberManager.registerClientCallback(clientCallback);
+ vmsSubscriberManager.setVmsSubscriberClientCallback(mExecutor, clientCallback);
vmsSubscriberManager.subscribe(SUBSCRIPTION_LAYER, PUBLISHER_ID);
// Inject a value and wait for its callback in TestClientCallback.onVmsMessageReceived.
VehiclePropValue v = VehiclePropValueBuilder.newBuilder(VehicleProperty.VEHICLE_MAP_SERVICE)
- .setAreaId(VehicleAreaType.VEHICLE_AREA_TYPE_NONE)
+ .setAreaId(VehicleAreaType.VEHICLE_AREA_TYPE_GLOBAL)
.setTimestamp(SystemClock.elapsedRealtimeNanos())
.build();
v.value.int32Values.add(VmsMessageType.DATA); // MessageType
@@ -204,18 +213,18 @@
}
// Test injecting a value in the HAL and verifying it does not propagate to a subscriber.
+ @Test
public void testUnsubscribe() throws Exception {
- if (!VmsTestUtils.canRunTest(TAG)) return;
VmsSubscriberManager vmsSubscriberManager = (VmsSubscriberManager) getCar().getCarManager(
Car.VMS_SUBSCRIBER_SERVICE);
TestClientCallback clientCallback = new TestClientCallback();
- vmsSubscriberManager.registerClientCallback(clientCallback);
+ vmsSubscriberManager.setVmsSubscriberClientCallback(mExecutor, clientCallback);
vmsSubscriberManager.subscribe(SUBSCRIPTION_LAYER);
vmsSubscriberManager.unsubscribe(SUBSCRIPTION_LAYER);
// Inject a value and wait for its callback in TestClientCallback.onVmsMessageReceived.
VehiclePropValue v = VehiclePropValueBuilder.newBuilder(VehicleProperty.VEHICLE_MAP_SERVICE)
- .setAreaId(VehicleAreaType.VEHICLE_AREA_TYPE_NONE)
+ .setAreaId(VehicleAreaType.VEHICLE_AREA_TYPE_GLOBAL)
.setTimestamp(SystemClock.elapsedRealtimeNanos())
.build();
v.value.int32Values.add(VmsMessageType.DATA); // MessageType
@@ -232,17 +241,17 @@
}
// Test injecting a value in the HAL and verifying it does not propagate to a subscriber.
+ @Test
public void testSubscribeFromWrongPublisher() throws Exception {
- if (!VmsTestUtils.canRunTest(TAG)) return;
VmsSubscriberManager vmsSubscriberManager = (VmsSubscriberManager) getCar().getCarManager(
Car.VMS_SUBSCRIBER_SERVICE);
TestClientCallback clientCallback = new TestClientCallback();
- vmsSubscriberManager.registerClientCallback(clientCallback);
+ vmsSubscriberManager.setVmsSubscriberClientCallback(mExecutor, clientCallback);
vmsSubscriberManager.subscribe(SUBSCRIPTION_LAYER, PUBLISHER_ID);
// Inject a value and wait for its callback in TestClientCallback.onVmsMessageReceived.
VehiclePropValue v = VehiclePropValueBuilder.newBuilder(VehicleProperty.VEHICLE_MAP_SERVICE)
- .setAreaId(VehicleAreaType.VEHICLE_AREA_TYPE_NONE)
+ .setAreaId(VehicleAreaType.VEHICLE_AREA_TYPE_GLOBAL)
.setTimestamp(SystemClock.elapsedRealtimeNanos())
.build();
v.value.int32Values.add(VmsMessageType.DATA); // MessageType
@@ -259,18 +268,18 @@
}
// Test injecting a value in the HAL and verifying it does not propagate to a subscriber.
+ @Test
public void testUnsubscribeFromPublisher() throws Exception {
- if (!VmsTestUtils.canRunTest(TAG)) return;
VmsSubscriberManager vmsSubscriberManager = (VmsSubscriberManager) getCar().getCarManager(
Car.VMS_SUBSCRIBER_SERVICE);
TestClientCallback clientCallback = new TestClientCallback();
- vmsSubscriberManager.registerClientCallback(clientCallback);
+ vmsSubscriberManager.setVmsSubscriberClientCallback(mExecutor, clientCallback);
vmsSubscriberManager.subscribe(SUBSCRIPTION_LAYER, PUBLISHER_ID);
vmsSubscriberManager.unsubscribe(SUBSCRIPTION_LAYER, PUBLISHER_ID);
// Inject a value and wait for its callback in TestClientCallback.onVmsMessageReceived.
VehiclePropValue v = VehiclePropValueBuilder.newBuilder(VehicleProperty.VEHICLE_MAP_SERVICE)
- .setAreaId(VehicleAreaType.VEHICLE_AREA_TYPE_NONE)
+ .setAreaId(VehicleAreaType.VEHICLE_AREA_TYPE_GLOBAL)
.setTimestamp(SystemClock.elapsedRealtimeNanos())
.build();
v.value.int32Values.add(VmsMessageType.DATA); // MessageType
@@ -286,19 +295,18 @@
assertFalse(mSubscriberSemaphore.tryAcquire(2L, TimeUnit.SECONDS));
}
-
// Test injecting a value in the HAL and verifying it propagates to a subscriber.
+ @Test
public void testSubscribeAll() throws Exception {
- if (!VmsTestUtils.canRunTest(TAG)) return;
VmsSubscriberManager vmsSubscriberManager = (VmsSubscriberManager) getCar().getCarManager(
Car.VMS_SUBSCRIBER_SERVICE);
TestClientCallback clientCallback = new TestClientCallback();
- vmsSubscriberManager.registerClientCallback(clientCallback);
+ vmsSubscriberManager.setVmsSubscriberClientCallback(mExecutor, clientCallback);
vmsSubscriberManager.startMonitoring();
// Inject a value and wait for its callback in TestClientCallback.onVmsMessageReceived.
VehiclePropValue v = VehiclePropValueBuilder.newBuilder(VehicleProperty.VEHICLE_MAP_SERVICE)
- .setAreaId(VehicleAreaType.VEHICLE_AREA_TYPE_NONE)
+ .setAreaId(VehicleAreaType.VEHICLE_AREA_TYPE_GLOBAL)
.setTimestamp(SystemClock.elapsedRealtimeNanos())
.build();
v.value.int32Values.add(VmsMessageType.DATA); // MessageType
@@ -318,27 +326,27 @@
}
// Test injecting a value in the HAL and verifying it propagates to a subscriber.
+ @Test
public void testSimpleAvailableLayers() throws Exception {
- if (!VmsTestUtils.canRunTest(TAG)) return;
VmsSubscriberManager vmsSubscriberManager = (VmsSubscriberManager) getCar().getCarManager(
Car.VMS_SUBSCRIBER_SERVICE);
TestClientCallback clientCallback = new TestClientCallback();
- vmsSubscriberManager.registerClientCallback(clientCallback);
+ vmsSubscriberManager.setVmsSubscriberClientCallback(mExecutor, clientCallback);
// Inject a value and wait for its callback in TestClientCallback.onLayersAvailabilityChanged.
VehiclePropValue v = VehiclePropValueBuilder.newBuilder(VehicleProperty.VEHICLE_MAP_SERVICE)
- .setAreaId(VehicleAreaType.VEHICLE_AREA_TYPE_NONE)
+ .setAreaId(VehicleAreaType.VEHICLE_AREA_TYPE_GLOBAL)
.setTimestamp(SystemClock.elapsedRealtimeNanos())
.build();
- /*
- Offering:
- Layer | Dependency
- ===============================
- (2, 3, 444), [17] | {}
+ //
+ // Offering:
+ // Layer | Dependency
+ // ===============================
+ // (2, 3, 444), [17] | {}
- Expected availability:
- {(2, 3, 444 [17])}
- */
+ // Expected availability:
+ // {(2, 3, 444 [17])}
+ //
v.value.int32Values.addAll(
Arrays.asList(
VmsMessageType.OFFERING, // MessageType
@@ -356,35 +364,35 @@
getMockedVehicleHal().injectEvent(v);
assertTrue(mSubscriberSemaphore.tryAcquire(2L, TimeUnit.SECONDS));
- List<VmsAssociatedLayer> expectedAvailableLayers =
- new ArrayList<>(Arrays.asList(SUBSCRIPTION_ASSOCIATED_LAYER));
- assertEquals(expectedAvailableLayers.size(), clientCallback.getAvailableLayers().size());
+ Set<VmsAssociatedLayer> associatedLayers =
+ new HashSet<>(Arrays.asList(SUBSCRIPTION_ASSOCIATED_LAYER));
+ assertEquals(associatedLayers, clientCallback.getAvailableLayers().getAssociatedLayers());
}
// Test injecting a value in the HAL and verifying it propagates to a subscriber after it has
// subscribed to a layer.
+ @Test
public void testSimpleAvailableLayersAfterSubscription() throws Exception {
- if (!VmsTestUtils.canRunTest(TAG)) return;
VmsSubscriberManager vmsSubscriberManager = (VmsSubscriberManager) getCar().getCarManager(
Car.VMS_SUBSCRIBER_SERVICE);
TestClientCallback clientCallback = new TestClientCallback();
- vmsSubscriberManager.registerClientCallback(clientCallback);
+ vmsSubscriberManager.setVmsSubscriberClientCallback(mExecutor, clientCallback);
vmsSubscriberManager.subscribe(SUBSCRIPTION_LAYER);
// Inject a value and wait for its callback in TestClientCallback.onLayersAvailabilityChanged.
VehiclePropValue v = VehiclePropValueBuilder.newBuilder(VehicleProperty.VEHICLE_MAP_SERVICE)
- .setAreaId(VehicleAreaType.VEHICLE_AREA_TYPE_NONE)
+ .setAreaId(VehicleAreaType.VEHICLE_AREA_TYPE_GLOBAL)
.setTimestamp(SystemClock.elapsedRealtimeNanos())
.build();
- /*
- Offering:
- Layer | Dependency
- ===============================
- (2, 3, 444), [17] | {}
+ //
+ // Offering:
+ // Layer | Dependency
+ // ===============================
+ // (2, 3, 444), [17] | {}
- Expected availability:
- {(2, 3, 444 [17])}
- */
+ // Expected availability:
+ // {(2, 3, 444 [17])}
+ //
v.value.int32Values.addAll(
Arrays.asList(
VmsMessageType.OFFERING, // MessageType
@@ -402,36 +410,36 @@
getMockedVehicleHal().injectEvent(v);
assertTrue(mSubscriberSemaphore.tryAcquire(2L, TimeUnit.SECONDS));
- List<VmsAssociatedLayer> expectedAvailableLayers =
- new ArrayList<>(Arrays.asList(SUBSCRIPTION_ASSOCIATED_LAYER));
- assertEquals(expectedAvailableLayers.size(), clientCallback.getAvailableLayers().size());
+ Set<VmsAssociatedLayer> associatedLayers =
+ new HashSet<>(Arrays.asList(SUBSCRIPTION_ASSOCIATED_LAYER));
+ assertEquals(associatedLayers, clientCallback.getAvailableLayers().getAssociatedLayers());
}
// Test injecting a value in the HAL and verifying it does not propagates to a subscriber after
- // it has unregistered its callback.
- public void testSimpleAvailableLayersAfterUnregister() throws Exception {
- if (!VmsTestUtils.canRunTest(TAG)) return;
+ // it has cleared its callback.
+ @Test
+ public void testSimpleAvailableLayersAfterClear() throws Exception {
VmsSubscriberManager vmsSubscriberManager = (VmsSubscriberManager) getCar().getCarManager(
Car.VMS_SUBSCRIBER_SERVICE);
TestClientCallback clientCallback = new TestClientCallback();
- vmsSubscriberManager.registerClientCallback(clientCallback);
- vmsSubscriberManager.unregisterClientCallback();
+ vmsSubscriberManager.setVmsSubscriberClientCallback(mExecutor, clientCallback);
+ vmsSubscriberManager.clearVmsSubscriberClientCallback();
// Inject a value and wait for its callback in TestClientCallback.onLayersAvailabilityChanged.
VehiclePropValue v = VehiclePropValueBuilder.newBuilder(VehicleProperty.VEHICLE_MAP_SERVICE)
- .setAreaId(VehicleAreaType.VEHICLE_AREA_TYPE_NONE)
+ .setAreaId(VehicleAreaType.VEHICLE_AREA_TYPE_GLOBAL)
.setTimestamp(SystemClock.elapsedRealtimeNanos())
.build();
- /*
- Offering:
- Layer | Dependency
- ===============================
- (2, 3, 444), [17] | {}
+ //
+ // Offering:
+ // Layer | Dependency
+ // ===============================
+ // (2, 3, 444), [17] | {}
- Expected availability:
- {(2, 3, 444 [17])}
- */
+ // Expected availability:
+ // {(2, 3, 444 [17])}
+ //
v.value.int32Values.addAll(
Arrays.asList(
VmsMessageType.OFFERING, // MessageType
@@ -450,49 +458,31 @@
assertFalse(mSubscriberSemaphore.tryAcquire(2L, TimeUnit.SECONDS));
}
- // Test injecting a value in the HAL and verifying it does not propagates to a subscriber after
- // it has unregistered its callback.
- public void testSomething() throws Exception {
- if (!VmsTestUtils.canRunTest(TAG)) return;
- VmsSubscriberManager vmsSubscriberManager = (VmsSubscriberManager) getCar().getCarManager(
- Car.VMS_SUBSCRIBER_SERVICE);
- TestClientCallback clientCallback = new TestClientCallback();
- vmsSubscriberManager.registerClientCallback(clientCallback);
- vmsSubscriberManager.subscribe(SUBSCRIPTION_LAYER);
- try {
- vmsSubscriberManager.unregisterClientCallback();
- } catch (IllegalArgumentException e) {
- return;
- }
- fail();
- }
-
-
// Test injecting a value in the HAL and verifying it propagates to a subscriber.
+ @Test
public void testComplexAvailableLayers() throws Exception {
- if (!VmsTestUtils.canRunTest(TAG)) return;
VmsSubscriberManager vmsSubscriberManager = (VmsSubscriberManager) getCar().getCarManager(
Car.VMS_SUBSCRIBER_SERVICE);
TestClientCallback clientCallback = new TestClientCallback();
- vmsSubscriberManager.registerClientCallback(clientCallback);
+ vmsSubscriberManager.setVmsSubscriberClientCallback(mExecutor, clientCallback);
// Inject a value and wait for its callback in TestClientCallback.onLayersAvailabilityChanged.
VehiclePropValue v = VehiclePropValueBuilder.newBuilder(VehicleProperty.VEHICLE_MAP_SERVICE)
- .setAreaId(VehicleAreaType.VEHICLE_AREA_TYPE_NONE)
+ .setAreaId(VehicleAreaType.VEHICLE_AREA_TYPE_GLOBAL)
.setTimestamp(SystemClock.elapsedRealtimeNanos())
.build();
- /*
- Offering:
- Layer | Dependency
- ====================
- (2, 3, 444), [17] | {}
- (4, 5, 444), [17] | {(2, 3)}
- (6, 7, 444), [17] | {(2, 3), (4, 5)}
- (6, 7, 444), [17] | {(100, 200)}
+ //
+ // Offering:
+ // Layer | Dependency
+ // =====================================
+ // (2, 3, 444), [17] | {}
+ // (4, 5, 444), [17] | {(2, 3)}
+ // (6, 7, 444), [17] | {(2, 3), (4, 5)}
+ // (6, 7, 444), [17] | {(100, 200)}
- Expected availability:
- {(2, 3, 444 [17]), (4, 5, 444 [17]), (6, 7, 444 [17])}
- */
+ // Expected availability:
+ // {(2, 3, 444 [17]), (4, 5, 444 [17]), (6, 7, 444 [17])}
+ //
v.value.int32Values.addAll(
Arrays.asList(
@@ -536,15 +526,156 @@
assertEquals(0, mSubscriberSemaphore.availablePermits());
- List<VmsAssociatedLayer> expectedAvailableLayers =
- new ArrayList<>(Arrays.asList(
+ Set<VmsAssociatedLayer> associatedLayers =
+ new HashSet<>(Arrays.asList(
SUBSCRIPTION_ASSOCIATED_LAYER,
SUBSCRIPTION_DEPENDANT_ASSOCIATED_LAYER_1,
SUBSCRIPTION_DEPENDANT_ASSOCIATED_LAYER_2
));
+
getMockedVehicleHal().injectEvent(v);
assertTrue(mSubscriberSemaphore.tryAcquire(2L, TimeUnit.SECONDS));
- assertEquals(expectedAvailableLayers.size(), clientCallback.getAvailableLayers().size());
+
+ // Verify applications API.
+ assertEquals(associatedLayers, clientCallback.getAvailableLayers().getAssociatedLayers());
+ assertEquals(1, clientCallback.getAvailableLayers().getSequence());
+
+ // Verify HAL API.
+ ArrayList<Integer> values = mHalHandler.getValue().value.int32Values;
+ int messageType = values.get(VmsAvailabilityStateIntegerValuesIndex.MESSAGE_TYPE);
+ int sequenceNumber = values.get(VmsAvailabilityStateIntegerValuesIndex.SEQUENCE_NUMBER);
+ int numberLayers =
+ values.get(VmsAvailabilityStateIntegerValuesIndex.NUMBER_OF_ASSOCIATED_LAYERS);
+
+ assertEquals(messageType, VmsMessageType.AVAILABILITY_CHANGE);
+ assertEquals(1, sequenceNumber);
+ assertEquals(3, numberLayers);
+ }
+
+ // Test injecting a value in the HAL twice the sequence for availability is incremented.
+ @Test
+ public void testDoubleOfferingAvailableLayers() throws Exception {
+ VmsSubscriberManager vmsSubscriberManager = (VmsSubscriberManager) getCar().getCarManager(
+ Car.VMS_SUBSCRIBER_SERVICE);
+ TestClientCallback clientCallback = new TestClientCallback();
+ vmsSubscriberManager.setVmsSubscriberClientCallback(mExecutor, clientCallback);
+
+ // Inject a value and wait for its callback in TestClientCallback.onLayersAvailabilityChanged.
+ VehiclePropValue v = VehiclePropValueBuilder.newBuilder(VehicleProperty.VEHICLE_MAP_SERVICE)
+ .setAreaId(VehicleAreaType.VEHICLE_AREA_TYPE_GLOBAL)
+ .setTimestamp(SystemClock.elapsedRealtimeNanos())
+ .build();
+ //
+ // Offering:
+ // Layer | Dependency
+ // ===============================
+ // (2, 3, 444), [17] | {}
+
+ // Expected availability:
+ // {(2, 3, 444 [17])}
+ //
+ v.value.int32Values.addAll(
+ Arrays.asList(
+ VmsMessageType.OFFERING, // MessageType
+ PUBLISHER_ID,
+ 1, // Number of offered layers
+
+ SUBSCRIPTION_LAYER_ID,
+ MOCK_PUBLISHER_LAYER_SUBTYPE,
+ SUBSCRIPTION_LAYER_VERSION,
+ 0 // number of dependencies for layer
+ )
+ );
+
+ assertEquals(0, mSubscriberSemaphore.availablePermits());
+
+ // Inject first offer.
+ getMockedVehicleHal().injectEvent(v);
+ assertTrue(mSubscriberSemaphore.tryAcquire(2L, TimeUnit.SECONDS));
+
+ // Verify applications API.
+ Set<VmsAssociatedLayer> associatedLayers =
+ new HashSet<>(Arrays.asList(SUBSCRIPTION_ASSOCIATED_LAYER));
+ assertEquals(associatedLayers, clientCallback.getAvailableLayers().getAssociatedLayers());
+ assertEquals(1, clientCallback.getAvailableLayers().getSequence());
+
+ // Verify HAL API.
+ ArrayList<Integer> values = mHalHandler.getValue().value.int32Values;
+ int messageType = values.get(VmsAvailabilityStateIntegerValuesIndex.MESSAGE_TYPE);
+ int sequenceNumber = values.get(VmsAvailabilityStateIntegerValuesIndex.SEQUENCE_NUMBER);
+ int numberLayers =
+ values.get(VmsAvailabilityStateIntegerValuesIndex.NUMBER_OF_ASSOCIATED_LAYERS);
+
+ assertEquals(messageType, VmsMessageType.AVAILABILITY_CHANGE);
+ assertEquals(1, sequenceNumber);
+ assertEquals(1, numberLayers);
+
+ // Inject second offer.
+ getMockedVehicleHal().injectEvent(v);
+ assertTrue(mSubscriberSemaphore.tryAcquire(2L, TimeUnit.SECONDS));
+
+ // Verify applications API.
+ assertEquals(2, clientCallback.getAvailableLayers().getSequence());
+
+ // Verify HAL API.
+ values = mHalHandler.getValue().value.int32Values;
+ messageType = values.get(VmsAvailabilityStateIntegerValuesIndex.MESSAGE_TYPE);
+ sequenceNumber = values.get(VmsAvailabilityStateIntegerValuesIndex.SEQUENCE_NUMBER);
+ numberLayers =
+ values.get(VmsAvailabilityStateIntegerValuesIndex.NUMBER_OF_ASSOCIATED_LAYERS);
+
+ assertEquals(messageType, VmsMessageType.AVAILABILITY_CHANGE);
+ assertEquals(2, sequenceNumber);
+ assertEquals(1, numberLayers);
+
+ }
+
+ // Test GetAvailableLayers().
+ @Test
+ public void testGetAvailableLayers() throws Exception {
+ VmsSubscriberManager vmsSubscriberManager = (VmsSubscriberManager) getCar().getCarManager(
+ Car.VMS_SUBSCRIBER_SERVICE);
+ TestClientCallback clientCallback = new TestClientCallback();
+ vmsSubscriberManager.setVmsSubscriberClientCallback(mExecutor, clientCallback);
+
+ // Inject a value and wait for its callback in TestClientCallback.onLayersAvailabilityChanged.
+ VehiclePropValue v = VehiclePropValueBuilder.newBuilder(VehicleProperty.VEHICLE_MAP_SERVICE)
+ .setAreaId(VehicleAreaType.VEHICLE_AREA_TYPE_GLOBAL)
+ .setTimestamp(SystemClock.elapsedRealtimeNanos())
+ .build();
+ //
+ // Offering:
+ // Layer | Dependency
+ // ===============================
+ // (2, 3, 444), [17] | {}
+
+ // Expected availability:
+ // {(2, 3, 444 [17])}
+ //
+ v.value.int32Values.addAll(
+ Arrays.asList(
+ VmsMessageType.OFFERING, // MessageType
+ PUBLISHER_ID,
+ 1, // Number of offered layers
+
+ SUBSCRIPTION_LAYER_ID,
+ MOCK_PUBLISHER_LAYER_SUBTYPE,
+ SUBSCRIPTION_LAYER_VERSION,
+ 0 // number of dependencies for layer
+ )
+ );
+
+ assertEquals(0, mSubscriberSemaphore.availablePermits());
+
+ getMockedVehicleHal().injectEvent(v);
+ assertTrue(mSubscriberSemaphore.tryAcquire(2L, TimeUnit.SECONDS));
+ Set<VmsAssociatedLayer> associatedLayers =
+ new HashSet<>(Arrays.asList(SUBSCRIPTION_ASSOCIATED_LAYER));
+ assertEquals(associatedLayers, clientCallback.getAvailableLayers().getAssociatedLayers());
+ assertEquals(1, clientCallback.getAvailableLayers().getSequence());
+
+ assertEquals(associatedLayers, vmsSubscriberManager.getAvailableLayers().getAssociatedLayers());
+ assertEquals(1, vmsSubscriberManager.getAvailableLayers().getSequence());
}
private class HalHandler implements VehicleHalPropertyHandler {
@@ -562,7 +693,7 @@
}
@Override
- public synchronized void onPropertySubscribe(int property, int zones, float sampleRate) {
+ public synchronized void onPropertySubscribe(int property, float sampleRate) {
Log.d(TAG, "onPropertySubscribe property " + property + " sampleRate " + sampleRate);
}
@@ -579,7 +710,7 @@
private class TestClientCallback implements VmsSubscriberClientCallback {
private VmsLayer mLayer;
private byte[] mPayload;
- private List<VmsLayer> mAvailableLayers = new ArrayList<>();
+ private VmsAvailableLayers mAvailableLayers;
@Override
public void onVmsMessageReceived(VmsLayer layer, byte[] payload) {
@@ -590,9 +721,9 @@
}
@Override
- public void onLayersAvailabilityChanged(List<VmsLayer> availableLayers) {
+ public void onLayersAvailabilityChanged(VmsAvailableLayers availableLayers) {
Log.d(TAG, "onLayersAvailabilityChanged: Layers: " + availableLayers);
- mAvailableLayers.addAll(availableLayers);
+ mAvailableLayers = availableLayers;
mSubscriberSemaphore.release();
}
@@ -604,7 +735,7 @@
return mPayload;
}
- public List<VmsLayer> getAvailableLayers() {
+ public VmsAvailableLayers getAvailableLayers() {
return mAvailableLayers;
}
}
diff --git a/tests/carservice_test/src/com/android/car/test/AudioRoutingPolicyTest.java b/tests/carservice_test/src/com/android/car/test/AudioRoutingPolicyTest.java
deleted file mode 100644
index 7f4aeac..0000000
--- a/tests/carservice_test/src/com/android/car/test/AudioRoutingPolicyTest.java
+++ /dev/null
@@ -1,143 +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.test;
-
-import android.hardware.automotive.vehicle.V2_0.VehicleAudioContextFlag;
-import android.hardware.automotive.vehicle.V2_0.VehicleAudioRoutingPolicyIndex;
-import android.hardware.automotive.vehicle.V2_0.VehiclePropValue;
-import android.hardware.automotive.vehicle.V2_0.VehicleProperty;
-import android.hardware.automotive.vehicle.V2_0.VehiclePropertyAccess;
-import android.test.suitebuilder.annotation.SmallTest;
-
-import com.google.android.collect.Lists;
-
-import com.android.car.vehiclehal.VehiclePropValueBuilder;
-import com.android.car.vehiclehal.test.MockedVehicleHal.FailingPropertyHandler;
-import com.android.car.vehiclehal.test.MockedVehicleHal.VehicleHalPropertyHandler;
-
-import java.util.ArrayList;
-import java.util.LinkedList;
-import java.util.concurrent.Semaphore;
-import java.util.concurrent.TimeUnit;
-
-@SmallTest
-public class AudioRoutingPolicyTest extends MockedCarTestBase {
- private static final String TAG = AudioRoutingPolicyTest.class.getSimpleName();
-
- private static final long TIMEOUT_MS = 3000;
-
- private final VehicleHalPropertyHandler mAudioRoutingPolicyHandler =
- new FailingPropertyHandler() {
-
- @Override
- public void onPropertySet(VehiclePropValue value) {
- handlePropertySetEvent(value);
- }
- };
-
- private final Semaphore mWaitSemaphore = new Semaphore(0);
- private final LinkedList<VehiclePropValue> mEvents = new LinkedList<>();
-
- @Override
- protected synchronized void setUp() throws Exception {
- super.setUp();
- }
-
- @Override
- protected synchronized void configureMockedHal() {
- addProperty(VehicleProperty.AUDIO_ROUTING_POLICY, mAudioRoutingPolicyHandler)
- .setAccess(VehiclePropertyAccess.WRITE);
- }
-
- public void testNoHwVariant() throws Exception {
- checkPolicy0();
- }
-
- public void testHwVariant0() throws Exception {
- addStaticProperty(VehicleProperty.AUDIO_HW_VARIANT,
- VehiclePropValueBuilder.newBuilder(VehicleProperty.AUDIO_HW_VARIANT)
- .addIntValue(0)
- .build())
- .setConfigArray(Lists.newArrayList(0));
-
- mEvents.clear();
- reinitializeMockedHal();
-
- checkPolicy0();
- }
-
- public void testHwVariantForTest() throws Exception {
- addStaticProperty(VehicleProperty.AUDIO_HW_VARIANT,
- VehiclePropValueBuilder.newBuilder(VehicleProperty.AUDIO_HW_VARIANT)
- .addIntValue(-1)
- .build())
- .setConfigArray(Lists.newArrayList(0));
-
- mEvents.clear();
- reinitializeMockedHal();
-
- checkPolicyForTest();
- }
-
- private void checkPolicy0() throws Exception {
- assertTrue(mWaitSemaphore.tryAcquire(TIMEOUT_MS, TimeUnit.MILLISECONDS));
- ArrayList<Integer> v = mEvents.get(0).value.int32Values;
- assertEquals(0, v.get(VehicleAudioRoutingPolicyIndex.STREAM).intValue());
- int contexts = v.get(VehicleAudioRoutingPolicyIndex.CONTEXTS);
- // check if all contexts are allowed ones.
- assertTrue((contexts & ~(
- VehicleAudioContextFlag.RINGTONE_FLAG |
- VehicleAudioContextFlag.ALARM_FLAG |
- VehicleAudioContextFlag.CALL_FLAG |
- VehicleAudioContextFlag.MUSIC_FLAG |
- VehicleAudioContextFlag.RADIO_FLAG |
- VehicleAudioContextFlag.NAVIGATION_FLAG |
- VehicleAudioContextFlag.NOTIFICATION_FLAG |
- VehicleAudioContextFlag.UNKNOWN_FLAG |
- VehicleAudioContextFlag.VOICE_COMMAND_FLAG |
- VehicleAudioContextFlag.SYSTEM_SOUND_FLAG |
- VehicleAudioContextFlag.SAFETY_ALERT_FLAG)) == 0);
- }
-
- private void checkPolicyForTest() throws Exception {
- // write happens twice.
- assertTrue(mWaitSemaphore.tryAcquire(TIMEOUT_MS, TimeUnit.MILLISECONDS));
- assertTrue(mWaitSemaphore.tryAcquire(TIMEOUT_MS, TimeUnit.MILLISECONDS));
- ArrayList<Integer> v = mEvents.get(0).value.int32Values;
- assertEquals(0, v.get(VehicleAudioRoutingPolicyIndex.STREAM).intValue());
- assertEquals(
- VehicleAudioContextFlag.CALL_FLAG |
- VehicleAudioContextFlag.MUSIC_FLAG |
- VehicleAudioContextFlag.RADIO_FLAG |
- VehicleAudioContextFlag.UNKNOWN_FLAG,
- v.get(VehicleAudioRoutingPolicyIndex.CONTEXTS).intValue());
- v = mEvents.get(1).value.int32Values;
- assertEquals(1, v.get(VehicleAudioRoutingPolicyIndex.STREAM).intValue());
- assertEquals(
- VehicleAudioContextFlag.ALARM_FLAG |
- VehicleAudioContextFlag.NAVIGATION_FLAG |
- VehicleAudioContextFlag.NOTIFICATION_FLAG |
- VehicleAudioContextFlag.VOICE_COMMAND_FLAG |
- VehicleAudioContextFlag.SYSTEM_SOUND_FLAG |
- VehicleAudioContextFlag.SAFETY_ALERT_FLAG,
- v.get(VehicleAudioRoutingPolicyIndex.CONTEXTS).intValue());
- }
-
- private void handlePropertySetEvent(VehiclePropValue value) {
- mEvents.add(value);
- mWaitSemaphore.release();
- }
-}
diff --git a/tests/carservice_test/src/com/android/car/test/AudioTestUtils.java b/tests/carservice_test/src/com/android/car/test/AudioTestUtils.java
deleted file mode 100644
index 8c3de7c..0000000
--- a/tests/carservice_test/src/com/android/car/test/AudioTestUtils.java
+++ /dev/null
@@ -1,57 +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.android.car.test;
-
-import android.media.AudioAttributes;
-import android.media.AudioFocusRequest;
-import android.media.AudioManager;
-import android.media.AudioManager.OnAudioFocusChangeListener;
-
-final class AudioTestUtils {
- private AudioTestUtils() {}
-
- static int doRequestFocus(
- AudioManager audioManager,
- OnAudioFocusChangeListener listener,
- int streamType,
- int androidFocus) {
- AudioAttributes.Builder attributesBuilder = new AudioAttributes.Builder();
- attributesBuilder.setLegacyStreamType(streamType);
- return doRequestFocus(audioManager, listener, attributesBuilder.build(), androidFocus);
- }
-
- static int doRequestFocus(
- AudioManager audioManager,
- OnAudioFocusChangeListener listener,
- AudioAttributes attributes,
- int androidFocus) {
- return doRequestFocus(audioManager, listener, attributes, androidFocus, false);
- }
-
- static int doRequestFocus(
- AudioManager audioManager,
- OnAudioFocusChangeListener listener,
- AudioAttributes attributes,
- int androidFocus,
- boolean acceptsDelayedFocus) {
- AudioFocusRequest.Builder focusBuilder = new AudioFocusRequest.Builder(androidFocus);
- focusBuilder.setOnAudioFocusChangeListener(listener).setAcceptsDelayedFocusGain(
- acceptsDelayedFocus);
- focusBuilder.setAudioAttributes(attributes);
-
- return audioManager.requestAudioFocus(focusBuilder.build());
- }
-}
diff --git a/tests/carservice_test/src/com/android/car/test/CarAudioExtFocusTest.java b/tests/carservice_test/src/com/android/car/test/CarAudioExtFocusTest.java
deleted file mode 100644
index 71e0d04..0000000
--- a/tests/carservice_test/src/com/android/car/test/CarAudioExtFocusTest.java
+++ /dev/null
@@ -1,999 +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.test;
-
-import static android.hardware.automotive.vehicle.V2_0.VehicleProperty.AUDIO_FOCUS;
-import static com.android.car.test.AudioTestUtils.doRequestFocus;
-import static java.lang.Integer.toHexString;
-
-import android.car.Car;
-import android.car.media.CarAudioManager;
-import android.content.Context;
-import android.hardware.automotive.vehicle.V2_0.VehicleAudioContextFlag;
-import android.hardware.automotive.vehicle.V2_0.VehicleAudioExtFocusFlag;
-import android.hardware.automotive.vehicle.V2_0.VehicleAudioFocusIndex;
-import android.hardware.automotive.vehicle.V2_0.VehicleAudioFocusRequest;
-import android.hardware.automotive.vehicle.V2_0.VehicleAudioFocusState;
-import android.hardware.automotive.vehicle.V2_0.VehicleAudioStream;
-import android.hardware.automotive.vehicle.V2_0.VehiclePropValue;
-import android.hardware.automotive.vehicle.V2_0.VehicleProperty;
-import android.hardware.automotive.vehicle.V2_0.VehiclePropertyAccess;
-import android.media.AudioAttributes;
-import android.media.AudioManager;
-import android.os.SystemClock;
-import android.test.suitebuilder.annotation.MediumTest;
-import android.util.Log;
-
-import com.google.android.collect.Lists;
-
-import com.android.car.vehiclehal.VehiclePropValueBuilder;
-import com.android.car.vehiclehal.test.MockedVehicleHal.FailingPropertyHandler;
-import com.android.car.vehiclehal.test.MockedVehicleHal.VehicleHalPropertyHandler;
-
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.LinkedList;
-import java.util.concurrent.Semaphore;
-import java.util.concurrent.TimeUnit;
-
-@MediumTest
-public class CarAudioExtFocusTest extends MockedCarTestBase {
- private static final String TAG = CarAudioExtFocusTest.class.getSimpleName();
-
- private static final long TIMEOUT_MS = 3000;
-
- private final VehicleHalPropertyHandler mAudioRoutingPolicyPropertyHandler =
- new FailingPropertyHandler() {
- @Override
- public void onPropertySet(VehiclePropValue value) {
- //TODO
- }
- };
-
- private final FocusPropertyHandler mAudioFocusPropertyHandler =
- new FocusPropertyHandler(this);
-
- private final ExtRoutingHintPropertyHandler mExtRoutingHintPropertyHandler =
- new ExtRoutingHintPropertyHandler();
-
- private static final String EXT_ROUTING_CONFIG =
- "0:RADIO_AM_FM:0,1:RADIO_SATELLITE:0,33:CD_DVD:0," +
- "64:com.google.test.SOMETHING_SPECIAL," +
- "4:EXT_NAV_GUIDANCE:1," +
- "5:AUX_IN0:0";
-
- private final Semaphore mWaitSemaphore = new Semaphore(0);
- private final LinkedList<VehiclePropValue> mEvents = new LinkedList<VehiclePropValue>();
- private AudioManager mAudioManager;
- private CarAudioManager mCarAudioManager;
-
- @Override
- protected synchronized void configureMockedHal() {
- addProperty(VehicleProperty.AUDIO_ROUTING_POLICY, mAudioRoutingPolicyPropertyHandler);
- addProperty(VehicleProperty.AUDIO_FOCUS, mAudioFocusPropertyHandler);
-
- addStaticProperty(VehicleProperty.AUDIO_HW_VARIANT,
- VehiclePropValueBuilder.newBuilder(VehicleProperty.AUDIO_HW_VARIANT)
- .addIntValue(-1)
- .build())
- .setConfigArray(Lists.newArrayList(0));
-
- addProperty(VehicleProperty.AUDIO_EXT_ROUTING_HINT, mExtRoutingHintPropertyHandler)
- .setAccess(VehiclePropertyAccess.WRITE)
- .setConfigString(EXT_ROUTING_CONFIG);
- }
-
- @Override
- protected void setUp() throws Exception {
- super.setUp();
- // AudioManager should be created in main thread to get focus event. :(
- runOnMainSync(new Runnable() {
- @Override
- public void run() {
- mAudioManager = (AudioManager) mContext.getSystemService(Context.AUDIO_SERVICE);
- }
- });
-
- mCarAudioManager = (CarAudioManager) getCar().getCarManager(Car.AUDIO_SERVICE);
- assertNotNull(mCarAudioManager);
- }
-
- public void testExtRoutings() throws Exception {
- String[] radioTypes = mCarAudioManager.getSupportedRadioTypes();
- assertNotNull(radioTypes);
- checkStringArrayContents(new String[] {"RADIO_AM_FM", "RADIO_SATELLITE"}, radioTypes);
-
- String[] nonRadioTypes = mCarAudioManager.getSupportedExternalSourceTypes();
- assertNotNull(nonRadioTypes);
- checkStringArrayContents(new String[] {"CD_DVD", "com.google.test.SOMETHING_SPECIAL",
- "EXT_NAV_GUIDANCE", "AUX_IN0"}, nonRadioTypes);
- }
-
- private void checkStringArrayContents(String[] expected, String[] actual) throws Exception {
- Arrays.sort(expected);
- Arrays.sort(actual);
- assertEquals(expected.length, actual.length);
- for (int i = 0; i < expected.length; i++) {
- assertEquals(expected[i], actual[i]);
- }
- }
-
- public void testRadioAttributeCreation() throws Exception {
- AudioAttributes attrb = mCarAudioManager.getAudioAttributesForRadio(
- CarAudioManager.CAR_RADIO_TYPE_AM_FM);
- assertNotNull(attrb);
-
- attrb = mCarAudioManager.getAudioAttributesForRadio(
- CarAudioManager.CAR_RADIO_TYPE_SATELLITE);
- assertNotNull(attrb);
-
- try {
- mCarAudioManager.getAudioAttributesForRadio(CarAudioManager.CAR_RADIO_TYPE_AM_FM_HD);
- fail();
- } catch (IllegalArgumentException e) {
- // expected
- }
- }
-
- public void testExtSourceAttributeCreation() throws Exception {
- AudioAttributes attrb = mCarAudioManager.getAudioAttributesForExternalSource(
- CarAudioManager.CAR_EXTERNAL_SOURCE_TYPE_CD_DVD);
- assertNotNull(attrb);
-
- attrb = mCarAudioManager.getAudioAttributesForExternalSource(
- CarAudioManager.CAR_EXTERNAL_SOURCE_TYPE_EXT_NAV_GUIDANCE);
- assertNotNull(attrb);
-
- attrb = mCarAudioManager.getAudioAttributesForExternalSource(
- "com.google.test.SOMETHING_SPECIAL");
- assertNotNull(attrb);
-
- try {
- mCarAudioManager.getAudioAttributesForExternalSource(
- CarAudioManager.CAR_RADIO_TYPE_AM_FM_HD);
- fail();
- } catch (IllegalArgumentException e) {
- // expected
- }
- }
-
- public void testRadioAmFmGainFocus() throws Exception {
- AudioAttributes attrb = mCarAudioManager.getAudioAttributesForRadio(
- CarAudioManager.CAR_RADIO_TYPE_AM_FM);
- assertNotNull(attrb);
- checkSingleRequestRelease(attrb, AudioManager.AUDIOFOCUS_GAIN, new int[] {1, 0, 0, 0},
- 0, VehicleAudioExtFocusFlag.PLAY_ONLY_FLAG,
- VehicleAudioContextFlag.RADIO_FLAG);
- }
-
- public void testRadioSatelliteGainFocus() throws Exception {
- AudioAttributes attrb = mCarAudioManager.getAudioAttributesForRadio(
- CarAudioManager.CAR_RADIO_TYPE_SATELLITE);
- assertNotNull(attrb);
- checkSingleRequestRelease(attrb, AudioManager.AUDIOFOCUS_GAIN, new int[] {2, 0, 0, 0},
- 0, VehicleAudioExtFocusFlag.PLAY_ONLY_FLAG,
- VehicleAudioContextFlag.RADIO_FLAG);
- }
-
- public void testCdGainFocus() throws Exception {
- AudioAttributes attrb = mCarAudioManager.getAudioAttributesForExternalSource(
- CarAudioManager.CAR_EXTERNAL_SOURCE_TYPE_CD_DVD);
- assertNotNull(attrb);
- checkSingleRequestRelease(attrb, AudioManager.AUDIOFOCUS_GAIN, new int[] {0, 2, 0, 0},
- 0, VehicleAudioExtFocusFlag.PLAY_ONLY_FLAG,
- VehicleAudioContextFlag.CD_ROM_FLAG);
- }
-
- public void testAuxInFocus() throws Exception {
- AudioAttributes attrb = mCarAudioManager.getAudioAttributesForExternalSource(
- CarAudioManager.CAR_EXTERNAL_SOURCE_TYPE_AUX_IN0);
- assertNotNull(attrb);
- checkSingleRequestRelease(attrb, AudioManager.AUDIOFOCUS_GAIN, new int[] {0x1<<5, 0, 0, 0},
- 0, VehicleAudioExtFocusFlag.PLAY_ONLY_FLAG,
- VehicleAudioContextFlag.AUX_AUDIO_FLAG);
- }
-
- public void testExtNavInFocus() throws Exception {
- AudioAttributes attrb = mCarAudioManager.getAudioAttributesForExternalSource(
- CarAudioManager.CAR_EXTERNAL_SOURCE_TYPE_EXT_NAV_GUIDANCE);
- assertNotNull(attrb);
- checkSingleRequestRelease(attrb, AudioManager.AUDIOFOCUS_GAIN, new int[] {0x1<<4, 0, 0, 0},
- 0, VehicleAudioExtFocusFlag.PLAY_ONLY_FLAG,
- VehicleAudioContextFlag.EXT_SOURCE_FLAG);
- }
-
- public void testCustomInFocus() throws Exception {
- AudioAttributes attrb = mCarAudioManager.getAudioAttributesForExternalSource(
- "com.google.test.SOMETHING_SPECIAL");
- assertNotNull(attrb);
- checkSingleRequestRelease(attrb, AudioManager.AUDIOFOCUS_GAIN, new int[] {0, 0, 1, 0},
- 0, VehicleAudioExtFocusFlag.PLAY_ONLY_FLAG,
- VehicleAudioContextFlag.EXT_SOURCE_FLAG);
- }
-
- public void testMediaNavFocus() throws Exception {
- //music start
- AudioFocusListener listenerMusic = new AudioFocusListener();
- int res = doRequestFocus(mAudioManager, listenerMusic,
- AudioManager.STREAM_MUSIC,
- AudioManager.AUDIOFOCUS_GAIN);
- assertEquals(AudioManager.AUDIOFOCUS_REQUEST_GRANTED, res);
- int[] request = mAudioFocusPropertyHandler.waitForAudioFocusRequest(TIMEOUT_MS);
- assertEquals(VehicleAudioFocusRequest.REQUEST_GAIN, request[0]);
- assertEquals(0x1 << VehicleAudioStream.STREAM0, request[1]);
- assertEquals(0, request[2]);
- assertEquals(VehicleAudioContextFlag.MUSIC_FLAG, request[3]);
- assertArrayEquals(new int[] {0, 0, 0, 0},
- mExtRoutingHintPropertyHandler.getLastHint());
- mAudioFocusPropertyHandler.sendAudioFocusState(
- VehicleAudioFocusState.STATE_GAIN,
- request[1],
- VehicleAudioExtFocusFlag.NONE_FLAG);
-
- // nav guidance start
- AudioFocusListener listenerNav = new AudioFocusListener();
- AudioAttributes navAttrib = (new AudioAttributes.Builder()).
- setContentType(AudioAttributes.CONTENT_TYPE_SONIFICATION).
- setUsage(AudioAttributes.USAGE_ASSISTANCE_NAVIGATION_GUIDANCE).
- build();
- doRequestFocus(mAudioManager, listenerNav, navAttrib,
- AudioManager.AUDIOFOCUS_GAIN_TRANSIENT_MAY_DUCK);
- request = mAudioFocusPropertyHandler.waitForAudioFocusRequest(TIMEOUT_MS);
- assertEquals(VehicleAudioFocusRequest.REQUEST_GAIN, request[0]);
- assertEquals(0x3, request[1]);
- assertEquals(0, request[2]);
- assertEquals(VehicleAudioContextFlag.MUSIC_FLAG |
- VehicleAudioContextFlag.NAVIGATION_FLAG, request[3]);
- assertArrayEquals(new int[] {0, 0, 0, 0},
- mExtRoutingHintPropertyHandler.getLastHint());
- mAudioFocusPropertyHandler.sendAudioFocusState(
- VehicleAudioFocusState.STATE_GAIN, request[1],
- VehicleAudioExtFocusFlag.NONE_FLAG);
-
- // nav guidance done
- mAudioManager.abandonAudioFocus(listenerNav);
- request = mAudioFocusPropertyHandler.waitForAudioFocusRequest(TIMEOUT_MS);
- assertEquals(VehicleAudioFocusRequest.REQUEST_GAIN, request[0]);
- assertEquals(0x1 << VehicleAudioStream.STREAM0, request[1]);
- assertEquals(0, request[2]);
- assertEquals(VehicleAudioContextFlag.MUSIC_FLAG, request[3]);
- assertArrayEquals(new int[] {0, 0, 0, 0},
- mExtRoutingHintPropertyHandler.getLastHint());
- mAudioFocusPropertyHandler.sendAudioFocusState(
- VehicleAudioFocusState.STATE_GAIN, request[1],
- VehicleAudioExtFocusFlag.NONE_FLAG);
-
- // music done
- mAudioManager.abandonAudioFocus(listenerMusic);
- request = mAudioFocusPropertyHandler.waitForAudioFocusRequest(TIMEOUT_MS);
- assertEquals(VehicleAudioFocusRequest.REQUEST_RELEASE, request[0]);
- assertEquals(0, request[1]);
- assertEquals(0, request[2]);
- assertEquals(0, request[3]);
- assertArrayEquals(new int[] {0, 0, 0, 0},
- mExtRoutingHintPropertyHandler.getLastHint());
- mAudioFocusPropertyHandler.sendAudioFocusState(
- VehicleAudioFocusState.STATE_LOSS, request[1],
- VehicleAudioExtFocusFlag.NONE_FLAG);
- }
-
- public void testMediaExternalMediaNavFocus() throws Exception {
- // android music
- AudioFocusListener listenerMusic = new AudioFocusListener();
- int res = doRequestFocus(mAudioManager, listenerMusic,
- AudioManager.STREAM_MUSIC,
- AudioManager.AUDIOFOCUS_GAIN);
- assertEquals(AudioManager.AUDIOFOCUS_REQUEST_GRANTED, res);
- int[] request = mAudioFocusPropertyHandler.waitForAudioFocusRequest(TIMEOUT_MS);
- assertEquals(VehicleAudioFocusRequest.REQUEST_GAIN, request[0]);
- assertEquals(0x1 << VehicleAudioStream.STREAM0, request[1]);
- assertEquals(0, request[2]);
- assertEquals(VehicleAudioContextFlag.MUSIC_FLAG, request[3]);
- assertArrayEquals(new int[] {0, 0, 0, 0},
- mExtRoutingHintPropertyHandler.getLastHint());
- mAudioFocusPropertyHandler.sendAudioFocusState(
- VehicleAudioFocusState.STATE_GAIN,
- request[1],
- VehicleAudioExtFocusFlag.NONE_FLAG);
-
- // car plays external media (=outside Android)
- mAudioFocusPropertyHandler.sendAudioFocusState(
- VehicleAudioFocusState.STATE_LOSS,
- 0,
- VehicleAudioExtFocusFlag.PERMANENT_FLAG);
- int focusChange = listenerMusic.waitAndGetFocusChange(TIMEOUT_MS);
- assertEquals(AudioManager.AUDIOFOCUS_LOSS, focusChange);
-
- // nav guidance start
- AudioFocusListener listenerNav = new AudioFocusListener();
- AudioAttributes navAttrib = (new AudioAttributes.Builder()).
- setContentType(AudioAttributes.CONTENT_TYPE_SONIFICATION).
- setUsage(AudioAttributes.USAGE_ASSISTANCE_NAVIGATION_GUIDANCE).
- build();
- doRequestFocus(mAudioManager, listenerNav, navAttrib,
- AudioManager.AUDIOFOCUS_GAIN_TRANSIENT_MAY_DUCK);
- request = mAudioFocusPropertyHandler.waitForAudioFocusRequest(TIMEOUT_MS);
- assertEquals(VehicleAudioFocusRequest.REQUEST_GAIN_TRANSIENT_MAY_DUCK,
- request[0]);
- assertEquals(0x1 << VehicleAudioStream.STREAM1, request[1]);
- assertEquals(0, request[2]);
- assertEquals(VehicleAudioContextFlag.NAVIGATION_FLAG, request[3]);
- assertArrayEquals(new int[] {0, 0, 0, 0},
- mExtRoutingHintPropertyHandler.getLastHint());
- mAudioFocusPropertyHandler.sendAudioFocusState(
- VehicleAudioFocusState.STATE_GAIN_TRANSIENT,
- 0x1 << VehicleAudioStream.STREAM1,
- VehicleAudioExtFocusFlag.PERMANENT_FLAG);
-
- // nav guidance ends
- mAudioManager.abandonAudioFocus(listenerNav);
- request = mAudioFocusPropertyHandler.waitForAudioFocusRequest(TIMEOUT_MS);
- assertEquals(VehicleAudioFocusRequest.REQUEST_RELEASE, request[0]);
- assertEquals(0, request[1]);
- assertEquals(0, request[2]);
- assertEquals(0, request[3]);
- assertArrayEquals(new int[] {0, 0, 0, 0},
- mExtRoutingHintPropertyHandler.getLastHint());
- mAudioFocusPropertyHandler.sendAudioFocusState(
- VehicleAudioFocusState.STATE_LOSS,
- 0,
- VehicleAudioExtFocusFlag.PERMANENT_FLAG);
-
- // now ends external play
- mAudioFocusPropertyHandler.sendAudioFocusState(
- VehicleAudioFocusState.STATE_LOSS,
- 0,
- 0);
- mAudioManager.abandonAudioFocus(listenerMusic);
- //TODO how to check this?
- }
-
- public void testExternalRadioExternalNav() throws Exception {
- // android radio
- AudioFocusListener listenerRadio = new AudioFocusListener();
- CarAudioManager carAudioManager = (CarAudioManager) getCar().getCarManager(
- Car.AUDIO_SERVICE);
- assertNotNull(carAudioManager);
- AudioAttributes radioAttributes = carAudioManager.getAudioAttributesForCarUsage(
- CarAudioManager.CAR_AUDIO_USAGE_RADIO);
- int res = doRequestFocus(mAudioManager, listenerRadio,
- radioAttributes, AudioManager.AUDIOFOCUS_GAIN);
- assertEquals(AudioManager.AUDIOFOCUS_REQUEST_GRANTED, res);
- int[] request = mAudioFocusPropertyHandler.waitForAudioFocusRequest(TIMEOUT_MS);
- assertEquals(VehicleAudioFocusRequest.REQUEST_GAIN, request[0]);
- assertEquals(0, request[1]);
- assertEquals(VehicleAudioExtFocusFlag.PLAY_ONLY_FLAG,
- request[2]);
- assertEquals(VehicleAudioContextFlag.RADIO_FLAG, request[3]);
- assertArrayEquals(new int[] {1, 0, 0, 0},
- mExtRoutingHintPropertyHandler.getLastHint());
- mAudioFocusPropertyHandler.sendAudioFocusState(
- VehicleAudioFocusState.STATE_GAIN,
- 0,
- VehicleAudioExtFocusFlag.PLAY_ONLY_FLAG);
-
- //external nav
- AudioFocusListener listenerNav = new AudioFocusListener();
- AudioAttributes extNavAttributes = mCarAudioManager.getAudioAttributesForExternalSource(
- CarAudioManager.CAR_EXTERNAL_SOURCE_TYPE_EXT_NAV_GUIDANCE);
- res = doRequestFocus(mAudioManager, listenerNav,
- extNavAttributes, AudioManager.AUDIOFOCUS_GAIN_TRANSIENT_MAY_DUCK);
- assertEquals(AudioManager.AUDIOFOCUS_REQUEST_GRANTED, res);
- request = mAudioFocusPropertyHandler.waitForAudioFocusRequest(TIMEOUT_MS);
- assertEquals(VehicleAudioFocusRequest.REQUEST_GAIN,
- request[0]);
- assertEquals(0, request[1]);
- assertEquals(VehicleAudioExtFocusFlag.PLAY_ONLY_FLAG,
- request[2]);
- assertEquals(VehicleAudioContextFlag.RADIO_FLAG |
- VehicleAudioContextFlag.EXT_SOURCE_FLAG, request[3]);
- assertArrayEquals(new int[] {1 | 1<<4, 0, 0, 0},
- mExtRoutingHintPropertyHandler.getLastHint());
- mAudioFocusPropertyHandler.sendAudioFocusState(
- VehicleAudioFocusState.STATE_GAIN,
- 0,
- VehicleAudioExtFocusFlag.PLAY_ONLY_FLAG);
-
- mAudioManager.abandonAudioFocus(listenerNav);
- request = mAudioFocusPropertyHandler.waitForAudioFocusRequest(TIMEOUT_MS);
- assertEquals(VehicleAudioFocusRequest.REQUEST_GAIN, request[0]);
- assertEquals(0, request[1]);
- assertEquals(VehicleAudioExtFocusFlag.PLAY_ONLY_FLAG,
- request[2]);
- assertEquals(VehicleAudioContextFlag.RADIO_FLAG, request[3]);
- assertArrayEquals(new int[] {1, 0, 0, 0},
- mExtRoutingHintPropertyHandler.getLastHint());
- mAudioFocusPropertyHandler.sendAudioFocusState(
- VehicleAudioFocusState.STATE_GAIN,
- 0,
- VehicleAudioExtFocusFlag.PLAY_ONLY_FLAG);
-
- mAudioManager.abandonAudioFocus(listenerRadio);
- request = mAudioFocusPropertyHandler.waitForAudioFocusRequest(TIMEOUT_MS);
- assertEquals(VehicleAudioFocusRequest.REQUEST_RELEASE, request[0]);
- assertEquals(0, request[1]);
- assertEquals(0, request[2]);
- assertEquals(0, request[3]);
- assertArrayEquals(new int[] {0, 0, 0, 0},
- mExtRoutingHintPropertyHandler.getLastHint());
- mAudioFocusPropertyHandler.sendAudioFocusState(
- VehicleAudioFocusState.STATE_LOSS,
- 0,
- 0);
- }
-
- public void testMediaExternalNav() throws Exception {
- // android music
- AudioFocusListener listenerMusic = new AudioFocusListener();
- int res = doRequestFocus(mAudioManager, listenerMusic,
- AudioManager.STREAM_MUSIC,
- AudioManager.AUDIOFOCUS_GAIN);
- assertEquals(AudioManager.AUDIOFOCUS_REQUEST_GRANTED, res);
- int[] request = mAudioFocusPropertyHandler.waitForAudioFocusRequest(TIMEOUT_MS);
- assertEquals(VehicleAudioFocusRequest.REQUEST_GAIN, request[0]);
- assertEquals(0x1 << VehicleAudioStream.STREAM0, request[1]);
- assertEquals(0, request[2]);
- assertEquals(VehicleAudioContextFlag.MUSIC_FLAG, request[3]);
- assertArrayEquals(new int[] {0, 0, 0, 0},
- mExtRoutingHintPropertyHandler.getLastHint());
- mAudioFocusPropertyHandler.sendAudioFocusState(
- VehicleAudioFocusState.STATE_GAIN,
- request[1],
- VehicleAudioExtFocusFlag.NONE_FLAG);
-
- //external nav
- AudioFocusListener listenerNav = new AudioFocusListener();
- AudioAttributes extNavAttributes = mCarAudioManager.getAudioAttributesForExternalSource(
- CarAudioManager.CAR_EXTERNAL_SOURCE_TYPE_EXT_NAV_GUIDANCE);
- res = doRequestFocus(mAudioManager, listenerNav,
- extNavAttributes, AudioManager.AUDIOFOCUS_GAIN_TRANSIENT_MAY_DUCK);
- assertEquals(AudioManager.AUDIOFOCUS_REQUEST_GRANTED, res);
- request = mAudioFocusPropertyHandler.waitForAudioFocusRequest(TIMEOUT_MS);
- assertEquals(VehicleAudioFocusRequest.REQUEST_GAIN,
- request[0]);
- assertEquals(0x1, request[1]);
- assertEquals(VehicleAudioExtFocusFlag.PLAY_ONLY_FLAG,
- request[2]);
- assertEquals(VehicleAudioContextFlag.MUSIC_FLAG |
- VehicleAudioContextFlag.EXT_SOURCE_FLAG, request[3]);
- assertArrayEquals(new int[] {1<<4, 0, 0, 0},
- mExtRoutingHintPropertyHandler.getLastHint());
- mAudioFocusPropertyHandler.sendAudioFocusState(
- VehicleAudioFocusState.STATE_GAIN,
- 0x1,
- VehicleAudioExtFocusFlag.PLAY_ONLY_FLAG);
-
- mAudioManager.abandonAudioFocus(listenerNav);
- request = mAudioFocusPropertyHandler.waitForAudioFocusRequest(TIMEOUT_MS);
- assertEquals(VehicleAudioFocusRequest.REQUEST_GAIN, request[0]);
- assertEquals(0x1 << VehicleAudioStream.STREAM0, request[1]);
- assertEquals(0, request[2]);
- assertEquals(VehicleAudioContextFlag.MUSIC_FLAG, request[3]);
- assertArrayEquals(new int[] {0, 0, 0, 0},
- mExtRoutingHintPropertyHandler.getLastHint());
- mAudioFocusPropertyHandler.sendAudioFocusState(
- VehicleAudioFocusState.STATE_GAIN,
- request[1],
- VehicleAudioExtFocusFlag.NONE_FLAG);
-
- mAudioManager.abandonAudioFocus(listenerMusic);
- request = mAudioFocusPropertyHandler.waitForAudioFocusRequest(TIMEOUT_MS);
- assertEquals(VehicleAudioFocusRequest.REQUEST_RELEASE, request[0]);
- assertEquals(0, request[1]);
- assertEquals(0, request[2]);
- assertEquals(0, request[3]);
- assertArrayEquals(new int[] {0, 0, 0, 0},
- mExtRoutingHintPropertyHandler.getLastHint());
- mAudioFocusPropertyHandler.sendAudioFocusState(
- VehicleAudioFocusState.STATE_LOSS,
- 0,
- 0);
- }
-
- /**
- * Test internal nav - external nav case.
- * External nav takes the same physical stream as internal nav. So internal nav
- * will be lost while external nav is played. This should not happen in real case when
- * AppFocus is used, but this test is to make sure that audio focus works as expected.
- */
- public void testNavExternalNav() throws Exception {
- // android nav
- AudioFocusListener listenerIntNav = new AudioFocusListener();
- AudioAttributes intNavAttributes = mCarAudioManager.getAudioAttributesForCarUsage(
- CarAudioManager.CAR_AUDIO_USAGE_NAVIGATION_GUIDANCE);
- int res = doRequestFocus(mAudioManager, listenerIntNav, intNavAttributes,
- AudioManager.AUDIOFOCUS_GAIN_TRANSIENT_MAY_DUCK);
- assertEquals(AudioManager.AUDIOFOCUS_REQUEST_GRANTED, res);
- int[] request = mAudioFocusPropertyHandler.waitForAudioFocusRequest(TIMEOUT_MS);
- assertEquals(VehicleAudioFocusRequest.REQUEST_GAIN_TRANSIENT_MAY_DUCK,
- request[0]);
- assertEquals(0x2, request[1]);
- assertEquals(0, request[2]);
- assertEquals(VehicleAudioContextFlag.NAVIGATION_FLAG, request[3]);
- assertArrayEquals(new int[] {0, 0, 0, 0},
- mExtRoutingHintPropertyHandler.getLastHint());
- mAudioFocusPropertyHandler.sendAudioFocusState(
- VehicleAudioFocusState.STATE_GAIN,
- request[1],
- VehicleAudioExtFocusFlag.NONE_FLAG);
-
- //external nav
- AudioFocusListener listenerExtNav = new AudioFocusListener();
- AudioAttributes extNavAttributes = mCarAudioManager.getAudioAttributesForExternalSource(
- CarAudioManager.CAR_EXTERNAL_SOURCE_TYPE_EXT_NAV_GUIDANCE);
- res = doRequestFocus(mAudioManager, listenerExtNav,
- extNavAttributes, AudioManager.AUDIOFOCUS_GAIN_TRANSIENT_MAY_DUCK);
- assertEquals(AudioManager.AUDIOFOCUS_REQUEST_GRANTED, res);
- request = mAudioFocusPropertyHandler.waitForAudioFocusRequest(TIMEOUT_MS);
- assertEquals(VehicleAudioFocusRequest.REQUEST_GAIN,
- request[0]);
- assertEquals(0, request[1]);
- assertEquals(VehicleAudioExtFocusFlag.PLAY_ONLY_FLAG,
- request[2]);
- assertEquals(VehicleAudioContextFlag.EXT_SOURCE_FLAG, request[3]);
- assertArrayEquals(new int[] {1<<4, 0, 0, 0},
- mExtRoutingHintPropertyHandler.getLastHint());
- mAudioFocusPropertyHandler.sendAudioFocusState(
- VehicleAudioFocusState.STATE_GAIN,
- 0x1,
- VehicleAudioExtFocusFlag.PLAY_ONLY_FLAG);
-
- mAudioManager.abandonAudioFocus(listenerExtNav);
- request = mAudioFocusPropertyHandler.waitForAudioFocusRequest(TIMEOUT_MS);
- assertEquals(VehicleAudioFocusRequest.REQUEST_GAIN_TRANSIENT_MAY_DUCK,
- request[0]);
- assertEquals(0x2, request[1]);
- assertEquals(0, request[2]);
- assertEquals(VehicleAudioContextFlag.NAVIGATION_FLAG, request[3]);
- assertArrayEquals(new int[] {0, 0, 0, 0},
- mExtRoutingHintPropertyHandler.getLastHint());
- mAudioFocusPropertyHandler.sendAudioFocusState(
- VehicleAudioFocusState.STATE_GAIN,
- request[1],
- VehicleAudioExtFocusFlag.NONE_FLAG);
-
- mAudioManager.abandonAudioFocus(listenerIntNav);
- request = mAudioFocusPropertyHandler.waitForAudioFocusRequest(TIMEOUT_MS);
- assertEquals(VehicleAudioFocusRequest.REQUEST_RELEASE, request[0]);
- assertEquals(0, request[1]);
- assertEquals(0, request[2]);
- assertEquals(0, request[3]);
- assertArrayEquals(new int[] {0, 0, 0, 0},
- mExtRoutingHintPropertyHandler.getLastHint());
- mAudioFocusPropertyHandler.sendAudioFocusState(
- VehicleAudioFocusState.STATE_LOSS,
- 0,
- 0);
- }
-
- public void testMediaExternalRadioNavMediaFocus() throws Exception {
- // android music
- AudioFocusListener listenerMusic = new AudioFocusListener();
- int res = doRequestFocus(mAudioManager, listenerMusic,
- AudioManager.STREAM_MUSIC,
- AudioManager.AUDIOFOCUS_GAIN);
- assertEquals(AudioManager.AUDIOFOCUS_REQUEST_GRANTED, res);
- int[] request = mAudioFocusPropertyHandler.waitForAudioFocusRequest(TIMEOUT_MS);
- assertEquals(VehicleAudioFocusRequest.REQUEST_GAIN, request[0]);
- assertEquals(0x1 << VehicleAudioStream.STREAM0, request[1]);
- assertEquals(0, request[2]);
- assertEquals(VehicleAudioContextFlag.MUSIC_FLAG, request[3]);
- assertArrayEquals(new int[] {0, 0, 0, 0},
- mExtRoutingHintPropertyHandler.getLastHint());
- mAudioFocusPropertyHandler.sendAudioFocusState(
- VehicleAudioFocusState.STATE_GAIN,
- request[1],
- VehicleAudioExtFocusFlag.NONE_FLAG);
-
- // android radio
- AudioFocusListener listenerRadio = new AudioFocusListener();
- CarAudioManager carAudioManager = (CarAudioManager) getCar().getCarManager(
- Car.AUDIO_SERVICE);
- assertNotNull(carAudioManager);
- AudioAttributes radioAttributes = carAudioManager.getAudioAttributesForCarUsage(
- CarAudioManager.CAR_AUDIO_USAGE_RADIO);
- res = doRequestFocus(mAudioManager, listenerRadio,
- radioAttributes, AudioManager.AUDIOFOCUS_GAIN);
- assertEquals(AudioManager.AUDIOFOCUS_REQUEST_GRANTED, res);
- request = mAudioFocusPropertyHandler.waitForAudioFocusRequest(TIMEOUT_MS);
- assertEquals(VehicleAudioFocusRequest.REQUEST_GAIN, request[0]);
- assertEquals(0, request[1]);
- assertEquals(VehicleAudioExtFocusFlag.PLAY_ONLY_FLAG,
- request[2]);
- assertEquals(VehicleAudioContextFlag.RADIO_FLAG, request[3]);
- assertArrayEquals(new int[] {1, 0, 0, 0},
- mExtRoutingHintPropertyHandler.getLastHint());
- mAudioFocusPropertyHandler.sendAudioFocusState(
- VehicleAudioFocusState.STATE_GAIN,
- 0,
- VehicleAudioExtFocusFlag.PLAY_ONLY_FLAG);
-
- // nav guidance start
- AudioFocusListener listenerNav = new AudioFocusListener();
- AudioAttributes navAttrib = (new AudioAttributes.Builder()).
- setContentType(AudioAttributes.CONTENT_TYPE_SONIFICATION).
- setUsage(AudioAttributes.USAGE_ASSISTANCE_NAVIGATION_GUIDANCE).
- build();
- res = doRequestFocus(mAudioManager, listenerNav, navAttrib,
- AudioManager.AUDIOFOCUS_GAIN_TRANSIENT_MAY_DUCK);
- request = mAudioFocusPropertyHandler.waitForAudioFocusRequest(TIMEOUT_MS);
- assertEquals(VehicleAudioFocusRequest.REQUEST_GAIN,
- request[0]);
- assertEquals(0x1 << VehicleAudioStream.STREAM1, request[1]);
- assertEquals(VehicleAudioExtFocusFlag.PLAY_ONLY_FLAG,
- request[2]);
- assertEquals(VehicleAudioContextFlag.NAVIGATION_FLAG |
- VehicleAudioContextFlag.RADIO_FLAG, request[3]);
- assertArrayEquals(new int[] {1, 0, 0, 0},
- mExtRoutingHintPropertyHandler.getLastHint());
- mAudioFocusPropertyHandler.sendAudioFocusState(
- VehicleAudioFocusState.STATE_GAIN,
- 0x1 << VehicleAudioStream.STREAM1,
- VehicleAudioExtFocusFlag.PLAY_ONLY_FLAG);
-
- // nav guidance ends
- mAudioManager.abandonAudioFocus(listenerNav);
- request = mAudioFocusPropertyHandler.waitForAudioFocusRequest(TIMEOUT_MS);
- assertEquals(VehicleAudioFocusRequest.REQUEST_GAIN,
- request[0]);
- assertEquals(0, request[1]);
- assertEquals(VehicleAudioExtFocusFlag.PLAY_ONLY_FLAG,
- request[2]);
- assertEquals(VehicleAudioContextFlag.RADIO_FLAG, request[3]);
- assertArrayEquals(new int[] {1, 0, 0, 0},
- mExtRoutingHintPropertyHandler.getLastHint());
- mAudioFocusPropertyHandler.sendAudioFocusState(
- VehicleAudioFocusState.STATE_GAIN,
- 0,
- VehicleAudioExtFocusFlag.PLAY_ONLY_FLAG);
-
- // ends radio. music will get the focus GAIN.
- // Music app is supposed to stop and release focus when it has lost focus, but here just
- // check if focus is working.
- mAudioManager.abandonAudioFocus(listenerRadio);
- listenerMusic.waitForFocus(TIMEOUT_MS, AudioManager.AUDIOFOCUS_GAIN);
- request = mAudioFocusPropertyHandler.waitForAudioFocusRequest(TIMEOUT_MS);
- assertEquals(VehicleAudioFocusRequest.REQUEST_GAIN, request[0]);
- assertEquals(0x1 << VehicleAudioStream.STREAM0, request[1]);
- assertEquals(0, request[2]);
- assertEquals(VehicleAudioContextFlag.MUSIC_FLAG, request[3]);
- assertArrayEquals(new int[] {0, 0, 0, 0},
- mExtRoutingHintPropertyHandler.getLastHint());
- mAudioFocusPropertyHandler.sendAudioFocusState(
- VehicleAudioFocusState.STATE_GAIN,
- 0x1 << VehicleAudioStream.STREAM0,
- 0);
-
- // now music release focus.
- mAudioManager.abandonAudioFocus(listenerMusic);
- request = mAudioFocusPropertyHandler.waitForAudioFocusRequest(TIMEOUT_MS);
- assertEquals(VehicleAudioFocusRequest.REQUEST_RELEASE, request[0]);
- assertEquals(0, request[1]);
- assertEquals(0, request[2]);
- assertEquals(0, request[3]);
- assertArrayEquals(new int[] {0, 0, 0, 0},
- mExtRoutingHintPropertyHandler.getLastHint());
- mAudioFocusPropertyHandler.sendAudioFocusState(
- VehicleAudioFocusState.STATE_LOSS,
- 0,
- VehicleAudioExtFocusFlag.NONE_FLAG);
- }
-
- private void checkSingleRequestRelease(AudioAttributes attrb, int androidFocusToRequest,
- int[] expectedExtRouting, int expectedStreams,
- int expectedExtState, int expectedContexts) throws Exception {
- AudioFocusListener lister = new AudioFocusListener();
- int res = mCarAudioManager.requestAudioFocus(lister, attrb, androidFocusToRequest, 0);
- assertEquals(AudioManager.AUDIOFOCUS_REQUEST_GRANTED, res);
- int[] request = mAudioFocusPropertyHandler.waitForAudioFocusRequest(TIMEOUT_MS);
- int expectedFocusRequest = VehicleAudioFocusRequest.REQUEST_RELEASE;
- int response = VehicleAudioFocusState.STATE_LOSS;
- switch (androidFocusToRequest) {
- case AudioManager.AUDIOFOCUS_GAIN:
- expectedFocusRequest = VehicleAudioFocusRequest.REQUEST_GAIN;
- response = VehicleAudioFocusState.STATE_GAIN;
- break;
- case AudioManager.AUDIOFOCUS_GAIN_TRANSIENT:
- expectedFocusRequest =
- VehicleAudioFocusRequest.REQUEST_GAIN_TRANSIENT;
- response = VehicleAudioFocusState.STATE_GAIN_TRANSIENT;
- break;
- case AudioManager.AUDIOFOCUS_GAIN_TRANSIENT_MAY_DUCK:
- expectedFocusRequest =
- VehicleAudioFocusRequest.REQUEST_GAIN_TRANSIENT_MAY_DUCK;
- response = VehicleAudioFocusState.STATE_GAIN_TRANSIENT;
- break;
- }
- assertEquals(expectedFocusRequest, request[0]);
- assertEquals(expectedStreams, request[1]);
- assertEquals(expectedExtState, request[2]);
- assertEquals(expectedContexts, request[3]);
- assertArrayEquals(expectedExtRouting, mExtRoutingHintPropertyHandler.getLastHint());
- mAudioFocusPropertyHandler.sendAudioFocusState(
- response,
- request[1],
- VehicleAudioExtFocusFlag.NONE_FLAG);
- mAudioManager.abandonAudioFocus(lister);
- request = mAudioFocusPropertyHandler.waitForAudioFocusRequest(TIMEOUT_MS);
- assertEquals(VehicleAudioFocusRequest.REQUEST_RELEASE, request[0]);
- assertEquals(0, request[1]);
- assertEquals(0, request[2]);
- assertEquals(0, request[3]);
- assertArrayEquals(new int[] {0, 0, 0, 0},
- mExtRoutingHintPropertyHandler.getLastHint());
- mAudioFocusPropertyHandler.sendAudioFocusState(
- VehicleAudioFocusState.STATE_LOSS,
- request[1],
- VehicleAudioExtFocusFlag.NONE_FLAG);
- }
-
- public void testRadioMute() throws Exception {
- testMediaMute(CarAudioManager.CAR_AUDIO_USAGE_RADIO,
- 0,
- VehicleAudioExtFocusFlag.PLAY_ONLY_FLAG,
- VehicleAudioContextFlag.RADIO_FLAG);
- }
-
- public void testMusicMute() throws Exception {
- testMediaMute(CarAudioManager.CAR_AUDIO_USAGE_MUSIC,
- 0x1,
- 0,
- VehicleAudioContextFlag.MUSIC_FLAG);
- }
-
- private void testMediaMute(int mediaUsage, int primaryStream, int extFocusFlag,
- int mediaContext) throws Exception {
- // android radio
- AudioFocusListener listenerMedia = new AudioFocusListener();
- CarAudioManager carAudioManager = (CarAudioManager) getCar().getCarManager(
- Car.AUDIO_SERVICE);
- assertNotNull(carAudioManager);
- AudioAttributes radioAttributes = carAudioManager.getAudioAttributesForCarUsage(mediaUsage);
- Log.i(TAG, "request media Focus");
- int res = doRequestFocus(mAudioManager, listenerMedia,
- radioAttributes, AudioManager.AUDIOFOCUS_GAIN);
- assertEquals(AudioManager.AUDIOFOCUS_REQUEST_GRANTED, res);
- int[] request = mAudioFocusPropertyHandler.waitForAudioFocusRequest(TIMEOUT_MS);
- assertEquals(VehicleAudioFocusRequest.REQUEST_GAIN, request[0]);
- assertEquals(primaryStream, request[1]);
- assertEquals(extFocusFlag, request[2]);
- assertEquals(mediaContext, request[3]);
- if (mediaUsage == CarAudioManager.CAR_AUDIO_USAGE_RADIO) {
- assertArrayEquals(new int[] {1, 0, 0, 0},
- mExtRoutingHintPropertyHandler.getLastHint());
- } else {
- assertArrayEquals(new int[] {0, 0, 0, 0},
- mExtRoutingHintPropertyHandler.getLastHint());
- }
- mAudioFocusPropertyHandler.sendAudioFocusState(
- VehicleAudioFocusState.STATE_GAIN,
- primaryStream,
- extFocusFlag);
- // now mute it.
- assertFalse(carAudioManager.isMediaMuted());
- Log.i(TAG, "mute media");
- assertTrue(carAudioManager.setMediaMute(true));
- request = mAudioFocusPropertyHandler.waitForAudioFocusRequest(TIMEOUT_MS);
- assertEquals(VehicleAudioFocusRequest.REQUEST_GAIN_TRANSIENT,
- request[0]);
- assertEquals(0, request[1]);
- assertEquals(VehicleAudioExtFocusFlag.MUTE_MEDIA_FLAG,
- request[2]);
- assertEquals(0, request[3]);
- assertArrayEquals(new int[] {0, 0, 0, 0},
- mExtRoutingHintPropertyHandler.getLastHint());
- mAudioFocusPropertyHandler.sendAudioFocusState(
- VehicleAudioFocusState.STATE_GAIN,
- 0,
- VehicleAudioExtFocusFlag.MUTE_MEDIA_FLAG);
- assertTrue(carAudioManager.isMediaMuted());
- // nav guidance on top of it
- AudioFocusListener listenerNav = new AudioFocusListener();
- AudioAttributes navAttrib = (new AudioAttributes.Builder()).
- setContentType(AudioAttributes.CONTENT_TYPE_SONIFICATION).
- setUsage(AudioAttributes.USAGE_ASSISTANCE_NAVIGATION_GUIDANCE).
- build();
- Log.i(TAG, "request nav Focus");
- res = doRequestFocus(mAudioManager, listenerNav, navAttrib,
- AudioManager.AUDIOFOCUS_GAIN_TRANSIENT_MAY_DUCK);
- request = mAudioFocusPropertyHandler.waitForAudioFocusRequest(TIMEOUT_MS);
- assertEquals(VehicleAudioFocusRequest.REQUEST_GAIN_TRANSIENT_MAY_DUCK,
- request[0]);
- assertEquals(0x1 << VehicleAudioStream.STREAM1, request[1]);
- assertEquals(VehicleAudioExtFocusFlag.MUTE_MEDIA_FLAG,
- request[2]);
- assertEquals(VehicleAudioContextFlag.NAVIGATION_FLAG, request[3]);
- assertArrayEquals(new int[] {0, 0, 0, 0},
- mExtRoutingHintPropertyHandler.getLastHint());
- assertTrue(carAudioManager.isMediaMuted());
- mAudioFocusPropertyHandler.sendAudioFocusState(
- VehicleAudioFocusState.STATE_GAIN,
- 0x1 << VehicleAudioStream.STREAM1,
- VehicleAudioExtFocusFlag.MUTE_MEDIA_FLAG);
- assertTrue(carAudioManager.isMediaMuted());
- // nav guidance ends
- mAudioManager.abandonAudioFocus(listenerNav);
- request = mAudioFocusPropertyHandler.waitForAudioFocusRequest(TIMEOUT_MS);
- assertEquals(VehicleAudioFocusRequest.REQUEST_GAIN_TRANSIENT,
- request[0]);
- assertEquals(0, request[1]);
- assertEquals(VehicleAudioExtFocusFlag.MUTE_MEDIA_FLAG,
- request[2]);
- assertEquals(0, request[3]);
- assertArrayEquals(new int[] {0, 0, 0, 0},
- mExtRoutingHintPropertyHandler.getLastHint());
- assertTrue(carAudioManager.isMediaMuted());
- mAudioFocusPropertyHandler.sendAudioFocusState(
- VehicleAudioFocusState.STATE_GAIN,
- 0,
- VehicleAudioExtFocusFlag.MUTE_MEDIA_FLAG);
- // now unmute it. media should resume.
- assertTrue(carAudioManager.isMediaMuted());
- assertFalse(carAudioManager.setMediaMute(false));
- assertFalse(carAudioManager.isMediaMuted());
- request = mAudioFocusPropertyHandler.waitForAudioFocusRequest(TIMEOUT_MS);
- assertEquals(VehicleAudioFocusRequest.REQUEST_GAIN, request[0]);
- assertEquals(primaryStream, request[1]);
- assertEquals(extFocusFlag,
- request[2]);
- assertEquals(mediaContext, request[3]);
- if (mediaUsage == CarAudioManager.CAR_AUDIO_USAGE_RADIO) {
- assertArrayEquals(new int[] {1, 0, 0, 0},
- mExtRoutingHintPropertyHandler.getLastHint());
- } else {
- assertArrayEquals(new int[] {0, 0, 0, 0},
- mExtRoutingHintPropertyHandler.getLastHint());
- }
- assertFalse(carAudioManager.isMediaMuted());
- mAudioFocusPropertyHandler.sendAudioFocusState(
- VehicleAudioFocusState.STATE_GAIN,
- primaryStream,
- extFocusFlag);
- assertFalse(carAudioManager.isMediaMuted());
- // release focus
- mAudioManager.abandonAudioFocus(listenerMedia);
- }
-
- protected static class AudioFocusListener implements AudioManager.OnAudioFocusChangeListener {
- private final Semaphore mFocusChangeWait = new Semaphore(0);
- private int mLastFocusChange;
-
- public int waitAndGetFocusChange(long timeoutMs) throws Exception {
- if (!mFocusChangeWait.tryAcquire(timeoutMs, TimeUnit.MILLISECONDS)) {
- fail("timeout waiting for focus change");
- }
- return mLastFocusChange;
- }
-
- public void waitForFocus(long timeoutMs, int expectedFocus) throws Exception {
- while (mLastFocusChange != expectedFocus) {
- if (!mFocusChangeWait.tryAcquire(timeoutMs, TimeUnit.MILLISECONDS)) {
- fail("timeout waiting for focus change");
- }
- }
- }
-
- @Override
- public void onAudioFocusChange(int focusChange) {
- mLastFocusChange = focusChange;
- mFocusChangeWait.release();
- }
- }
-
- protected static class FocusPropertyHandler implements VehicleHalPropertyHandler {
-
- private int mState = VehicleAudioFocusState.STATE_LOSS;
- private int mStreams = 0;
- private int mExtFocus = 0;
- private int mRequest;
- private int mRequestedStreams;
- private int mRequestedExtFocus;
- private int mRequestedAudioContexts;
- private final MockedCarTestBase mCarTest;
-
- private final Semaphore mSetWaitSemaphore = new Semaphore(0);
-
- public FocusPropertyHandler(MockedCarTestBase carTest) {
- mCarTest = carTest;
- }
-
- public void sendAudioFocusState(int state, int streams, int extFocus) {
- synchronized (this) {
- mState = state;
- mStreams = streams;
- mExtFocus = extFocus;
- }
- mCarTest.getMockedVehicleHal().injectEvent(
- VehiclePropValueBuilder.newBuilder(VehicleProperty.AUDIO_FOCUS)
- .setTimestamp(SystemClock.elapsedRealtimeNanos())
- .addIntValue(state, streams, extFocus, 0)
- .build());
- }
-
- public int[] waitForAudioFocusRequest(long timeoutMs) throws Exception {
- if (!mSetWaitSemaphore.tryAcquire(timeoutMs, TimeUnit.MILLISECONDS)) {
- fail("timeout");
- }
- synchronized (this) {
- return new int[] { mRequest, mRequestedStreams, mRequestedExtFocus,
- mRequestedAudioContexts };
- }
- }
-
- @Override
- public void onPropertySet(VehiclePropValue value) {
- Log.i(TAG, "onPropertySet, prop: 0x" + toHexString(value.prop));
- assertEquals(AUDIO_FOCUS, value.prop);
- ArrayList<Integer> v = value.value.int32Values;
- synchronized (this) {
- mRequest = v.get(VehicleAudioFocusIndex.FOCUS);
- mRequestedStreams = v.get(VehicleAudioFocusIndex.STREAMS);
- mRequestedExtFocus = v.get(VehicleAudioFocusIndex.EXTERNAL_FOCUS_STATE);
- mRequestedAudioContexts = v.get(VehicleAudioFocusIndex.AUDIO_CONTEXTS);
- }
- Log.i(TAG, "onPropertySet, values: " + Arrays.toString(v.toArray()));
- mSetWaitSemaphore.release();
- }
-
- @Override
- public VehiclePropValue onPropertyGet(VehiclePropValue value) {
- assertEquals(AUDIO_FOCUS, value.prop);
- int state, streams, extFocus;
- synchronized (this) {
- state = mState;
- streams = mStreams;
- extFocus = mExtFocus;
- }
- return VehiclePropValueBuilder.newBuilder(VehicleProperty.AUDIO_FOCUS)
- .setTimestamp(SystemClock.elapsedRealtimeNanos())
- .addIntValue(state, streams, extFocus, 0)
- .build();
- }
-
- @Override
- public void onPropertySubscribe(int property, int zones, float sampleRate) {
- assertEquals(AUDIO_FOCUS, property);
- }
-
- @Override
- public void onPropertyUnsubscribe(int property) {
- assertEquals(AUDIO_FOCUS, property);
- }
- }
-
- private static class ExtRoutingHintPropertyHandler extends FailingPropertyHandler {
- private int[] mLastHint = {0, 0, 0, 0};
-
- public int[] getLastHint() {
- int[] lastHint = new int[mLastHint.length];
- synchronized (this) {
- System.arraycopy(mLastHint, 0, lastHint, 0, mLastHint.length);
- }
- return lastHint;
- }
-
- @Override
- public void onPropertySet(VehiclePropValue value) {
- assertEquals(VehicleProperty.AUDIO_EXT_ROUTING_HINT, value.prop);
- assertEquals(mLastHint.length, value.value.int32Values.size());
- synchronized (this) {
- for (int i = 0; i < mLastHint.length; i++) {
- mLastHint[i] = value.value.int32Values.get(i);
- }
- }
- }
- }
-}
diff --git a/tests/carservice_test/src/com/android/car/test/CarAudioFocusSystemSoundTest.java b/tests/carservice_test/src/com/android/car/test/CarAudioFocusSystemSoundTest.java
deleted file mode 100644
index afafb28..0000000
--- a/tests/carservice_test/src/com/android/car/test/CarAudioFocusSystemSoundTest.java
+++ /dev/null
@@ -1,394 +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.test;
-
-import static android.hardware.automotive.vehicle.V2_0.VehicleProperty.AUDIO_FOCUS;
-import static android.hardware.automotive.vehicle.V2_0.VehicleProperty.AUDIO_STREAM_STATE;
-import static com.android.car.test.AudioTestUtils.doRequestFocus;
-
-import com.google.android.collect.Lists;
-
-import android.car.Car;
-import android.car.media.CarAudioManager;
-import android.content.Context;
-import android.hardware.automotive.vehicle.V2_0.VehicleAudioContextFlag;
-import android.hardware.automotive.vehicle.V2_0.VehicleAudioExtFocusFlag;
-import android.hardware.automotive.vehicle.V2_0.VehicleAudioFocusIndex;
-import android.hardware.automotive.vehicle.V2_0.VehicleAudioFocusRequest;
-import android.hardware.automotive.vehicle.V2_0.VehicleAudioFocusState;
-import android.hardware.automotive.vehicle.V2_0.VehicleAudioStream;
-import android.hardware.automotive.vehicle.V2_0.VehiclePropValue;
-import android.hardware.automotive.vehicle.V2_0.VehicleProperty;
-import android.hardware.automotive.vehicle.V2_0.VehiclePropertyAccess;
-import android.media.AudioAttributes;
-import android.media.AudioManager;
-import android.os.SystemClock;
-import android.test.suitebuilder.annotation.MediumTest;
-
-import com.android.car.vehiclehal.VehiclePropValueBuilder;
-import com.android.car.vehiclehal.test.MockedVehicleHal.FailingPropertyHandler;
-import com.android.car.vehiclehal.test.MockedVehicleHal.VehicleHalPropertyHandler;
-
-import java.util.ArrayList;
-import java.util.concurrent.Semaphore;
-import java.util.concurrent.TimeUnit;
-
-/**
- * Test to check if system sound can be played without having focus.
- */
-@MediumTest
-public class CarAudioFocusSystemSoundTest extends MockedCarTestBase {
- private static final String TAG = CarAudioFocusTest.class.getSimpleName();
-
- private static final long TIMEOUT_MS = 3000;
-
- private final VehicleHalPropertyHandler mAudioRoutingPolicyPropertyHandler =
- new FailingPropertyHandler() {
- @Override
- public void onPropertySet(VehiclePropValue value) {
- //TODO
- }
- };
-
- private final FocusPropertyHandler mAudioFocusPropertyHandler =
- new FocusPropertyHandler(this);
-
- private AudioManager mAudioManager;
-
- @Override
- protected synchronized void configureMockedHal() {
- addProperty(VehicleProperty.AUDIO_ROUTING_POLICY, mAudioRoutingPolicyPropertyHandler)
- .setAccess(VehiclePropertyAccess.WRITE);
- addProperty(VehicleProperty.AUDIO_FOCUS, mAudioFocusPropertyHandler);
- addProperty(VehicleProperty.AUDIO_STREAM_STATE);
-
-
- addStaticProperty(VehicleProperty.AUDIO_HW_VARIANT,
- VehiclePropValueBuilder.newBuilder(VehicleProperty.AUDIO_HW_VARIANT)
- .addIntValue(-1)
- .build())
- .setConfigArray(Lists.newArrayList(0));
- }
-
- @Override
- protected void setUp() throws Exception {
- super.setUp();
- // AudioManager should be created in main thread to get focus event. :(
- runOnMainSync(new Runnable() {
- @Override
- public void run() {
- mAudioManager = (AudioManager) mContext.getSystemService(Context.AUDIO_SERVICE);
- }
- });
- }
-
- private void notifyStreamState(int streamNumber, boolean active) {
- getMockedVehicleHal().injectEvent(VehiclePropValueBuilder.newBuilder(AUDIO_STREAM_STATE)
- .setTimestamp()
- .addIntValue(new int[] { active ? 1 : 0, streamNumber })
- .build());
- }
-
- public void testSystemSoundPlayStop() throws Exception {
- //system sound start
- notifyStreamState(1, true);
- int[] request = mAudioFocusPropertyHandler.waitForAudioFocusRequest(TIMEOUT_MS);
- assertEquals(VehicleAudioFocusRequest.REQUEST_GAIN_TRANSIENT_NO_DUCK,
- request[0]);
- assertEquals(0x2, request[1]);
- assertEquals(0, request[2]);
- assertEquals(VehicleAudioContextFlag.SYSTEM_SOUND_FLAG, request[3]);
- mAudioFocusPropertyHandler.sendAudioFocusState(
- VehicleAudioFocusState.STATE_GAIN_TRANSIENT,
- request[1],
- VehicleAudioExtFocusFlag.NONE_FLAG);
- // system sound stop
- notifyStreamState(1, false);
- request = mAudioFocusPropertyHandler.waitForAudioFocusRequest(TIMEOUT_MS);
- assertEquals(VehicleAudioFocusRequest.REQUEST_RELEASE,
- request[0]);
- assertEquals(0, request[1]);
- assertEquals(0, request[2]);
- assertEquals(0, request[3]);
- mAudioFocusPropertyHandler.sendAudioFocusState(
- VehicleAudioFocusState.STATE_LOSS,
- request[1],
- VehicleAudioExtFocusFlag.NONE_FLAG);
- }
-
- public void testRadioSystemSound() throws Exception {
- // radio start
- AudioFocusListener listenerRadio = new AudioFocusListener();
- CarAudioManager carAudioManager = (CarAudioManager) getCar().getCarManager(
- Car.AUDIO_SERVICE);
- assertNotNull(carAudioManager);
- AudioAttributes radioAttributes = carAudioManager.getAudioAttributesForCarUsage(
- CarAudioManager.CAR_AUDIO_USAGE_RADIO);
- int res = doRequestFocus(mAudioManager, listenerRadio,
- radioAttributes, AudioManager.AUDIOFOCUS_GAIN);
- assertEquals(AudioManager.AUDIOFOCUS_REQUEST_GRANTED, res);
- int[] request = mAudioFocusPropertyHandler.waitForAudioFocusRequest(TIMEOUT_MS);
- assertEquals(VehicleAudioFocusRequest.REQUEST_GAIN, request[0]);
- assertEquals(0, request[1]);
- assertEquals(VehicleAudioExtFocusFlag.PLAY_ONLY_FLAG,
- request[2]);
- assertEquals(VehicleAudioContextFlag.RADIO_FLAG, request[3]);
- mAudioFocusPropertyHandler.sendAudioFocusState(
- VehicleAudioFocusState.STATE_GAIN,
- 0,
- VehicleAudioExtFocusFlag.PLAY_ONLY_FLAG);
- // system sound start
- notifyStreamState(1, true);
- request = mAudioFocusPropertyHandler.waitForAudioFocusRequest(TIMEOUT_MS);
- assertEquals(VehicleAudioFocusRequest.REQUEST_GAIN, request[0]);
- assertEquals(0x2, request[1]);
- assertEquals(VehicleAudioExtFocusFlag.PLAY_ONLY_FLAG,
- request[2]);
- assertEquals(VehicleAudioContextFlag.RADIO_FLAG |
- VehicleAudioContextFlag.SYSTEM_SOUND_FLAG, request[3]);
- mAudioFocusPropertyHandler.sendAudioFocusState(
- VehicleAudioFocusState.STATE_GAIN,
- request[1],
- VehicleAudioExtFocusFlag.PLAY_ONLY_FLAG);
- // system sound stop
- notifyStreamState(1, false);
- request = mAudioFocusPropertyHandler.waitForAudioFocusRequest(TIMEOUT_MS);
- assertEquals(VehicleAudioFocusRequest.REQUEST_GAIN, request[0]);
- assertEquals(0, request[1]);
- assertEquals(VehicleAudioExtFocusFlag.PLAY_ONLY_FLAG,
- request[2]);
- assertEquals(VehicleAudioContextFlag.RADIO_FLAG, request[3]);
- mAudioFocusPropertyHandler.sendAudioFocusState(
- VehicleAudioFocusState.STATE_GAIN,
- 0,
- VehicleAudioExtFocusFlag.PLAY_ONLY_FLAG);
- // radio stop
- mAudioManager.abandonAudioFocus(listenerRadio);
- request = mAudioFocusPropertyHandler.waitForAudioFocusRequest(TIMEOUT_MS);
- assertEquals(VehicleAudioFocusRequest.REQUEST_RELEASE, request[0]);
- assertEquals(0, request[1]);
- assertEquals(0, request[2]);
- assertEquals(0, request[3]);
- mAudioFocusPropertyHandler.sendAudioFocusState(
- VehicleAudioFocusState.STATE_LOSS,
- request[1],
- VehicleAudioExtFocusFlag.NONE_FLAG);
- }
-
- public void testMusicSystemSound() throws Exception {
- // music start
- AudioFocusListener listenerMusic = new AudioFocusListener();
- int res = doRequestFocus(mAudioManager, listenerMusic,
- AudioManager.STREAM_MUSIC,
- AudioManager.AUDIOFOCUS_GAIN);
- assertEquals(AudioManager.AUDIOFOCUS_REQUEST_GRANTED, res);
- int[] request = mAudioFocusPropertyHandler.waitForAudioFocusRequest(TIMEOUT_MS);
- assertEquals(VehicleAudioFocusRequest.REQUEST_GAIN, request[0]);
- assertEquals(0x1 << VehicleAudioStream.STREAM0, request[1]);
- assertEquals(0, request[2]);
- assertEquals(VehicleAudioContextFlag.MUSIC_FLAG, request[3]);
- mAudioFocusPropertyHandler.sendAudioFocusState(
- VehicleAudioFocusState.STATE_GAIN,
- request[1],
- VehicleAudioExtFocusFlag.NONE_FLAG);
- // system sound start
- notifyStreamState(1, true);
- request = mAudioFocusPropertyHandler.waitForAudioFocusRequest(TIMEOUT_MS);
- assertEquals(VehicleAudioFocusRequest.REQUEST_GAIN, request[0]);
- assertEquals(0x1 | 0x2, request[1]);
- assertEquals(0, request[2]);
- assertEquals(VehicleAudioContextFlag.MUSIC_FLAG |
- VehicleAudioContextFlag.SYSTEM_SOUND_FLAG, request[3]);
- mAudioFocusPropertyHandler.sendAudioFocusState(
- VehicleAudioFocusState.STATE_GAIN,
- request[1],
- VehicleAudioExtFocusFlag.NONE_FLAG);
- // system sound stop
- notifyStreamState(1, false);
- request = mAudioFocusPropertyHandler.waitForAudioFocusRequest(TIMEOUT_MS);
- assertEquals(VehicleAudioFocusRequest.REQUEST_GAIN, request[0]);
- assertEquals(0x1 << VehicleAudioStream.STREAM0, request[1]);
- assertEquals(0, request[2]);
- assertEquals(VehicleAudioContextFlag.MUSIC_FLAG, request[3]);
- mAudioFocusPropertyHandler.sendAudioFocusState(
- VehicleAudioFocusState.STATE_GAIN,
- request[1],
- VehicleAudioExtFocusFlag.NONE_FLAG);
- // music stop
- mAudioManager.abandonAudioFocus(listenerMusic);
- request = mAudioFocusPropertyHandler.waitForAudioFocusRequest(TIMEOUT_MS);
- assertEquals(VehicleAudioFocusRequest.REQUEST_RELEASE, request[0]);
- assertEquals(0, request[1]);
- assertEquals(0, request[2]);
- assertEquals(0, request[3]);
- mAudioFocusPropertyHandler.sendAudioFocusState(
- VehicleAudioFocusState.STATE_LOSS,
- request[1],
- VehicleAudioExtFocusFlag.NONE_FLAG);
- }
-
- public void testNavigationSystemSound() throws Exception {
- // nav guidance start
- AudioFocusListener listenerNav = new AudioFocusListener();
- AudioAttributes navAttrib = (new AudioAttributes.Builder()).
- setContentType(AudioAttributes.CONTENT_TYPE_SONIFICATION).
- setUsage(AudioAttributes.USAGE_ASSISTANCE_NAVIGATION_GUIDANCE).
- build();
- int res = doRequestFocus(mAudioManager, listenerNav, navAttrib,
- AudioManager.AUDIOFOCUS_GAIN_TRANSIENT_MAY_DUCK);
- assertEquals(AudioManager.AUDIOFOCUS_REQUEST_GRANTED, res);
- int[] request = mAudioFocusPropertyHandler.waitForAudioFocusRequest(TIMEOUT_MS);
- assertEquals(VehicleAudioFocusRequest.REQUEST_GAIN_TRANSIENT_MAY_DUCK,
- request[0]);
- assertEquals(0x2, request[1]);
- assertEquals(0, request[2]);
- assertEquals(VehicleAudioContextFlag.NAVIGATION_FLAG, request[3]);
- mAudioFocusPropertyHandler.sendAudioFocusState(
- VehicleAudioFocusState.STATE_GAIN_TRANSIENT,
- request[1],
- VehicleAudioExtFocusFlag.NONE_FLAG);
- // system sound start
- notifyStreamState(1, true);
- // cannot distinguish this case from nav only. so no focus change.
- mAudioFocusPropertyHandler.assertNoFocusRequest(1000);
- // cannot distinguish this case from nav only. so no focus change.
- notifyStreamState(1, false);
- mAudioFocusPropertyHandler.assertNoFocusRequest(1000);
- // nav guidance stop
- mAudioManager.abandonAudioFocus(listenerNav);
- request = mAudioFocusPropertyHandler.waitForAudioFocusRequest(TIMEOUT_MS);
- assertEquals(VehicleAudioFocusRequest.REQUEST_RELEASE, request[0]);
- assertEquals(0, request[1]);
- assertEquals(0, request[2]);
- assertEquals(0, request[3]);
- mAudioFocusPropertyHandler.sendAudioFocusState(
- VehicleAudioFocusState.STATE_LOSS,
- request[1],
- VehicleAudioExtFocusFlag.NONE_FLAG);
- }
-
- private static class AudioFocusListener implements AudioManager.OnAudioFocusChangeListener {
- private final Semaphore mFocusChangeWait = new Semaphore(0);
- private int mLastFocusChange;
-
- // TODO: not used?
- public int waitAndGetFocusChange(long timeoutMs) throws Exception {
- if (!mFocusChangeWait.tryAcquire(timeoutMs, TimeUnit.MILLISECONDS)) {
- fail("timeout waiting for focus change");
- }
- return mLastFocusChange;
- }
-
- public void waitForFocus(long timeoutMs, int expectedFocus) throws Exception {
- while (mLastFocusChange != expectedFocus) {
- if (!mFocusChangeWait.tryAcquire(timeoutMs, TimeUnit.MILLISECONDS)) {
- fail("timeout waiting for focus change");
- }
- }
- }
-
- @Override
- public void onAudioFocusChange(int focusChange) {
- mLastFocusChange = focusChange;
- mFocusChangeWait.release();
- }
- }
-
- private static class FocusPropertyHandler implements VehicleHalPropertyHandler {
-
- private int mState = VehicleAudioFocusState.STATE_LOSS;
- private int mStreams = 0;
- private int mExtFocus = 0;
- private int mRequest;
- private int mRequestedStreams;
- private int mRequestedExtFocus;
- private int mRequestedAudioContexts;
- private final MockedCarTestBase mCarTest;
-
- private final Semaphore mSetWaitSemaphore = new Semaphore(0);
-
- FocusPropertyHandler(MockedCarTestBase carTest) {
- mCarTest = carTest;
- }
-
- void sendAudioFocusState(int state, int streams, int extFocus) {
- synchronized (this) {
- mState = state;
- mStreams = streams;
- mExtFocus = extFocus;
- }
- mCarTest.getMockedVehicleHal().injectEvent(
- VehiclePropValueBuilder.newBuilder(AUDIO_FOCUS)
- .setTimestamp(SystemClock.elapsedRealtimeNanos())
- .addIntValue(state, streams, extFocus, 0)
- .build());
- }
-
- int[] waitForAudioFocusRequest(long timeoutMs) throws Exception {
- if (!mSetWaitSemaphore.tryAcquire(timeoutMs, TimeUnit.MILLISECONDS)) {
- fail("timeout");
- }
- synchronized (this) {
- return new int[] { mRequest, mRequestedStreams, mRequestedExtFocus,
- mRequestedAudioContexts };
- }
- }
-
- void assertNoFocusRequest(long timeoutMs) throws Exception {
- if (mSetWaitSemaphore.tryAcquire(timeoutMs, TimeUnit.MILLISECONDS)) {
- fail("should not get focus request");
- }
- }
-
- @Override
- public void onPropertySet(VehiclePropValue value) {
- assertEquals(AUDIO_FOCUS, value.prop);
- ArrayList<Integer> v = value.value.int32Values;
- synchronized (this) {
- mRequest = v.get(VehicleAudioFocusIndex.FOCUS);
- mRequestedStreams = v.get(VehicleAudioFocusIndex.STREAMS);
- mRequestedExtFocus = v.get(VehicleAudioFocusIndex.EXTERNAL_FOCUS_STATE);
- mRequestedAudioContexts = v.get(VehicleAudioFocusIndex.AUDIO_CONTEXTS);
- }
- mSetWaitSemaphore.release();
- }
-
- @Override
- public VehiclePropValue onPropertyGet(VehiclePropValue value) {
- assertEquals(VehicleProperty.AUDIO_FOCUS, value.prop);
- int state, streams, extFocus;
- synchronized (this) {
- state = mState;
- streams = mStreams;
- extFocus = mExtFocus;
- }
- return VehiclePropValueBuilder.newBuilder(AUDIO_FOCUS)
- .setTimestamp(SystemClock.elapsedRealtimeNanos())
- .addIntValue(state, streams, extFocus, 0)
- .build();
- }
-
- @Override
- public void onPropertySubscribe(int property, int zones, float sampleRate) {
- assertEquals(VehicleProperty.AUDIO_FOCUS, property);
- }
-
- @Override
- public void onPropertyUnsubscribe(int property) {
- assertEquals(VehicleProperty.AUDIO_FOCUS, property);
- }
- }
-}
diff --git a/tests/carservice_test/src/com/android/car/test/CarAudioFocusTest.java b/tests/carservice_test/src/com/android/car/test/CarAudioFocusTest.java
deleted file mode 100644
index 6f5da5f..0000000
--- a/tests/carservice_test/src/com/android/car/test/CarAudioFocusTest.java
+++ /dev/null
@@ -1,618 +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.test;
-
-import static android.hardware.automotive.vehicle.V2_0.VehicleProperty.AUDIO_FOCUS;
-import static com.android.car.test.AudioTestUtils.doRequestFocus;
-
-import android.car.Car;
-import android.car.media.CarAudioManager;
-import android.content.Context;
-import android.hardware.automotive.vehicle.V2_0.VehicleAudioContextFlag;
-import android.hardware.automotive.vehicle.V2_0.VehicleAudioExtFocusFlag;
-import android.hardware.automotive.vehicle.V2_0.VehicleAudioFocusIndex;
-import android.hardware.automotive.vehicle.V2_0.VehicleAudioFocusRequest;
-import android.hardware.automotive.vehicle.V2_0.VehicleAudioFocusState;
-import android.hardware.automotive.vehicle.V2_0.VehicleAudioStream;
-import android.hardware.automotive.vehicle.V2_0.VehiclePropValue;
-import android.hardware.automotive.vehicle.V2_0.VehicleProperty;
-import android.hardware.automotive.vehicle.V2_0.VehiclePropertyAccess;
-import android.media.AudioAttributes;
-import android.media.AudioManager;
-import android.os.SystemClock;
-import android.test.suitebuilder.annotation.MediumTest;
-import android.util.Log;
-
-import com.google.android.collect.Lists;
-
-import com.android.car.vehiclehal.VehiclePropValueBuilder;
-import com.android.car.vehiclehal.test.MockedVehicleHal.FailingPropertyHandler;
-import com.android.car.vehiclehal.test.MockedVehicleHal.VehicleHalPropertyHandler;
-
-import java.util.ArrayList;
-import java.util.concurrent.Semaphore;
-import java.util.concurrent.TimeUnit;
-
-// TODO: refactor all CarAudio*Test classes, they have a lot of common logic.
-@MediumTest
-public class CarAudioFocusTest extends MockedCarTestBase {
- private static final String TAG = CarAudioFocusTest.class.getSimpleName();
-
- private static final long TIMEOUT_MS = 3000;
-
- private final VehicleHalPropertyHandler mAudioRoutingPolicyPropertyHandler =
- new FailingPropertyHandler() {
- @Override
- public void onPropertySet(VehiclePropValue value) {
- //TODO
- }
- };
-
- private final FocusPropertyHandler mAudioFocusPropertyHandler =
- new FocusPropertyHandler(this);
-
- private AudioManager mAudioManager;
-
- @Override
- protected synchronized void configureMockedHal() {
- addProperty(VehicleProperty.AUDIO_ROUTING_POLICY, mAudioRoutingPolicyPropertyHandler)
- .setAccess(VehiclePropertyAccess.WRITE);
-
- addProperty(VehicleProperty.AUDIO_FOCUS, mAudioFocusPropertyHandler);
-
- addStaticProperty(VehicleProperty.AUDIO_HW_VARIANT,
- VehiclePropValueBuilder.newBuilder(VehicleProperty.AUDIO_HW_VARIANT)
- .addIntValue(-1)
- .build())
- .setConfigArray(Lists.newArrayList(0));
- }
-
- @Override
- protected void setUp() throws Exception {
- super.setUp();
- // AudioManager should be created in main thread to get focus event. :(
- runOnMainSync(new Runnable() {
- @Override
- public void run() {
- mAudioManager = (AudioManager) mContext.getSystemService(Context.AUDIO_SERVICE);
- }
- });
- }
-
- public void testMediaGainFocus() throws Exception {
- //TODO update this to check config
- checkSingleRequestRelease(
- AudioManager.STREAM_MUSIC,
- AudioManager.AUDIOFOCUS_GAIN,
- VehicleAudioStream.STREAM0,
- VehicleAudioContextFlag.MUSIC_FLAG);
- }
-
- public void testMediaGainTransientFocus() throws Exception {
- checkSingleRequestRelease(
- AudioManager.STREAM_MUSIC,
- AudioManager.AUDIOFOCUS_GAIN_TRANSIENT,
- VehicleAudioStream.STREAM0,
- VehicleAudioContextFlag.MUSIC_FLAG);
- }
-
- public void testMediaGainTransientMayDuckFocus() throws Exception {
- checkSingleRequestRelease(
- AudioManager.STREAM_MUSIC,
- AudioManager.AUDIOFOCUS_GAIN_TRANSIENT_MAY_DUCK,
- VehicleAudioStream.STREAM0,
- VehicleAudioContextFlag.MUSIC_FLAG);
- }
-
- public void testAlarmGainTransientFocus() throws Exception {
- checkSingleRequestRelease(
- AudioManager.STREAM_ALARM,
- AudioManager.AUDIOFOCUS_GAIN_TRANSIENT,
- VehicleAudioStream.STREAM1,
- VehicleAudioContextFlag.ALARM_FLAG);
- }
-
- public void testAlarmGainTransientMayDuckFocus() throws Exception {
- checkSingleRequestRelease(
- AudioManager.STREAM_ALARM,
- AudioManager.AUDIOFOCUS_GAIN_TRANSIENT_MAY_DUCK,
- VehicleAudioStream.STREAM1,
- VehicleAudioContextFlag.ALARM_FLAG);
- }
-
- public void testMediaNavFocus() throws Exception {
- //music start
- AudioFocusListener listenerMusic = new AudioFocusListener();
- int res = doRequestFocus(mAudioManager, listenerMusic,
- AudioManager.STREAM_MUSIC,
- AudioManager.AUDIOFOCUS_GAIN);
- assertEquals(AudioManager.AUDIOFOCUS_REQUEST_GRANTED, res);
- int[] request = mAudioFocusPropertyHandler.waitForAudioFocusRequest(TIMEOUT_MS);
- assertEquals(VehicleAudioFocusRequest.REQUEST_GAIN, request[0]);
- assertEquals(0x1 << VehicleAudioStream.STREAM0, request[1]);
- assertEquals(0, request[2]);
- assertEquals(VehicleAudioContextFlag.MUSIC_FLAG, request[3]);
- mAudioFocusPropertyHandler.sendAudioFocusState(
- VehicleAudioFocusState.STATE_GAIN,
- request[1],
- VehicleAudioExtFocusFlag.NONE_FLAG);
-
- // nav guidance start
- AudioFocusListener listenerNav = new AudioFocusListener();
- AudioAttributes navAttrib = (new AudioAttributes.Builder()).
- setContentType(AudioAttributes.CONTENT_TYPE_SONIFICATION).
- setUsage(AudioAttributes.USAGE_ASSISTANCE_NAVIGATION_GUIDANCE).
- build();
- doRequestFocus(mAudioManager, listenerNav, navAttrib,
- AudioManager.AUDIOFOCUS_GAIN_TRANSIENT_MAY_DUCK);
- request = mAudioFocusPropertyHandler.waitForAudioFocusRequest(TIMEOUT_MS);
- assertEquals(VehicleAudioFocusRequest.REQUEST_GAIN, request[0]);
- assertEquals(0x3, request[1]);
- assertEquals(0, request[2]);
- assertEquals(VehicleAudioContextFlag.MUSIC_FLAG |
- VehicleAudioContextFlag.NAVIGATION_FLAG, request[3]);
- mAudioFocusPropertyHandler.sendAudioFocusState(
- VehicleAudioFocusState.STATE_GAIN, request[1],
- VehicleAudioExtFocusFlag.NONE_FLAG);
-
- // nav guidance done
- mAudioManager.abandonAudioFocus(listenerNav);
- request = mAudioFocusPropertyHandler.waitForAudioFocusRequest(TIMEOUT_MS);
- assertEquals(VehicleAudioFocusRequest.REQUEST_GAIN, request[0]);
- assertEquals(0x1 << VehicleAudioStream.STREAM0, request[1]);
- assertEquals(0, request[2]);
- assertEquals(VehicleAudioContextFlag.MUSIC_FLAG, request[3]);
- mAudioFocusPropertyHandler.sendAudioFocusState(
- VehicleAudioFocusState.STATE_GAIN, request[1],
- VehicleAudioExtFocusFlag.NONE_FLAG);
-
- // music done
- mAudioManager.abandonAudioFocus(listenerMusic);
- request = mAudioFocusPropertyHandler.waitForAudioFocusRequest(TIMEOUT_MS);
- assertEquals(VehicleAudioFocusRequest.REQUEST_RELEASE, request[0]);
- assertEquals(0, request[1]);
- assertEquals(0, request[2]);
- assertEquals(0, request[3]);
- mAudioFocusPropertyHandler.sendAudioFocusState(
- VehicleAudioFocusState.STATE_LOSS, request[1],
- VehicleAudioExtFocusFlag.NONE_FLAG);
- }
-
- public void testMediaExternalMediaNavFocus() throws Exception {
- // android music
- AudioFocusListener listenerMusic = new AudioFocusListener();
- int res = doRequestFocus(mAudioManager, listenerMusic,
- AudioManager.STREAM_MUSIC,
- AudioManager.AUDIOFOCUS_GAIN);
- assertEquals(AudioManager.AUDIOFOCUS_REQUEST_GRANTED, res);
- int[] request = mAudioFocusPropertyHandler.waitForAudioFocusRequest(TIMEOUT_MS);
- assertEquals(VehicleAudioFocusRequest.REQUEST_GAIN, request[0]);
- assertEquals(0x1 << VehicleAudioStream.STREAM0, request[1]);
- assertEquals(0, request[2]);
- assertEquals(VehicleAudioContextFlag.MUSIC_FLAG, request[3]);
- mAudioFocusPropertyHandler.sendAudioFocusState(
- VehicleAudioFocusState.STATE_GAIN,
- request[1],
- VehicleAudioExtFocusFlag.NONE_FLAG);
-
- // car plays external media (=outside Android)
- mAudioFocusPropertyHandler.sendAudioFocusState(
- VehicleAudioFocusState.STATE_LOSS,
- 0,
- VehicleAudioExtFocusFlag.PERMANENT_FLAG);
- int focusChange = listenerMusic.waitAndGetFocusChange(TIMEOUT_MS);
- assertEquals(AudioManager.AUDIOFOCUS_LOSS, focusChange);
-
- // nav guidance start
- AudioFocusListener listenerNav = new AudioFocusListener();
- AudioAttributes navAttrib = (new AudioAttributes.Builder()).
- setContentType(AudioAttributes.CONTENT_TYPE_SONIFICATION).
- setUsage(AudioAttributes.USAGE_ASSISTANCE_NAVIGATION_GUIDANCE).
- build();
- doRequestFocus(mAudioManager, listenerNav, navAttrib,
- AudioManager.AUDIOFOCUS_GAIN_TRANSIENT_MAY_DUCK);
- request = mAudioFocusPropertyHandler.waitForAudioFocusRequest(TIMEOUT_MS);
- assertEquals(VehicleAudioFocusRequest.REQUEST_GAIN_TRANSIENT_MAY_DUCK,
- request[0]);
- assertEquals(0x1 << VehicleAudioStream.STREAM1, request[1]);
- assertEquals(0, request[2]);
- assertEquals(VehicleAudioContextFlag.NAVIGATION_FLAG, request[3]);
- mAudioFocusPropertyHandler.sendAudioFocusState(
- VehicleAudioFocusState.STATE_GAIN_TRANSIENT,
- 0x1 << VehicleAudioStream.STREAM1,
- VehicleAudioExtFocusFlag.PERMANENT_FLAG);
-
- // nav guidance ends
- mAudioManager.abandonAudioFocus(listenerNav);
- request = mAudioFocusPropertyHandler.waitForAudioFocusRequest(TIMEOUT_MS);
- assertEquals(VehicleAudioFocusRequest.REQUEST_RELEASE, request[0]);
- assertEquals(0, request[1]);
- assertEquals(0, request[2]);
- assertEquals(0, request[3]);
- mAudioFocusPropertyHandler.sendAudioFocusState(
- VehicleAudioFocusState.STATE_LOSS,
- 0,
- VehicleAudioExtFocusFlag.PERMANENT_FLAG);
-
- // now ends external play
- mAudioFocusPropertyHandler.sendAudioFocusState(
- VehicleAudioFocusState.STATE_LOSS,
- 0,
- 0);
- mAudioManager.abandonAudioFocus(listenerMusic);
- //TODO how to check this?
- }
-
- public void testMediaExternalRadioNavMediaFocus() throws Exception {
- // android music
- AudioFocusListener listenerMusic = new AudioFocusListener();
- int res = doRequestFocus(mAudioManager, listenerMusic,
- AudioManager.STREAM_MUSIC,
- AudioManager.AUDIOFOCUS_GAIN);
- assertEquals(AudioManager.AUDIOFOCUS_REQUEST_GRANTED, res);
- int[] request = mAudioFocusPropertyHandler.waitForAudioFocusRequest(TIMEOUT_MS);
- assertEquals(VehicleAudioFocusRequest.REQUEST_GAIN, request[0]);
- assertEquals(0x1 << VehicleAudioStream.STREAM0, request[1]);
- assertEquals(0, request[2]);
- assertEquals(VehicleAudioContextFlag.MUSIC_FLAG, request[3]);
- mAudioFocusPropertyHandler.sendAudioFocusState(
- VehicleAudioFocusState.STATE_GAIN,
- request[1],
- VehicleAudioExtFocusFlag.NONE_FLAG);
-
- // android radio
- AudioFocusListener listenerRadio = new AudioFocusListener();
- CarAudioManager carAudioManager = (CarAudioManager) getCar().getCarManager(
- Car.AUDIO_SERVICE);
- assertNotNull(carAudioManager);
- AudioAttributes radioAttributes = carAudioManager.getAudioAttributesForCarUsage(
- CarAudioManager.CAR_AUDIO_USAGE_RADIO);
- res = doRequestFocus(mAudioManager, listenerRadio,
- radioAttributes, AudioManager.AUDIOFOCUS_GAIN);
- assertEquals(AudioManager.AUDIOFOCUS_REQUEST_GRANTED, res);
- request = mAudioFocusPropertyHandler.waitForAudioFocusRequest(TIMEOUT_MS);
- assertEquals(VehicleAudioFocusRequest.REQUEST_GAIN, request[0]);
- assertEquals(0, request[1]);
- assertEquals(VehicleAudioExtFocusFlag.PLAY_ONLY_FLAG,
- request[2]);
- assertEquals(VehicleAudioContextFlag.RADIO_FLAG, request[3]);
- mAudioFocusPropertyHandler.sendAudioFocusState(
- VehicleAudioFocusState.STATE_GAIN,
- 0,
- VehicleAudioExtFocusFlag.PLAY_ONLY_FLAG);
-
- // nav guidance start
- AudioFocusListener listenerNav = new AudioFocusListener();
- AudioAttributes navAttrib = (new AudioAttributes.Builder()).
- setContentType(AudioAttributes.CONTENT_TYPE_SONIFICATION).
- setUsage(AudioAttributes.USAGE_ASSISTANCE_NAVIGATION_GUIDANCE).
- build();
- res = doRequestFocus(mAudioManager, listenerNav, navAttrib,
- AudioManager.AUDIOFOCUS_GAIN_TRANSIENT_MAY_DUCK);
- request = mAudioFocusPropertyHandler.waitForAudioFocusRequest(TIMEOUT_MS);
- assertEquals(VehicleAudioFocusRequest.REQUEST_GAIN,
- request[0]);
- assertEquals(0x1 << VehicleAudioStream.STREAM1, request[1]);
- assertEquals(VehicleAudioExtFocusFlag.PLAY_ONLY_FLAG,
- request[2]);
- assertEquals(VehicleAudioContextFlag.NAVIGATION_FLAG |
- VehicleAudioContextFlag.RADIO_FLAG, request[3]);
- mAudioFocusPropertyHandler.sendAudioFocusState(
- VehicleAudioFocusState.STATE_GAIN,
- 0x1 << VehicleAudioStream.STREAM1,
- VehicleAudioExtFocusFlag.PLAY_ONLY_FLAG);
-
- // nav guidance ends
- mAudioManager.abandonAudioFocus(listenerNav);
- request = mAudioFocusPropertyHandler.waitForAudioFocusRequest(TIMEOUT_MS);
- assertEquals(VehicleAudioFocusRequest.REQUEST_GAIN,
- request[0]);
- assertEquals(0, request[1]);
- assertEquals(VehicleAudioExtFocusFlag.PLAY_ONLY_FLAG,
- request[2]);
- assertEquals(VehicleAudioContextFlag.RADIO_FLAG, request[3]);
- mAudioFocusPropertyHandler.sendAudioFocusState(
- VehicleAudioFocusState.STATE_GAIN,
- 0,
- VehicleAudioExtFocusFlag.PLAY_ONLY_FLAG);
-
- // ends radio. music will get the focus GAIN.
- // Music app is supposed to stop and release focus when it has lost focus, but here just
- // check if focus is working.
- mAudioManager.abandonAudioFocus(listenerRadio);
- listenerMusic.waitForFocus(TIMEOUT_MS, AudioManager.AUDIOFOCUS_GAIN);
- request = mAudioFocusPropertyHandler.waitForAudioFocusRequest(TIMEOUT_MS);
- assertEquals(VehicleAudioFocusRequest.REQUEST_GAIN, request[0]);
- assertEquals(0x1 << VehicleAudioStream.STREAM0, request[1]);
- assertEquals(0, request[2]);
- assertEquals(VehicleAudioContextFlag.MUSIC_FLAG, request[3]);
- mAudioFocusPropertyHandler.sendAudioFocusState(
- VehicleAudioFocusState.STATE_GAIN,
- 0x1 << VehicleAudioStream.STREAM0,
- 0);
-
- // now music release focus.
- mAudioManager.abandonAudioFocus(listenerMusic);
- request = mAudioFocusPropertyHandler.waitForAudioFocusRequest(TIMEOUT_MS);
- assertEquals(VehicleAudioFocusRequest.REQUEST_RELEASE, request[0]);
- assertEquals(0, request[1]);
- assertEquals(0, request[2]);
- assertEquals(0, request[3]);
- mAudioFocusPropertyHandler.sendAudioFocusState(
- VehicleAudioFocusState.STATE_LOSS,
- 0,
- VehicleAudioExtFocusFlag.NONE_FLAG);
- }
-
- private void checkSingleRequestRelease(int streamType, int androidFocus, int streamNumber,
- int context)
- throws Exception {
- AudioFocusListener lister = new AudioFocusListener();
- int res = doRequestFocus(mAudioManager, lister,
- streamType,
- androidFocus);
- assertEquals(AudioManager.AUDIOFOCUS_REQUEST_GRANTED, res);
- int[] request = mAudioFocusPropertyHandler.waitForAudioFocusRequest(TIMEOUT_MS);
- int expectedRequest = VehicleAudioFocusRequest.REQUEST_RELEASE;
- int response = VehicleAudioFocusState.STATE_LOSS;
- switch (androidFocus) {
- case AudioManager.AUDIOFOCUS_GAIN:
- expectedRequest = VehicleAudioFocusRequest.REQUEST_GAIN;
- response = VehicleAudioFocusState.STATE_GAIN;
- break;
- case AudioManager.AUDIOFOCUS_GAIN_TRANSIENT:
- expectedRequest =
- VehicleAudioFocusRequest.REQUEST_GAIN_TRANSIENT;
- response = VehicleAudioFocusState.STATE_GAIN_TRANSIENT;
- break;
- case AudioManager.AUDIOFOCUS_GAIN_TRANSIENT_MAY_DUCK:
- expectedRequest =
- VehicleAudioFocusRequest.REQUEST_GAIN_TRANSIENT_MAY_DUCK;
- response = VehicleAudioFocusState.STATE_GAIN_TRANSIENT;
- break;
- }
- assertEquals(expectedRequest, request[0]);
- assertEquals(0x1 << streamNumber, request[1]);
- assertEquals(0, request[2]);
- assertEquals(context, request[3]);
- mAudioFocusPropertyHandler.sendAudioFocusState(
- response,
- request[1],
- VehicleAudioExtFocusFlag.NONE_FLAG);
- mAudioManager.abandonAudioFocus(lister);
- request = mAudioFocusPropertyHandler.waitForAudioFocusRequest(TIMEOUT_MS);
- assertEquals(VehicleAudioFocusRequest.REQUEST_RELEASE, request[0]);
- assertEquals(0, request[1]);
- assertEquals(0, request[2]);
- assertEquals(0, request[3]);
- mAudioFocusPropertyHandler.sendAudioFocusState(
- VehicleAudioFocusState.STATE_LOSS,
- request[1],
- VehicleAudioExtFocusFlag.NONE_FLAG);
- }
-
- public void testRadioMute() throws Exception {
- doTestMediaMute(CarAudioManager.CAR_AUDIO_USAGE_RADIO,
- 0,
- VehicleAudioExtFocusFlag.PLAY_ONLY_FLAG,
- VehicleAudioContextFlag.RADIO_FLAG);
- }
-
- public void testMusicMute() throws Exception {
- doTestMediaMute(CarAudioManager.CAR_AUDIO_USAGE_MUSIC,
- 0x1,
- 0,
- VehicleAudioContextFlag.MUSIC_FLAG);
- }
-
- private void doTestMediaMute(int mediaUsage, int primaryStream, int extFocusFlag,
- int mediaContext) throws Exception {
- // android radio
- AudioFocusListener listenerMedia = new AudioFocusListener();
- CarAudioManager carAudioManager = (CarAudioManager) getCar().getCarManager(
- Car.AUDIO_SERVICE);
- assertNotNull(carAudioManager);
- AudioAttributes radioAttributes = carAudioManager.getAudioAttributesForCarUsage(mediaUsage);
- Log.i(TAG, "request media Focus");
- int res = doRequestFocus(mAudioManager, listenerMedia,
- radioAttributes, AudioManager.AUDIOFOCUS_GAIN);
- assertEquals(AudioManager.AUDIOFOCUS_REQUEST_GRANTED, res);
- int[] request = mAudioFocusPropertyHandler.waitForAudioFocusRequest(TIMEOUT_MS);
- assertEquals(VehicleAudioFocusRequest.REQUEST_GAIN, request[0]);
- assertEquals(primaryStream, request[1]);
- assertEquals(extFocusFlag, request[2]);
- assertEquals(mediaContext, request[3]);
- mAudioFocusPropertyHandler.sendAudioFocusState(
- VehicleAudioFocusState.STATE_GAIN,
- primaryStream,
- extFocusFlag);
- // now mute it.
- assertFalse(carAudioManager.isMediaMuted());
- Log.i(TAG, "mute media");
- assertTrue(carAudioManager.setMediaMute(true));
- request = mAudioFocusPropertyHandler.waitForAudioFocusRequest(TIMEOUT_MS);
- assertEquals(VehicleAudioFocusRequest.REQUEST_GAIN_TRANSIENT,
- request[0]);
- assertEquals(0, request[1]);
- assertEquals(VehicleAudioExtFocusFlag.MUTE_MEDIA_FLAG,
- request[2]);
- assertEquals(0, request[3]);
- mAudioFocusPropertyHandler.sendAudioFocusState(
- VehicleAudioFocusState.STATE_GAIN,
- 0,
- VehicleAudioExtFocusFlag.MUTE_MEDIA_FLAG);
- assertTrue(carAudioManager.isMediaMuted());
- // nav guidance on top of it
- AudioFocusListener listenerNav = new AudioFocusListener();
- AudioAttributes navAttrib = (new AudioAttributes.Builder()).
- setContentType(AudioAttributes.CONTENT_TYPE_SONIFICATION).
- setUsage(AudioAttributes.USAGE_ASSISTANCE_NAVIGATION_GUIDANCE).
- build();
- Log.i(TAG, "request nav Focus");
- res = doRequestFocus(mAudioManager, listenerNav, navAttrib,
- AudioManager.AUDIOFOCUS_GAIN_TRANSIENT_MAY_DUCK);
- request = mAudioFocusPropertyHandler.waitForAudioFocusRequest(TIMEOUT_MS);
- assertEquals(VehicleAudioFocusRequest.REQUEST_GAIN_TRANSIENT_MAY_DUCK,
- request[0]);
- assertEquals(0x1 << VehicleAudioStream.STREAM1, request[1]);
- assertEquals(VehicleAudioExtFocusFlag.MUTE_MEDIA_FLAG,
- request[2]);
- assertEquals(VehicleAudioContextFlag.NAVIGATION_FLAG, request[3]);
- assertTrue(carAudioManager.isMediaMuted());
- mAudioFocusPropertyHandler.sendAudioFocusState(
- VehicleAudioFocusState.STATE_GAIN,
- 0x1 << VehicleAudioStream.STREAM1,
- VehicleAudioExtFocusFlag.MUTE_MEDIA_FLAG);
- assertTrue(carAudioManager.isMediaMuted());
- // nav guidance ends
- mAudioManager.abandonAudioFocus(listenerNav);
- request = mAudioFocusPropertyHandler.waitForAudioFocusRequest(TIMEOUT_MS);
- assertEquals(VehicleAudioFocusRequest.REQUEST_GAIN_TRANSIENT,
- request[0]);
- assertEquals(0, request[1]);
- assertEquals(VehicleAudioExtFocusFlag.MUTE_MEDIA_FLAG,
- request[2]);
- assertEquals(0, request[3]);
- assertTrue(carAudioManager.isMediaMuted());
- mAudioFocusPropertyHandler.sendAudioFocusState(
- VehicleAudioFocusState.STATE_GAIN,
- 0,
- VehicleAudioExtFocusFlag.MUTE_MEDIA_FLAG);
- // now unmute it. radio should resume.
- assertTrue(carAudioManager.isMediaMuted());
- assertFalse(carAudioManager.setMediaMute(false));
- assertFalse(carAudioManager.isMediaMuted());
- request = mAudioFocusPropertyHandler.waitForAudioFocusRequest(TIMEOUT_MS);
- assertEquals(VehicleAudioFocusRequest.REQUEST_GAIN, request[0]);
- assertEquals(primaryStream, request[1]);
- assertEquals(extFocusFlag,
- request[2]);
- assertEquals(mediaContext, request[3]);
- assertFalse(carAudioManager.isMediaMuted());
- mAudioFocusPropertyHandler.sendAudioFocusState(
- VehicleAudioFocusState.STATE_GAIN,
- primaryStream,
- extFocusFlag);
- assertFalse(carAudioManager.isMediaMuted());
- // release focus
- mAudioManager.abandonAudioFocus(listenerMedia);
- }
-
- static class AudioFocusListener implements AudioManager.OnAudioFocusChangeListener {
- private final Semaphore mFocusChangeWait = new Semaphore(0);
- private int mLastFocusChange;
-
- int waitAndGetFocusChange(long timeoutMs) throws Exception {
- if (!mFocusChangeWait.tryAcquire(timeoutMs, TimeUnit.MILLISECONDS)) {
- fail("timeout waiting for focus change");
- }
- return mLastFocusChange;
- }
-
- void waitForFocus(long timeoutMs, int expectedFocus) throws Exception {
- while (mLastFocusChange != expectedFocus) {
- if (!mFocusChangeWait.tryAcquire(timeoutMs, TimeUnit.MILLISECONDS)) {
- fail("timeout waiting for focus change");
- }
- }
- }
-
- @Override
- public void onAudioFocusChange(int focusChange) {
- mLastFocusChange = focusChange;
- mFocusChangeWait.release();
- }
- }
-
- static class FocusPropertyHandler implements VehicleHalPropertyHandler {
-
- private int mState = VehicleAudioFocusState.STATE_LOSS;
- private int mStreams = 0;
- private int mExtFocus = 0;
- private int mRequest;
- private int mRequestedStreams;
- private int mRequestedExtFocus;
- private int mRequestedAudioContexts;
- private final MockedCarTestBase mCarTest;
-
- private final Semaphore mSetWaitSemaphore = new Semaphore(0);
-
- FocusPropertyHandler(MockedCarTestBase carTest) {
- mCarTest = carTest;
- }
-
- void sendAudioFocusState(int state, int streams, int extFocus) {
- synchronized (this) {
- mState = state;
- mStreams = streams;
- mExtFocus = extFocus;
- }
- mCarTest.getMockedVehicleHal().injectEvent(
- VehiclePropValueBuilder.newBuilder(VehicleProperty.AUDIO_FOCUS)
- .setTimestamp(SystemClock.elapsedRealtimeNanos())
- .addIntValue(state, streams, extFocus, 0)
- .build());
- }
-
- int[] waitForAudioFocusRequest(long timeoutMs) throws Exception {
- if (!mSetWaitSemaphore.tryAcquire(timeoutMs, TimeUnit.MILLISECONDS)) {
- fail("timeout");
- }
- synchronized (this) {
- return new int[] { mRequest, mRequestedStreams, mRequestedExtFocus,
- mRequestedAudioContexts };
- }
- }
-
- @Override
- public void onPropertySet(VehiclePropValue value) {
- assertEquals(VehicleProperty.AUDIO_FOCUS, value.prop);
- ArrayList<Integer> v = value.value.int32Values;
- synchronized (this) {
- mRequest = v.get(VehicleAudioFocusIndex.FOCUS);
- mRequestedStreams = v.get(VehicleAudioFocusIndex.STREAMS);
- mRequestedExtFocus = v.get(VehicleAudioFocusIndex.EXTERNAL_FOCUS_STATE);
- mRequestedAudioContexts = v.get(VehicleAudioFocusIndex.AUDIO_CONTEXTS);
- }
- mSetWaitSemaphore.release();
- }
-
- @Override
- public VehiclePropValue onPropertyGet(VehiclePropValue value) {
- assertEquals(VehicleProperty.AUDIO_FOCUS, value.prop);
- int state, streams, extFocus;
- synchronized (this) {
- state = mState;
- streams = mStreams;
- extFocus = mExtFocus;
- }
- return VehiclePropValueBuilder.newBuilder(VehicleProperty.AUDIO_FOCUS)
- .setTimestamp(SystemClock.elapsedRealtimeNanos())
- .addIntValue(state, streams, extFocus, 0)
- .build();
- }
-
- @Override
- public void onPropertySubscribe(int property, int zones, float sampleRate) {
- assertEquals(AUDIO_FOCUS, property);
- }
-
- @Override
- public void onPropertyUnsubscribe(int property) {
- assertEquals(AUDIO_FOCUS, property);
- }
- }
-}
diff --git a/tests/carservice_test/src/com/android/car/test/CarAudioManagerTest.java b/tests/carservice_test/src/com/android/car/test/CarAudioManagerTest.java
deleted file mode 100644
index 07646d4..0000000
--- a/tests/carservice_test/src/com/android/car/test/CarAudioManagerTest.java
+++ /dev/null
@@ -1,225 +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.android.car.test;
-
-import android.car.Car;
-import android.car.media.CarAudioManager;
-import android.hardware.automotive.vehicle.V2_0.VehiclePropValue;
-import android.hardware.automotive.vehicle.V2_0.VehicleProperty;
-import android.hardware.automotive.vehicle.V2_0.VehiclePropertyAccess;
-import android.os.SystemClock;
-import android.test.suitebuilder.annotation.MediumTest;
-
-import com.android.car.vehiclehal.VehiclePropValueBuilder;
-import com.android.car.vehiclehal.test.MockedVehicleHal.VehicleHalPropertyHandler;
-
-import java.util.concurrent.Semaphore;
-import java.util.concurrent.TimeUnit;
-
-@MediumTest
-public class CarAudioManagerTest extends MockedCarTestBase {
- private final AudioParametersPropertyHandler mAudioParametersPropertyHandler =
- new AudioParametersPropertyHandler();
- CarAudioManager mCarAudioManager;
-
- @Override
- protected synchronized void configureMockedHal() {
- addProperty(VehicleProperty.AUDIO_PARAMETERS, mAudioParametersPropertyHandler)
- .setAccess(VehiclePropertyAccess.READ_WRITE)
- .setConfigString("com.android.test.param1;com.android.test.param2");
- }
-
- @Override
- protected void setUp() throws Exception {
- super.setUp();
- mCarAudioManager = (CarAudioManager) getCar().getCarManager(
- Car.AUDIO_SERVICE);
- assertNotNull(mCarAudioManager);
- }
-
- public void testAudioParamConfig() throws Exception {
- String[] keys = mCarAudioManager.getParameterKeys();
- assertNotNull(keys);
- assertEquals(2, keys.length);
- assertEquals("com.android.test.param1", keys[0]);
- assertEquals("com.android.test.param2", keys[1]);
- }
-
- public void testAudioParamSet() throws Exception {
- try {
- mCarAudioManager.setParameters(null);
- fail();
- } catch (IllegalArgumentException e) {
- // expected
- }
-
- try {
- mCarAudioManager.setParameters("com.android.test.param3=3");
- fail();
- } catch (IllegalArgumentException e) {
- // expected
- }
-
- final String SET_OK1 = "com.android.test.param1=1";
- mCarAudioManager.setParameters(SET_OK1);
- mAudioParametersPropertyHandler.waitForSet(DEFAULT_WAIT_TIMEOUT_MS, SET_OK1);
-
- final String SET_OK2 = "com.android.test.param1=1;com.android.test.param2=2";
- mCarAudioManager.setParameters(SET_OK2);
- mAudioParametersPropertyHandler.waitForSet(DEFAULT_WAIT_TIMEOUT_MS, SET_OK2);
- }
-
- public void testAudioParamGet() throws Exception {
- try {
- mCarAudioManager.getParameters(null);
- fail();
- } catch (IllegalArgumentException e) {
- // expected
- }
-
- try {
- mCarAudioManager.getParameters("com.android.test.param3");
- fail();
- } catch (IllegalArgumentException e) {
- // expected
- }
-
- try {
- mCarAudioManager.getParameters("com.android.test.param1;com.android.test.param3");
- fail();
- } catch (IllegalArgumentException e) {
- // expected
- }
-
- final String GET_RESP1 = "com.android.test.param1=1";
- mAudioParametersPropertyHandler.setValueForGet(GET_RESP1);
- String get1 = mCarAudioManager.getParameters("com.android.test.param1");
- assertEquals(GET_RESP1, get1);
-
- final String GET_RESP2 = "com.android.test.param1=1;com.android.test.param2=2";
- mAudioParametersPropertyHandler.setValueForGet(GET_RESP2);
- String get2 = mCarAudioManager.getParameters(
- "com.android.test.param1;com.android.test.param2");
- assertEquals(GET_RESP2, get2);
- }
-
- public void testAudioParamChangeListener() throws Exception {
- AudioParamListener listener1 = new AudioParamListener();
- AudioParamListener listener2 = new AudioParamListener();
-
- mCarAudioManager.setOnParameterChangeListener(listener1);
- final String EVENT1 = "com.android.test.param1=10";
- sendAudioParamChange(EVENT1);
- listener1.waitForChange(DEFAULT_WAIT_TIMEOUT_MS, EVENT1);
-
- mCarAudioManager.setOnParameterChangeListener(listener2);
- listener1.clearParameter();
- final String EVENT2 = "com.android.test.param1=20;com.android.test.param2=10";
- sendAudioParamChange(EVENT2);
- listener2.waitForChange(DEFAULT_WAIT_TIMEOUT_MS, EVENT2);
- listener1.assertParameter(null);
-
- mCarAudioManager.setOnParameterChangeListener(null);
- listener2.clearParameter();
- sendAudioParamChange(EVENT1);
- Thread.sleep(200);
- listener1.assertParameter(null);
- listener2.assertParameter(null);
- }
-
- private void sendAudioParamChange(String params) {
- getMockedVehicleHal().injectEvent(
- VehiclePropValueBuilder.newBuilder(VehicleProperty.AUDIO_PARAMETERS)
- .setTimestamp(SystemClock.elapsedRealtimeNanos())
- .setStringValue(params)
- .build());
- }
-
- static class AudioParametersPropertyHandler implements VehicleHalPropertyHandler {
- private final Semaphore mSetWaitSemaphore = new Semaphore(0);
-
- private String mValueSet;
- private String mGetResponse;
-
- public void waitForSet(long waitTimeMs, String expected) throws Exception {
- mSetWaitSemaphore.tryAcquire(waitTimeMs, TimeUnit.MILLISECONDS);
- synchronized (this) {
- assertEquals(expected, mValueSet);
- }
- }
-
- public synchronized void setValueForGet(String value) {
- mGetResponse = value;
- }
-
- @Override
- public void onPropertySet(VehiclePropValue value) {
- assertEquals(VehicleProperty.AUDIO_PARAMETERS, value.prop);
- String setValue = value.value.stringValue;
- synchronized (this) {
- mValueSet = setValue;
- }
- mSetWaitSemaphore.release();
- }
-
- @Override
- public VehiclePropValue onPropertyGet(VehiclePropValue value) {
- assertEquals(VehicleProperty.AUDIO_PARAMETERS, value.prop);
- String response;
- synchronized (this) {
- response = mGetResponse;
- }
- return VehiclePropValueBuilder.newBuilder(VehicleProperty.AUDIO_PARAMETERS)
- .setTimestamp(SystemClock.elapsedRealtimeNanos())
- .setStringValue(mGetResponse)
- .build();
- }
-
- @Override
- public void onPropertySubscribe(int property, int zones, float sampleRate) {
- assertEquals(VehicleProperty.AUDIO_PARAMETERS, property);
- }
-
- @Override
- public void onPropertyUnsubscribe(int property) {
- assertEquals(VehicleProperty.AUDIO_PARAMETERS, property);
- }
- }
-
- static class AudioParamListener implements CarAudioManager.OnParameterChangeListener {
- private String mParameter;
- private final Semaphore mChangeWaitSemaphore = new Semaphore(0);
-
- @Override
- public void onParameterChange(String parameters) {
- mParameter = parameters;
- mChangeWaitSemaphore.release();
- }
-
- public void waitForChange(long waitTimeMs, String expected) throws Exception {
- mChangeWaitSemaphore.tryAcquire(waitTimeMs, TimeUnit.MILLISECONDS);
- assertEquals(expected, mParameter);
- }
-
- public void clearParameter() {
- mParameter = null;
- }
-
- public void assertParameter(String expected) {
- assertEquals(expected, mParameter);
- }
- }
-}
diff --git a/tests/carservice_test/src/com/android/car/test/CarRadioManagerTest.java b/tests/carservice_test/src/com/android/car/test/CarRadioManagerTest.java
deleted file mode 100644
index 169a370..0000000
--- a/tests/carservice_test/src/com/android/car/test/CarRadioManagerTest.java
+++ /dev/null
@@ -1,192 +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.test;
-
-import android.car.Car;
-import android.car.hardware.radio.CarRadioEvent;
-import android.car.hardware.radio.CarRadioManager;
-import android.car.hardware.radio.CarRadioManager.CarRadioEventListener;
-import android.car.hardware.radio.CarRadioPreset;
-import android.hardware.radio.RadioManager;
-import android.hardware.automotive.vehicle.V2_0.VehiclePropValue;
-import android.hardware.automotive.vehicle.V2_0.VehicleProperty;
-import android.os.SystemClock;
-import android.test.suitebuilder.annotation.MediumTest;
-import android.util.Log;
-
-import com.google.android.collect.Lists;
-
-import com.android.car.vehiclehal.VehiclePropValueBuilder;
-import com.android.car.vehiclehal.test.MockedVehicleHal.VehicleHalPropertyHandler;
-
-import java.util.HashMap;
-import java.util.concurrent.Semaphore;
-import java.util.concurrent.TimeUnit;
-
-@MediumTest
-public class CarRadioManagerTest extends MockedCarTestBase {
-
- private static final String TAG = CarRadioManagerTest.class.getSimpleName();
-
- // Use this semaphore to block until the callback is heard of.
- private Semaphore mAvailable;
-
- private static final int NUM_PRESETS = 2;
- private final HashMap<Integer, CarRadioPreset> mRadioPresets = new HashMap<>();
-
- private CarRadioManager mCarRadioManager;
-
- private class RadioPresetPropertyHandler implements VehicleHalPropertyHandler {
- public RadioPresetPropertyHandler() { }
-
- @Override
- public synchronized void onPropertySet(VehiclePropValue value) {
- assertEquals(value.prop, VehicleProperty.RADIO_PRESET);
-
- Integer[] valueList = new Integer[4];
- value.value.int32Values.toArray(valueList);
- assertFalse(
- "Index out of range: " + valueList[0] + " (0, " + NUM_PRESETS + ")",
- valueList[0] < 1);
- assertFalse(
- "Index out of range: " + valueList[0] + " (0, " + NUM_PRESETS + ")",
- valueList[0] > NUM_PRESETS);
-
- CarRadioPreset preset =
- new CarRadioPreset(valueList[0], valueList[1], valueList[2], valueList[3]);
- mRadioPresets.put(valueList[0], preset);
-
- // The test case must be waiting for the semaphore, if not we should throw exception.
- if (mAvailable.availablePermits() != 0) {
- Log.d(TAG, "Lock was free, should have been locked.");
- }
- mAvailable.release();
- }
-
- @Override
- public synchronized VehiclePropValue onPropertyGet(VehiclePropValue value) {
- assertEquals(value.prop, VehicleProperty.RADIO_PRESET);
-
- Integer[] valueList = new Integer[4];
- value.value.int32Values.toArray(valueList);
-
- // Get the actual preset.
- if (valueList[0] < 1 || valueList[0] > NUM_PRESETS) {
- // VNS will call get method when subscribe is called, just return an empty
- // value.
- return value;
- }
- CarRadioPreset preset = mRadioPresets.get(valueList[0]);
- return VehiclePropValueBuilder.newBuilder(VehicleProperty.RADIO_PRESET)
- .setTimestamp(SystemClock.elapsedRealtimeNanos())
- .addIntValue(
- preset.getPresetNumber(),
- preset.getBand(),
- preset.getChannel(),
- preset.getSubChannel())
- .build();
- }
-
- @Override
- public synchronized void onPropertySubscribe(int property, int zones, float sampleRate) {
- Log.d(TAG, "onPropertySubscribe property: " + property + " rate: " + sampleRate);
- if (mAvailable.availablePermits() != 0) {
- Log.d(TAG, "Lock was free, should have been locked.");
- return;
- }
- mAvailable.release();
- }
-
- @Override
- public synchronized void onPropertyUnsubscribe(int property) {
- }
- }
-
- private class EventListener implements CarRadioEventListener {
- public EventListener() { }
-
- @Override
- public void onEvent(CarRadioEvent event) {
- // Print the event and release the lock.
- Log.d(TAG, event.toString());
- if (mAvailable.availablePermits() != 0) {
- Log.e(TAG, "Lock should be taken.");
- // Let the timeout fail the test here.
- return;
- }
- mAvailable.release();
- }
- }
-
- @Override
- protected synchronized void configureMockedHal() {
- addProperty(VehicleProperty.RADIO_PRESET, new RadioPresetPropertyHandler())
- .setConfigArray(Lists.newArrayList(NUM_PRESETS));
- }
-
- @Override
- protected void setUp() throws Exception {
- super.setUp();
- mAvailable = new Semaphore(0);
- mCarRadioManager = (CarRadioManager) getCar().getCarManager(Car.RADIO_SERVICE);
- }
-
- public void testPresetCount() throws Exception {
- int presetCount = mCarRadioManager.getPresetCount();
- assertEquals("Preset count not same.", NUM_PRESETS, presetCount);
- }
-
- public void testSetAndGetPreset() throws Exception {
- // Create a preset.
- CarRadioPreset preset = new CarRadioPreset(1, RadioManager.BAND_FM, 1234, -1);
- assertEquals("Lock should be freed by now.", 0, mAvailable.availablePermits());
- // mAvailable.acquire(1);
- mCarRadioManager.setPreset(preset);
-
- // Wait for acquire to be available again, fail if timeout.
- boolean success = mAvailable.tryAcquire(5L, TimeUnit.SECONDS);
- assertEquals("Could not finish setting, timeout!", true, success);
-
- // Test that get preset gives you the same element.
- assertEquals(preset, mCarRadioManager.getPreset(1));
- }
-
- public void testSubscribe() throws Exception {
- EventListener listener = new EventListener();
- assertEquals("Lock should be freed by now.", 0, mAvailable.availablePermits());
- mCarRadioManager.registerListener(listener);
-
- // Wait for acquire to be available again, fail if timeout.
- boolean success = mAvailable.tryAcquire(5L, TimeUnit.SECONDS);
- assertEquals("addListener timeout", true, success);
-
- // Inject an event and wait for its callback in onPropertySet.
- CarRadioPreset preset = new CarRadioPreset(2, RadioManager.BAND_AM, 4321, -1);
-
- VehiclePropValue v = VehiclePropValueBuilder.newBuilder(VehicleProperty.RADIO_PRESET)
- .setTimestamp(SystemClock.elapsedRealtimeNanos())
- .addIntValue(
- preset.getPresetNumber(),
- preset.getBand(),
- preset.getChannel(),
- preset.getSubChannel())
- .build();
- getMockedVehicleHal().injectEvent(v);
-
- success = mAvailable.tryAcquire(5L, TimeUnit.SECONDS);
- assertEquals("injectEvent, onEvent timeout!", true, success);
- }
-}
diff --git a/tests/carservice_test/src/com/android/car/test/CarServiceTestApp.java b/tests/carservice_test/src/com/android/car/test/CarServiceTestApp.java
new file mode 100644
index 0000000..e1354c9
--- /dev/null
+++ b/tests/carservice_test/src/com/android/car/test/CarServiceTestApp.java
@@ -0,0 +1,36 @@
+/*
+ * 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.test;
+
+import android.app.Application;
+import android.content.Context;
+
+// This class only exists to provide an application-level context. The context we mock
+// does not contain a valid ApplicationInfo, and because of that is not usable to instantiate
+// at least some system services (notably BluetoothManager). Having an Application allows us
+// to grab a valid Context early on and use it as needed.
+public class CarServiceTestApp extends Application {
+ private static Context mAppContext;
+
+ @Override
+ public void onCreate() {
+ mAppContext = getApplicationContext();
+ }
+
+ public static Context getAppContext() {
+ return mAppContext;
+ }
+}
diff --git a/tests/carservice_test/src/com/android/car/test/CarVolumeServiceTest.java b/tests/carservice_test/src/com/android/car/test/CarVolumeServiceTest.java
deleted file mode 100644
index 2e92a59..0000000
--- a/tests/carservice_test/src/com/android/car/test/CarVolumeServiceTest.java
+++ /dev/null
@@ -1,513 +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.test;
-
-import static com.android.car.test.AudioTestUtils.doRequestFocus;
-
-import android.car.Car;
-import android.car.CarNotConnectedException;
-import android.car.media.CarAudioManager;
-import android.content.Context;
-import android.hardware.automotive.vehicle.V2_0.VehicleAudioContextFlag;
-import android.hardware.automotive.vehicle.V2_0.VehicleAudioExtFocusFlag;
-import android.hardware.automotive.vehicle.V2_0.VehicleAudioFocusState;
-import android.hardware.automotive.vehicle.V2_0.VehicleAudioVolumeIndex;
-import android.hardware.automotive.vehicle.V2_0.VehicleHwKeyInputAction;
-import android.hardware.automotive.vehicle.V2_0.VehiclePropValue;
-import android.hardware.automotive.vehicle.V2_0.VehicleProperty;
-import android.hardware.automotive.vehicle.V2_0.VehiclePropertyAccess;
-import android.media.AudioAttributes;
-import android.media.AudioManager;
-import android.media.IVolumeController;
-import android.os.RemoteException;
-import android.os.SystemClock;
-import android.test.suitebuilder.annotation.MediumTest;
-import android.util.Log;
-import android.util.Pair;
-import android.util.SparseIntArray;
-import android.view.KeyEvent;
-
-import com.android.car.VolumeUtils;
-import com.android.car.vehiclehal.VehiclePropValueBuilder;
-import com.android.car.vehiclehal.test.MockedVehicleHal.VehicleHalPropertyHandler;
-import com.android.internal.annotations.GuardedBy;
-
-import com.google.android.collect.Lists;
-
-import java.util.ArrayList;
-import java.util.List;
-
-@MediumTest
-public class CarVolumeServiceTest extends MockedCarTestBase {
- private static final String TAG = CarVolumeServiceTest.class.getSimpleName();
-
- private static final int MIN_VOL = 1;
- private static final int MAX_VOL = 20;
- private static final long TIMEOUT_MS = 3000;
- private static final long POLL_INTERVAL_MS = 50;
-
- private static final int[] LOGICAL_STREAMS = {
- AudioManager.STREAM_VOICE_CALL,
- AudioManager.STREAM_SYSTEM,
- AudioManager.STREAM_RING,
- AudioManager.STREAM_MUSIC,
- AudioManager.STREAM_ALARM,
- AudioManager.STREAM_NOTIFICATION,
- AudioManager.STREAM_DTMF,
- };
-
- private CarAudioManager mCarAudioManager;
- private AudioManager mAudioManager;
-
- @Override
- protected synchronized void setUp() throws Exception {
- super.setUp();
- // AudioManager should be created in main thread to get focus event. :(
- runOnMainSync(new Runnable() {
- @Override
- public void run() {
- mAudioManager = (AudioManager) mContext.getSystemService(Context.AUDIO_SERVICE);
- }
- });
- }
-
- private SingleChannelVolumeHandler setupExternalVolumeEmulation(boolean supportAudioContext)
- throws Exception {
- List<Integer> maxs = new ArrayList<>();
- int supportedAudioContext = 0;
- if (!supportAudioContext) {
- // set up 2 physical streams
- maxs.add(MAX_VOL);
- maxs.add(MAX_VOL);
- } else {
- // add supported contexts
- int[] contexts = VolumeUtils.CAR_AUDIO_CONTEXT;
- for (int context : contexts) {
- supportedAudioContext |= context;
- maxs.add(MAX_VOL);
- }
- }
- SingleChannelVolumeHandler handler =
- startVolumeEmulation(supportedAudioContext, maxs);
- mCarAudioManager = (CarAudioManager) getCar().getCarManager(Car.AUDIO_SERVICE);
- return handler;
- }
-
- public void testUnknownVolumeChange() throws Exception {
- SingleChannelVolumeHandler volumeHandler = setupExternalVolumeEmulation(true);
- VolumeController volumeController = new VolumeController();
- mCarAudioManager.setVolumeController(volumeController);
- mCarAudioManager.setStreamVolume(AudioManager.STREAM_MUSIC, 2, 0);
- // give focus to music, now current context becomes VehicleAudioContextFlag.MUSIC_FLAG
- CarAudioFocusTest.AudioFocusListener listenerMusic =
- new CarAudioFocusTest.AudioFocusListener();
- int res = doRequestFocus(mAudioManager, listenerMusic,
- AudioManager.STREAM_MUSIC,
- AudioManager.AUDIOFOCUS_GAIN);
- assertEquals(AudioManager.AUDIOFOCUS_REQUEST_GRANTED, res);
- int[] request = mAudioFocusPropertyHandler.waitForAudioFocusRequest(TIMEOUT_MS);
- mAudioFocusPropertyHandler.sendAudioFocusState(
- VehicleAudioFocusState.STATE_GAIN,
- request[1],
- VehicleAudioExtFocusFlag.NONE_FLAG);
-
- // let vehicle hal report volume change from unknown context, we should map it to the
- // current context (music).
- volumeHandler.injectVolumeEvent(VehicleAudioContextFlag.UNKNOWN_FLAG, 3);
- // now music volume should be recorded as 3.
- volumeVerificationPoll(createStreamVolPair(AudioManager.STREAM_MUSIC, 3));
- }
-
- public void testVolumeLimits() throws Exception {
- setupExternalVolumeEmulation(false);
- for (int stream : LOGICAL_STREAMS) {
- assertEquals(MAX_VOL, mCarAudioManager.getStreamMaxVolume(stream));
- }
- }
-
- public void testVolumeSet() throws Exception {
- try {
- setupExternalVolumeEmulation(false);
- int callVol = 10;
- int musicVol = 15;
- mCarAudioManager.setStreamVolume(AudioManager.STREAM_MUSIC, musicVol, 0);
- mCarAudioManager.setStreamVolume(AudioManager.STREAM_VOICE_CALL, callVol, 0);
-
- volumeVerificationPoll(createStreamVolPair(AudioManager.STREAM_MUSIC, musicVol),
- createStreamVolPair(AudioManager.STREAM_VOICE_CALL, callVol));
-
- musicVol = MAX_VOL + 1;
- mCarAudioManager.setStreamVolume(AudioManager.STREAM_MUSIC, musicVol, 0);
-
- volumeVerificationPoll(createStreamVolPair(AudioManager.STREAM_MUSIC, MAX_VOL),
- createStreamVolPair(AudioManager.STREAM_VOICE_CALL, callVol));
- } catch (CarNotConnectedException e) {
- fail("Car not connected");
- }
- }
-
- public void testSuppressVolumeUI() {
- try {
- setupExternalVolumeEmulation(false);
- VolumeController volumeController = new VolumeController();
- mCarAudioManager.setVolumeController(volumeController);
-
- // first give focus to system sound
- CarAudioFocusTest.AudioFocusListener listenerMusic =
- new CarAudioFocusTest.AudioFocusListener();
- int res = doRequestFocus(mAudioManager, listenerMusic,
- AudioManager.STREAM_SYSTEM,
- AudioManager.AUDIOFOCUS_GAIN);
- assertEquals(AudioManager.AUDIOFOCUS_REQUEST_GRANTED, res);
- int[] request = mAudioFocusPropertyHandler.waitForAudioFocusRequest(TIMEOUT_MS);
- mAudioFocusPropertyHandler.sendAudioFocusState(
- VehicleAudioFocusState.STATE_GAIN,
- request[1],
- VehicleAudioExtFocusFlag.NONE_FLAG);
-
- // focus gives to Alarm, there should be a audio context change.
- CarAudioFocusTest.AudioFocusListener listenerAlarm = new
- CarAudioFocusTest.AudioFocusListener();
- AudioAttributes callAttrib = (new AudioAttributes.Builder()).
- setUsage(AudioAttributes.USAGE_ALARM).
- build();
- res = doRequestFocus(mAudioManager, listenerAlarm, callAttrib,
- AudioManager.AUDIOFOCUS_GAIN_TRANSIENT_MAY_DUCK);
- assertEquals(AudioManager.AUDIOFOCUS_REQUEST_GRANTED, res);
- request = mAudioFocusPropertyHandler.waitForAudioFocusRequest(TIMEOUT_MS);
- mAudioFocusPropertyHandler.sendAudioFocusState(
- VehicleAudioFocusState.STATE_GAIN, request[1],
- VehicleAudioExtFocusFlag.NONE_FLAG);
- // should not show UI
- volumeChangeVerificationPoll(AudioManager.STREAM_ALARM, false, volumeController);
-
- int alarmVol = mCarAudioManager.getStreamVolume(AudioManager.STREAM_ALARM);
- // set alarm volume with show_ui flag and a different volume
- mCarAudioManager.setStreamVolume(AudioManager.STREAM_ALARM,
- (alarmVol + 1) % mCarAudioManager.getStreamMaxVolume(AudioManager.STREAM_ALARM),
- AudioManager.FLAG_SHOW_UI);
- // should show ui
- volumeChangeVerificationPoll(AudioManager.STREAM_ALARM, true, volumeController);
- mAudioManager.abandonAudioFocus(listenerAlarm);
- } catch (Exception e) {
- fail(e.getMessage());
- }
- }
-
- public void testVolumeKeys() throws Exception {
- try {
- setupExternalVolumeEmulation(false);
- int musicVol = 10;
- mCarAudioManager.setStreamVolume(AudioManager.STREAM_MUSIC, musicVol, 0);
- int callVol = 12;
- mCarAudioManager.setStreamVolume(AudioManager.STREAM_VOICE_CALL, callVol, 0);
-
- CarAudioFocusTest.AudioFocusListener listenerMusic =
- new CarAudioFocusTest.AudioFocusListener();
- int res = doRequestFocus(mAudioManager, listenerMusic,
- AudioManager.STREAM_MUSIC,
- AudioManager.AUDIOFOCUS_GAIN);
- assertEquals(AudioManager.AUDIOFOCUS_REQUEST_GRANTED, res);
- int[] request = mAudioFocusPropertyHandler.waitForAudioFocusRequest(TIMEOUT_MS);
- mAudioFocusPropertyHandler.sendAudioFocusState(
- VehicleAudioFocusState.STATE_GAIN,
- request[1],
- VehicleAudioExtFocusFlag.NONE_FLAG);
-
-
- assertEquals(musicVol, mCarAudioManager.getStreamVolume(AudioManager.STREAM_MUSIC));
- sendVolumeKey(true /*vol up*/);
- musicVol++;
- volumeVerificationPoll(createStreamVolPair(AudioManager.STREAM_MUSIC, musicVol));
-
- // call start
- CarAudioFocusTest.AudioFocusListener listenerCall = new
- CarAudioFocusTest.AudioFocusListener();
- AudioAttributes callAttrib = (new AudioAttributes.Builder()).
- setUsage(AudioAttributes.USAGE_VOICE_COMMUNICATION).
- build();
- doRequestFocus(mAudioManager, listenerCall, callAttrib,
- AudioManager.AUDIOFOCUS_GAIN_TRANSIENT_MAY_DUCK);
- request = mAudioFocusPropertyHandler.waitForAudioFocusRequest(TIMEOUT_MS);
- mAudioFocusPropertyHandler.sendAudioFocusState(
- VehicleAudioFocusState.STATE_GAIN, request[1],
- VehicleAudioExtFocusFlag.NONE_FLAG);
-
- sendVolumeKey(true /*vol up*/);
- callVol++;
- volumeVerificationPoll(createStreamVolPair(AudioManager.STREAM_MUSIC, musicVol),
- createStreamVolPair(AudioManager.STREAM_VOICE_CALL, callVol));
- } catch (CarNotConnectedException | InterruptedException e) {
- fail(e.toString());
- }
- }
-
- private Pair<Integer, Integer> createStreamVolPair(int stream, int vol) {
- return new Pair<>(stream, vol);
- }
-
- private void volumeVerificationPoll(Pair<Integer, Integer>... expectedStreamVolPairs) {
- boolean isVolExpected = false;
- int timeElapsedMs = 0;
- try {
- while (!isVolExpected && timeElapsedMs <= TIMEOUT_MS) {
- Thread.sleep(POLL_INTERVAL_MS);
- isVolExpected = true;
- for (Pair<Integer, Integer> vol : expectedStreamVolPairs) {
- if (mCarAudioManager.getStreamVolume(vol.first) != vol.second) {
- isVolExpected = false;
- break;
- }
- }
- timeElapsedMs += POLL_INTERVAL_MS;
- }
- assertEquals(isVolExpected, true);
- } catch (InterruptedException | CarNotConnectedException e) {
- fail(e.toString());
- }
- }
-
- private void volumeChangeVerificationPoll(int stream, boolean showUI,
- VolumeController controller) {
- boolean isVolExpected = false;
- int timeElapsedMs = 0;
- try {
- while (!isVolExpected && timeElapsedMs <= TIMEOUT_MS) {
- Thread.sleep(POLL_INTERVAL_MS);
- Pair<Integer, Integer> volChange = controller.getLastVolumeChanges();
- if (volChange.first == stream
- && (((volChange.second.intValue() & AudioManager.FLAG_SHOW_UI) != 0)
- == showUI)) {
- isVolExpected = true;
- break;
- }
- timeElapsedMs += POLL_INTERVAL_MS;
- }
- assertEquals(true, isVolExpected);
- } catch (Exception e) {
- fail(e.toString());
- }
- }
-
- private class SingleChannelVolumeHandler implements VehicleHalPropertyHandler {
- private final List<Integer> mMaxs;
- private final SparseIntArray mCurrent;
-
- public SingleChannelVolumeHandler(List<Integer> maxs) {
- mMaxs = maxs;
- int size = maxs.size();
- mCurrent = new SparseIntArray(size);
- // initialize the vol to be the min volume.
- for (int i = 0; i < size; i++) {
- mCurrent.put(i, mMaxs.get(i));
- }
- }
-
- public void injectVolumeEvent(int context, int volume) {
- getMockedVehicleHal().injectEvent(
- VehiclePropValueBuilder.newBuilder(VehicleProperty.AUDIO_VOLUME)
- .setTimestamp(SystemClock.elapsedRealtimeNanos())
- .addIntValue(context, volume, 0)
- .build());
- }
-
- @Override
- public void onPropertySet(VehiclePropValue value) {
- ArrayList<Integer> v = value.value.int32Values;
- int stream = v.get(VehicleAudioVolumeIndex.STREAM);
- int volume = v.get(VehicleAudioVolumeIndex.VOLUME);
- int state = v.get(VehicleAudioVolumeIndex.STATE);
- Log.d(TAG, "state " + state);
-
- mCurrent.put(stream, volume);
- getMockedVehicleHal().injectEvent(
- VehiclePropValueBuilder.newBuilder(VehicleProperty.AUDIO_VOLUME)
- .setTimestamp(SystemClock.elapsedRealtimeNanos())
- .addIntValue(stream, volume, state)
- .build());
- }
-
- @Override
- public VehiclePropValue onPropertyGet(VehiclePropValue value) {
- int stream = value.value.int32Values.get(VehicleAudioVolumeIndex.STREAM);
- int volume = mCurrent.get(stream);
- return VehiclePropValueBuilder.newBuilder(VehicleProperty.AUDIO_VOLUME)
- .setTimestamp(SystemClock.elapsedRealtimeNanos())
- .addIntValue(stream, volume, 0)
- .build();
- }
-
- @Override
- public void onPropertySubscribe(int property, int zones, float sampleRate) {
- }
-
- @Override
- public void onPropertyUnsubscribe(int property) {
- }
- }
-
- private final CarAudioFocusTest.FocusPropertyHandler mAudioFocusPropertyHandler =
- new CarAudioFocusTest.FocusPropertyHandler(this);
-
- private final VehicleHalPropertyHandler mAudioRoutingPolicyPropertyHandler =
- new VehicleHalPropertyHandler() {
- @Override
- public void onPropertySet(VehiclePropValue value) {
- //TODO
- }
-
- @Override
- public VehiclePropValue onPropertyGet(VehiclePropValue value) {
- fail("cannot get");
- return null;
- }
-
- @Override
- public void onPropertySubscribe(int property, int zones, float sampleRate) {
- fail("cannot subscribe");
- }
-
- @Override
- public void onPropertyUnsubscribe(int property) {
- fail("cannot unsubscribe");
- }
- };
-
- private final VehicleHalPropertyHandler mHWKeyHandler = new VehicleHalPropertyHandler() {
- @Override
- public void onPropertySet(VehiclePropValue value) {
- //TODO
- }
-
- @Override
- public VehiclePropValue onPropertyGet(VehiclePropValue value) {
- return VehiclePropValueBuilder.newBuilder(VehicleProperty.HW_KEY_INPUT)
- .setTimestamp(SystemClock.elapsedRealtimeNanos())
- .addIntValue(0, 0, 0, 0)
- .build();
- }
-
- @Override
- public void onPropertySubscribe(int property, int zones, float sampleRate) {
- //
- }
-
- @Override
- public void onPropertyUnsubscribe(int property) {
- //
- }
- };
-
- private SingleChannelVolumeHandler startVolumeEmulation(int supportedAudioVolumeContext,
- List<Integer> maxs) {
- SingleChannelVolumeHandler singleChannelVolumeHandler =
- new SingleChannelVolumeHandler(maxs);
- int zones = (1<<maxs.size()) - 1;
-
- ArrayList<Integer> audioVolumeConfigArray =
- Lists.newArrayList(
- supportedAudioVolumeContext,
- 0 /* capability flag*/,
- 0, /* reserved */
- 0 /* reserved */);
- audioVolumeConfigArray.addAll(maxs);
-
- addProperty(VehicleProperty.AUDIO_VOLUME, singleChannelVolumeHandler)
- .setConfigArray(audioVolumeConfigArray)
- .setSupportedAreas(zones);
-
- addProperty(VehicleProperty.HW_KEY_INPUT, mHWKeyHandler)
- .setAccess(VehiclePropertyAccess.READ);
-
- addProperty(VehicleProperty.AUDIO_FOCUS, mAudioFocusPropertyHandler);
-
- addProperty(VehicleProperty.AUDIO_ROUTING_POLICY, mAudioRoutingPolicyPropertyHandler)
- .setAccess(VehiclePropertyAccess.WRITE);
-
- addStaticProperty(VehicleProperty.AUDIO_HW_VARIANT,
- VehiclePropValueBuilder.newBuilder(VehicleProperty.AUDIO_HW_VARIANT)
- .addIntValue(-1)
- .build())
- .setConfigArray(Lists.newArrayList(0));
-
- reinitializeMockedHal();
- return singleChannelVolumeHandler;
- }
-
- private void sendVolumeKey(boolean volUp) {
- int[] actionDown = {
- VehicleHwKeyInputAction.ACTION_DOWN,
- volUp ? KeyEvent.KEYCODE_VOLUME_UP : KeyEvent.KEYCODE_VOLUME_DOWN, 0, 0};
-
- VehiclePropValue injectValue =
- VehiclePropValueBuilder.newBuilder(VehicleProperty.HW_KEY_INPUT)
- .setTimestamp(SystemClock.elapsedRealtimeNanos())
- .addIntValue(actionDown)
- .build();
-
- getMockedVehicleHal().injectEvent(injectValue);
-
- int[] actionUp = {
- VehicleHwKeyInputAction.ACTION_UP,
- volUp ? KeyEvent.KEYCODE_VOLUME_UP : KeyEvent.KEYCODE_VOLUME_DOWN, 0, 0 };
-
- injectValue =
- VehiclePropValueBuilder.newBuilder(VehicleProperty.HW_KEY_INPUT)
- .setTimestamp(SystemClock.elapsedRealtimeNanos())
- .addIntValue(actionUp)
- .build();
-
- getMockedVehicleHal().injectEvent(injectValue);
- }
-
- private static class VolumeController extends IVolumeController.Stub {
- @GuardedBy("this")
- private int mLastStreamChanged = -1;
-
- @GuardedBy("this")
- private int mLastFlags = -1;
-
- public synchronized Pair<Integer, Integer> getLastVolumeChanges() {
- return new Pair<>(mLastStreamChanged, mLastFlags);
- }
-
- @Override
- public void displaySafeVolumeWarning(int flags) throws RemoteException {}
-
- @Override
- public void volumeChanged(int streamType, int flags) throws RemoteException {
- synchronized (this) {
- mLastStreamChanged = streamType;
- mLastFlags = flags;
- }
- }
-
- @Override
- public void masterMuteChanged(int flags) throws RemoteException {}
-
- @Override
- public void setLayoutDirection(int layoutDirection) throws RemoteException {
- }
-
- @Override
- public void dismiss() throws RemoteException {
- }
-
- @Override
- public void setA11yMode(int mode) throws RemoteException {
- }
- }
-}
diff --git a/tests/carservice_test/src/com/android/car/test/GarageModeTest.java b/tests/carservice_test/src/com/android/car/test/GarageModeTest.java
deleted file mode 100644
index 19ccb6e..0000000
--- a/tests/carservice_test/src/com/android/car/test/GarageModeTest.java
+++ /dev/null
@@ -1,148 +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.test;
-
-import android.car.settings.CarSettings;
-import android.content.Context;
-import android.test.AndroidTestCase;
-import android.test.suitebuilder.annotation.MediumTest;
-
-import com.android.car.CarPowerManagementService;
-import com.android.car.DeviceIdleControllerWrapper;
-import com.android.car.GarageModeService;
-
-@MediumTest
-public class GarageModeTest extends AndroidTestCase {
-
- 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());
-
- controller.setMaintenanceActivity(false);
- assertEquals(false, garageMode.isInGarageMode());
- assertEquals(false, garageMode.isMaintenanceActive());
- final int index2 = garageMode.getGarageModeIndex();
-
- assertEquals(1, index2 - index1);
- }
-
- 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 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());
- }
-
- 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 {
- public GarageModeServiceForTest(Context context,
- CarPowerManagementService powerManagementService,
- DeviceIdleControllerWrapper controllerWrapper) {
- super(context, powerManagementService, controllerWrapper);
- }
-
- 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 static class MockDeviceIdleController extends DeviceIdleControllerWrapper {
-
- private final boolean mInitialActive;
- public 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);
- }
- }
-}
diff --git a/tests/carservice_test/src/com/android/car/test/MockedCarTestBase.java b/tests/carservice_test/src/com/android/car/test/MockedCarTestBase.java
deleted file mode 100644
index a060496..0000000
--- a/tests/carservice_test/src/com/android/car/test/MockedCarTestBase.java
+++ /dev/null
@@ -1,296 +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.test;
-
-import android.car.test.CarTestManager;
-import android.car.test.CarTestManagerBinderWrapper;
-import android.content.ComponentName;
-import android.content.Context;
-import android.content.ServiceConnection;
-import android.content.pm.PackageManager.NameNotFoundException;
-import android.hardware.automotive.vehicle.V2_0.VehiclePropValue;
-import android.hardware.automotive.vehicle.V2_0.VehiclePropertyAccess;
-import android.hardware.automotive.vehicle.V2_0.VehiclePropertyChangeMode;
-import android.os.Binder;
-import android.os.Handler;
-import android.os.IBinder;
-import android.os.Looper;
-import android.test.AndroidTestCase;
-import android.util.Log;
-
-import com.android.car.CarPowerManagementService;
-import com.android.car.ICarImpl;
-import com.android.car.SystemInterface;
-import com.android.car.vehiclehal.test.MockedVehicleHal;
-import com.android.car.vehiclehal.test.MockedVehicleHal.DefaultPropertyHandler;
-import com.android.car.vehiclehal.test.MockedVehicleHal.StaticPropertyHandler;
-import com.android.car.vehiclehal.test.MockedVehicleHal.VehicleHalPropertyHandler;
-import com.android.car.vehiclehal.test.VehiclePropConfigBuilder;
-
-import java.util.Arrays;
-import java.util.HashMap;
-import java.util.Map;
-import java.util.concurrent.Semaphore;
-import java.util.concurrent.TimeUnit;
-
-/**
- * Base class for testing with mocked vehicle HAL (=car).
- * It is up to each app to start emulation by getMockedVehicleHal().start() as there will be
- * per test set up that should be done before starting.
- */
-public class MockedCarTestBase extends AndroidTestCase {
- private static final String TAG = MockedCarTestBase.class.getSimpleName();
- static final long DEFAULT_WAIT_TIMEOUT_MS = 3000;
- static final long SHORT_WAIT_TIMEOUT_MS = 500;
-
- private android.car.Car mCar;
- private ICarImpl mCarImpl;
- private MockedVehicleHal mMockedVehicleHal;
- private FakeSystemInterface mFakeSystemInterface;
-
- private final Semaphore mWaitForMain = new Semaphore(0);
- private final Handler mMainHandler = new Handler(Looper.getMainLooper());
-
- private static final IBinder mCarServiceToken = new Binder();
- private static boolean mRealCarServiceReleased = false;
-
- protected synchronized MockedVehicleHal createMockedVehicleHal() {
- return new MockedVehicleHal();
- }
-
- protected synchronized MockedVehicleHal getMockedVehicleHal() {
- return mMockedVehicleHal;
- }
-
- protected synchronized void configureMockedHal() {
- }
-
- @Override
- protected synchronized void setUp() throws Exception {
- super.setUp();
-
- releaseRealCarService(getContext());
-
- mMockedVehicleHal = createMockedVehicleHal();
- configureMockedHal();
-
- mFakeSystemInterface = new FakeSystemInterface();
- Context context = getCarServiceContext();
- mCarImpl = new ICarImpl(context, mMockedVehicleHal, mFakeSystemInterface,
- null /* error notifier */);
-
- initMockedHal(false /* no need to release */);
-
- mCar = new android.car.Car(context, mCarImpl, null /* handler */);
- }
-
- @Override
- protected synchronized void tearDown() throws Exception {
- super.tearDown();
-
- mCar.disconnect();
- mCarImpl.release();
- }
-
- protected Context getCarServiceContext() throws NameNotFoundException {
- return getContext()
- .createPackageContext("com.android.car", Context.CONTEXT_IGNORE_SECURITY);
- }
-
- protected synchronized void reinitializeMockedHal() {
- initMockedHal(true /* release */);
- }
-
- private synchronized void initMockedHal(boolean release) {
- if (release) {
- mCarImpl.release();
- }
-
- for (Map.Entry<VehiclePropConfigBuilder, VehicleHalPropertyHandler> entry
- : mHalConfig.entrySet()) {
- mMockedVehicleHal.addProperty(entry.getKey().build(), entry.getValue());
- }
- mHalConfig.clear();
- mCarImpl.init();
- }
-
- private final Map<VehiclePropConfigBuilder, VehicleHalPropertyHandler> mHalConfig =
- new HashMap<>();
-
- protected synchronized VehiclePropConfigBuilder addProperty(int propertyId,
- VehicleHalPropertyHandler propertyHandler) {
- VehiclePropConfigBuilder builder = VehiclePropConfigBuilder.newBuilder(propertyId);
- mHalConfig.put(builder, propertyHandler);
- return builder;
- }
-
- protected synchronized VehiclePropConfigBuilder addProperty(int propertyId) {
- VehiclePropConfigBuilder builder = VehiclePropConfigBuilder.newBuilder(propertyId);
- mHalConfig.put(builder, new DefaultPropertyHandler(builder.build(), null));
- return builder;
- }
-
- protected synchronized VehiclePropConfigBuilder addProperty(int propertyId,
- VehiclePropValue value) {
- VehiclePropConfigBuilder builder = VehiclePropConfigBuilder.newBuilder(propertyId);
- mHalConfig.put(builder, new DefaultPropertyHandler(builder.build(), value));
- return builder;
- }
-
- protected synchronized VehiclePropConfigBuilder addStaticProperty(int propertyId,
- VehiclePropValue value) {
- VehiclePropConfigBuilder builder = VehiclePropConfigBuilder.newBuilder(propertyId)
- .setChangeMode(VehiclePropertyChangeMode.STATIC)
- .setAccess(VehiclePropertyAccess.READ);
-
- mHalConfig.put(builder, new StaticPropertyHandler(value));
- return builder;
- }
-
- protected synchronized android.car.Car getCar() {
- return mCar;
- }
-
- protected void runOnMain(final Runnable r) {
- mMainHandler.post(r);
- }
-
- protected void runOnMainSync(final Runnable r) throws Exception {
- mMainHandler.post(new Runnable() {
- @Override
- public void run() {
- r.run();
- mWaitForMain.release();
- }
- });
- mWaitForMain.acquire();
- }
-
- protected boolean waitForFakeDisplayState(boolean expectedState) throws Exception {
- return mFakeSystemInterface.waitForDisplayState(expectedState, SHORT_WAIT_TIMEOUT_MS);
- }
-
- public static <T> void assertArrayEquals(T[] expected, T[] actual) {
- if (!Arrays.equals(expected, actual)) {
- fail("expected:<" + Arrays.toString(expected) +
- "> but was:<" + Arrays.toString(actual) + ">");
- }
- }
-
- public static void assertArrayEquals(int[] expected, int[] actual) {
- if (!Arrays.equals(expected, actual)) {
- fail("expected:<" + Arrays.toString(expected) +
- "> but was:<" + Arrays.toString(actual) + ">");
- }
- }
-
- /*
- * In order to eliminate interfering with real car service we will disable it. It will be
- * enabled back in CarTestService when mCarServiceToken will go away (tests finish).
- */
- private synchronized static void releaseRealCarService(Context context) throws Exception {
- if (mRealCarServiceReleased) {
- return; // We just want to release it once.
- }
-
- mRealCarServiceReleased = true; // To make sure it was called once.
-
- Object waitForConnection = new Object();
- android.car.Car car = android.car.Car.createCar(context, new ServiceConnection() {
- @Override
- public void onServiceConnected(ComponentName name, IBinder service) {
- synchronized (waitForConnection) {
- waitForConnection.notify();
- }
- }
-
- @Override
- public void onServiceDisconnected(ComponentName name) { }
- });
-
- car.connect();
- synchronized (waitForConnection) {
- if (!car.isConnected()) {
- waitForConnection.wait(DEFAULT_WAIT_TIMEOUT_MS);
- }
- }
-
- if (car.isConnected()) {
- Log.i(TAG, "Connected to real car service");
- CarTestManagerBinderWrapper binderWrapper =
- (CarTestManagerBinderWrapper) car.getCarManager(android.car.Car.TEST_SERVICE);
- assertNotNull(binderWrapper);
-
- CarTestManager mgr = new CarTestManager(binderWrapper.binder);
- mgr.stopCarService(mCarServiceToken);
- }
- }
-
- private static class FakeSystemInterface extends SystemInterface {
-
- private boolean mDisplayOn = true;
- private final Semaphore mDisplayStateWait = new Semaphore(0);
-
- @Override
- public synchronized void setDisplayState(boolean on) {
- mDisplayOn = on;
- mDisplayStateWait.release();
- }
-
- boolean waitForDisplayState(boolean expectedState, long timeoutMs)
- throws Exception {
- if (expectedState == mDisplayOn) {
- return true;
- }
- mDisplayStateWait.tryAcquire(timeoutMs, TimeUnit.MILLISECONDS);
- return expectedState == mDisplayOn;
- }
-
- @Override
- public void releaseAllWakeLocks() {
- }
-
- @Override
- public void shutdown() { }
-
- @Override
- public void enterDeepSleep(int wakeupTimeSec) { }
-
- @Override
- public boolean isSystemSupportingDeepSleep() {
- return false;
- }
-
- @Override
- public void switchToPartialWakeLock() {
- }
-
- @Override
- public void switchToFullWakeLock() {
- }
-
- @Override
- public void startDisplayStateMonitoring(CarPowerManagementService service) {
- }
-
- @Override
- public void stopDisplayStateMonitoring() {
- }
-
- @Override
- public boolean isWakeupCausedByTimer() { return false; }
- }
-}
diff --git a/tests/carservice_test/src/com/android/car/test/SystemActivityMonitoringServiceTest.java b/tests/carservice_test/src/com/android/car/test/SystemActivityMonitoringServiceTest.java
deleted file mode 100644
index 3345605..0000000
--- a/tests/carservice_test/src/com/android/car/test/SystemActivityMonitoringServiceTest.java
+++ /dev/null
@@ -1,227 +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.test;
-
-import android.app.Activity;
-import android.content.ComponentName;
-import android.content.Intent;
-import android.hardware.automotive.vehicle.V2_0.VehicleDrivingStatus;
-import android.hardware.automotive.vehicle.V2_0.VehiclePropValue;
-import android.hardware.automotive.vehicle.V2_0.VehicleProperty;
-import android.hardware.automotive.vehicle.V2_0.VehiclePropertyAccess;
-import android.os.SystemClock;
-import android.test.suitebuilder.annotation.MediumTest;
-
-import com.android.car.SystemActivityMonitoringService;
-import com.android.car.SystemActivityMonitoringService.TopTaskInfoContainer;
-import com.android.car.vehiclehal.VehiclePropValueBuilder;
-import com.android.car.vehiclehal.test.MockedVehicleHal.VehicleHalPropertyHandler;
-
-import java.util.ArrayList;
-import java.util.List;
-import java.util.concurrent.Semaphore;
-import java.util.concurrent.TimeUnit;
-
-@MediumTest
-public class SystemActivityMonitoringServiceTest extends MockedCarTestBase {
- private static final long TIMEOUT_MS = 3000;
- private static final long POLL_INTERVAL_MS = 50;
- private static final Semaphore sAvailable = new Semaphore(0);
-
- private final DrivingStatusHandler mDrivingStatusHandler = new DrivingStatusHandler();
-
- @Override
- protected synchronized void configureMockedHal() {
- addProperty(VehicleProperty.DRIVING_STATUS, mDrivingStatusHandler)
- .setAccess(VehiclePropertyAccess.READ);
- }
-
- private void init(boolean drivingStatusRestricted) {
- // Set no restriction to driving status, to avoid CarPackageManagerService to launch a
- // blocking activity.
- mDrivingStatusHandler.setDrivingStatusRestricted(drivingStatusRestricted);
-
- // Due to asynchronous nature of Car Service initialization, if we won't wait we may inject
- // an event while SensorHalService is not subscribed yet.
- assertTrue(getMockedVehicleHal()
- .waitForSubscriber(VehicleProperty.DRIVING_STATUS, TIMEOUT_MS));
-
- VehiclePropValue injectValue =
- VehiclePropValueBuilder.newBuilder(VehicleProperty.DRIVING_STATUS)
- .setTimestamp(SystemClock.elapsedRealtimeNanos())
- .addIntValue(0)
- .build();
- getMockedVehicleHal().injectEvent(injectValue);
- }
-
- public void testActivityLaunch() {
- init(false);
- List<TopTaskInfoContainer> taskList = new ArrayList<>();
- SystemActivityMonitoringService systemActivityMonitoringService =
- new SystemActivityMonitoringService(getContext());
- systemActivityMonitoringService.registerActivityLaunchListener(
- new SystemActivityMonitoringService.ActivityLaunchListener() {
- @Override
- public void onActivityLaunch(
- SystemActivityMonitoringService.TopTaskInfoContainer topTask) {
- taskList.add(topTask);
- }
- });
- getContext().startActivity(new Intent(getContext(), ActivityA.class));
- verifyTopActivityPolling(taskList, 0, new ComponentName(getContext().getPackageName(),
- ActivityA.class.getName()));
- sAvailable.release();
-
- verifyTopActivityPolling(taskList, 1, new ComponentName(getContext().getPackageName(),
- ActivityB.class.getName()));
- sAvailable.release();
-
- verifyTopActivityPolling(taskList, 2, new ComponentName(getContext().getPackageName(),
- ActivityC.class.getName()));
- }
-
- public void testActivityBlocking() {
- init(false);
- Semaphore blocked = new Semaphore(0);
- List<TopTaskInfoContainer> taskList = new ArrayList<>();
- SystemActivityMonitoringService systemActivityMonitoringService =
- new SystemActivityMonitoringService(getContext());
-
- ComponentName blackListedActivity = new ComponentName(getContext().getPackageName(),
- ActivityC.class.getName());
- ComponentName blockingActivity = new ComponentName(getContext().getPackageName(),
- BlockingActivity.class.getName());
- Intent newActivityIntent = new Intent();
- newActivityIntent.setComponent(blockingActivity);
-
- systemActivityMonitoringService.registerActivityLaunchListener(
- new SystemActivityMonitoringService.ActivityLaunchListener() {
- @Override
- public void onActivityLaunch(
- SystemActivityMonitoringService.TopTaskInfoContainer topTask) {
- taskList.add(topTask);
- if (topTask.topActivity.equals(blackListedActivity)) {
- systemActivityMonitoringService.blockActivity(topTask,
- newActivityIntent);
- blocked.release();
- }
- }
- });
- // start a black listed activity
- getContext().startActivity(new Intent(getContext(), ActivityC.class));
- // wait for the listener to call blockActivity()
- try {
- blocked.tryAcquire(2, TimeUnit.SECONDS);
- } catch (InterruptedException e) {
- fail(e.getMessage());
- }
- // We should first receive the blackListedActivity launch,
- // and later the blockActivity launch
- verifyTopActivityPolling(taskList, 0, blackListedActivity);
- verifyTopActivityPolling(taskList, 1, blockingActivity);
- }
-
- private void verifyTopActivityPolling(
- List<TopTaskInfoContainer> topTaskList, int i, ComponentName activity) {
- boolean activityVerified = false;
- int timeElapsedMs = 0;
- try {
- while (!activityVerified && timeElapsedMs <= TIMEOUT_MS) {
- Thread.sleep(POLL_INTERVAL_MS);
- timeElapsedMs += POLL_INTERVAL_MS;
- if (topTaskList.size() <= i) continue;
- TopTaskInfoContainer topTask = topTaskList.get(i);
- if (topTask != null && topTask.topActivity.equals(activity)) {
- activityVerified = true;
- break;
- }
- }
- assertEquals(true, activityVerified);
- } catch (Exception e) {
- fail(e.toString());
- }
- }
-
- public static class ActivityA extends Activity {
- @Override
- protected void onPostResume() {
- super.onPostResume();
- // Wait until the activity launch event is consumed by the listener.
- try {
- if (!sAvailable.tryAcquire(2, TimeUnit.SECONDS)) {
- fail("Time out");
- }
- } catch (Exception e) {
- fail(e.toString());
- }
- Intent intent = new Intent(this, ActivityB.class);
- intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
- startActivity(intent);
- }
- }
-
- public static class ActivityB extends Activity {
- @Override
- protected void onPostResume() {
- super.onPostResume();
- // Wait until the activity launch event is consumed by the listener.
- try {
- if (!sAvailable.tryAcquire(2, TimeUnit.SECONDS)) {
- fail("Time out");
- }
- } catch (Exception e) {
- fail(e.toString());
- }
- Intent intent = new Intent(this, ActivityC.class);
- startActivity(intent);
- }
- }
-
- public static class ActivityC extends Activity {
- }
-
- public static class BlockingActivity extends Activity {
- }
-
- private class DrivingStatusHandler implements VehicleHalPropertyHandler {
- int mDrivingStatus = VehicleDrivingStatus.UNRESTRICTED;
-
- public void setDrivingStatusRestricted(boolean restricted) {
- mDrivingStatus = restricted ? VehicleDrivingStatus.NO_VIDEO
- : VehicleDrivingStatus.UNRESTRICTED;
- }
-
- @Override
- public void onPropertySet(VehiclePropValue value) {
- }
-
- @Override
- public VehiclePropValue onPropertyGet(VehiclePropValue value) {
- return VehiclePropValueBuilder.newBuilder(VehicleProperty.DRIVING_STATUS)
- .setTimestamp(SystemClock.elapsedRealtimeNanos())
- .addIntValue(mDrivingStatus)
- .build();
- }
-
- @Override
- public void onPropertySubscribe(int property, int zones, float sampleRate) {
- }
-
- @Override
- public void onPropertyUnsubscribe(int property) {
- }
- }
-}
\ No newline at end of file
diff --git a/tests/carservice_test/src/com/android/car/test/VmsPublisherSubscriberTest.java b/tests/carservice_test/src/com/android/car/test/VmsPublisherSubscriberTest.java
deleted file mode 100644
index 5b387d2..0000000
--- a/tests/carservice_test/src/com/android/car/test/VmsPublisherSubscriberTest.java
+++ /dev/null
@@ -1,238 +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.android.car.test;
-
-import android.annotation.ArrayRes;
-import android.car.Car;
-import android.car.VehicleAreaType;
-import android.car.annotation.FutureFeature;
-import android.car.vms.VmsAssociatedLayer;
-import android.car.vms.VmsLayer;
-import android.car.vms.VmsSubscriberManager;
-import android.content.Context;
-import android.content.ContextWrapper;
-import android.content.pm.PackageManager;
-import android.content.res.Resources;
-import android.hardware.automotive.vehicle.V2_0.VehiclePropertyAccess;
-import android.hardware.automotive.vehicle.V2_0.VehiclePropertyChangeMode;
-import android.hardware.automotive.vehicle.V2_0.VehicleProperty;
-import android.test.suitebuilder.annotation.MediumTest;
-
-import com.android.car.vehiclehal.test.MockedVehicleHal;
-
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.HashSet;
-import java.util.List;
-import java.util.concurrent.Semaphore;
-import java.util.concurrent.TimeUnit;
-
-@FutureFeature
-@MediumTest
-public class VmsPublisherSubscriberTest extends MockedCarTestBase {
- private static final int LAYER_ID = 88;
- private static final int LAYER_VERSION = 19;
- private static final int LAYER_SUBTYPE = 55;
- private static final String TAG = "VmsPubSubTest";
-
- // The expected publisher ID is 0 since it the expected assigned ID from the VMS core.
- public static final int EXPECTED_PUBLISHER_ID = 0;
- public static final VmsLayer LAYER = new VmsLayer(LAYER_ID, LAYER_SUBTYPE, LAYER_VERSION);
- public static final VmsAssociatedLayer ASSOCIATED_LAYER =
- new VmsAssociatedLayer(LAYER, new HashSet<>(Arrays.asList(EXPECTED_PUBLISHER_ID)));
- public static final byte[] PAYLOAD = new byte[]{2, 3, 5, 7, 11, 13, 17};
-
- private static final List<VmsAssociatedLayer> AVAILABLE_ASSOCIATED_LAYERS =
- new ArrayList<>(Arrays.asList(ASSOCIATED_LAYER));
-
-
- private static final int SUBSCRIBED_LAYER_ID = 89;
- public static final VmsLayer SUBSCRIBED_LAYER =
- new VmsLayer(SUBSCRIBED_LAYER_ID, LAYER_SUBTYPE, LAYER_VERSION);
- public static final VmsAssociatedLayer ASSOCIATED_SUBSCRIBED_LAYER =
- new VmsAssociatedLayer(SUBSCRIBED_LAYER, new HashSet<>(Arrays.asList(EXPECTED_PUBLISHER_ID)));
- private static final List<VmsAssociatedLayer> AVAILABLE_ASSOCIATED_LAYERS_WITH_SUBSCRIBED_LAYER =
- new ArrayList<>(Arrays.asList(ASSOCIATED_LAYER, ASSOCIATED_SUBSCRIBED_LAYER));
-
-
- private HalHandler mHalHandler;
- // Used to block until a value is propagated to the TestClientCallback.onVmsMessageReceived.
- private Semaphore mSubscriberSemaphore;
- private Semaphore mAvailabilitySemaphore;
-
- @Override
- protected synchronized void configureMockedHal() {
- mHalHandler = new HalHandler();
- addProperty(VehicleProperty.VEHICLE_MAP_SERVICE, mHalHandler)
- .setChangeMode(VehiclePropertyChangeMode.ON_CHANGE)
- .setAccess(VehiclePropertyAccess.READ_WRITE)
- .setSupportedAreas(VehicleAreaType.VEHICLE_AREA_TYPE_NONE);
- }
-
- /**
- * Creates a context with the resource vmsPublisherClients overridden. The overridden value
- * contains the name of the test service defined also in this test package.
- */
- @Override
- protected Context getCarServiceContext() throws PackageManager.NameNotFoundException {
- Context context = getContext()
- .createPackageContext("com.android.car", Context.CONTEXT_IGNORE_SECURITY);
- Resources resources = new Resources(context.getAssets(),
- context.getResources().getDisplayMetrics(),
- context.getResources().getConfiguration()) {
- @Override
- public String[] getStringArray(@ArrayRes int id) throws NotFoundException {
- if (id == com.android.car.R.array.vmsPublisherClients) {
- return new String[]{"com.android.car.test/.VmsPublisherClientMockService"};
- }
- return super.getStringArray(id);
- }
- };
- ContextWrapper wrapper = new ContextWrapper(context) {
- @Override
- public Resources getResources() {
- return resources;
- }
- };
- return wrapper;
- }
-
- @Override
- protected void setUp() throws Exception {
- if (!VmsTestUtils.canRunTest(TAG)) return;
- super.setUp();
- mSubscriberSemaphore = new Semaphore(0);
- mAvailabilitySemaphore = new Semaphore(0);
- }
-
- @Override
- protected synchronized void tearDown() throws Exception {
- if (!VmsTestUtils.canRunTest(TAG)) return;
- super.tearDown();
- }
-
- /**
- * The method setUp initializes all the Car services, including the VmsPublisherService.
- * The VmsPublisherService will start and configure its list of clients. This list was
- * overridden in the method getCarServiceContext. Therefore, only VmsPublisherClientMockService
- * will be started. This test method subscribes to a layer and triggers
- * VmsPublisherClientMockService.onVmsSubscriptionChange. In turn, the mock service will publish
- * a message, which is validated in this test.
- */
- public void testPublisherToSubscriber() throws Exception {
- if (!VmsTestUtils.canRunTest(TAG)) return;
- VmsSubscriberManager vmsSubscriberManager = (VmsSubscriberManager) getCar().getCarManager(
- Car.VMS_SUBSCRIBER_SERVICE);
- TestClientCallback clientCallback = new TestClientCallback();
- vmsSubscriberManager.registerClientCallback(clientCallback);
- vmsSubscriberManager.subscribe(LAYER);
-
- assertTrue(mSubscriberSemaphore.tryAcquire(2L, TimeUnit.SECONDS));
- assertEquals(LAYER, clientCallback.getLayer());
- assertTrue(Arrays.equals(PAYLOAD, clientCallback.getPayload()));
- }
-
- /**
- * The Mock service will get a publisher ID by sending its information when it will get
- * ServiceReady as well as on SubscriptionChange. Since clients are not notified when
- * publishers are assigned IDs, this test waits until the availability is changed which indicates
- * that the Mock service has gotten its ServiceReady and publisherId.
- */
- public void testPublisherInfo() throws Exception {
- if (!VmsTestUtils.canRunTest(TAG)) return;
- VmsSubscriberManager vmsSubscriberManager = (VmsSubscriberManager) getCar().getCarManager(
- Car.VMS_SUBSCRIBER_SERVICE);
- // Subscribe to layer as a way to make sure the mock client completed setting the information.
- TestClientCallback clientCallback = new TestClientCallback();
- vmsSubscriberManager.registerClientCallback(clientCallback);
- vmsSubscriberManager.subscribe(LAYER);
-
- assertTrue(mAvailabilitySemaphore.tryAcquire(2L, TimeUnit.SECONDS));
-
- byte[] info = vmsSubscriberManager.getPublisherInfo(EXPECTED_PUBLISHER_ID);
- assertTrue(Arrays.equals(PAYLOAD, info));
- }
-
- /**
- * The Mock service offers all the subscribed layers as available layers.
- * In this test the client subscribes to a layer and verifies that it gets the
- * notification that it is available.
- */
- public void testAvailabilityWithSubscription() throws Exception {
- if (!VmsTestUtils.canRunTest(TAG)) return;
- VmsSubscriberManager vmsSubscriberManager = (VmsSubscriberManager) getCar().getCarManager(
- Car.VMS_SUBSCRIBER_SERVICE);
- TestClientCallback clientCallback = new TestClientCallback();
- vmsSubscriberManager.registerClientCallback(clientCallback);
- vmsSubscriberManager.subscribe(SUBSCRIBED_LAYER);
-
- assertTrue(mAvailabilitySemaphore.tryAcquire(2L, TimeUnit.SECONDS));
- assertEquals(AVAILABLE_ASSOCIATED_LAYERS_WITH_SUBSCRIBED_LAYER, clientCallback.getAvailalbeLayers());
- }
-
- /**
- * The Mock service offers all the subscribed layers as available layers, so in this
- * test the client subscribes to a layer and verifies that it gets the notification that it
- * is available.
- */
- public void testAvailabilityWithoutSubscription() throws Exception {
- if (!VmsTestUtils.canRunTest(TAG)) return;
- VmsSubscriberManager vmsSubscriberManager = (VmsSubscriberManager) getCar().getCarManager(
- Car.VMS_SUBSCRIBER_SERVICE);
- TestClientCallback clientCallback = new TestClientCallback();
- vmsSubscriberManager.registerClientCallback(clientCallback);
-
- assertTrue(mAvailabilitySemaphore.tryAcquire(2L, TimeUnit.SECONDS));
- assertEquals(AVAILABLE_ASSOCIATED_LAYERS, clientCallback.getAvailalbeLayers());
- }
-
- private class HalHandler implements MockedVehicleHal.VehicleHalPropertyHandler {
- }
-
- private class TestClientCallback implements VmsSubscriberManager.VmsSubscriberClientCallback {
- private VmsLayer mLayer;
- private byte[] mPayload;
- private List<VmsLayer> mAvailableLayers;
-
- @Override
- public void onVmsMessageReceived(VmsLayer layer, byte[] payload) {
- assertEquals(LAYER, layer);
- assertTrue(Arrays.equals(PAYLOAD, payload));
- mLayer = layer;
- mPayload = payload;
- mSubscriberSemaphore.release();
- }
-
- @Override
- public void onLayersAvailabilityChanged(List<VmsLayer> availableLayers) {
- mAvailableLayers = availableLayers;
- mAvailabilitySemaphore.release();
- }
-
- public VmsLayer getLayer() {
- return mLayer;
- }
-
- public byte[] getPayload() {
- return mPayload;
- }
-
- public List<VmsLayer> getAvailalbeLayers() {
- return mAvailableLayers;
- }
- }
-}
diff --git a/tests/carservice_test/src/com/android/car/test/VmsTestUtils.java b/tests/carservice_test/src/com/android/car/test/VmsTestUtils.java
deleted file mode 100644
index 2f3af52..0000000
--- a/tests/carservice_test/src/com/android/car/test/VmsTestUtils.java
+++ /dev/null
@@ -1,16 +0,0 @@
-package com.android.car.test;
-
-import android.car.annotation.FutureFeature;
-import android.util.Log;
-
-import com.android.car.internal.FeatureConfiguration;
-
-@FutureFeature
-public class VmsTestUtils {
- public static boolean canRunTest(String tag) {
- if (!FeatureConfiguration.ENABLE_VEHICLE_MAP_SERVICE) {
- Log.i(tag, "Skipping test because ENABLE_VEHICLE_MAP_SERVICE = false");
- }
- return FeatureConfiguration.ENABLE_VEHICLE_MAP_SERVICE;
- }
-}
diff --git a/tests/carservice_unit_test/Android.mk b/tests/carservice_unit_test/Android.mk
index 4b28475..06e50b7 100644
--- a/tests/carservice_unit_test/Android.mk
+++ b/tests/carservice_unit_test/Android.mk
@@ -34,7 +34,16 @@
LOCAL_INSTRUMENTATION_FOR := CarService
-LOCAL_JAVA_LIBRARIES := android.car android.test.runner
-LOCAL_STATIC_JAVA_LIBRARIES := junit legacy-android-test android-support-test mockito-target-minus-junit4
+LOCAL_JAVA_LIBRARIES := \
+ android.car \
+ android.test.runner \
+ android.test.base
+
+LOCAL_STATIC_JAVA_LIBRARIES := \
+ junit \
+ android-support-test \
+ mockito-target-minus-junit4 \
+ com.android.car.test.utils \
+ truth-prebuilt
include $(BUILD_PACKAGE)
diff --git a/tests/carservice_unit_test/src/com/android/car/BluetoothAutoConnectPolicyTest.java b/tests/carservice_unit_test/src/com/android/car/BluetoothAutoConnectPolicyTest.java
index 85ec54f..a180886 100644
--- a/tests/carservice_unit_test/src/com/android/car/BluetoothAutoConnectPolicyTest.java
+++ b/tests/carservice_unit_test/src/com/android/car/BluetoothAutoConnectPolicyTest.java
@@ -16,36 +16,41 @@
package com.android.car;
+import static org.mockito.Mockito.*;
+
import android.annotation.Nullable;
import android.bluetooth.BluetoothA2dpSink;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothHeadsetClient;
import android.bluetooth.BluetoothMapClient;
+import android.bluetooth.BluetoothPan;
import android.bluetooth.BluetoothPbapClient;
import android.bluetooth.BluetoothProfile;
+import android.car.CarBluetoothManager;
import android.car.ICarUserService;
import android.car.hardware.CarPropertyValue;
import android.car.hardware.cabin.CarCabinManager;
import android.car.hardware.property.CarPropertyEvent;
-import android.car.CarBluetoothManager;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
+import android.content.res.Resources;
import android.os.Handler;
import android.os.Looper;
import android.os.RemoteException;
import android.test.AndroidTestCase;
+import android.test.suitebuilder.annotation.Suppress;
+import org.junit.Test;
import org.mockito.Matchers;
+import org.mockito.Mock;
import org.mockito.Mockito;
-
-import static org.mockito.Mockito.*;
-
+import org.mockito.MockitoAnnotations;
import org.mockito.invocation.InvocationOnMock;
import org.mockito.stubbing.Answer;
-import org.junit.Test;
+import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
@@ -66,14 +71,17 @@
private BroadcastReceiver mReceiver;
private BluetoothDeviceConnectionPolicy.CarPropertyListener mCabinEventListener;
private Handler mMainHandler;
- private Context mockContext;
+ private Context mMockContext;
// Mock of Services that the policy interacts with
- private CarCabinService mockCarCabinService;
- private CarSensorService mockCarSensorService;
- private CarBluetoothUserService mockBluetoothUserService;
- private PerUserCarServiceHelper mockPerUserCarServiceHelper;
- private ICarUserService mockPerUserCarService;
- private CarBluetoothService mockCarBluetoothService;
+ private CarPropertyService mMockCarPropertyService;
+ private CarUxRestrictionsManagerService mMockCarUxRService;
+ private CarBluetoothUserService mMockBluetoothUserService;
+ private PerUserCarServiceHelper mMockPerUserCarServiceHelper;
+ private ICarUserService mMockPerUserCarService;
+ private CarBluetoothService mMockCarBluetoothService;
+ @Mock
+ private Resources mMockResources;
+
// Timeouts
private static final int CONNECTION_STATE_CHANGE_TIME = 200; //ms
private static final int CONNECTION_REQUEST_TIMEOUT = 10000;//ms
@@ -82,9 +90,12 @@
@Override
protected void setUp() throws Exception {
super.setUp();
+ MockitoAnnotations.initMocks(this);
mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
mMainHandler = new Handler(Looper.getMainLooper());
makeMockServices();
+ when(mMockResources.getInteger(R.integer.fastPairModelId)).thenReturn(0);
+ when(mMockContext.getResources()).thenReturn(mMockResources);
}
@Override
@@ -179,6 +190,9 @@
case BluetoothProfile.MAP_CLIENT:
connectionIntent = new Intent(BluetoothMapClient.ACTION_CONNECTION_STATE_CHANGED);
break;
+ case BluetoothProfile.PAN:
+ connectionIntent = new Intent(BluetoothPan.ACTION_CONNECTION_STATE_CHANGED);
+ break;
case BluetoothProfile.PBAP_CLIENT:
connectionIntent = new Intent(BluetoothPbapClient.ACTION_CONNECTION_STATE_CHANGED);
break;
@@ -206,23 +220,25 @@
private void triggerFakeVehicleEvent() throws RemoteException {
assertNotNull(mCabinEventListener);
CarPropertyValue<Boolean> value = new CarPropertyValue<>(CarCabinManager.ID_DOOR_LOCK,
- false);
+ 0, false);
CarPropertyEvent event = new CarPropertyEvent(
CarPropertyEvent.PROPERTY_EVENT_PROPERTY_CHANGE, value);
- mCabinEventListener.onEvent(event);
+ List<CarPropertyEvent> events = new ArrayList<>();
+ events.add(event);
+ mCabinEventListener.onEvent(events);
}
/**
* Put all the mock creations in one place. To be called from setup()
*/
private void makeMockServices() {
- mockContext = mock(Context.class);
- mockCarCabinService = mock(CarCabinService.class);
- mockCarSensorService = mock(CarSensorService.class);
- mockPerUserCarServiceHelper = mock(PerUserCarServiceHelper.class);
- mockPerUserCarService = mock(ICarUserService.class);
- mockCarBluetoothService = mock(CarBluetoothService.class);
- mockBluetoothUserService = mock(CarBluetoothUserService.class,
+ mMockContext = mock(Context.class);
+ mMockCarPropertyService = mock(CarPropertyService.class);
+ mMockCarUxRService = mock(CarUxRestrictionsManagerService.class);
+ mMockPerUserCarServiceHelper = mock(PerUserCarServiceHelper.class);
+ mMockPerUserCarService = mock(ICarUserService.class);
+ mMockCarBluetoothService = mock(CarBluetoothService.class);
+ mMockBluetoothUserService = mock(CarBluetoothUserService.class,
Mockito.withSettings().verboseLogging());
}
@@ -237,8 +253,8 @@
if (mBluetoothDeviceConnectionPolicyTest != null) {
for (Integer profile : mBluetoothDeviceConnectionPolicyTest.getProfilesToConnect()) {
Mockito.doAnswer(createDeviceAvailabilityAnswer(available)).when(
- mockBluetoothUserService).
- bluetoothConnectToProfile(profile, device);
+ mMockBluetoothUserService)
+ .bluetoothConnectToProfile(profile, device);
}
}
}
@@ -275,13 +291,14 @@
*/
private void createAndSetupBluetoothPolicy() throws Exception {
// Return the mock Bluetooth User Service when asked for
- when(mockBluetoothUserService.isBluetoothConnectionProxyAvailable(
+ when(mMockBluetoothUserService.isBluetoothConnectionProxyAvailable(
Matchers.anyInt())).thenReturn(true);
- when(mockPerUserCarService.getBluetoothUserService()).thenReturn(mockBluetoothUserService);
+ when(mMockPerUserCarService.getBluetoothUserService())
+ .thenReturn(mMockBluetoothUserService);
- mBluetoothDeviceConnectionPolicyTest = BluetoothDeviceConnectionPolicy.create(mockContext,
- mockCarCabinService, mockCarSensorService, mockPerUserCarServiceHelper,
- mockCarBluetoothService);
+ mBluetoothDeviceConnectionPolicyTest = BluetoothDeviceConnectionPolicy.create(mMockContext,
+ mMockCarPropertyService, mMockPerUserCarServiceHelper,
+ mMockCarUxRService, mMockCarBluetoothService);
mBluetoothDeviceConnectionPolicyTest.setAllowReadWriteToSettings(false);
mBluetoothDeviceConnectionPolicyTest.init();
@@ -293,7 +310,7 @@
mCabinEventListener = mBluetoothDeviceConnectionPolicyTest.getCarPropertyListener();
assertNotNull(mCabinEventListener);
- serviceConnectionCallback.onServiceConnected(mockPerUserCarService);
+ serviceConnectionCallback.onServiceConnected(mMockPerUserCarService);
}
/**
@@ -347,7 +364,7 @@
triggerFakeVehicleEvent();
// Verify that on all profiles, device1 connected
for (Integer profile : mBluetoothDeviceConnectionPolicyTest.getProfilesToConnect()) {
- verify(mockBluetoothUserService,
+ verify(mMockBluetoothUserService,
Mockito.timeout(CONNECTION_REQUEST_TIMEOUT).times(1)).bluetoothConnectToProfile(
profile, device1);
}
@@ -359,6 +376,46 @@
mReceiver.onReceive(null, createBluetoothBondStateChangedIntent(device1, false));
}
+ /** When android/iphone connects on HFP, it doesn't explicitly try to connect on PBAP and MAP.
+ * In such cases, the Auto should try to connect on PBAP and MAP profiles.
+ * The following tests that scenario.
+ */
+ @Test
+ public void testDeviceConnectExplicitlyOnPbapAndMap() throws Exception {
+ // This tests the following: when a device connects on HFP, try to connect on
+ // PBAP and MAP. When android/iphone connects on HFP, it doesn't explicitly try to
+ // connect on PBA and MAP. Thats when the Auto should connect on those profiles after
+ // receiving HFP connect.
+ createAndSetupBluetoothPolicy();
+ // Tell the policy a new device connected - this mimics pairing
+ BluetoothDevice device1 = mBluetoothAdapter.getRemoteDevice("DE:AD:BE:EF:00:01");
+ mockDeviceAvailability(device1, true);
+ List<Integer> profilesToConnect = Arrays.asList(BluetoothProfile.HEADSET_CLIENT,
+ BluetoothProfile.PBAP_CLIENT, BluetoothProfile.MAP_CLIENT);
+ for (Integer profile : profilesToConnect) {
+ pairDeviceOnProfile(device1, profile);
+ }
+ // Disconnect
+ sendFakeConnectionStateChange(device1, false);
+
+ // Send connect change event (true) on HFP client only.
+ sendFakeConnectionStateChangeOnProfile(device1, BluetoothProfile.HEADSET_CLIENT, true);
+
+ // Verify device1 connected on PBAP and MAP
+ verify(mMockBluetoothUserService,
+ Mockito.timeout(CONNECTION_REQUEST_TIMEOUT).atLeastOnce()).bluetoothConnectToProfile(
+ BluetoothProfile.PBAP_CLIENT, device1);
+ verify(mMockBluetoothUserService,
+ Mockito.timeout(CONNECTION_REQUEST_TIMEOUT).atLeastOnce()).bluetoothConnectToProfile(
+ BluetoothProfile.MAP_CLIENT, device1);
+
+ // Before we cleanup wait for the last Connection Status change from mockDeviceAvailability
+ // is broadcast to the policy.
+ Thread.sleep(WAIT_FOR_COMPLETION_TIME);
+ // Inject an Unbond event to the policy
+ mReceiver.onReceive(null, createBluetoothBondStateChangedIntent(device1, false));
+ }
+
/**
* Multi device test
* 1. Pair 4 different devices 2 on HFP and PBAP (since they allow 2 connections) and 1 each on
@@ -387,6 +444,7 @@
pairDeviceOnProfile(device2, BluetoothProfile.PBAP_CLIENT);
pairDeviceOnProfile(device3, BluetoothProfile.A2DP_SINK);
pairDeviceOnProfile(device4, BluetoothProfile.MAP_CLIENT);
+ pairDeviceOnProfile(device4, BluetoothProfile.PAN);
// Disconnect all the 4 devices on the respective connected profiles
sendFakeConnectionStateChangeOnProfile(device1, BluetoothProfile.HEADSET_CLIENT, false);
@@ -395,28 +453,32 @@
sendFakeConnectionStateChangeOnProfile(device2, BluetoothProfile.PBAP_CLIENT, false);
sendFakeConnectionStateChangeOnProfile(device3, BluetoothProfile.A2DP_SINK, false);
sendFakeConnectionStateChangeOnProfile(device4, BluetoothProfile.MAP_CLIENT, false);
+ sendFakeConnectionStateChangeOnProfile(device4, BluetoothProfile.PAN, false);
triggerFakeVehicleEvent();
- verify(mockBluetoothUserService,
+ verify(mMockBluetoothUserService,
Mockito.timeout(CONNECTION_REQUEST_TIMEOUT).times(1)).bluetoothConnectToProfile(
BluetoothProfile.HEADSET_CLIENT, device1);
- verify(mockBluetoothUserService,
+ verify(mMockBluetoothUserService,
Mockito.timeout(CONNECTION_REQUEST_TIMEOUT).times(1)).bluetoothConnectToProfile(
BluetoothProfile.PBAP_CLIENT, device1);
- verify(mockBluetoothUserService,
+ verify(mMockBluetoothUserService,
Mockito.timeout(CONNECTION_REQUEST_TIMEOUT).times(1)).bluetoothConnectToProfile(
BluetoothProfile.HEADSET_CLIENT, device2);
- verify(mockBluetoothUserService,
+ verify(mMockBluetoothUserService,
Mockito.timeout(CONNECTION_REQUEST_TIMEOUT).times(1)).bluetoothConnectToProfile(
BluetoothProfile.PBAP_CLIENT, device2);
- verify(mockBluetoothUserService,
+ verify(mMockBluetoothUserService,
Mockito.timeout(CONNECTION_REQUEST_TIMEOUT).times(1)).bluetoothConnectToProfile(
BluetoothProfile.A2DP_SINK, device3);
- verify(mockBluetoothUserService,
+ verify(mMockBluetoothUserService,
Mockito.timeout(CONNECTION_REQUEST_TIMEOUT).times(1)).bluetoothConnectToProfile(
BluetoothProfile.MAP_CLIENT, device4);
+ verify(mMockBluetoothUserService,
+ Mockito.timeout(CONNECTION_REQUEST_TIMEOUT).times(1)).bluetoothConnectToProfile(
+ BluetoothProfile.PAN, device4);
// Before we cleanup wait for the last Connection Status change from is broadcast to the
// policy.
@@ -439,8 +501,10 @@
* 6. Disconnect and tag another device.
* 7. Send a Connection trigger.
* 8. Verify if the newly tagged device connected.
+ * TODO(vnori): fix b/69122852 and enable this test again
*/
- @Test
+ //@Test
+ @Suppress
public void testAutoConnectSetPrimaryPriority() throws Exception {
createAndSetupBluetoothPolicy();
BluetoothDevice device1 = mBluetoothAdapter.getRemoteDevice("DE:AD:BE:EF:00:01");
@@ -467,16 +531,19 @@
// Device order should be {device3, device1, device2, device4} now
// Now when we trigger an auto connect, device 3 should connect on all profiles
triggerFakeVehicleEvent();
- verify(mockBluetoothUserService,
+ verify(mMockBluetoothUserService,
Mockito.timeout(CONNECTION_REQUEST_TIMEOUT).times(1)).bluetoothConnectToProfile(
BluetoothProfile.HEADSET_CLIENT, device3);
- verify(mockBluetoothUserService,
+ verify(mMockBluetoothUserService,
+ Mockito.timeout(CONNECTION_REQUEST_TIMEOUT).times(1)).bluetoothConnectToProfile(
+ BluetoothProfile.PAN, device3);
+ verify(mMockBluetoothUserService,
Mockito.timeout(CONNECTION_REQUEST_TIMEOUT).times(1)).bluetoothConnectToProfile(
BluetoothProfile.PBAP_CLIENT, device3);
- verify(mockBluetoothUserService,
+ verify(mMockBluetoothUserService,
Mockito.timeout(CONNECTION_REQUEST_TIMEOUT).times(1)).bluetoothConnectToProfile(
BluetoothProfile.A2DP_SINK, device3);
- verify(mockBluetoothUserService,
+ verify(mMockBluetoothUserService,
Mockito.timeout(CONNECTION_REQUEST_TIMEOUT).times(1)).bluetoothConnectToProfile(
BluetoothProfile.MAP_CLIENT, device3);
Thread.sleep(WAIT_FOR_COMPLETION_TIME);
@@ -493,16 +560,19 @@
triggerFakeVehicleEvent();
// Check if device4 connects now
- verify(mockBluetoothUserService,
+ verify(mMockBluetoothUserService,
Mockito.timeout(CONNECTION_REQUEST_TIMEOUT).times(1)).bluetoothConnectToProfile(
BluetoothProfile.HEADSET_CLIENT, device4);
- verify(mockBluetoothUserService,
+ verify(mMockBluetoothUserService,
+ Mockito.timeout(CONNECTION_REQUEST_TIMEOUT).times(1)).bluetoothConnectToProfile(
+ BluetoothProfile.PAN, device4);
+ verify(mMockBluetoothUserService,
Mockito.timeout(CONNECTION_REQUEST_TIMEOUT).times(1)).bluetoothConnectToProfile(
BluetoothProfile.PBAP_CLIENT, device4);
- verify(mockBluetoothUserService,
+ verify(mMockBluetoothUserService,
Mockito.timeout(CONNECTION_REQUEST_TIMEOUT).times(1)).bluetoothConnectToProfile(
BluetoothProfile.A2DP_SINK, device4);
- verify(mockBluetoothUserService,
+ verify(mMockBluetoothUserService,
Mockito.timeout(CONNECTION_REQUEST_TIMEOUT).times(1)).bluetoothConnectToProfile(
BluetoothProfile.MAP_CLIENT, device4);
@@ -525,8 +595,10 @@
* Change Primary device to unavailable.
* Trigger Connection.
* Secondary device should now be connected on A2DP (since Primary is not available)
+ * TODO(vnori): fix b/69122852 and enable this test again
*/
- @Test
+ //@Test
+ @Suppress
public void testAutoConnectSetSecondaryPriority() throws Exception {
createAndSetupBluetoothPolicy();
BluetoothDevice device1 = mBluetoothAdapter.getRemoteDevice("DE:AD:BE:EF:00:01");
@@ -560,9 +632,9 @@
triggerFakeVehicleEvent();
// Mockito.never() doesn't have a timeout option, hence the sleep here.
Thread.sleep(WAIT_FOR_COMPLETION_TIME);
- verify(mockBluetoothUserService, Mockito.never()).bluetoothConnectToProfile(
+ verify(mMockBluetoothUserService, Mockito.never()).bluetoothConnectToProfile(
BluetoothProfile.A2DP_SINK, device4);
- verify(mockBluetoothUserService,
+ verify(mMockBluetoothUserService,
Mockito.timeout(CONNECTION_REQUEST_TIMEOUT).times(1)).bluetoothConnectToProfile(
BluetoothProfile.HEADSET_CLIENT, device4);
@@ -573,7 +645,7 @@
triggerFakeVehicleEvent();
// Now a connection attempt should be made on device4 for A2DP_SINK for the same reasons as
// above
- verify(mockBluetoothUserService,
+ verify(mMockBluetoothUserService,
Mockito.timeout(CONNECTION_REQUEST_TIMEOUT).times(1)).bluetoothConnectToProfile(
BluetoothProfile.A2DP_SINK, device4);
Thread.sleep(WAIT_FOR_COMPLETION_TIME);
@@ -611,6 +683,13 @@
mockDeviceAvailability(device2, false);
triggerFakeVehicleEvent();
Thread.sleep(WAIT_FOR_COMPLETION_TIME);
+
+ verify(mMockBluetoothUserService,
+ Mockito.timeout(CONNECTION_REQUEST_TIMEOUT).times(1)).bluetoothConnectToProfile(
+ BluetoothProfile.HEADSET_CLIENT, device1);
+ verify(mMockBluetoothUserService, times(1)).bluetoothConnectToProfile(
+ BluetoothProfile.A2DP_SINK, device1);
+
// At this point device1 should have connected and device2 disconnected, since it is mocked
// to be out of range (unavailable)
// Now bring device2 in range (mock it to be available)
@@ -622,17 +701,17 @@
// 1 connection)
// There should have been 2 connection attempts on the device2 - the first one unsuccessful
// due to its unavailability and the second one successful.
- verify(mockBluetoothUserService,
+ verify(mMockBluetoothUserService,
Mockito.timeout(CONNECTION_REQUEST_TIMEOUT).times(2)).bluetoothConnectToProfile(
BluetoothProfile.HEADSET_CLIENT, device2);
// There should be only 1 connection attempt on device1 - since it is available to connect
// from the beginning. The first connection attempt on the first vehicle event should have
// been successful. For the second vehicle event, we should not have tried to connect on
// device1 - this tests if we try to connect on already connected devices.
- verify(mockBluetoothUserService,
+ verify(mMockBluetoothUserService,
Mockito.timeout(CONNECTION_REQUEST_TIMEOUT).times(1)).bluetoothConnectToProfile(
BluetoothProfile.HEADSET_CLIENT, device1);
- verify(mockBluetoothUserService, Mockito.never()).bluetoothConnectToProfile(
+ verify(mMockBluetoothUserService, Mockito.never()).bluetoothConnectToProfile(
BluetoothProfile.A2DP_SINK, device2);
Thread.sleep(WAIT_FOR_COMPLETION_TIME);
mReceiver.onReceive(null, createBluetoothBondStateChangedIntent(device1, false));
diff --git a/tests/carservice_unit_test/src/com/android/car/CarConfigurationServiceTest.java b/tests/carservice_unit_test/src/com/android/car/CarConfigurationServiceTest.java
new file mode 100644
index 0000000..58b9c9a
--- /dev/null
+++ b/tests/carservice_unit_test/src/com/android/car/CarConfigurationServiceTest.java
@@ -0,0 +1,171 @@
+/*
+ * 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;
+
+import static com.android.car.CarConfigurationService.DEFAULT_SPEED_BUMP_ACQUIRED_PERMITS_PER_SECOND;
+import static com.android.car.CarConfigurationService.DEFAULT_SPEED_BUMP_MAX_PERMIT_POOL;
+import static com.android.car.CarConfigurationService.DEFAULT_SPEED_BUMP_PERMIT_FILL_DELAY;
+import static com.android.car.CarConfigurationService.SPEED_BUMP_ACQUIRED_PERMITS_PER_SECOND_KEY;
+import static com.android.car.CarConfigurationService.SPEED_BUMP_CONFIG_KEY;
+import static com.android.car.CarConfigurationService.SPEED_BUMP_MAX_PERMIT_POOL_KEY;
+import static com.android.car.CarConfigurationService.SPEED_BUMP_PERMIT_FILL_DELAY_KEY;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import android.car.settings.SpeedBumpConfiguration;
+import android.support.test.InstrumentationRegistry;
+import android.support.test.runner.AndroidJUnit4;
+
+import org.json.JSONException;
+import org.json.JSONObject;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.MockitoAnnotations;
+
+/**
+ * Tests for {@link CarConfigurationService}.
+ */
+@RunWith(AndroidJUnit4.class)
+public class CarConfigurationServiceTest {
+ @Before
+ public void setUp() {
+ MockitoAnnotations.initMocks(this);
+ }
+
+ @Test
+ public void testJsonResourceSuccessfullyRead() {
+ // Use the default JsonReader to check that the resource JSON can be retrieved.
+ CarConfigurationService service = new CarConfigurationService(
+ InstrumentationRegistry.getTargetContext(),
+ new JsonReaderImpl());
+ service.init();
+
+ assertThat(service.mConfigFile).isNotNull();
+
+ // Default values should be stored in the JSON file as well.
+ SpeedBumpConfiguration expectedConfiguration = new SpeedBumpConfiguration(
+ DEFAULT_SPEED_BUMP_ACQUIRED_PERMITS_PER_SECOND,
+ DEFAULT_SPEED_BUMP_MAX_PERMIT_POOL,
+ DEFAULT_SPEED_BUMP_PERMIT_FILL_DELAY);
+
+ assertThat(service.getSpeedBumpConfiguration()).isEqualTo(expectedConfiguration);
+ }
+
+ @Test
+ public void testJsonFileSuccessfullyRead() {
+ // Return an empty json file.
+ CarConfigurationService service = new CarConfigurationService(
+ InstrumentationRegistry.getTargetContext(),
+ (context, resId) -> "{}");
+ service.init();
+
+ // The configuration should still be initialized.
+ assertThat(service.mConfigFile).isNotNull();
+ }
+
+ @Test
+ public void testNullJsonStringResultsInNullConfigFile() {
+ // Return null as the string representation.
+ CarConfigurationService service = new CarConfigurationService(
+ InstrumentationRegistry.getTargetContext(),
+ (context, resId) -> null);
+ service.init();
+
+ // No config file should be created.
+ assertThat(service.mConfigFile).isNull();
+ }
+
+ @Test
+ public void testSpeedBumpConfigurationSuccessfullyRead() throws JSONException {
+ double acquiredPermitsPerSecond = 5d;
+ double maxPermitPool = 10d;
+ long permitFillDelay = 500L;
+
+ String jsonFile = new SpeedBumpJsonBuilder()
+ .setAcquiredPermitsPerSecond(acquiredPermitsPerSecond)
+ .setMaxPermitPool(maxPermitPool)
+ .setPermitFillDelay(permitFillDelay)
+ .build();
+
+ CarConfigurationService service = new CarConfigurationService(
+ InstrumentationRegistry.getTargetContext(),
+ (context, resId) -> jsonFile);
+ service.init();
+
+ SpeedBumpConfiguration expectedConfiguration = new SpeedBumpConfiguration(
+ acquiredPermitsPerSecond,
+ maxPermitPool,
+ permitFillDelay);
+
+ assertThat(service.getSpeedBumpConfiguration()).isEqualTo(expectedConfiguration);
+ }
+
+ @Test
+ public void testDefaultSpeedBumpConfigurationReturned() {
+ // Return null as the JSON representation.
+ CarConfigurationService service = new CarConfigurationService(
+ InstrumentationRegistry.getTargetContext(),
+ (context, resId) -> null);
+ service.init();
+
+ // Default values should be used.
+ SpeedBumpConfiguration expectedConfiguration = new SpeedBumpConfiguration(
+ DEFAULT_SPEED_BUMP_ACQUIRED_PERMITS_PER_SECOND,
+ DEFAULT_SPEED_BUMP_MAX_PERMIT_POOL,
+ DEFAULT_SPEED_BUMP_PERMIT_FILL_DELAY);
+
+ assertThat(service.getSpeedBumpConfiguration()).isEqualTo(expectedConfiguration);
+ }
+
+ /**
+ * Builder for a string that represents the contents of a JSON file with speed bump
+ * configuration.
+ */
+ private class SpeedBumpJsonBuilder {
+ private double mAcquiredPermitsPerSecond;
+ private double mMaxPermitPool;
+ private long mPermitFillDelay;
+
+ SpeedBumpJsonBuilder setAcquiredPermitsPerSecond(double acquiredPermitsPerSecond) {
+ mAcquiredPermitsPerSecond = acquiredPermitsPerSecond;
+ return this;
+ }
+
+ SpeedBumpJsonBuilder setMaxPermitPool(double maxPermitPool) {
+ mMaxPermitPool = maxPermitPool;
+ return this;
+ }
+
+ SpeedBumpJsonBuilder setPermitFillDelay(long permitFillDelay) {
+ mPermitFillDelay = permitFillDelay;
+ return this;
+ }
+
+ String build() throws JSONException {
+ JSONObject speedBump = new JSONObject();
+ speedBump.put(SPEED_BUMP_ACQUIRED_PERMITS_PER_SECOND_KEY, mAcquiredPermitsPerSecond);
+ speedBump.put(SPEED_BUMP_MAX_PERMIT_POOL_KEY, mMaxPermitPool);
+ speedBump.put(SPEED_BUMP_PERMIT_FILL_DELAY_KEY, mPermitFillDelay);
+
+ JSONObject container = new JSONObject();
+ container.put(SPEED_BUMP_CONFIG_KEY, speedBump);
+
+ return container.toString();
+ }
+ }
+}
diff --git a/tests/carservice_unit_test/src/com/android/car/CarLocationServiceTest.java b/tests/carservice_unit_test/src/com/android/car/CarLocationServiceTest.java
new file mode 100644
index 0000000..8ac7d9b
--- /dev/null
+++ b/tests/carservice_unit_test/src/com/android/car/CarLocationServiceTest.java
@@ -0,0 +1,441 @@
+/*
+ * 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;
+
+import static junit.framework.Assert.assertEquals;
+import static junit.framework.Assert.assertTrue;
+
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import android.car.hardware.CarPropertyValue;
+import android.car.hardware.CarSensorEvent;
+import android.car.hardware.CarSensorManager;
+import android.car.hardware.property.CarPropertyEvent;
+import android.car.hardware.property.ICarPropertyEventListener;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.content.pm.PackageManager;
+import android.location.Location;
+import android.location.LocationManager;
+import android.os.RemoteException;
+import android.os.SystemClock;
+import android.support.test.InstrumentationRegistry;
+import android.support.test.runner.AndroidJUnit4;
+
+import com.android.internal.util.ArrayUtils;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.ArgumentCaptor;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+
+import java.io.BufferedReader;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import java.util.concurrent.CountDownLatch;
+import java.util.stream.Collectors;
+
+/**
+ * This class contains unit tests for the {@link CarLocationService}.
+ * It tests that {@link LocationManager}'s last known location is stored in and loaded from a JSON
+ * file upon appropriate system events.
+ *
+ * The following mocks are used:
+ * 1. {@link Context} provides files and a mocked {@link LocationManager}.
+ * 2. {@link LocationManager} provides dummy {@link Location}s.
+ * 3. {@link CarSensorService} registers a handler for sensor events and sends ignition-off events.
+ */
+@RunWith(AndroidJUnit4.class)
+public class CarLocationServiceTest {
+ private static String TAG = "CarLocationServiceTest";
+ private static String TEST_FILENAME = "location_cache_test.json";
+ private CarLocationService mCarLocationService;
+ private Context mContext;
+ private CountDownLatch mLatch;
+ @Mock private Context mMockContext;
+ @Mock private LocationManager mMockLocationManager;
+ @Mock private CarPropertyService mMockCarPropertyService;
+ @Mock private CarPowerManagementService mMockCarPowerManagementService;
+
+ /**
+ * Initialize all of the objects with the @Mock annotation.
+ */
+ @Before
+ public void setUp() throws Exception {
+ MockitoAnnotations.initMocks(this);
+ mContext = InstrumentationRegistry.getTargetContext();
+ mLatch = new CountDownLatch(1);
+ mCarLocationService = new CarLocationService(mMockContext, mMockCarPowerManagementService,
+ mMockCarPropertyService) {
+ @Override
+ void asyncOperation(Runnable operation) {
+ super.asyncOperation(() -> {
+ operation.run();
+ mLatch.countDown();
+ });
+ }
+ };
+ }
+
+ @After
+ public void tearDown() throws Exception {
+ if (mCarLocationService != null) {
+ mCarLocationService.release();
+ }
+ mContext.deleteFile(TEST_FILENAME);
+ }
+
+ /**
+ * Test that the {@link CarLocationService} has the permissions necessary to call the
+ * {@link LocationManager} injectLocation API.
+ *
+ * Note that this test will never fail even if the relevant permissions are removed from the
+ * manifest since {@link CarService} runs in a system process.
+ */
+ @Test
+ public void testCarLocationServiceShouldHavePermissions() {
+ int fineLocationCheck =
+ mContext.checkSelfPermission(android.Manifest.permission.ACCESS_FINE_LOCATION);
+ int locationHardwareCheck =
+ mContext.checkSelfPermission(android.Manifest.permission.LOCATION_HARDWARE);
+ assertEquals(PackageManager.PERMISSION_GRANTED, fineLocationCheck);
+ assertEquals(PackageManager.PERMISSION_GRANTED, locationHardwareCheck);
+ }
+
+ /**
+ * Test that the {@link CarLocationService} registers to receive the locked boot completed
+ * intent and ignition sensor events upon initialization.
+ */
+ @Test
+ public void testRegistersToReceiveEvents() {
+ ArgumentCaptor<IntentFilter> argument = ArgumentCaptor.forClass(IntentFilter.class);
+ mCarLocationService.init();
+ verify(mMockCarPowerManagementService).registerPowerEventProcessingHandler(
+ mCarLocationService);
+ verify(mMockContext).registerReceiver(eq(mCarLocationService), argument.capture());
+ IntentFilter intentFilter = argument.getValue();
+ assertEquals(3, intentFilter.countActions());
+ String[] actions = {intentFilter.getAction(0), intentFilter.getAction(1),
+ intentFilter.getAction(2)};
+ assertTrue(ArrayUtils.contains(actions, Intent.ACTION_LOCKED_BOOT_COMPLETED));
+ assertTrue(ArrayUtils.contains(actions, LocationManager.MODE_CHANGED_ACTION));
+ assertTrue(ArrayUtils.contains(actions, LocationManager.GPS_ENABLED_CHANGE_ACTION));
+ verify(mMockCarPropertyService).registerListener(
+ eq(CarSensorManager.SENSOR_TYPE_IGNITION_STATE), eq(0.0f), any());
+ }
+
+ /**
+ * Test that the {@link CarLocationService} unregisters its event receivers.
+ */
+ @Test
+ public void testUnregistersEventReceivers() {
+ mCarLocationService.release();
+ verify(mMockContext).unregisterReceiver(mCarLocationService);
+ verify(mMockCarPropertyService).unregisterListener(
+ eq(CarSensorManager.SENSOR_TYPE_IGNITION_STATE), any());
+ }
+
+ /**
+ * Test that the {@link CarLocationService} parses a location from a JSON serialization and then
+ * injects it into the {@link LocationManager} upon boot complete.
+ */
+ @Test
+ public void testLoadsLocation() throws IOException, InterruptedException {
+ long currentTime = System.currentTimeMillis();
+ long elapsedTime = SystemClock.elapsedRealtimeNanos();
+ long pastTime = currentTime - 60000;
+ writeCacheFile("{\"provider\": \"gps\", \"latitude\": 16.7666, \"longitude\": 3.0026,"
+ + "\"accuracy\":12.3, \"captureTime\": " + pastTime + "}");
+ ArgumentCaptor<Location> argument = ArgumentCaptor.forClass(Location.class);
+ when(mMockContext.getSystemService(Context.LOCATION_SERVICE))
+ .thenReturn(mMockLocationManager);
+ when(mMockLocationManager.injectLocation(argument.capture())).thenReturn(true);
+ when(mMockContext.getFileStreamPath("location_cache.json"))
+ .thenReturn(mContext.getFileStreamPath(TEST_FILENAME));
+
+ mCarLocationService.onReceive(mMockContext,
+ new Intent(Intent.ACTION_LOCKED_BOOT_COMPLETED));
+ mLatch.await();
+
+ Location location = argument.getValue();
+ assertEquals("gps", location.getProvider());
+ assertEquals(16.7666, location.getLatitude());
+ assertEquals(3.0026, location.getLongitude());
+ assertEquals(12.3f, location.getAccuracy());
+ assertTrue(location.getTime() >= currentTime);
+ assertTrue(location.getElapsedRealtimeNanos() >= elapsedTime);
+ }
+
+ /**
+ * Test that the {@link CarLocationService} does not inject a location if there is no location
+ * cache file.
+ */
+ @Test
+ public void testDoesNotLoadLocationWhenNoFileExists()
+ throws FileNotFoundException, InterruptedException {
+ when(mMockContext.getSystemService(Context.LOCATION_SERVICE))
+ .thenReturn(mMockLocationManager);
+ when(mMockLocationManager.getLastKnownLocation(LocationManager.GPS_PROVIDER))
+ .thenReturn(null);
+ when(mMockContext.getFileStreamPath("location_cache.json"))
+ .thenReturn(mContext.getFileStreamPath(TEST_FILENAME));
+ mCarLocationService.onReceive(mMockContext,
+ new Intent(Intent.ACTION_LOCKED_BOOT_COMPLETED));
+ mLatch.await();
+ verify(mMockLocationManager, never()).injectLocation(any());
+ }
+
+ /**
+ * Test that the {@link CarLocationService} handles an incomplete JSON file gracefully.
+ */
+ @Test
+ public void testDoesNotLoadLocationFromIncompleteFile() throws IOException,
+ InterruptedException {
+ writeCacheFile("{\"provider\": \"gps\", \"latitude\": 16.7666, \"longitude\": 3.0026,");
+ when(mMockContext.getSystemService(Context.LOCATION_SERVICE))
+ .thenReturn(mMockLocationManager);
+ when(mMockLocationManager.getLastKnownLocation(LocationManager.GPS_PROVIDER))
+ .thenReturn(null);
+ when(mMockContext.getFileStreamPath("location_cache.json"))
+ .thenReturn(mContext.getFileStreamPath(TEST_FILENAME));
+ mCarLocationService.onReceive(mMockContext,
+ new Intent(Intent.ACTION_LOCKED_BOOT_COMPLETED));
+ mLatch.await();
+ verify(mMockLocationManager, never()).injectLocation(any());
+ }
+
+ /**
+ * Test that the {@link CarLocationService} handles a corrupt JSON file gracefully.
+ */
+ @Test
+ public void testDoesNotLoadLocationFromCorruptFile() throws IOException, InterruptedException {
+ writeCacheFile("{\"provider\":\"latitude\":16.7666,\"longitude\": \"accuracy\":1.0}");
+ when(mMockContext.getSystemService(Context.LOCATION_SERVICE))
+ .thenReturn(mMockLocationManager);
+ when(mMockLocationManager.getLastKnownLocation(LocationManager.GPS_PROVIDER))
+ .thenReturn(null);
+ when(mMockContext.getFileStreamPath("location_cache.json"))
+ .thenReturn(mContext.getFileStreamPath(TEST_FILENAME));
+ mCarLocationService.onReceive(mMockContext,
+ new Intent(Intent.ACTION_LOCKED_BOOT_COMPLETED));
+ mLatch.await();
+ verify(mMockLocationManager, never()).injectLocation(any());
+ }
+
+ /**
+ * Test that the {@link CarLocationService} does not inject a location that is missing
+ * accuracy.
+ */
+ @Test
+ public void testDoesNotLoadIncompleteLocation() throws IOException, InterruptedException {
+ writeCacheFile("{\"provider\": \"gps\", \"latitude\": 16.7666, \"longitude\": 3.0026}");
+ when(mMockContext.getSystemService(Context.LOCATION_SERVICE))
+ .thenReturn(mMockLocationManager);
+ when(mMockLocationManager.getLastKnownLocation(LocationManager.GPS_PROVIDER))
+ .thenReturn(null);
+ when(mMockContext.getFileStreamPath("location_cache.json"))
+ .thenReturn(mContext.getFileStreamPath(TEST_FILENAME));
+ mCarLocationService.onReceive(mMockContext,
+ new Intent(Intent.ACTION_LOCKED_BOOT_COMPLETED));
+ mLatch.await();
+ verify(mMockLocationManager, never()).injectLocation(any());
+ }
+
+ /**
+ * Test that the {@link CarLocationService} does not inject a location that is older than
+ * thirty days.
+ */
+ @Test
+ public void testDoesNotLoadOldLocation() throws IOException, InterruptedException {
+ long thirtyThreeDaysMs = 33 * 24 * 60 * 60 * 1000L;
+ long oldTime = System.currentTimeMillis() - thirtyThreeDaysMs;
+ writeCacheFile("{\"provider\": \"gps\", \"latitude\": 16.7666, \"longitude\": 3.0026,"
+ + "\"accuracy\":12.3, \"captureTime\": " + oldTime + "}");
+ when(mMockContext.getSystemService(Context.LOCATION_SERVICE))
+ .thenReturn(mMockLocationManager);
+ when(mMockLocationManager.getLastKnownLocation(LocationManager.GPS_PROVIDER))
+ .thenReturn(null);
+ when(mMockContext.getFileStreamPath("location_cache.json"))
+ .thenReturn(mContext.getFileStreamPath(TEST_FILENAME));
+ mCarLocationService.onReceive(mMockContext,
+ new Intent(Intent.ACTION_LOCKED_BOOT_COMPLETED));
+ mLatch.await();
+ verify(mMockLocationManager, never()).injectLocation(any());
+ }
+
+ /**
+ * Test that the {@link CarLocationService} stores the {@link LocationManager}'s last known
+ * location in a JSON file upon ignition-off events.
+ */
+ @Test
+ public void testStoresLocationUponIgnitionOff()
+ throws IOException, RemoteException, InterruptedException {
+ long currentTime = System.currentTimeMillis();
+ long elapsedTime = SystemClock.elapsedRealtimeNanos();
+ Location timbuktu = new Location(LocationManager.GPS_PROVIDER);
+ timbuktu.setLatitude(16.7666);
+ timbuktu.setLongitude(3.0026);
+ timbuktu.setAccuracy(13.75f);
+ timbuktu.setTime(currentTime);
+ timbuktu.setElapsedRealtimeNanos(elapsedTime);
+ when(mMockContext.getSystemService(Context.LOCATION_SERVICE))
+ .thenReturn(mMockLocationManager);
+ when(mMockLocationManager.getLastKnownLocation(LocationManager.GPS_PROVIDER))
+ .thenReturn(timbuktu);
+ when(mMockContext.getFileStreamPath("location_cache.json"))
+ .thenReturn(mContext.getFileStreamPath(TEST_FILENAME));
+ sendIgnitionOffEvent();
+ mLatch.await();
+ verify(mMockLocationManager).getLastKnownLocation(LocationManager.GPS_PROVIDER);
+ String actualContents = readCacheFile();
+ long oneDayMs = 24 * 60 * 60 * 1000;
+ long granularCurrentTime = (currentTime / oneDayMs) * oneDayMs;
+ String expectedContents = "{\"provider\":\"gps\",\"latitude\":16.7666,\"longitude\":"
+ + "3.0026,\"accuracy\":13.75,\"captureTime\":" + granularCurrentTime + "}";
+ assertEquals(expectedContents, actualContents);
+ }
+
+ /**
+ * Test that the {@link CarLocationService} stores the {@link LocationManager}'s last known
+ * location upon prepare-shutdown events.
+ */
+ @Test
+ public void testStoresLocationUponPrepareShutdown()
+ throws IOException, RemoteException, InterruptedException {
+ long currentTime = System.currentTimeMillis();
+ long elapsedTime = SystemClock.elapsedRealtimeNanos();
+ Location timbuktu = new Location(LocationManager.GPS_PROVIDER);
+ timbuktu.setLatitude(16.7666);
+ timbuktu.setLongitude(3.0026);
+ timbuktu.setAccuracy(13.75f);
+ timbuktu.setTime(currentTime);
+ timbuktu.setElapsedRealtimeNanos(elapsedTime);
+ when(mMockContext.getSystemService(Context.LOCATION_SERVICE))
+ .thenReturn(mMockLocationManager);
+ when(mMockLocationManager.getLastKnownLocation(LocationManager.GPS_PROVIDER))
+ .thenReturn(timbuktu);
+ when(mMockContext.getFileStreamPath("location_cache.json"))
+ .thenReturn(mContext.getFileStreamPath(TEST_FILENAME));
+ mCarLocationService.onPrepareShutdown(true);
+ mLatch.await();
+ verify(mMockLocationManager).getLastKnownLocation(LocationManager.GPS_PROVIDER);
+ String actualContents = readCacheFile();
+ long oneDayMs = 24 * 60 * 60 * 1000;
+ long granularCurrentTime = (currentTime / oneDayMs) * oneDayMs;
+ String expectedContents = "{\"provider\":\"gps\",\"latitude\":16.7666,\"longitude\":"
+ + "3.0026,\"accuracy\":13.75,\"captureTime\":" + granularCurrentTime + "}";
+ assertEquals(expectedContents, actualContents);
+ }
+
+ /**
+ * Test that the {@link CarLocationService} does not store null locations.
+ */
+ @Test
+ public void testDoesNotStoreNullLocation() throws Exception {
+ when(mMockContext.getSystemService(Context.LOCATION_SERVICE))
+ .thenReturn(mMockLocationManager);
+ when(mMockLocationManager.getLastKnownLocation(LocationManager.GPS_PROVIDER))
+ .thenReturn(null);
+ when(mMockContext.getFileStreamPath("location_cache.json"))
+ .thenReturn(mContext.getFileStreamPath(TEST_FILENAME));
+ sendIgnitionOffEvent();
+ mLatch.await();
+ verify(mMockLocationManager).getLastKnownLocation(LocationManager.GPS_PROVIDER);
+ verify(mMockContext).deleteFile("location_cache.json");
+ }
+
+ /**
+ * Test that the {@link CarLocationService} deletes location_cache.json when location is
+ * disabled.
+ */
+ @Test
+ public void testDeletesCacheFileWhenLocationIsDisabled() throws Exception {
+ when(mMockContext.getSystemService(Context.LOCATION_SERVICE))
+ .thenReturn(mMockLocationManager);
+ when(mMockLocationManager.isLocationEnabled()).thenReturn(false);
+ mCarLocationService.init();
+ mCarLocationService.onReceive(mMockContext,
+ new Intent(LocationManager.MODE_CHANGED_ACTION));
+ mLatch.await();
+ verify(mMockLocationManager, times(1)).isLocationEnabled();
+ verify(mMockContext).deleteFile("location_cache.json");
+ }
+
+ /**
+ * Test that the {@link CarLocationService} deletes location_cache.json when the GPS location
+ * provider is disabled.
+ */
+ @Test
+ public void testDeletesCacheFileWhenTheGPSProviderIsDisabled() throws Exception {
+ when(mMockContext.getSystemService(Context.LOCATION_SERVICE))
+ .thenReturn(mMockLocationManager);
+ when(mMockLocationManager.isProviderEnabled(LocationManager.GPS_PROVIDER)).thenReturn(
+ false);
+ mCarLocationService.init();
+ mCarLocationService.onReceive(mMockContext,
+ new Intent(LocationManager.GPS_ENABLED_CHANGE_ACTION));
+ mLatch.await();
+ verify(mMockLocationManager, times(1))
+ .isProviderEnabled(LocationManager.GPS_PROVIDER);
+ verify(mMockContext).deleteFile("location_cache.json");
+ }
+
+ private void writeCacheFile(String json) throws IOException {
+ FileOutputStream fos = mContext.openFileOutput(TEST_FILENAME, Context.MODE_PRIVATE);
+ fos.write(json.getBytes());
+ fos.close();
+ }
+
+ private String readCacheFile() throws IOException {
+ FileInputStream fis = mContext.openFileInput(TEST_FILENAME);
+ String json = new BufferedReader(new InputStreamReader(fis)).lines()
+ .parallel().collect(Collectors.joining("\n"));
+ fis.close();
+ return json;
+ }
+
+ private void sendIgnitionOffEvent() throws RemoteException {
+ mCarLocationService.init();
+ ArgumentCaptor<ICarPropertyEventListener> argument =
+ ArgumentCaptor.forClass(ICarPropertyEventListener.class);
+ verify(mMockCarPropertyService).registerListener(
+ eq(CarSensorManager.SENSOR_TYPE_IGNITION_STATE), eq(0.0f), argument.capture());
+ ICarPropertyEventListener carPropertyEventListener = argument.getValue();
+ int intValues = CarSensorEvent.IGNITION_STATE_OFF;
+ CarPropertyValue ignitionOff = new CarPropertyValue(
+ CarSensorManager.SENSOR_TYPE_IGNITION_STATE, 0, 0,
+ System.currentTimeMillis(), intValues);
+ CarPropertyEvent event = new CarPropertyEvent(0, ignitionOff);
+ List<CarPropertyEvent> events = new ArrayList<>(Arrays.asList(event));
+ carPropertyEventListener.onEvent(events);
+ }
+}
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 78f13e3..cb2b4b8 100644
--- a/tests/carservice_unit_test/src/com/android/car/CarPowerManagementServiceTest.java
+++ b/tests/carservice_unit_test/src/com/android/car/CarPowerManagementServiceTest.java
@@ -24,7 +24,16 @@
import com.android.car.CarPowerManagementService.PowerServiceEventListener;
import com.android.car.hal.PowerHalService;
import com.android.car.hal.PowerHalService.PowerState;
+import com.android.car.systeminterface.DisplayInterface;
+import com.android.car.systeminterface.IOInterface;
+import com.android.car.systeminterface.SystemInterface;
+import com.android.car.systeminterface.SystemStateInterface;
+import com.android.car.systeminterface.WakeLockInterface;
+import com.android.car.test.utils.TemporaryDirectory;
+import java.io.File;
+import java.io.IOException;
+import java.time.Duration;
import java.util.concurrent.Semaphore;
import java.util.concurrent.TimeUnit;
@@ -34,8 +43,13 @@
private static final long WAIT_TIMEOUT_MS = 2000;
private static final long WAIT_TIMEOUT_LONG_MS = 5000;
+ private final MockDisplayInterface mDisplayInterface = new MockDisplayInterface();
+ private final MockSystemStateInterface mSystemStateInterface = new MockSystemStateInterface();
+ private final MockWakeLockInterface mWakeLockInterface = new MockWakeLockInterface();
+ private final MockIOInterface mIOInterface = new MockIOInterface();
+
private MockedPowerHalService mPowerHal;
- private SystemInterfaceImpl mSystemInterface;
+ private SystemInterface mSystemInterface;
private CarPowerManagementService mService;
private final PowerEventListener mPowerEventListener = new PowerEventListener();
private PowerEventProcessingHandlerImpl mPowerEventProcessingHandler;
@@ -45,7 +59,11 @@
super.setUp();
mPowerHal = new MockedPowerHalService(true /*isPowerStateSupported*/,
true /*isDeepSleepAllowed*/, true /*isTimedWakeupAllowed*/);
- mSystemInterface = new SystemInterfaceImpl();
+ mSystemInterface = SystemInterface.Builder.defaultSystemInterface(getContext())
+ .withDisplayInterface(mDisplayInterface)
+ .withSystemStateInterface(mSystemStateInterface)
+ .withWakeLockInterface(mWakeLockInterface)
+ .withIOInterface(mIOInterface).build();
}
@Override
@@ -54,106 +72,84 @@
if (mService != null) {
mService.release();
}
+ mIOInterface.tearDown();
+ }
+
+ /**
+ * Helper method to create mService and initialize a test case
+ */
+ private void initTest(long processingTimeMs, int wakeupTime) throws Exception {
+ mService = new CarPowerManagementService(getContext(), mPowerHal, mSystemInterface);
+ mService.init();
+ mService.registerPowerEventListener(mPowerEventListener);
+ mPowerEventProcessingHandler = new PowerEventProcessingHandlerImpl(processingTimeMs,
+ wakeupTime);
+ mService.registerPowerEventProcessingHandler(mPowerEventProcessingHandler);
+ assertStateReceived(MockedPowerHalService.SET_BOOT_COMPLETE, 0);
+ mPowerEventProcessingHandler.waitForPowerOn(WAIT_TIMEOUT_MS);
}
public void testBootComplete() throws Exception {
- mService = new CarPowerManagementService(mPowerHal, mSystemInterface);
- mService.init();
- mService.registerPowerEventListener(mPowerEventListener);
- mPowerEventProcessingHandler = new PowerEventProcessingHandlerImpl(0, 0);
- mService.registerPowerEventProcessingHandler(mPowerEventProcessingHandler);
- assertStateReceived(MockedPowerHalService.SET_BOOT_COMPLETE, 0);
- mPowerEventProcessingHandler.waitForPowerOn(WAIT_TIMEOUT_MS);
+ initTest(0, 0);
}
public void testDisplayOff() throws Exception {
- mService = new CarPowerManagementService(mPowerHal, mSystemInterface);
- mService.init();
- mService.registerPowerEventListener(mPowerEventListener);
- mPowerEventProcessingHandler = new PowerEventProcessingHandlerImpl(0, 0);
- mService.registerPowerEventProcessingHandler(mPowerEventProcessingHandler);
- assertStateReceived(MockedPowerHalService.SET_BOOT_COMPLETE, 0);
- mPowerEventProcessingHandler.waitForPowerOn(WAIT_TIMEOUT_MS);
+ initTest(0,0);
// it will call display on for initial state
- assertTrue(mSystemInterface.waitForDisplayStateChange(WAIT_TIMEOUT_MS));
+ assertTrue(mDisplayInterface.waitForDisplayStateChange(WAIT_TIMEOUT_MS));
mPowerHal.setCurrentPowerState(new PowerState(PowerHalService.STATE_ON_DISP_OFF, 0));
- assertFalse(mSystemInterface.waitForDisplayStateChange(WAIT_TIMEOUT_MS));
+ assertFalse(mDisplayInterface.waitForDisplayStateChange(WAIT_TIMEOUT_MS));
}
public void testDisplayOn() throws Exception {
// start with display off
mSystemInterface.setDisplayState(false);
- mSystemInterface.waitForDisplayStateChange(WAIT_TIMEOUT_MS);
- mService = new CarPowerManagementService(mPowerHal, mSystemInterface);
- mService.init();
- mService.registerPowerEventListener(mPowerEventListener);
- mPowerEventProcessingHandler = new PowerEventProcessingHandlerImpl(0, 0);
- mService.registerPowerEventProcessingHandler(mPowerEventProcessingHandler);
- assertStateReceived(MockedPowerHalService.SET_BOOT_COMPLETE, 0);
- mPowerEventProcessingHandler.waitForPowerOn(WAIT_TIMEOUT_MS);
+ mDisplayInterface.waitForDisplayStateChange(WAIT_TIMEOUT_MS);
+ initTest(0,0);
// display should be turned on as it started with off state.
- assertTrue(mSystemInterface.waitForDisplayStateChange(WAIT_TIMEOUT_MS));
+ assertTrue(mDisplayInterface.waitForDisplayStateChange(WAIT_TIMEOUT_MS));
}
public void testShutdown() throws Exception {
final int wakeupTime = 100;
- mService = new CarPowerManagementService(mPowerHal, mSystemInterface);
- mService.init();
- mService.registerPowerEventListener(mPowerEventListener);
- mPowerEventProcessingHandler = new PowerEventProcessingHandlerImpl(0, wakeupTime);
- mService.registerPowerEventProcessingHandler(mPowerEventProcessingHandler);
- assertStateReceived(MockedPowerHalService.SET_BOOT_COMPLETE, 0);
- mPowerEventProcessingHandler.waitForPowerOn(WAIT_TIMEOUT_MS);
- assertTrue(mSystemInterface.waitForDisplayStateChange(WAIT_TIMEOUT_MS));
+ initTest(0, wakeupTime);
+ assertTrue(mDisplayInterface.waitForDisplayStateChange(WAIT_TIMEOUT_MS));
mPowerHal.setCurrentPowerState(new PowerState(PowerHalService.STATE_SHUTDOWN_PREPARE,
- PowerHalService.FLAG_SHUTDOWN_IMMEDIATELY));
+ PowerHalService.SHUTDOWN_IMMEDIATELY));
assertStateReceived(PowerHalService.SET_SHUTDOWN_START, wakeupTime);
- assertFalse(mSystemInterface.waitForDisplayStateChange(WAIT_TIMEOUT_MS));
+ assertFalse(mDisplayInterface.waitForDisplayStateChange(WAIT_TIMEOUT_MS));
mPowerEventListener.waitForShutdown(WAIT_TIMEOUT_MS);
- mSystemInterface.waitForShutdown(WAIT_TIMEOUT_MS);
+ mSystemStateInterface.waitForShutdown(WAIT_TIMEOUT_MS);
}
public void testShutdownWithProcessing() throws Exception {
final long processingTimeMs = 3000;
final int wakeupTime = 100;
- mService = new CarPowerManagementService(mPowerHal, mSystemInterface);
- mService.init();
- mService.registerPowerEventListener(mPowerEventListener);
- mPowerEventProcessingHandler = new PowerEventProcessingHandlerImpl(processingTimeMs,
- wakeupTime);
- mService.registerPowerEventProcessingHandler(mPowerEventProcessingHandler);
- assertStateReceived(MockedPowerHalService.SET_BOOT_COMPLETE, 0);
- mPowerEventProcessingHandler.waitForPowerOn(WAIT_TIMEOUT_MS);
- assertTrue(mSystemInterface.waitForDisplayStateChange(WAIT_TIMEOUT_MS));
+ initTest(processingTimeMs, wakeupTime);
+ assertTrue(mDisplayInterface.waitForDisplayStateChange(WAIT_TIMEOUT_MS));
mPowerHal.setCurrentPowerState(new PowerState(PowerHalService.STATE_SHUTDOWN_PREPARE, 0));
mPowerEventProcessingHandler.waitForPrepareShutdown(WAIT_TIMEOUT_MS);
assertStateReceivedForShutdownOrSleepWithPostpone(PowerHalService.SET_SHUTDOWN_START,
WAIT_TIMEOUT_LONG_MS, wakeupTime);
- assertFalse(mSystemInterface.waitForDisplayStateChange(WAIT_TIMEOUT_MS));
+ assertFalse(mDisplayInterface.waitForDisplayStateChange(WAIT_TIMEOUT_MS));
mPowerEventListener.waitForShutdown(WAIT_TIMEOUT_MS);
- mSystemInterface.waitForShutdown(WAIT_TIMEOUT_MS);
+ mSystemStateInterface.waitForShutdown(WAIT_TIMEOUT_MS);
}
public void testSleepEntryAndWakeup() throws Exception {
final int wakeupTime = 100;
- mService = new CarPowerManagementService(mPowerHal, mSystemInterface);
- mService.init();
- mService.registerPowerEventListener(mPowerEventListener);
- mPowerEventProcessingHandler = new PowerEventProcessingHandlerImpl(0, wakeupTime);
- mService.registerPowerEventProcessingHandler(mPowerEventProcessingHandler);
- assertStateReceived(MockedPowerHalService.SET_BOOT_COMPLETE, 0);
- mPowerEventProcessingHandler.waitForPowerOn(WAIT_TIMEOUT_MS);
- assertTrue(mSystemInterface.waitForDisplayStateChange(WAIT_TIMEOUT_MS));
+ initTest(0, wakeupTime);
+ assertTrue(mDisplayInterface.waitForDisplayStateChange(WAIT_TIMEOUT_MS));
mPowerHal.setCurrentPowerState(new PowerState(PowerHalService.STATE_SHUTDOWN_PREPARE,
- PowerHalService.FLAG_SHUTDOWN_PARAM_CAN_SLEEP));
- assertFalse(mSystemInterface.waitForDisplayStateChange(WAIT_TIMEOUT_MS));
+ PowerHalService.SHUTDOWN_CAN_SLEEP));
+ assertFalse(mDisplayInterface.waitForDisplayStateChange(WAIT_TIMEOUT_MS));
assertStateReceived(PowerHalService.SET_DEEP_SLEEP_ENTRY, 0);
mPowerEventListener.waitForSleepEntry(WAIT_TIMEOUT_MS);
- int wakeupTimeReceived = mSystemInterface.waitForSleepEntryAndWakeup(WAIT_TIMEOUT_MS);
+ int wakeupTimeReceived = mSystemStateInterface.waitForSleepEntryAndWakeup(WAIT_TIMEOUT_MS);
assertEquals(wakeupTime, wakeupTimeReceived);
assertStateReceived(PowerHalService.SET_DEEP_SLEEP_EXIT, 0);
mPowerEventListener.waitForSleepExit(WAIT_TIMEOUT_MS);
@@ -163,27 +159,20 @@
public void testSleepEntryAndPowerOnWithProcessing() throws Exception {
final long processingTimeMs = 3000;
final int wakeupTime = 100;
- mService = new CarPowerManagementService(mPowerHal, mSystemInterface);
- mService.init();
- mService.registerPowerEventListener(mPowerEventListener);
- mPowerEventProcessingHandler = new PowerEventProcessingHandlerImpl(processingTimeMs,
- wakeupTime);
- mService.registerPowerEventProcessingHandler(mPowerEventProcessingHandler);
- assertStateReceived(MockedPowerHalService.SET_BOOT_COMPLETE, 0);
- mPowerEventProcessingHandler.waitForPowerOn(WAIT_TIMEOUT_MS);
- assertTrue(mSystemInterface.waitForDisplayStateChange(WAIT_TIMEOUT_MS));
+ initTest(processingTimeMs, wakeupTime);
+ assertTrue(mDisplayInterface.waitForDisplayStateChange(WAIT_TIMEOUT_MS));
mPowerHal.setCurrentPowerState(new PowerState(PowerHalService.STATE_SHUTDOWN_PREPARE,
- PowerHalService.FLAG_SHUTDOWN_PARAM_CAN_SLEEP));
+ PowerHalService.SHUTDOWN_CAN_SLEEP));
mPowerEventProcessingHandler.waitForPrepareShutdown(WAIT_TIMEOUT_MS);
- assertFalse(mSystemInterface.waitForDisplayStateChange(WAIT_TIMEOUT_MS));
+ assertFalse(mDisplayInterface.waitForDisplayStateChange(WAIT_TIMEOUT_MS));
assertStateReceivedForShutdownOrSleepWithPostpone(PowerHalService.SET_DEEP_SLEEP_ENTRY,
WAIT_TIMEOUT_LONG_MS, 0);
mPowerEventListener.waitForSleepEntry(WAIT_TIMEOUT_MS);
// set power on here without notification. PowerManager should check the state after sleep
// exit
mPowerHal.setCurrentPowerState(new PowerState(PowerHalService.STATE_ON_DISP_OFF, 0), false);
- int wakeupTimeReceived = mSystemInterface.waitForSleepEntryAndWakeup(WAIT_TIMEOUT_MS);
+ int wakeupTimeReceived = mSystemStateInterface.waitForSleepEntryAndWakeup(WAIT_TIMEOUT_MS);
assertEquals(wakeupTime, wakeupTimeReceived);
assertStateReceived(PowerHalService.SET_DEEP_SLEEP_EXIT, 0);
mPowerEventListener.waitForSleepExit(WAIT_TIMEOUT_MS);
@@ -193,43 +182,36 @@
public void testSleepEntryAndWakeUpForProcessing() throws Exception {
final long processingTimeMs = 3000;
final int wakeupTime = 100;
- mService = new CarPowerManagementService(mPowerHal, mSystemInterface);
- mService.init();
- mService.registerPowerEventListener(mPowerEventListener);
- mPowerEventProcessingHandler = new PowerEventProcessingHandlerImpl(processingTimeMs,
- wakeupTime);
- mService.registerPowerEventProcessingHandler(mPowerEventProcessingHandler);
- assertStateReceived(MockedPowerHalService.SET_BOOT_COMPLETE, 0);
- mPowerEventProcessingHandler.waitForPowerOn(WAIT_TIMEOUT_MS);
- assertTrue(mSystemInterface.waitForDisplayStateChange(WAIT_TIMEOUT_MS));
+ initTest(processingTimeMs, wakeupTime);
+ assertTrue(mDisplayInterface.waitForDisplayStateChange(WAIT_TIMEOUT_MS));
mPowerHal.setCurrentPowerState(new PowerState(PowerHalService.STATE_SHUTDOWN_PREPARE,
- PowerHalService.FLAG_SHUTDOWN_PARAM_CAN_SLEEP));
+ PowerHalService.SHUTDOWN_CAN_SLEEP));
mPowerEventProcessingHandler.waitForPrepareShutdown(WAIT_TIMEOUT_MS);
- assertFalse(mSystemInterface.waitForDisplayStateChange(WAIT_TIMEOUT_MS));
+ assertFalse(mDisplayInterface.waitForDisplayStateChange(WAIT_TIMEOUT_MS));
assertStateReceivedForShutdownOrSleepWithPostpone(PowerHalService.SET_DEEP_SLEEP_ENTRY,
WAIT_TIMEOUT_LONG_MS, 0);
mPowerEventListener.waitForSleepEntry(WAIT_TIMEOUT_MS);
- mSystemInterface.setWakeupCausedByTimer(true);
- int wakeupTimeReceived = mSystemInterface.waitForSleepEntryAndWakeup(WAIT_TIMEOUT_MS);
+ mSystemStateInterface.setWakeupCausedByTimer(true);
+ int wakeupTimeReceived = mSystemStateInterface.waitForSleepEntryAndWakeup(WAIT_TIMEOUT_MS);
assertEquals(wakeupTime, wakeupTimeReceived);
assertStateReceived(PowerHalService.SET_DEEP_SLEEP_EXIT, 0);
mPowerEventListener.waitForSleepExit(WAIT_TIMEOUT_MS);
// second processing after wakeup
- assertFalse(mSystemInterface.getDisplayState());
+ assertFalse(mDisplayInterface.getDisplayState());
mPowerEventProcessingHandler.waitForPrepareShutdown(WAIT_TIMEOUT_MS);
assertStateReceivedForShutdownOrSleepWithPostpone(PowerHalService.SET_DEEP_SLEEP_ENTRY,
WAIT_TIMEOUT_LONG_MS, 0);
mPowerEventListener.waitForSleepEntry(WAIT_TIMEOUT_MS);
// PM will shutdown system as it was not woken-up due to timer and it is not power on.
- mSystemInterface.setWakeupCausedByTimer(false);
- wakeupTimeReceived = mSystemInterface.waitForSleepEntryAndWakeup(WAIT_TIMEOUT_MS);
+ mSystemStateInterface.setWakeupCausedByTimer(false);
+ wakeupTimeReceived = mSystemStateInterface.waitForSleepEntryAndWakeup(WAIT_TIMEOUT_MS);
assertEquals(wakeupTime, wakeupTimeReceived);
assertStateReceived(PowerHalService.SET_DEEP_SLEEP_EXIT, 0);
assertStateReceived(PowerHalService.SET_SHUTDOWN_START, wakeupTime);
mPowerEventListener.waitForShutdown(WAIT_TIMEOUT_MS);
- mSystemInterface.waitForShutdown(WAIT_TIMEOUT_MS);
- assertFalse(mSystemInterface.getDisplayState());
+ mSystemStateInterface.waitForShutdown(WAIT_TIMEOUT_MS);
+ assertFalse(mDisplayInterface.getDisplayState());
}
private void assertStateReceived(int expectedState, int expectedParam) throws Exception {
@@ -259,15 +241,12 @@
}
}
- private static class SystemInterfaceImpl extends SystemInterface {
-
+ private static final class MockDisplayInterface implements DisplayInterface {
private boolean mDisplayOn = true;
private final Semaphore mDisplayStateWait = new Semaphore(0);
- private final Semaphore mShutdownWait = new Semaphore(0);
- private final Semaphore mSleepWait = new Semaphore(0);
- private final Semaphore mSleepExitWait = new Semaphore(0);
- private int mWakeupTime;
- private boolean mWakeupCausedByTimer = false;
+
+ @Override
+ public void setDisplayBrightness(int brightness) {}
@Override
public synchronized void setDisplayState(boolean on) {
@@ -285,8 +264,18 @@
}
@Override
- public void releaseAllWakeLocks() {
- }
+ public void startDisplayStateMonitoring(CarPowerManagementService service) {}
+
+ @Override
+ public void stopDisplayStateMonitoring() {}
+ }
+
+ private static final class MockSystemStateInterface implements SystemStateInterface {
+ private final Semaphore mShutdownWait = new Semaphore(0);
+ private final Semaphore mSleepWait = new Semaphore(0);
+ private final Semaphore mSleepExitWait = new Semaphore(0);
+ private int mWakeupTime;
+ private boolean mWakeupCausedByTimer = false;
@Override
public void shutdown() {
@@ -298,17 +287,13 @@
}
@Override
- public void enterDeepSleep(int wakeupTimeSec) {
+ public boolean enterDeepSleep(int wakeupTimeSec) {
mWakeupTime = wakeupTimeSec;
mSleepWait.release();
try {
mSleepExitWait.acquire();
} catch (InterruptedException e) {
}
- }
-
- @Override
- public boolean isSystemSupportingDeepSleep() {
return true;
}
@@ -319,23 +304,10 @@
}
@Override
- public void switchToPartialWakeLock() {
- }
+ public void scheduleActionForBootCompleted(Runnable action, Duration delay) {}
@Override
- public void switchToFullWakeLock() {
- }
-
- @Override
- public void startDisplayStateMonitoring(CarPowerManagementService service) {
- }
-
- @Override
- public void stopDisplayStateMonitoring() {
- }
-
- @Override
- public synchronized boolean isWakeupCausedByTimer() {
+ public boolean isWakeupCausedByTimer() {
Log.i(TAG, "isWakeupCausedByTimer:" + mWakeupCausedByTimer);
return mWakeupCausedByTimer;
}
@@ -343,6 +315,50 @@
public synchronized void setWakeupCausedByTimer(boolean set) {
mWakeupCausedByTimer = set;
}
+
+ @Override
+ public boolean isSystemSupportingDeepSleep() {
+ return true;
+ }
+ }
+
+ private static final class MockWakeLockInterface implements WakeLockInterface {
+
+ @Override
+ public void releaseAllWakeLocks() {}
+
+ @Override
+ public void switchToPartialWakeLock() {}
+
+ @Override
+ public void switchToFullWakeLock() {}
+ }
+
+ private static final class MockIOInterface implements IOInterface {
+ private TemporaryDirectory mFilesDir;
+
+ @Override
+ public File getFilesDir() {
+ if (mFilesDir == null) {
+ try {
+ mFilesDir = new TemporaryDirectory(TAG);
+ } catch (IOException e) {
+ Log.e(TAG, "failed to create temporary directory", e);
+ fail("failed to create temporary directory. exception was: " + e);
+ }
+ }
+ return mFilesDir.getDirectory();
+ }
+
+ public void tearDown() {
+ if (mFilesDir != null) {
+ try {
+ mFilesDir.close();
+ } catch (Exception e) {
+ Log.w(TAG, "could not remove temporary directory", e);
+ }
+ }
+ }
}
private class PowerEventListener implements PowerServiceEventListener {
diff --git a/tests/carservice_unit_test/src/com/android/car/CarUserManagerHelperTest.java b/tests/carservice_unit_test/src/com/android/car/CarUserManagerHelperTest.java
new file mode 100644
index 0000000..44cc0d6
--- /dev/null
+++ b/tests/carservice_unit_test/src/com/android/car/CarUserManagerHelperTest.java
@@ -0,0 +1,387 @@
+/*
+ * 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;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import android.app.ActivityManager;
+import android.car.user.CarUserManagerHelper;
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.content.pm.UserInfo;
+import android.graphics.Bitmap;
+import android.graphics.drawable.Drawable;
+import android.os.Handler;
+import android.os.SystemProperties;
+import android.os.UserHandle;
+import android.os.UserManager;
+import android.support.test.InstrumentationRegistry;
+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.Mock;
+import org.mockito.MockitoAnnotations;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * This class contains unit tests for the {@link CarUserManagerHelper}.
+ * It tests that {@link CarUserManagerHelper} does the right thing for user management flows.
+ *
+ * The following mocks are used:
+ * 1. {@link Context} provides system services and resources.
+ * 2. {@link UserManager} provides dummy users and user info.
+ * 3. {@link ActivityManager} provides dummy current process user.
+ * 4. {@link CarUserManagerHelper.OnUsersUpdateListener} registers a listener for user updates.
+ */
+@RunWith(AndroidJUnit4.class)
+public class CarUserManagerHelperTest {
+ @Mock
+ private Context mContext;
+ @Mock
+ private UserManager mUserManager;
+ @Mock
+ private ActivityManager mActivityManager;
+ @Mock
+ private CarUserManagerHelper.OnUsersUpdateListener mTestListener;
+
+ private CarUserManagerHelper mHelper;
+ private UserInfo mCurrentProcessUser;
+ private UserInfo mSystemUser;
+ private String mGuestUserName = "testGuest";
+ private String mTestUserName = "testUser";
+
+ @Before
+ public void setUpMocksAndVariables() throws Exception {
+ MockitoAnnotations.initMocks(this);
+ when(mContext.getSystemService(Context.USER_SERVICE)).thenReturn(mUserManager);
+ when(mContext.getSystemService(Context.ACTIVITY_SERVICE)).thenReturn(mActivityManager);
+ when(mContext.getResources())
+ .thenReturn(InstrumentationRegistry.getTargetContext().getResources());
+ when(mContext.getApplicationContext()).thenReturn(mContext);
+ mHelper = new CarUserManagerHelper(mContext);
+
+ mCurrentProcessUser = createUserInfoForId(UserHandle.myUserId());
+ mSystemUser = createUserInfoForId(UserHandle.USER_SYSTEM);
+ when(mUserManager.getUserInfo(UserHandle.myUserId())).thenReturn(mCurrentProcessUser);
+ }
+
+ @Test
+ public void checkIsSystemUser() {
+ UserInfo testInfo = new UserInfo();
+
+ testInfo.id = UserHandle.USER_SYSTEM;
+ assertThat(mHelper.isSystemUser(testInfo)).isTrue();
+
+ testInfo.id = UserHandle.USER_SYSTEM + 2; // Make it different than system id.
+ assertThat(mHelper.isSystemUser(testInfo)).isFalse();
+ }
+
+ // System user will not be returned when calling get all users.
+ @Test
+ public void testHeadlessUser0GetAllUsers_NotReturnSystemUser() {
+ SystemProperties.set("android.car.systemuser.headless", "true");
+ UserInfo otherUser1 = createUserInfoForId(10);
+ UserInfo otherUser2 = createUserInfoForId(11);
+ UserInfo otherUser3 = createUserInfoForId(12);
+
+ List<UserInfo> testUsers = new ArrayList<>();
+ testUsers.add(mSystemUser);
+ testUsers.add(otherUser1);
+ testUsers.add(otherUser2);
+ testUsers.add(otherUser3);
+
+ when(mUserManager.getUsers(true)).thenReturn(testUsers);
+
+ // Should return 3 users that don't have SYSTEM USER id.
+ assertThat(mHelper.getAllUsers()).hasSize(3);
+ assertThat(mHelper.getAllUsers())
+ .containsExactly(otherUser1, otherUser2, otherUser3);
+ }
+
+ @Test
+ public void testHeadlessUser0GetAllUsersWithActiveForegroundUser_NotReturnSystemUser() {
+ SystemProperties.set("android.car.systemuser.headless", "true");
+ mCurrentProcessUser = createUserInfoForId(10);
+
+ UserInfo otherUser1 = createUserInfoForId(11);
+ UserInfo otherUser2 = createUserInfoForId(12);
+ UserInfo otherUser3 = createUserInfoForId(13);
+
+ List<UserInfo> testUsers = new ArrayList<>();
+ testUsers.add(mSystemUser);
+ testUsers.add(mCurrentProcessUser);
+ testUsers.add(otherUser1);
+ testUsers.add(otherUser2);
+ testUsers.add(otherUser3);
+
+ when(mUserManager.getUsers(true)).thenReturn(testUsers);
+
+ assertThat(mHelper.getAllUsers().size()).isEqualTo(4);
+ assertThat(mHelper.getAllUsers())
+ .containsExactly(mCurrentProcessUser, otherUser1, otherUser2, otherUser3);
+ }
+
+ @Test
+ public void testGetAllSwitchableUsers() {
+ UserInfo user1 = createUserInfoForId(10);
+ UserInfo user2 = createUserInfoForId(11);
+ UserInfo user3 = createUserInfoForId(12);
+
+ List<UserInfo> testUsers = new ArrayList<>();
+ testUsers.add(mSystemUser);
+ testUsers.add(user1);
+ testUsers.add(user2);
+ testUsers.add(user3);
+
+ when(mUserManager.getUsers(true)).thenReturn(new ArrayList<>(testUsers));
+
+ // Should return all 3 non-system users.
+ assertThat(mHelper.getAllUsers().size())
+ .isEqualTo(3);
+
+ when(mUserManager.getUserInfo(UserHandle.myUserId())).thenReturn(user1);
+ // Should return user 10, 11 and 12.
+ assertThat(mHelper.getAllSwitchableUsers().size())
+ .isEqualTo(3);
+ assertThat(mHelper.getAllSwitchableUsers()).contains(user1);
+ assertThat(mHelper.getAllSwitchableUsers()).contains(user2);
+ assertThat(mHelper.getAllSwitchableUsers()).contains(user3);
+ }
+
+ // Get all users for headless user 0 model should exclude system user by default.
+ @Test
+ public void testHeadlessUser0GetAllSwitchableUsers() {
+ SystemProperties.set("android.car.systemuser.headless", "true");
+ UserInfo user1 = createUserInfoForId(10);
+ UserInfo user2 = createUserInfoForId(11);
+ UserInfo user3 = createUserInfoForId(12);
+
+ List<UserInfo> testUsers = new ArrayList<>();
+ testUsers.add(mSystemUser);
+ testUsers.add(user1);
+ testUsers.add(user2);
+ testUsers.add(user3);
+
+ when(mUserManager.getUsers(true)).thenReturn(new ArrayList<>(testUsers));
+
+ // Should return all 3 non-system users.
+ assertThat(mHelper.getAllUsers()).hasSize(3);
+
+ when(mUserManager.getUserInfo(UserHandle.myUserId())).thenReturn(user1);
+ // Should return user 10, 11 and 12.
+ assertThat(mHelper.getAllSwitchableUsers()).containsExactly(user1, user2, user3);
+ }
+
+ @Test
+ public void testUserCanBeRemoved() {
+ UserInfo testInfo = new UserInfo();
+
+ // System user cannot be removed.
+ testInfo.id = UserHandle.USER_SYSTEM;
+ assertThat(mHelper.canUserBeRemoved(testInfo)).isFalse();
+
+ testInfo.id = UserHandle.USER_SYSTEM + 2; // Make it different than system id.
+ assertThat(mHelper.canUserBeRemoved(testInfo)).isTrue();
+ }
+
+ @Test
+ public void testCurrentProcessCanAddUsers() {
+ when(mUserManager.hasUserRestriction(UserManager.DISALLOW_ADD_USER)).thenReturn(false);
+ assertThat(mHelper.canCurrentProcessAddUsers()).isTrue();
+
+ when(mUserManager.hasUserRestriction(UserManager.DISALLOW_ADD_USER)).thenReturn(true);
+ assertThat(mHelper.canCurrentProcessAddUsers()).isFalse();
+ }
+
+ @Test
+ public void testCurrentProcessCanRemoveUsers() {
+ when(mUserManager.hasUserRestriction(UserManager.DISALLOW_REMOVE_USER)).thenReturn(false);
+ assertThat(mHelper.canCurrentProcessRemoveUsers()).isTrue();
+
+ when(mUserManager.hasUserRestriction(UserManager.DISALLOW_REMOVE_USER)).thenReturn(true);
+ assertThat(mHelper.canCurrentProcessRemoveUsers()).isFalse();
+ }
+
+ @Test
+ public void testCurrentProcessCanSwitchUsers() {
+ when(mUserManager.hasUserRestriction(UserManager.DISALLOW_USER_SWITCH)).thenReturn(false);
+ assertThat(mHelper.canCurrentProcessSwitchUsers()).isTrue();
+
+ when(mUserManager.hasUserRestriction(UserManager.DISALLOW_USER_SWITCH)).thenReturn(true);
+ assertThat(mHelper.canCurrentProcessSwitchUsers()).isFalse();
+ }
+
+ @Test
+ public void testCurrentGuestProcessCannotModifyAccounts() {
+ assertThat(mHelper.canCurrentProcessModifyAccounts()).isTrue();
+
+ when(mUserManager.isGuestUser()).thenReturn(true);
+ assertThat(mHelper.canCurrentProcessModifyAccounts()).isFalse();
+ }
+
+ @Test
+ public void testCurrentDemoProcessCannotModifyAccounts() {
+ assertThat(mHelper.canCurrentProcessModifyAccounts()).isTrue();
+
+ when(mUserManager.isDemoUser()).thenReturn(true);
+ assertThat(mHelper.canCurrentProcessModifyAccounts()).isFalse();
+ }
+
+ @Test
+ public void testCurrentDisallowModifyAccountsProcessIsEnforced() {
+ assertThat(mHelper.canCurrentProcessModifyAccounts()).isTrue();
+
+ when(mUserManager.hasUserRestriction(UserManager.DISALLOW_MODIFY_ACCOUNTS))
+ .thenReturn(true);
+ assertThat(mHelper.canCurrentProcessModifyAccounts()).isFalse();
+ }
+
+ @Test
+ public void testCreateNewAdminUser() {
+ // Verify createUser on UserManager gets called.
+ mHelper.createNewAdminUser(mTestUserName);
+ verify(mUserManager).createUser(mTestUserName, UserInfo.FLAG_ADMIN);
+
+ when(mUserManager.createUser(mTestUserName, UserInfo.FLAG_ADMIN)).thenReturn(null);
+ assertThat(mHelper.createNewAdminUser(mTestUserName)).isNull();
+
+ UserInfo newUser = new UserInfo();
+ newUser.name = mTestUserName;
+ when(mUserManager.createUser(mTestUserName, UserInfo.FLAG_ADMIN)).thenReturn(newUser);
+ assertThat(mHelper.createNewAdminUser(mTestUserName)).isEqualTo(newUser);
+ }
+
+ @Test
+ public void testCreateNewNonAdminUser() {
+ // Verify createUser on UserManager gets called.
+ mHelper.createNewNonAdminUser(mTestUserName);
+ verify(mUserManager).createUser(mTestUserName, 0);
+
+ when(mUserManager.createUser(mTestUserName, 0)).thenReturn(null);
+ assertThat(mHelper.createNewNonAdminUser(mTestUserName)).isNull();
+
+ UserInfo newUser = new UserInfo();
+ newUser.name = mTestUserName;
+ when(mUserManager.createUser(mTestUserName, 0)).thenReturn(newUser);
+ assertThat(mHelper.createNewNonAdminUser(mTestUserName)).isEqualTo(newUser);
+ }
+
+ @Test
+ public void testRemoveUser() {
+ // Cannot remove system user.
+ assertThat(mHelper.removeUser(mSystemUser, mGuestUserName)).isFalse();
+
+ // Removing non-current, non-system user, simply calls removeUser.
+ UserInfo userToRemove = createUserInfoForId(mCurrentProcessUser.id + 2);
+
+ mHelper.removeUser(userToRemove, mGuestUserName);
+ verify(mUserManager).removeUser(mCurrentProcessUser.id + 2);
+ }
+
+ @Test
+ public void testSwitchToGuest() {
+ mHelper.startNewGuestSession(mGuestUserName);
+ verify(mUserManager).createGuest(mContext, mGuestUserName);
+
+ UserInfo guestInfo = new UserInfo(21, mGuestUserName, UserInfo.FLAG_GUEST);
+ when(mUserManager.createGuest(mContext, mGuestUserName)).thenReturn(guestInfo);
+ mHelper.startNewGuestSession(mGuestUserName);
+ verify(mActivityManager).switchUser(21);
+ }
+
+ @Test
+ public void testGetUserIcon() {
+ mHelper.getUserIcon(mCurrentProcessUser);
+ verify(mUserManager).getUserIcon(mCurrentProcessUser.id);
+ }
+
+ @Test
+ public void testScaleUserIcon() {
+ Bitmap fakeIcon = Bitmap.createBitmap(100, 100, Bitmap.Config.ARGB_8888);
+ Drawable scaledIcon = mHelper.scaleUserIcon(fakeIcon, 300);
+ assertThat(scaledIcon.getIntrinsicWidth()).isEqualTo(300);
+ assertThat(scaledIcon.getIntrinsicHeight()).isEqualTo(300);
+ }
+
+ @Test
+ public void testSetUserName() {
+ UserInfo testInfo = createUserInfoForId(mCurrentProcessUser.id + 3);
+ String newName = "New Test Name";
+ mHelper.setUserName(testInfo, newName);
+ verify(mUserManager).setUserName(mCurrentProcessUser.id + 3, newName);
+ }
+
+ @Test
+ public void testRegisterUserChangeReceiver() {
+ mHelper.registerOnUsersUpdateListener(mTestListener);
+
+ ArgumentCaptor<BroadcastReceiver> receiverCaptor =
+ ArgumentCaptor.forClass(BroadcastReceiver.class);
+ ArgumentCaptor<UserHandle> handleCaptor = ArgumentCaptor.forClass(UserHandle.class);
+ ArgumentCaptor<IntentFilter> filterCaptor = ArgumentCaptor.forClass(IntentFilter.class);
+ ArgumentCaptor<String> permissionCaptor = ArgumentCaptor.forClass(String.class);
+ ArgumentCaptor<Handler> handlerCaptor = ArgumentCaptor.forClass(Handler.class);
+
+ verify(mContext).registerReceiverAsUser(
+ receiverCaptor.capture(),
+ handleCaptor.capture(),
+ filterCaptor.capture(),
+ permissionCaptor.capture(),
+ handlerCaptor.capture());
+
+ // Verify we're listening to Intents from ALL users.
+ assertThat(handleCaptor.getValue()).isEqualTo(UserHandle.ALL);
+
+ // Verify the presence of each intent in the filter.
+ // Verify the exact number of filters. Every time a new intent is added, this test should
+ // get updated.
+ assertThat(filterCaptor.getValue().countActions()).isEqualTo(6);
+ assertThat(filterCaptor.getValue().hasAction(Intent.ACTION_USER_REMOVED)).isTrue();
+ assertThat(filterCaptor.getValue().hasAction(Intent.ACTION_USER_ADDED)).isTrue();
+ assertThat(filterCaptor.getValue().hasAction(Intent.ACTION_USER_INFO_CHANGED)).isTrue();
+ assertThat(filterCaptor.getValue().hasAction(Intent.ACTION_USER_SWITCHED)).isTrue();
+ assertThat(filterCaptor.getValue().hasAction(Intent.ACTION_USER_STOPPED)).isTrue();
+ assertThat(filterCaptor.getValue().hasAction(Intent.ACTION_USER_UNLOCKED)).isTrue();
+
+ // Verify that calling the receiver calls the listener.
+ receiverCaptor.getValue().onReceive(mContext, new Intent());
+ verify(mTestListener).onUsersUpdate();
+
+ assertThat(permissionCaptor.getValue()).isNull();
+ assertThat(handlerCaptor.getValue()).isNull();
+
+ // Unregister the receiver.
+ mHelper.unregisterOnUsersUpdateListener();
+ verify(mContext).unregisterReceiver(receiverCaptor.getValue());
+ }
+
+ private UserInfo createUserInfoForId(int id) {
+ UserInfo userInfo = new UserInfo();
+ userInfo.id = id;
+ return userInfo;
+ }
+}
diff --git a/tests/carservice_unit_test/src/com/android/car/MockedPowerHalService.java b/tests/carservice_unit_test/src/com/android/car/MockedPowerHalService.java
index fbb70d4..405c014 100644
--- a/tests/carservice_unit_test/src/com/android/car/MockedPowerHalService.java
+++ b/tests/carservice_unit_test/src/com/android/car/MockedPowerHalService.java
@@ -35,7 +35,7 @@
public MockedPowerHalService(boolean isPowerStateSupported, boolean isDeepSleepAllowed,
boolean isTimedWakeupAllowed) {
- super(new VehicleHal(null, null, null, null, null, null, null, null, null));
+ super(new VehicleHal(null, null, null, null));
mIsPowerStateSupported = isPowerStateSupported;
mIsDeepSleepAllowed = isDeepSleepAllowed;
mIsTimedWakeupAllowed = isTimedWakeupAllowed;
diff --git a/tests/carservice_unit_test/src/com/android/car/SlidingWindowTest.java b/tests/carservice_unit_test/src/com/android/car/SlidingWindowTest.java
new file mode 100644
index 0000000..5d372d9
--- /dev/null
+++ b/tests/carservice_unit_test/src/com/android/car/SlidingWindowTest.java
@@ -0,0 +1,74 @@
+/*
+ * 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.android.car;
+
+import android.test.suitebuilder.annotation.MediumTest;
+
+import java.util.Arrays;
+import java.util.Iterator;
+import java.util.List;
+import junit.framework.TestCase;
+
+@MediumTest
+public class SlidingWindowTest extends TestCase {
+ static final String TAG = SlidingWindowTest.class.getSimpleName();
+
+ private static <T> boolean sameContents(Iterator<T> t1, Iterator<T> t2) {
+ while(t1.hasNext()) {
+ if (!t2.hasNext()) {
+ return false;
+ }
+ T e1 = t1.next();
+ T e2 = t2.next();
+ if (!e1.equals(e2)) {
+ return false;
+ }
+ }
+ return !t2.hasNext();
+ }
+
+ public void testAdd() {
+ final List<Integer> elements = Arrays.asList(3, 4);
+ SlidingWindow<Integer> window = new SlidingWindow<>(5);
+ elements.forEach(window::add);
+ assertTrue(sameContents(elements.iterator(), window.iterator()));
+ }
+
+ public void testAddOverflow() {
+ final List<Integer> elements = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
+ final List<Integer> expectedElements = Arrays.asList(6, 7, 8, 9, 10);
+ SlidingWindow<Integer> window = new SlidingWindow<>(5);
+ window.addAll(elements);
+ assertTrue(sameContents(expectedElements.iterator(), window.iterator()));
+ }
+
+ public void testStream() {
+ final List<Integer> elements = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
+ final List<Integer> expectedElements = Arrays.asList(6, 7, 8, 9, 10);
+ SlidingWindow<Integer> window = new SlidingWindow<>(5);
+ window.addAll(elements);
+ for (Integer e : expectedElements) {
+ assertTrue(window.stream().anyMatch(e::equals));
+ }
+ }
+
+ public void testCount() {
+ final List<Integer> elements = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
+ SlidingWindow<Integer> window = new SlidingWindow<>(5);
+ window.addAll(elements);
+ assertEquals(3, window.count((Integer e) -> (e % 2) == 0));
+ }
+}
diff --git a/tests/carservice_unit_test/src/com/android/car/UptimeTrackerTest.java b/tests/carservice_unit_test/src/com/android/car/UptimeTrackerTest.java
new file mode 100644
index 0000000..1b46825
--- /dev/null
+++ b/tests/carservice_unit_test/src/com/android/car/UptimeTrackerTest.java
@@ -0,0 +1,143 @@
+/*
+ * 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.android.car;
+
+import android.test.suitebuilder.annotation.MediumTest;
+import com.android.car.systeminterface.TimeInterface;
+import com.android.car.test.utils.TemporaryFile;
+
+import junit.framework.TestCase;
+
+@MediumTest
+public class UptimeTrackerTest extends TestCase {
+ static final String TAG = UptimeTrackerTest.class.getSimpleName();
+
+ static final class MockTimeInterface implements TimeInterface {
+ private long mCurrentTime = 0;
+ private Runnable mRunnable = null;
+
+ MockTimeInterface incrementTime(long by) {
+ mCurrentTime += by;
+ return this;
+ }
+
+ MockTimeInterface tick() {
+ if (mRunnable != null) {
+ mRunnable.run();
+ }
+ return this;
+ }
+
+ @Override
+ public long getUptime(boolean includeDeepSleepTime) {
+ return mCurrentTime;
+ }
+
+ @Override
+ public void scheduleAction(Runnable r, long delayMs) {
+ if (mRunnable != null) {
+ throw new IllegalStateException("task already scheduled");
+ }
+ mRunnable = r;
+ }
+
+ @Override
+ public void cancelAllActions() {
+ mRunnable = null;
+ }
+ }
+
+ private static final long SNAPSHOT_INTERVAL = 0; // actual time doesn't matter for this test
+
+ public void testUptimeTrackerFromCleanSlate() throws Exception {
+ MockTimeInterface timeInterface = new MockTimeInterface();
+ try (TemporaryFile uptimeFile = new TemporaryFile(TAG)) {
+ UptimeTracker uptimeTracker = new UptimeTracker(uptimeFile.getFile(),
+ SNAPSHOT_INTERVAL, timeInterface);
+
+ assertEquals(0, uptimeTracker.getTotalUptime());
+
+ timeInterface.incrementTime(5000).tick();
+ assertEquals(5000, uptimeTracker.getTotalUptime());
+
+ timeInterface.tick();
+ assertEquals(5000, uptimeTracker.getTotalUptime());
+
+ timeInterface.incrementTime(1000).tick();
+ assertEquals(6000, uptimeTracker.getTotalUptime());
+
+ timeInterface.incrementTime(400).tick();
+ assertEquals(6400, uptimeTracker.getTotalUptime());
+ }
+ }
+
+ public void testUptimeTrackerWithHistoricalState() throws Exception {
+ MockTimeInterface timeInterface = new MockTimeInterface();
+ try (TemporaryFile uptimeFile = new TemporaryFile(TAG)) {
+ uptimeFile.write("{\"uptime\" : 5000}");
+ UptimeTracker uptimeTracker = new UptimeTracker(uptimeFile.getFile(),
+ SNAPSHOT_INTERVAL, timeInterface);
+
+ assertEquals(5000, uptimeTracker.getTotalUptime());
+
+ timeInterface.incrementTime(5000).tick();
+ assertEquals(10000, uptimeTracker.getTotalUptime());
+
+ timeInterface.incrementTime(1000).tick();
+ assertEquals(11000, uptimeTracker.getTotalUptime());
+ }
+ }
+
+ public void testUptimeTrackerAcrossHistoricalState() throws Exception {
+ MockTimeInterface timeInterface = new MockTimeInterface();
+ try (TemporaryFile uptimeFile = new TemporaryFile(TAG)) {
+ uptimeFile.write("{\"uptime\" : 5000}");
+ UptimeTracker uptimeTracker = new UptimeTracker(uptimeFile.getFile(),
+ SNAPSHOT_INTERVAL, timeInterface);
+
+ assertEquals(5000, uptimeTracker.getTotalUptime());
+
+ timeInterface.incrementTime(5000).tick();
+ assertEquals(10000, uptimeTracker.getTotalUptime());
+
+ timeInterface.incrementTime(500).tick();
+ uptimeTracker.onDestroy();
+ timeInterface.cancelAllActions();
+
+ uptimeTracker = new UptimeTracker(uptimeFile.getFile(),
+ SNAPSHOT_INTERVAL, timeInterface);
+
+ timeInterface.incrementTime(3000).tick();
+ assertEquals(13500, uptimeTracker.getTotalUptime());
+ }
+ }
+
+ public void testUptimeTrackerShutdown() throws Exception {
+ MockTimeInterface timeInterface = new MockTimeInterface();
+ try (TemporaryFile uptimeFile = new TemporaryFile(TAG)) {
+ UptimeTracker uptimeTracker = new UptimeTracker(uptimeFile.getFile(),
+ SNAPSHOT_INTERVAL, timeInterface);
+
+ timeInterface.incrementTime(6000);
+ uptimeTracker.onDestroy();
+ timeInterface.cancelAllActions();
+
+ uptimeTracker = new UptimeTracker(uptimeFile.getFile(),
+ SNAPSHOT_INTERVAL, timeInterface);
+ assertEquals(6000, uptimeTracker.getTotalUptime());
+ }
+ }
+}
diff --git a/tests/carservice_unit_test/src/com/android/car/VmsAssociatedLayerTest.java b/tests/carservice_unit_test/src/com/android/car/VmsAssociatedLayerTest.java
new file mode 100644
index 0000000..1d384cc
--- /dev/null
+++ b/tests/carservice_unit_test/src/com/android/car/VmsAssociatedLayerTest.java
@@ -0,0 +1,140 @@
+/*
+ * 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.android.car;
+
+import static org.junit.Assert.assertNotEquals;
+
+import android.car.vms.VmsAssociatedLayer;
+import android.car.vms.VmsLayer;
+import android.test.AndroidTestCase;
+import android.test.suitebuilder.annotation.SmallTest;
+
+import android.os.Parcel;
+
+import java.util.Arrays;
+import java.util.HashSet;
+
+
+/*
+ * A class to test the VmsAssociatedLayer parcelability.
+ */
+@SmallTest
+public class VmsAssociatedLayerTest extends AndroidTestCase {
+ private static final int LAYER_ID = 12;
+ private static final int LAYER_VERSION = 34;
+ private static final int LAYER_SUBTYPE = 56;
+
+ private static final int PUBLISHER_ID_1 = 111;
+ private static final int PUBLISHER_ID_2 = 222;
+
+ private static final int DIFFERENT_LAYER_ID = 99;
+
+ private static final VmsLayer VMS_LAYER = new VmsLayer(
+ LAYER_ID,
+ LAYER_SUBTYPE,
+ LAYER_VERSION);
+
+ private static final VmsLayer ANOTHER_VMS_LAYER = new VmsLayer(
+ DIFFERENT_LAYER_ID,
+ LAYER_SUBTYPE,
+ LAYER_VERSION);
+
+
+ public void testNoPublishersAssociatedLayerParcel() throws Exception {
+ VmsAssociatedLayer vmsAssociatedLayer =
+ new VmsAssociatedLayer(
+ VMS_LAYER,
+ new HashSet<>(Arrays.asList()));
+ Parcel parcel = Parcel.obtain();
+ vmsAssociatedLayer.writeToParcel(parcel, vmsAssociatedLayer.describeContents());
+ parcel.setDataPosition(0);
+ VmsAssociatedLayer createdFromParcel = VmsAssociatedLayer.CREATOR.createFromParcel(parcel);
+ assertEquals(vmsAssociatedLayer, createdFromParcel);
+ }
+
+ public void testLayerWithMultiplePublishersParcel() throws Exception {
+ VmsAssociatedLayer vmsAssociatedLayer =
+ new VmsAssociatedLayer(
+ VMS_LAYER,
+ new HashSet<>(Arrays.asList(PUBLISHER_ID_1, PUBLISHER_ID_2)));
+ Parcel parcel = Parcel.obtain();
+ vmsAssociatedLayer.writeToParcel(parcel, vmsAssociatedLayer.describeContents());
+ parcel.setDataPosition(0);
+ VmsAssociatedLayer createdFromParcel = VmsAssociatedLayer.CREATOR.createFromParcel(parcel);
+ assertEquals(vmsAssociatedLayer, createdFromParcel);
+ }
+
+ public void testNoPublishersAssociatedLayerEquality() throws Exception {
+ VmsAssociatedLayer original =
+ new VmsAssociatedLayer(
+ VMS_LAYER,
+ new HashSet<>(Arrays.asList()));
+
+ VmsAssociatedLayer similar =
+ new VmsAssociatedLayer(
+ VMS_LAYER,
+ new HashSet<>(Arrays.asList()));
+
+ assertEquals(original.getVmsLayer(), similar.getVmsLayer());
+ assertEquals(original.getPublisherIds(), similar.getPublisherIds());
+ assertEquals(original, similar);
+ }
+
+ public void testLayerWithMultiplePublishersEquality() throws Exception {
+ VmsAssociatedLayer original =
+ new VmsAssociatedLayer(
+ VMS_LAYER,
+ new HashSet<>(Arrays.asList(PUBLISHER_ID_1, PUBLISHER_ID_2)));
+
+ VmsAssociatedLayer similar =
+ new VmsAssociatedLayer(
+ VMS_LAYER,
+ new HashSet<>(Arrays.asList(PUBLISHER_ID_1, PUBLISHER_ID_2)));
+
+ assertEquals(original.getVmsLayer(), similar.getVmsLayer());
+ assertEquals(original.getPublisherIds(), similar.getPublisherIds());
+ assertEquals(original, similar);
+ }
+
+ public void testVerifyNonEqualOnLayer() throws Exception {
+ VmsAssociatedLayer original =
+ new VmsAssociatedLayer(
+ ANOTHER_VMS_LAYER,
+ new HashSet<>(Arrays.asList()));
+
+ VmsAssociatedLayer similar =
+ new VmsAssociatedLayer(
+ VMS_LAYER,
+ new HashSet<>(Arrays.asList()));
+
+ assertNotEquals(original, similar);
+ }
+
+ public void testVerifyNonEqualOnPublisherIds() throws Exception {
+ VmsAssociatedLayer original =
+ new VmsAssociatedLayer(
+ VMS_LAYER,
+ new HashSet<>(Arrays.asList(PUBLISHER_ID_1)));
+
+ VmsAssociatedLayer similar =
+ new VmsAssociatedLayer(
+ VMS_LAYER,
+ new HashSet<>(Arrays.asList(PUBLISHER_ID_2)));
+
+ assertNotEquals(original, similar);
+ }
+}
\ No newline at end of file
diff --git a/tests/carservice_unit_test/src/com/android/car/VmsAvailableLayersTest.java b/tests/carservice_unit_test/src/com/android/car/VmsAvailableLayersTest.java
new file mode 100644
index 0000000..63ac1a3
--- /dev/null
+++ b/tests/carservice_unit_test/src/com/android/car/VmsAvailableLayersTest.java
@@ -0,0 +1,156 @@
+/*
+ * 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.android.car;
+
+import static org.junit.Assert.assertNotEquals;
+
+import android.car.vms.VmsAssociatedLayer;
+import android.car.vms.VmsAvailableLayers;
+import android.car.vms.VmsLayer;
+import android.test.AndroidTestCase;
+import android.test.suitebuilder.annotation.SmallTest;
+
+import android.os.Parcel;
+
+import java.util.Arrays;
+import java.util.HashSet;
+
+
+/*
+ * A class to test the VmsAvailableLayers parcelability.
+ */
+@SmallTest
+public class VmsAvailableLayersTest extends AndroidTestCase {
+ private static final int LAYER_ID = 12;
+ private static final int LAYER_VERSION = 34;
+ private static final int LAYER_SUBTYPE = 56;
+ private static final int PUBLISHER_ID = 999;
+ private static final int SEQUENCE_NUMBER = 17;
+
+ private static final int DIFFERENT_SEQUENCE_NUMBER = 71;
+ private static final int DIFFERENT_LAYER_ID = 21;
+
+ private static final VmsLayer VMS_LAYER = new VmsLayer(
+ LAYER_ID,
+ LAYER_SUBTYPE,
+ LAYER_VERSION);
+
+ private static final VmsLayer ANOTHER_VMS_LAYER = new VmsLayer(
+ DIFFERENT_LAYER_ID,
+ LAYER_SUBTYPE,
+ LAYER_VERSION);
+
+ private static final VmsAssociatedLayer VMS_ASSOCIATED_LAYER = new VmsAssociatedLayer(
+ VMS_LAYER,
+ new HashSet<>(Arrays.asList(PUBLISHER_ID)));
+
+ private static final VmsAssociatedLayer ANOTHER_VMS_ASSOCIATED_LAYER = new VmsAssociatedLayer(
+ ANOTHER_VMS_LAYER,
+ new HashSet<>(Arrays.asList(PUBLISHER_ID)));
+
+ public void testNoAvailableLayersParcel() throws Exception {
+ VmsAvailableLayers vmsAvailableLayers =
+ new VmsAvailableLayers(new HashSet<>(Arrays.asList()), SEQUENCE_NUMBER);
+
+ Parcel parcel = Parcel.obtain();
+
+ vmsAvailableLayers.writeToParcel(parcel, vmsAvailableLayers.describeContents());
+ parcel.setDataPosition(0);
+ VmsAvailableLayers createdFromParcel = VmsAvailableLayers.CREATOR.createFromParcel(parcel);
+ assertEquals(vmsAvailableLayers, createdFromParcel);
+ }
+
+ public void testMultipleAvailableLayersParcel() throws Exception {
+ VmsAvailableLayers vmsAvailableLayers =
+ new VmsAvailableLayers(
+ new HashSet<>(Arrays.asList(
+ VMS_ASSOCIATED_LAYER,
+ ANOTHER_VMS_ASSOCIATED_LAYER)),
+ SEQUENCE_NUMBER);
+
+ Parcel parcel = Parcel.obtain();
+
+ vmsAvailableLayers.writeToParcel(parcel, vmsAvailableLayers.describeContents());
+ parcel.setDataPosition(0);
+ VmsAvailableLayers createdFromParcel = VmsAvailableLayers.CREATOR.createFromParcel(parcel);
+ assertEquals(vmsAvailableLayers, createdFromParcel);
+ }
+
+ public void testNoAvailableLayerEquality() throws Exception {
+ VmsAvailableLayers original =
+ new VmsAvailableLayers(
+ new HashSet<>(Arrays.asList()),
+ SEQUENCE_NUMBER);
+
+ VmsAvailableLayers similar =
+ new VmsAvailableLayers(
+ new HashSet<>(Arrays.asList()),
+ SEQUENCE_NUMBER);
+
+ assertEquals(original.getAssociatedLayers(), similar.getAssociatedLayers());
+ assertEquals(original.getSequence(), similar.getSequence());
+ assertEquals(original, similar);
+ }
+
+ public void testMultipleAvailableLayerEquality() throws Exception {
+ VmsAvailableLayers original =
+ new VmsAvailableLayers(
+ new HashSet<>(Arrays.asList(
+ VMS_ASSOCIATED_LAYER,
+ ANOTHER_VMS_ASSOCIATED_LAYER)),
+ SEQUENCE_NUMBER);
+
+ VmsAvailableLayers similar =
+ new VmsAvailableLayers(
+ new HashSet<>(Arrays.asList(
+ VMS_ASSOCIATED_LAYER,
+ ANOTHER_VMS_ASSOCIATED_LAYER)),
+ SEQUENCE_NUMBER);
+
+ assertEquals(original.getAssociatedLayers(), similar.getAssociatedLayers());
+ assertEquals(original.getSequence(), similar.getSequence());
+ assertEquals(original, similar);
+ }
+
+ public void testVerifyNonEqualOnAssociatedLayer() throws Exception {
+ VmsAvailableLayers original =
+ new VmsAvailableLayers(
+ new HashSet<>(Arrays.asList(VMS_ASSOCIATED_LAYER)),
+ SEQUENCE_NUMBER);
+
+ VmsAvailableLayers similar =
+ new VmsAvailableLayers(
+ new HashSet<>(Arrays.asList(ANOTHER_VMS_ASSOCIATED_LAYER)),
+ SEQUENCE_NUMBER);
+
+ assertNotEquals(original, similar);
+ }
+
+ public void testVerifyNonEqualOnSequence() throws Exception {
+ VmsAvailableLayers original =
+ new VmsAvailableLayers(
+ new HashSet<>(Arrays.asList(VMS_ASSOCIATED_LAYER)),
+ SEQUENCE_NUMBER);
+
+ VmsAvailableLayers similar =
+ new VmsAvailableLayers(
+ new HashSet<>(Arrays.asList(VMS_ASSOCIATED_LAYER)),
+ DIFFERENT_SEQUENCE_NUMBER);
+
+ assertNotEquals(original, similar);
+ }
+}
\ No newline at end of file
diff --git a/tests/carservice_unit_test/src/com/android/car/VmsLayerDependencyTest.java b/tests/carservice_unit_test/src/com/android/car/VmsLayerDependencyTest.java
new file mode 100644
index 0000000..4c659cd
--- /dev/null
+++ b/tests/carservice_unit_test/src/com/android/car/VmsLayerDependencyTest.java
@@ -0,0 +1,149 @@
+/*
+ * 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.android.car;
+
+import static org.junit.Assert.assertNotEquals;
+
+import android.car.vms.VmsLayer;
+import android.car.vms.VmsLayerDependency;
+import android.test.AndroidTestCase;
+import android.test.suitebuilder.annotation.SmallTest;
+
+import android.os.Parcel;
+
+import java.util.Arrays;
+import java.util.HashSet;
+
+
+/*
+ * A class to test the VmsLayerDependency parcelability.
+ */
+@SmallTest
+public class VmsLayerDependencyTest extends AndroidTestCase {
+ private static final int LAYER_ID = 112;
+ private static final int LAYER_VERSION = 134;
+ private static final int LAYER_SUBTYPE = 156;
+
+ private static final int DEPENDENT_LAYER_ID = 212;
+ private static final int DEPENDENT_LAYER_VERSION = 234;
+ private static final int DEPENDENT_LAYER_SUBTYPE = 256;
+
+ private static final int DIFFERENT_LAYER_ID = 99;
+
+ private static final VmsLayer VMS_LAYER = new VmsLayer(
+ LAYER_ID,
+ LAYER_SUBTYPE,
+ LAYER_VERSION);
+
+ private static final VmsLayer ANOTHER_VMS_LAYER = new VmsLayer(
+ DIFFERENT_LAYER_ID,
+ LAYER_SUBTYPE,
+ LAYER_VERSION);
+
+ private static final VmsLayer DEPENDENT_VMS_LAYER = new VmsLayer(
+ DEPENDENT_LAYER_ID,
+ DEPENDENT_LAYER_SUBTYPE,
+ DEPENDENT_LAYER_VERSION);
+
+ private static final VmsLayer ANOTHER_DEPENDENT_VMS_LAYER = new VmsLayer(
+ DIFFERENT_LAYER_ID,
+ DEPENDENT_LAYER_SUBTYPE,
+ DEPENDENT_LAYER_VERSION);
+
+ public void testNoDependendtLayerParcel() throws Exception {
+ VmsLayerDependency vmsLayerDependency =
+ new VmsLayerDependency(
+ VMS_LAYER,
+ new HashSet<>(Arrays.asList()));
+
+ Parcel parcel = Parcel.obtain();
+ vmsLayerDependency.writeToParcel(parcel, vmsLayerDependency.describeContents());
+ parcel.setDataPosition(0);
+ VmsLayerDependency createdFromParcel = VmsLayerDependency.CREATOR.createFromParcel(parcel);
+ assertEquals(vmsLayerDependency, createdFromParcel);
+ }
+
+ public void testMultipleDependendtLayerParcel() throws Exception {
+ VmsLayerDependency vmsLayerDependency =
+ new VmsLayerDependency(
+ VMS_LAYER,
+ new HashSet<>(Arrays.asList(DEPENDENT_VMS_LAYER, ANOTHER_DEPENDENT_VMS_LAYER)));
+
+ Parcel parcel = Parcel.obtain();
+ vmsLayerDependency.writeToParcel(parcel, vmsLayerDependency.describeContents());
+ parcel.setDataPosition(0);
+ VmsLayerDependency createdFromParcel = VmsLayerDependency.CREATOR.createFromParcel(parcel);
+ assertEquals(vmsLayerDependency, createdFromParcel);
+ }
+
+ public void testNoDependendtLayerEquality() throws Exception {
+ VmsLayerDependency original =
+ new VmsLayerDependency(
+ VMS_LAYER,
+ new HashSet<>(Arrays.asList()));
+
+ VmsLayerDependency similar =
+ new VmsLayerDependency(VMS_LAYER);
+
+ assertEquals(original.getLayer(), similar.getLayer());
+ assertEquals(original.getDependencies(), similar.getDependencies());
+ assertEquals(original, similar);
+ }
+
+ public void testMultipleDependendtLayerEquality() throws Exception {
+ VmsLayerDependency original =
+ new VmsLayerDependency(
+ VMS_LAYER,
+ new HashSet<>(Arrays.asList(DEPENDENT_VMS_LAYER, ANOTHER_DEPENDENT_VMS_LAYER)));
+
+ VmsLayerDependency similar =
+ new VmsLayerDependency(
+ VMS_LAYER,
+ new HashSet<>(Arrays.asList(DEPENDENT_VMS_LAYER, ANOTHER_DEPENDENT_VMS_LAYER)));
+ assertEquals(original.getLayer(), similar.getLayer());
+ assertEquals(original.getDependencies(), similar.getDependencies());
+ assertEquals(original, similar);
+ }
+
+ public void testVerifyNonEqualOnLayer() throws Exception {
+ VmsLayerDependency original =
+ new VmsLayerDependency(
+ VMS_LAYER,
+ new HashSet<>(Arrays.asList(DEPENDENT_VMS_LAYER)));
+
+ VmsLayerDependency similar =
+ new VmsLayerDependency(
+ ANOTHER_DEPENDENT_VMS_LAYER,
+ new HashSet<>(Arrays.asList(DEPENDENT_VMS_LAYER)));
+
+ assertNotEquals(original, similar);
+ }
+
+ public void testVerifyNonEqualOnDependentLayer() throws Exception {
+ VmsLayerDependency original =
+ new VmsLayerDependency(
+ VMS_LAYER,
+ new HashSet<>(Arrays.asList(DEPENDENT_VMS_LAYER)));
+
+ VmsLayerDependency similar =
+ new VmsLayerDependency(
+ VMS_LAYER,
+ new HashSet<>(Arrays.asList(ANOTHER_DEPENDENT_VMS_LAYER)));
+
+ assertNotEquals(original, similar);
+ }
+}
diff --git a/tests/carservice_unit_test/src/com/android/car/VmsLayerTest.java b/tests/carservice_unit_test/src/com/android/car/VmsLayerTest.java
new file mode 100644
index 0000000..56fb129
--- /dev/null
+++ b/tests/carservice_unit_test/src/com/android/car/VmsLayerTest.java
@@ -0,0 +1,89 @@
+/*
+ * 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.android.car;
+
+import static org.junit.Assert.assertNotEquals;
+
+import android.car.vms.VmsLayer;
+import android.test.AndroidTestCase;
+import android.test.suitebuilder.annotation.SmallTest;
+
+import android.os.Parcel;
+
+import java.util.Arrays;
+import java.util.HashSet;
+
+/*
+ * A class to test the VmsLayer parcelability.
+ */
+@SmallTest
+public class VmsLayerTest extends AndroidTestCase {
+ private static final int LAYER_ID = 12;
+ private static final int LAYER_VERSION = 34;
+ private static final int LAYER_SUBTYPE = 56;
+
+ private static final int DIFFERENT_LAYER_ID = 99;
+
+ public void testLayerParcel() throws Exception {
+ VmsLayer vmsLayer =
+ new VmsLayer(
+ LAYER_ID,
+ LAYER_SUBTYPE,
+ LAYER_VERSION);
+
+ Parcel parcel = Parcel.obtain();
+ vmsLayer.writeToParcel(parcel, vmsLayer.describeContents());
+ parcel.setDataPosition(0);
+ VmsLayer createdFromParcel = VmsLayer.CREATOR.createFromParcel(parcel);
+ assertEquals(vmsLayer, createdFromParcel);
+ }
+
+ public void testLayerEquality() throws Exception {
+ VmsLayer original =
+ new VmsLayer(
+ LAYER_ID,
+ LAYER_SUBTYPE,
+ LAYER_VERSION);
+
+ VmsLayer similar =
+ new VmsLayer(
+ LAYER_ID,
+ LAYER_SUBTYPE,
+ LAYER_VERSION);
+
+ assertEquals(original.getType(), similar.getType());
+ assertEquals(original.getSubtype(), similar.getSubtype());
+ assertEquals(original.getVersion(), similar.getVersion());
+ assertEquals(original, similar);
+ }
+
+ public void testVerifyNonEqual() throws Exception {
+ VmsLayer original =
+ new VmsLayer(
+ LAYER_ID,
+ LAYER_SUBTYPE,
+ LAYER_VERSION);
+
+ VmsLayer similar =
+ new VmsLayer(
+ DIFFERENT_LAYER_ID,
+ LAYER_SUBTYPE,
+ LAYER_VERSION);
+
+ assertNotEquals(original, similar);
+ }
+}
\ No newline at end of file
diff --git a/tests/carservice_unit_test/src/com/android/car/VmsLayersAvailabilityTest.java b/tests/carservice_unit_test/src/com/android/car/VmsLayersAvailabilityTest.java
index 4a09d4f..ebf50d8 100644
--- a/tests/carservice_unit_test/src/com/android/car/VmsLayersAvailabilityTest.java
+++ b/tests/carservice_unit_test/src/com/android/car/VmsLayersAvailabilityTest.java
@@ -75,12 +75,12 @@
}
public void testNoOffering() {
- assertTrue(mLayersAvailability.getAvailableLayers().isEmpty());
+ assertTrue(mLayersAvailability.getAvailableLayers().getAssociatedLayers().isEmpty());
}
public void testEmptyOffering() {
mLayersAvailability.setPublishersOffering(Collections.EMPTY_LIST);
- assertTrue(mLayersAvailability.getAvailableLayers().isEmpty());
+ assertTrue(mLayersAvailability.getAvailableLayers().getAssociatedLayers().isEmpty());
}
public void testSingleLayerNoDeps() throws Exception {
@@ -94,7 +94,8 @@
mOfferings.add(offering);
mLayersAvailability.setPublishersOffering(mOfferings);
- assertEquals(expectedAvailableAssociatedLayers, mLayersAvailability.getAvailableLayers());
+ assertEquals(expectedAvailableAssociatedLayers,
+ mLayersAvailability.getAvailableLayers().getAssociatedLayers());
}
public void testChainOfDependenciesSatisfied() throws Exception {
@@ -105,14 +106,16 @@
VmsLayersOffering offering =
new VmsLayersOffering(
- new HashSet<>(Arrays.asList(X_DEPENDS_ON_Y, Y_DEPENDS_ON_Z, Z_DEPENDS_ON_NOTHING)),
+ new HashSet<>(Arrays.asList(
+ X_DEPENDS_ON_Y, Y_DEPENDS_ON_Z, Z_DEPENDS_ON_NOTHING)),
PUBLISHER_ID_1);
mOfferings.add(offering);
mLayersAvailability.setPublishersOffering(mOfferings);
assertEquals(expectedAvailableAssociatedLayers,
- new HashSet<VmsAssociatedLayer>(mLayersAvailability.getAvailableLayers()));
+ new HashSet<VmsAssociatedLayer>(
+ mLayersAvailability.getAvailableLayers().getAssociatedLayers()));
}
public void testChainOfDependenciesSatisfiedTwoOfferings() throws Exception {
@@ -135,7 +138,8 @@
mLayersAvailability.setPublishersOffering(mOfferings);
assertEquals(expectedAvailableAssociatedLayers,
- new HashSet<VmsAssociatedLayer>(mLayersAvailability.getAvailableLayers()));
+ new HashSet<VmsAssociatedLayer>(
+ mLayersAvailability.getAvailableLayers().getAssociatedLayers()));
}
public void testChainOfDependencieNotSatisfied() throws Exception {
@@ -148,15 +152,8 @@
mLayersAvailability.setPublishersOffering(mOfferings);
assertEquals(expectedAvailableAssociatedLayers,
- new HashSet<VmsAssociatedLayer>(mLayersAvailability.getAvailableLayers()));
-
- Set<VmsAssociatedLayer> expectedUnavailableAssociatedLayers = new HashSet<>();
- expectedUnavailableAssociatedLayers.add(new VmsAssociatedLayer(LAYER_X, PUBLISHERS_1));
- expectedUnavailableAssociatedLayers.add(new VmsAssociatedLayer(LAYER_Y, PUBLISHERS_1));
-
-
- assertEquals(expectedUnavailableAssociatedLayers,
- new HashSet<VmsAssociatedLayer>(mLayersAvailability.getUnavailableLayers()));
+ new HashSet<VmsAssociatedLayer>(
+ mLayersAvailability.getAvailableLayers().getAssociatedLayers()));
}
public void testOneOfMultipleDependencySatisfied() throws Exception {
@@ -175,7 +172,8 @@
mLayersAvailability.setPublishersOffering(mOfferings);
assertEquals(expectedAvailableAssociatedLayers,
- new HashSet<VmsAssociatedLayer>(mLayersAvailability.getAvailableLayers()));
+ new HashSet<VmsAssociatedLayer>(
+ mLayersAvailability.getAvailableLayers().getAssociatedLayers()));
}
public void testCyclicDependency() throws Exception {
@@ -191,7 +189,8 @@
mLayersAvailability.setPublishersOffering(mOfferings);
assertEquals(expectedAvailableAssociatedLayers,
- new HashSet<VmsAssociatedLayer>(mLayersAvailability.getAvailableLayers()));
+ new HashSet<VmsAssociatedLayer>(
+ mLayersAvailability.getAvailableLayers().getAssociatedLayers()));
}
public void testAlmostCyclicDependency() throws Exception {
@@ -213,7 +212,8 @@
mOfferings.add(offering2);
mLayersAvailability.setPublishersOffering(mOfferings);
- assertEquals(expectedAvailableAssociatedLayers, mLayersAvailability.getAvailableLayers());
+ assertEquals(expectedAvailableAssociatedLayers,
+ mLayersAvailability.getAvailableLayers().getAssociatedLayers());
}
public void testCyclicDependencyAndLayerWithoutDependency() throws Exception {
@@ -234,14 +234,8 @@
mLayersAvailability.setPublishersOffering(mOfferings);
assertEquals(expectedAvailableAssociatedLayers,
- new HashSet<VmsAssociatedLayer>(mLayersAvailability.getAvailableLayers()));
-
- Set<VmsAssociatedLayer> expectedUnavailableAssociatedLayers = new HashSet<>();
- expectedUnavailableAssociatedLayers.add(new VmsAssociatedLayer(LAYER_X, PUBLISHERS_1));
- expectedUnavailableAssociatedLayers.add(new VmsAssociatedLayer(LAYER_Y, PUBLISHERS_2));
-
- assertEquals(expectedUnavailableAssociatedLayers,
- new HashSet<VmsAssociatedLayer>(mLayersAvailability.getUnavailableLayers()));
+ new HashSet<VmsAssociatedLayer>(
+ mLayersAvailability.getAvailableLayers().getAssociatedLayers()));
}
public void testSelfDependency() throws Exception {
@@ -255,12 +249,7 @@
mLayersAvailability.setPublishersOffering(mOfferings);
assertEquals(expectedAvailableAssociatedLayers,
- new HashSet<VmsAssociatedLayer>(mLayersAvailability.getAvailableLayers()));
-
- Set<VmsAssociatedLayer> expectedUnavailableAssociatedLayers = new HashSet<>();
- expectedUnavailableAssociatedLayers.add(new VmsAssociatedLayer(LAYER_X, PUBLISHERS_1));
-
- assertEquals(expectedUnavailableAssociatedLayers,
- new HashSet<VmsAssociatedLayer>(mLayersAvailability.getUnavailableLayers()));
+ new HashSet<VmsAssociatedLayer>(
+ mLayersAvailability.getAvailableLayers().getAssociatedLayers()));
}
}
\ No newline at end of file
diff --git a/tests/carservice_unit_test/src/com/android/car/VmsLayersOfferingTest.java b/tests/carservice_unit_test/src/com/android/car/VmsLayersOfferingTest.java
new file mode 100644
index 0000000..c2111a9
--- /dev/null
+++ b/tests/carservice_unit_test/src/com/android/car/VmsLayersOfferingTest.java
@@ -0,0 +1,154 @@
+/*
+ * 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.android.car;
+
+import static org.junit.Assert.assertNotEquals;
+
+import android.car.vms.VmsLayer;
+import android.car.vms.VmsLayerDependency;
+import android.car.vms.VmsLayersOffering;
+import android.test.AndroidTestCase;
+import android.test.suitebuilder.annotation.SmallTest;
+import android.os.Parcel;
+
+import java.util.Arrays;
+import java.util.HashSet;
+
+import android.util.Log;
+
+/*
+ * A class to test the VmsLayersOffering parcelability.
+ */
+@SmallTest
+public class VmsLayersOfferingTest extends AndroidTestCase {
+ private static final int PUBLISHER_ID = 1;
+
+ private static final int LAYER_ID = 112;
+ private static final int LAYER_VERSION = 134;
+ private static final int LAYER_SUBTYPE = 156;
+
+ private static final int DEPENDENT_LAYER_ID = 212;
+ private static final int DEPENDENT_LAYER_VERSION = 234;
+ private static final int DEPENDENT_LAYER_SUBTYPE = 256;
+
+ private static final int DIFFERENT_LAYER_ID = 99;
+ private static final int DIFFERENT_PUBLISHER_ID = 2;
+
+ private static final VmsLayer VMS_LAYER = new VmsLayer(
+ LAYER_ID,
+ LAYER_SUBTYPE,
+ LAYER_VERSION);
+
+ private static final VmsLayer DEPENDENT_VMS_LAYER = new VmsLayer(
+ DEPENDENT_LAYER_ID,
+ DEPENDENT_LAYER_SUBTYPE,
+ DEPENDENT_LAYER_VERSION);
+
+ private static final VmsLayer ANOTHER_DEPENDENT_VMS_LAYER = new VmsLayer(
+ DIFFERENT_LAYER_ID,
+ DEPENDENT_LAYER_SUBTYPE,
+ DEPENDENT_LAYER_VERSION);
+
+ private static final VmsLayerDependency VMS_LAYER_DEPENDENCY =
+ new VmsLayerDependency(
+ VMS_LAYER,
+ new HashSet<>(Arrays.asList(DEPENDENT_VMS_LAYER)));
+
+ private static final VmsLayerDependency ANOTHER_VMS_LAYER_DEPENDENCY =
+ new VmsLayerDependency(
+ VMS_LAYER,
+ new HashSet<>(Arrays.asList(ANOTHER_DEPENDENT_VMS_LAYER)));
+
+ public void testNoOfferingParcel() throws Exception {
+ VmsLayersOffering vmsLayersOffering =
+ new VmsLayersOffering(new HashSet<>(Arrays.asList()), PUBLISHER_ID);
+
+ Parcel parcel = Parcel.obtain();
+ vmsLayersOffering.writeToParcel(parcel, vmsLayersOffering.describeContents());
+ parcel.setDataPosition(0);
+ VmsLayersOffering createdFromParcel = VmsLayersOffering.CREATOR.createFromParcel(parcel);
+ assertEquals(vmsLayersOffering, createdFromParcel);
+ }
+
+ public void testMultipleOfferingParcel() throws Exception {
+ VmsLayersOffering vmsLayersOffering =
+ new VmsLayersOffering(
+ new HashSet<>(Arrays.asList(
+ VMS_LAYER_DEPENDENCY,
+ ANOTHER_VMS_LAYER_DEPENDENCY)),
+ PUBLISHER_ID);
+
+ Parcel parcel = Parcel.obtain();
+ vmsLayersOffering.writeToParcel(parcel, vmsLayersOffering.describeContents());
+ parcel.setDataPosition(0);
+ VmsLayersOffering createdFromParcel = VmsLayersOffering.CREATOR.createFromParcel(parcel);
+
+ assertEquals(vmsLayersOffering, createdFromParcel);
+ }
+
+ public void testNoOfferingEquality() throws Exception {
+ VmsLayersOffering original =
+ new VmsLayersOffering(
+ new HashSet<>(Arrays.asList()), PUBLISHER_ID);
+
+ VmsLayersOffering similar =
+ new VmsLayersOffering(
+ new HashSet<>(Arrays.asList()), PUBLISHER_ID);
+
+ assertEquals(original.getDependencies(), similar.getDependencies());
+ assertEquals(original.getPublisherId(), similar.getPublisherId());
+ assertEquals(original, similar);
+ }
+
+ public void testMultipleOfferingEquality() throws Exception {
+ VmsLayersOffering original =
+ new VmsLayersOffering(
+ new HashSet<>(Arrays.asList(VMS_LAYER_DEPENDENCY, ANOTHER_VMS_LAYER_DEPENDENCY)), PUBLISHER_ID);
+
+ VmsLayersOffering similar =
+ new VmsLayersOffering(
+ new HashSet<>(Arrays.asList(VMS_LAYER_DEPENDENCY, ANOTHER_VMS_LAYER_DEPENDENCY)), PUBLISHER_ID);
+
+ assertEquals(original.getDependencies(), similar.getDependencies());
+ assertEquals(original.getPublisherId(), similar.getPublisherId());
+ assertEquals(original, similar);
+ }
+
+ public void testVerifyNonEqualOnPublisherId() throws Exception {
+ VmsLayersOffering original =
+ new VmsLayersOffering(
+ new HashSet<>(Arrays.asList(VMS_LAYER_DEPENDENCY)), PUBLISHER_ID);
+
+ VmsLayersOffering similar =
+ new VmsLayersOffering(
+ new HashSet<>(Arrays.asList(VMS_LAYER_DEPENDENCY)), DIFFERENT_PUBLISHER_ID);
+
+ assertNotEquals(original, similar);
+ }
+
+ public void testVerifyNonEqualOnDependency() throws Exception {
+ VmsLayersOffering original =
+ new VmsLayersOffering(
+ new HashSet<>(Arrays.asList(VMS_LAYER_DEPENDENCY)), PUBLISHER_ID);
+
+ VmsLayersOffering similar =
+ new VmsLayersOffering(
+ new HashSet<>(Arrays.asList(ANOTHER_VMS_LAYER_DEPENDENCY)), PUBLISHER_ID);
+
+ assertNotEquals(original, similar);
+ }
+}
diff --git a/tests/carservice_unit_test/src/com/android/car/VmsPublishersInfoTest.java b/tests/carservice_unit_test/src/com/android/car/VmsPublishersInfoTest.java
index 2b75012..3f922c9 100644
--- a/tests/carservice_unit_test/src/com/android/car/VmsPublishersInfoTest.java
+++ b/tests/carservice_unit_test/src/com/android/car/VmsPublishersInfoTest.java
@@ -16,14 +16,12 @@
package com.android.car;
-import android.car.annotation.FutureFeature;
import android.test.AndroidTestCase;
import android.test.suitebuilder.annotation.SmallTest;
import java.util.Arrays;
import java.util.Map;
-@FutureFeature
@SmallTest
public class VmsPublishersInfoTest extends AndroidTestCase {
public static final byte[] MOCK_INFO_0 = new byte[]{2, 3, 5, 7, 11, 13, 17};
diff --git a/tests/carservice_unit_test/src/com/android/car/VmsRoutingTest.java b/tests/carservice_unit_test/src/com/android/car/VmsRoutingTest.java
index 8fe849b..9589f86 100644
--- a/tests/carservice_unit_test/src/com/android/car/VmsRoutingTest.java
+++ b/tests/carservice_unit_test/src/com/android/car/VmsRoutingTest.java
@@ -18,6 +18,7 @@
import android.car.vms.IVmsSubscriberClient;
import android.car.vms.VmsAssociatedLayer;
+import android.car.vms.VmsAvailableLayers;
import android.car.vms.VmsLayer;
import android.car.vms.VmsSubscriptionState;
import android.test.AndroidTestCase;
@@ -303,7 +304,7 @@
}
@Override
- public void onLayersAvailabilityChanged(List<VmsAssociatedLayer> availableLayers) {
+ public void onLayersAvailabilityChanged(VmsAvailableLayers availableLayers) {
}
}
}
\ No newline at end of file
diff --git a/tests/carservice_unit_test/src/com/android/car/VmsSubscriptionStateTest.java b/tests/carservice_unit_test/src/com/android/car/VmsSubscriptionStateTest.java
new file mode 100644
index 0000000..ea41286
--- /dev/null
+++ b/tests/carservice_unit_test/src/com/android/car/VmsSubscriptionStateTest.java
@@ -0,0 +1,183 @@
+/*
+ * 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.android.car;
+
+import static org.junit.Assert.assertNotEquals;
+
+import android.car.vms.VmsAssociatedLayer;
+import android.car.vms.VmsLayer;
+import android.car.vms.VmsSubscriptionState;
+import android.test.AndroidTestCase;
+import android.test.suitebuilder.annotation.SmallTest;
+
+import android.os.Parcel;
+
+import java.util.Arrays;
+import java.util.HashSet;
+
+/*
+ * A class to test the VmsSubscriptionState parcelability.
+ */
+@SmallTest
+public class VmsSubscriptionStateTest extends AndroidTestCase {
+ private static final int LAYER_ID = 12;
+ private static final int LAYER_VERSION = 34;
+ private static final int LAYER_SUBTYPE = 56;
+
+ private static final int PUBLISHER_ID_1= 111;
+ private static final int PUBLISHER_ID_2= 222;
+
+ private static final int DIFFERENT_LAYER_ID = 99;
+
+ private static final int SEQUENCE_NUMBER = 1;
+ private static final int DIFFERENT_SEQUENCE_NUMBER = 2;
+
+ private static final VmsLayer VMS_LAYER = new VmsLayer(
+ LAYER_ID,
+ LAYER_SUBTYPE,
+ LAYER_VERSION);
+
+ private static final VmsLayer ANOTHER_VMS_LAYER = new VmsLayer(
+ DIFFERENT_LAYER_ID,
+ LAYER_SUBTYPE,
+ LAYER_VERSION);
+
+ private static final VmsAssociatedLayer VMS_ASSOCIATED_LAYER =
+ new VmsAssociatedLayer(
+ VMS_LAYER,
+ new HashSet<>(Arrays.asList(PUBLISHER_ID_1)));
+
+ public void testNoSubscriptionsParcel() throws Exception {
+ VmsSubscriptionState vmsSubscriptionState =
+ new VmsSubscriptionState(
+ SEQUENCE_NUMBER,
+ new HashSet<>(Arrays.asList()),
+ new HashSet<>(Arrays.asList()));
+
+ Parcel parcel = Parcel.obtain();
+ vmsSubscriptionState.writeToParcel(parcel, vmsSubscriptionState.describeContents());
+ parcel.setDataPosition(0);
+ VmsSubscriptionState createdFromParcel = VmsSubscriptionState.CREATOR.createFromParcel(parcel);
+ assertEquals(vmsSubscriptionState, createdFromParcel);
+ }
+
+ public void testMultipleSubscriptionsParcel() throws Exception {
+ VmsSubscriptionState vmsSubscriptionState =
+ new VmsSubscriptionState(
+ SEQUENCE_NUMBER,
+ new HashSet<>(Arrays.asList(VMS_LAYER)),
+ new HashSet<>(Arrays.asList(VMS_ASSOCIATED_LAYER)));
+
+ Parcel parcel = Parcel.obtain();
+ vmsSubscriptionState.writeToParcel(parcel, vmsSubscriptionState.describeContents());
+ parcel.setDataPosition(0);
+ VmsSubscriptionState createdFromParcel = VmsSubscriptionState.CREATOR.createFromParcel(parcel);
+ assertEquals(vmsSubscriptionState, createdFromParcel);
+ }
+
+ public void testNoSubscriptionsEquality() throws Exception {
+ VmsSubscriptionState original =
+ new VmsSubscriptionState(
+ SEQUENCE_NUMBER,
+ new HashSet<>(Arrays.asList()),
+ new HashSet<>(Arrays.asList()));
+
+ VmsSubscriptionState similar =
+ new VmsSubscriptionState(
+ SEQUENCE_NUMBER,
+ new HashSet<>(Arrays.asList()),
+ new HashSet<>(Arrays.asList()));
+
+ assertEquals(original.getSequenceNumber(), similar.getSequenceNumber());
+ assertEquals(original.getLayers(), similar.getLayers());
+ assertEquals(original.getAssociatedLayers(), similar.getAssociatedLayers());
+ assertEquals(original, similar);
+ }
+
+ public void testMultipleSubscriptionsEquality() throws Exception {
+ VmsSubscriptionState original =
+ new VmsSubscriptionState(
+ SEQUENCE_NUMBER,
+ new HashSet<>(Arrays.asList(VMS_LAYER)),
+ new HashSet<>(Arrays.asList(VMS_ASSOCIATED_LAYER)));
+
+ VmsSubscriptionState similar =
+ new VmsSubscriptionState(
+ SEQUENCE_NUMBER,
+ new HashSet<>(Arrays.asList(VMS_LAYER)),
+ new HashSet<>(Arrays.asList(VMS_ASSOCIATED_LAYER)));
+
+ assertEquals(original.getSequenceNumber(), similar.getSequenceNumber());
+ assertEquals(original.getLayers(), similar.getLayers());
+ assertEquals(original.getAssociatedLayers(), similar.getAssociatedLayers());
+ assertEquals(original, similar);
+ }
+
+ public void testVerifyNonEqualOnSequenceNumber() throws Exception {
+ VmsSubscriptionState original =
+ new VmsSubscriptionState(
+ SEQUENCE_NUMBER,
+ new HashSet<>(Arrays.asList(VMS_LAYER)),
+ new HashSet<>(Arrays.asList(VMS_ASSOCIATED_LAYER)));
+
+ VmsSubscriptionState similar =
+ new VmsSubscriptionState(
+ DIFFERENT_SEQUENCE_NUMBER,
+ new HashSet<>(Arrays.asList(VMS_LAYER)),
+ new HashSet<>(Arrays.asList(VMS_ASSOCIATED_LAYER)));
+
+ if (!original.equals(similar)) {
+ return;
+ }
+ fail("VmsSubscriptionState with different sequence numbers appear to be equal. original: " +
+ original +
+ ", similar: " +
+ similar);
+ }
+
+ public void testVerifyNonEqualOnLayers() throws Exception {
+ VmsSubscriptionState original =
+ new VmsSubscriptionState(
+ SEQUENCE_NUMBER,
+ new HashSet<>(Arrays.asList(VMS_LAYER)),
+ new HashSet<>(Arrays.asList(VMS_ASSOCIATED_LAYER)));
+
+ VmsSubscriptionState similar =
+ new VmsSubscriptionState(
+ SEQUENCE_NUMBER,
+ new HashSet<>(Arrays.asList()),
+ new HashSet<>(Arrays.asList(VMS_ASSOCIATED_LAYER)));
+
+ assertNotEquals(original, similar);
+ }
+
+ public void testVerifyNonEqualOnAssociatedLayers() throws Exception {
+ VmsSubscriptionState original =
+ new VmsSubscriptionState(
+ SEQUENCE_NUMBER,
+ new HashSet<>(Arrays.asList(VMS_LAYER)),
+ new HashSet<>(Arrays.asList(VMS_ASSOCIATED_LAYER)));
+
+ VmsSubscriptionState similar =
+ new VmsSubscriptionState(
+ SEQUENCE_NUMBER,
+ new HashSet<>(Arrays.asList(VMS_LAYER)),
+ new HashSet<>(Arrays.asList()));
+
+ assertNotEquals(original, similar);
+ }
+}
\ No newline at end of file
diff --git a/tests/carservice_unit_test/src/com/android/car/storagemonitoring/CarStorageMonitoringTest.java b/tests/carservice_unit_test/src/com/android/car/storagemonitoring/CarStorageMonitoringTest.java
new file mode 100644
index 0000000..deb24f6
--- /dev/null
+++ b/tests/carservice_unit_test/src/com/android/car/storagemonitoring/CarStorageMonitoringTest.java
@@ -0,0 +1,694 @@
+/*
+ * 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.android.car.storagemonitoring;
+
+import android.car.storagemonitoring.IoStatsEntry;
+import android.car.storagemonitoring.IoStats;
+import android.car.storagemonitoring.LifetimeWriteInfo;
+import android.car.storagemonitoring.UidIoRecord;
+import android.car.storagemonitoring.WearEstimate;
+import android.car.storagemonitoring.WearEstimateChange;
+import android.os.Parcel;
+import android.test.suitebuilder.annotation.MediumTest;
+
+import android.util.SparseArray;
+import com.android.car.test.utils.TemporaryDirectory;
+import com.android.car.test.utils.TemporaryFile;
+import android.util.JsonReader;
+import android.util.JsonWriter;
+
+import java.io.FileWriter;
+import java.io.StringReader;
+import java.io.StringWriter;
+import java.nio.file.Files;
+import java.time.Instant;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+import junit.framework.TestCase;
+import org.json.JSONObject;
+
+/**
+ * Tests the storage monitoring API in CarService.
+ */
+@MediumTest
+public class CarStorageMonitoringTest extends TestCase {
+ static final String TAG = CarStorageMonitoringTest.class.getSimpleName();
+
+ public void testEMmcWearInformationProvider() throws Exception {
+ try (TemporaryFile lifetimeFile = new TemporaryFile(TAG)) {
+ try (TemporaryFile eolFile = new TemporaryFile(TAG)) {
+ lifetimeFile.write("0x05 0x00");
+ eolFile.write("01");
+
+ EMmcWearInformationProvider wearInfoProvider = new EMmcWearInformationProvider(
+ lifetimeFile.getFile(), eolFile.getFile());
+
+ WearInformation wearInformation = wearInfoProvider.load();
+
+ assertNotNull(wearInformation);
+ assertEquals(40, wearInformation.lifetimeEstimateA);
+ assertEquals(WearInformation.UNKNOWN_LIFETIME_ESTIMATE,
+ wearInformation.lifetimeEstimateB);
+
+ assertEquals(WearInformation.PRE_EOL_INFO_NORMAL, wearInformation.preEolInfo);
+ }
+ }
+ }
+
+ public void testUfsWearInformationProvider() throws Exception {
+ try (TemporaryFile lifetimeFile = new TemporaryFile(TAG)) {
+ lifetimeFile.write("ufs version: 1.0\n" +
+ "Health Descriptor[Byte offset 0x2]: bPreEOLInfo = 0x2\n" +
+ "Health Descriptor[Byte offset 0x1]: bDescriptionIDN = 0x1\n" +
+ "Health Descriptor[Byte offset 0x3]: bDeviceLifeTimeEstA = 0x0\n" +
+ "Health Descriptor[Byte offset 0x5]: VendorPropInfo = somedatahere\n" +
+ "Health Descriptor[Byte offset 0x4]: bDeviceLifeTimeEstB = 0xA\n");
+
+ UfsWearInformationProvider wearInfoProvider = new UfsWearInformationProvider(
+ lifetimeFile.getFile());
+
+ WearInformation wearInformation = wearInfoProvider.load();
+
+ assertNotNull(wearInformation);
+ assertEquals(90, wearInformation.lifetimeEstimateB);
+ assertEquals(WearInformation.PRE_EOL_INFO_WARNING, wearInformation.preEolInfo);
+ assertEquals(WearInformation.UNKNOWN_LIFETIME_ESTIMATE,
+ wearInformation.lifetimeEstimateA);
+ }
+ }
+
+ public void testWearEstimateEquality() {
+ WearEstimate wearEstimate1 = new WearEstimate(10, 20);
+ WearEstimate wearEstimate2 = new WearEstimate(10, 20);
+ WearEstimate wearEstimate3 = new WearEstimate(20, 30);
+ assertEquals(wearEstimate1, wearEstimate1);
+ assertEquals(wearEstimate1, wearEstimate2);
+ assertNotSame(wearEstimate1, wearEstimate3);
+ }
+
+ public void testWearEstimateParcel() throws Exception {
+ WearEstimate originalWearEstimate = new WearEstimate(10, 20);
+ Parcel p = Parcel.obtain();
+ originalWearEstimate.writeToParcel(p, 0);
+ p.setDataPosition(0);
+ WearEstimate newWearEstimate = new WearEstimate(p);
+ assertEquals(originalWearEstimate, newWearEstimate);
+ p.recycle();
+ }
+
+ public void testWearEstimateChangeEquality() {
+ WearEstimateChange wearEstimateChange1 = new WearEstimateChange(
+ new WearEstimate(10, 20),
+ new WearEstimate(20, 30),
+ 5000L,
+ Instant.now(),
+ false);
+ WearEstimateChange wearEstimateChange2 = new WearEstimateChange(
+ new WearEstimate(10, 20),
+ new WearEstimate(20, 30),
+ 5000L,
+ wearEstimateChange1.dateAtChange,
+ false);
+ assertEquals(wearEstimateChange1, wearEstimateChange1);
+ assertEquals(wearEstimateChange1, wearEstimateChange2);
+ WearEstimateChange wearEstimateChange3 = new WearEstimateChange(
+ new WearEstimate(10, 30),
+ new WearEstimate(20, 30),
+ 3000L,
+ Instant.now(),
+ true);
+ assertNotSame(wearEstimateChange1, wearEstimateChange3);
+ }
+
+ public void testWearEstimateChangeParcel() throws Exception {
+ WearEstimateChange originalWearEstimateChange = new WearEstimateChange(
+ new WearEstimate(10, 0),
+ new WearEstimate(20, 10),
+ 123456789L,
+ Instant.now(),
+ false);
+ Parcel p = Parcel.obtain();
+ originalWearEstimateChange.writeToParcel(p, 0);
+ p.setDataPosition(0);
+ WearEstimateChange newWearEstimateChange = new WearEstimateChange(p);
+ assertEquals(originalWearEstimateChange, newWearEstimateChange);
+ p.recycle();
+ }
+
+ public void testWearEstimateJson() throws Exception {
+ WearEstimate originalWearEstimate = new WearEstimate(20, 0);
+ StringWriter stringWriter = new StringWriter(1024);
+ JsonWriter jsonWriter = new JsonWriter(stringWriter);
+ originalWearEstimate.writeToJson(jsonWriter);
+ StringReader stringReader = new StringReader(stringWriter.toString());
+ JsonReader jsonReader = new JsonReader(stringReader);
+ WearEstimate newWearEstimate = new WearEstimate(jsonReader);
+ assertEquals(originalWearEstimate, newWearEstimate);
+ }
+
+ public void testWearEstimateRecordJson() throws Exception {
+ try (TemporaryFile temporaryFile = new TemporaryFile(TAG)) {
+ WearEstimateRecord originalWearEstimateRecord = new WearEstimateRecord(new WearEstimate(10, 20),
+ new WearEstimate(10, 30), 5000, Instant.ofEpochMilli(1000));
+ try (JsonWriter jsonWriter = new JsonWriter(new FileWriter(temporaryFile.getFile()))) {
+ originalWearEstimateRecord.writeToJson(jsonWriter);
+ }
+ JSONObject jsonObject = new JSONObject(
+ new String(Files.readAllBytes(temporaryFile.getPath())));
+ WearEstimateRecord newWearEstimateRecord = new WearEstimateRecord(jsonObject);
+ assertEquals(originalWearEstimateRecord, newWearEstimateRecord);
+ }
+ }
+
+ public void testWearEstimateRecordEquality() throws Exception {
+ WearEstimateRecord wearEstimateRecord1 = new WearEstimateRecord(WearEstimate.UNKNOWN_ESTIMATE,
+ new WearEstimate(10, 20), 5000, Instant.ofEpochMilli(2000));
+ WearEstimateRecord wearEstimateRecord2 = new WearEstimateRecord(WearEstimate.UNKNOWN_ESTIMATE,
+ new WearEstimate(10, 20), 5000, Instant.ofEpochMilli(2000));
+ WearEstimateRecord wearEstimateRecord3 = new WearEstimateRecord(WearEstimate.UNKNOWN_ESTIMATE,
+ new WearEstimate(10, 40), 5000, Instant.ofEpochMilli(1000));
+
+ assertEquals(wearEstimateRecord1, wearEstimateRecord1);
+ assertEquals(wearEstimateRecord1, wearEstimateRecord2);
+ assertNotSame(wearEstimateRecord1, wearEstimateRecord3);
+ }
+
+ public void testWearHistoryJson() throws Exception {
+ try (TemporaryFile temporaryFile = new TemporaryFile(TAG)) {
+ WearEstimateRecord wearEstimateRecord1 = new WearEstimateRecord(
+ WearEstimate.UNKNOWN_ESTIMATE,
+ new WearEstimate(10, 20), 5000, Instant.ofEpochMilli(2000));
+ WearEstimateRecord wearEstimateRecord2 = new WearEstimateRecord(
+ wearEstimateRecord1.getOldWearEstimate(),
+ new WearEstimate(10, 40), 9000, Instant.ofEpochMilli(16000));
+ WearEstimateRecord wearEstimateRecord3 = new WearEstimateRecord(
+ wearEstimateRecord2.getOldWearEstimate(),
+ new WearEstimate(20, 40), 12000, Instant.ofEpochMilli(21000));
+ WearHistory originalWearHistory = WearHistory.fromRecords(wearEstimateRecord1,
+ wearEstimateRecord2, wearEstimateRecord3);
+ try (JsonWriter jsonWriter = new JsonWriter(new FileWriter(temporaryFile.getFile()))) {
+ originalWearHistory.writeToJson(jsonWriter);
+ }
+ JSONObject jsonObject = new JSONObject(
+ new String(Files.readAllBytes(temporaryFile.getPath())));
+ WearHistory newWearHistory = new WearHistory(jsonObject);
+ assertEquals(originalWearHistory, newWearHistory);
+ }
+ }
+
+ public void testWearHistoryEquality() throws Exception {
+ WearEstimateRecord wearEstimateRecord1 = new WearEstimateRecord(
+ WearEstimate.UNKNOWN_ESTIMATE,
+ new WearEstimate(10, 20), 5000, Instant.ofEpochMilli(2000));
+ WearEstimateRecord wearEstimateRecord2 = new WearEstimateRecord(
+ wearEstimateRecord1.getOldWearEstimate(),
+ new WearEstimate(10, 40), 9000, Instant.ofEpochMilli(16000));
+ WearEstimateRecord wearEstimateRecord3 = new WearEstimateRecord(
+ wearEstimateRecord2.getOldWearEstimate(),
+ new WearEstimate(20, 40), 12000, Instant.ofEpochMilli(21000));
+ WearEstimateRecord wearEstimateRecord4 = new WearEstimateRecord(
+ wearEstimateRecord3.getOldWearEstimate(),
+ new WearEstimate(30, 50), 17000, Instant.ofEpochMilli(34000));
+ WearEstimateRecord wearEstimateRecord5 = new WearEstimateRecord(
+ wearEstimateRecord3.getOldWearEstimate(),
+ new WearEstimate(20, 50), 15000, Instant.ofEpochMilli(34000));
+
+ WearHistory wearHistory1 = WearHistory.fromRecords(wearEstimateRecord1,
+ wearEstimateRecord2, wearEstimateRecord3, wearEstimateRecord4);
+ WearHistory wearHistory2 = WearHistory.fromRecords(wearEstimateRecord4,
+ wearEstimateRecord1, wearEstimateRecord2, wearEstimateRecord3);
+ WearHistory wearHistory3 = WearHistory.fromRecords(wearEstimateRecord1,
+ wearEstimateRecord2, wearEstimateRecord3, wearEstimateRecord5);
+
+ assertEquals(wearHistory1, wearHistory1);
+ assertEquals(wearHistory1, wearHistory2);
+ assertNotSame(wearHistory1, wearHistory3);
+ }
+
+ public void testWearHistoryToChanges() {
+ WearEstimateRecord wearEstimateRecord1 = new WearEstimateRecord(
+ WearEstimate.UNKNOWN_ESTIMATE,
+ new WearEstimate(10, 20), 3600000, Instant.ofEpochMilli(2000));
+ WearEstimateRecord wearEstimateRecord2 = new WearEstimateRecord(
+ wearEstimateRecord1.getOldWearEstimate(),
+ new WearEstimate(10, 40), 172000000, Instant.ofEpochMilli(16000));
+ WearEstimateRecord wearEstimateRecord3 = new WearEstimateRecord(
+ wearEstimateRecord2.getOldWearEstimate(),
+ new WearEstimate(20, 40), 172000001, Instant.ofEpochMilli(21000));
+
+ WearHistory wearHistory = WearHistory.fromRecords(wearEstimateRecord1,
+ wearEstimateRecord2, wearEstimateRecord3);
+
+ List<WearEstimateChange> wearEstimateChanges = wearHistory.toWearEstimateChanges(1);
+
+ assertEquals(3, wearEstimateChanges.size());
+ WearEstimateChange unknownToOne = wearEstimateChanges.get(0);
+ WearEstimateChange oneToTwo = wearEstimateChanges.get(1);
+ WearEstimateChange twoToThree = wearEstimateChanges.get(2);
+
+ assertEquals(unknownToOne.oldEstimate, wearEstimateRecord1.getOldWearEstimate());
+ assertEquals(unknownToOne.newEstimate, wearEstimateRecord1.getNewWearEstimate());
+ assertEquals(unknownToOne.uptimeAtChange, wearEstimateRecord1.getTotalCarServiceUptime());
+ assertEquals(unknownToOne.dateAtChange, wearEstimateRecord1.getUnixTimestamp());
+ assertTrue(unknownToOne.isAcceptableDegradation);
+
+ assertEquals(oneToTwo.oldEstimate, wearEstimateRecord2.getOldWearEstimate());
+ assertEquals(oneToTwo.newEstimate, wearEstimateRecord2.getNewWearEstimate());
+ assertEquals(oneToTwo.uptimeAtChange, wearEstimateRecord2.getTotalCarServiceUptime());
+ assertEquals(oneToTwo.dateAtChange, wearEstimateRecord2.getUnixTimestamp());
+ assertTrue(oneToTwo.isAcceptableDegradation);
+
+ assertEquals(twoToThree.oldEstimate, wearEstimateRecord3.getOldWearEstimate());
+ assertEquals(twoToThree.newEstimate, wearEstimateRecord3.getNewWearEstimate());
+ assertEquals(twoToThree.uptimeAtChange, wearEstimateRecord3.getTotalCarServiceUptime());
+ assertEquals(twoToThree.dateAtChange, wearEstimateRecord3.getUnixTimestamp());
+ assertFalse(twoToThree.isAcceptableDegradation);
+ }
+
+ public void testUidIoStatEntry() throws Exception {
+ try (TemporaryFile statsFile = new TemporaryFile(TAG)) {
+ statsFile.write("0 256797495 181736102 362132480 947167232 0 0 0 0 250 0\n"
+ + "1006 489007 196802 0 20480 51474 2048 1024 2048 1 1\n");
+
+ ProcfsUidIoStatsProvider statsProvider = new ProcfsUidIoStatsProvider(
+ statsFile.getPath());
+
+ SparseArray<UidIoRecord> entries = statsProvider.load();
+
+ assertNotNull(entries);
+ assertEquals(2, entries.size());
+
+ IoStatsEntry entry = new IoStatsEntry(entries.get(0), 1234);
+ assertNotNull(entry);
+ assertEquals(0, entry.uid);
+ assertEquals(1234, entry.runtimeMillis);
+ assertEquals(256797495, entry.foreground.bytesRead);
+ assertEquals(181736102, entry.foreground.bytesWritten);
+ assertEquals(362132480, entry.foreground.bytesReadFromStorage);
+ assertEquals(947167232, entry.foreground.bytesWrittenToStorage);
+ assertEquals(250, entry.foreground.fsyncCalls);
+ assertEquals(0, entry.background.bytesRead);
+ assertEquals(0, entry.background.bytesWritten);
+ assertEquals(0, entry.background.bytesReadFromStorage);
+ assertEquals(0, entry.background.bytesWrittenToStorage);
+ assertEquals(0, entry.background.fsyncCalls);
+
+ entry = new IoStatsEntry(entries.get(1006), 4321);
+ assertNotNull(entry);
+ assertEquals(1006, entry.uid);
+ assertEquals(4321, entry.runtimeMillis);
+ assertEquals(489007, entry.foreground.bytesRead);
+ assertEquals(196802, entry.foreground.bytesWritten);
+ assertEquals(0, entry.foreground.bytesReadFromStorage);
+ assertEquals(20480, entry.foreground.bytesWrittenToStorage);
+ assertEquals(1, entry.foreground.fsyncCalls);
+ assertEquals(51474, entry.background.bytesRead);
+ assertEquals(2048, entry.background.bytesWritten);
+ assertEquals(1024, entry.background.bytesReadFromStorage);
+ assertEquals(2048, entry.background.bytesWrittenToStorage);
+ assertEquals(1, entry.background.fsyncCalls);
+ }
+ }
+
+ public void testUidIoStatEntryMissingFields() throws Exception {
+ try (TemporaryFile statsFile = new TemporaryFile(TAG)) {
+ statsFile.write("0 256797495 181736102 362132480 947167232 0 0 0 0 250 0\n"
+ + "1 2 3 4 5 6 7 8 9\n");
+
+ ProcfsUidIoStatsProvider statsProvider = new ProcfsUidIoStatsProvider(
+ statsFile.getPath());
+
+ SparseArray<UidIoRecord> entries = statsProvider.load();
+
+ assertNull(entries);
+ }
+ }
+
+ public void testUidIoStatEntryNonNumericFields() throws Exception {
+ try (TemporaryFile statsFile = new TemporaryFile(TAG)) {
+ statsFile.write("0 256797495 181736102 362132480 947167232 0 0 0 0 250 0\n"
+ + "notanumber 489007 196802 0 20480 51474 2048 1024 2048 1 1\n");
+
+ ProcfsUidIoStatsProvider statsProvider = new ProcfsUidIoStatsProvider(
+ statsFile.getPath());
+
+ SparseArray<UidIoRecord> entries = statsProvider.load();
+
+ assertNull(entries);
+ }
+ }
+
+ public void testUidIoStatEntryEquality() throws Exception {
+ IoStatsEntry statEntry1 = new IoStatsEntry(10, 1234,
+ new IoStatsEntry.Metrics(10, 20, 30, 40, 50),
+ new IoStatsEntry.Metrics(100, 200, 300, 400, 500));
+ IoStatsEntry statEntry2 = new IoStatsEntry(10, 1234,
+ new IoStatsEntry.Metrics(10, 20, 30, 40, 50),
+ new IoStatsEntry.Metrics(100, 200, 300, 400, 500));
+ IoStatsEntry statEntry3 = new IoStatsEntry(30, 4567,
+ new IoStatsEntry.Metrics(1, 20, 30, 42, 50),
+ new IoStatsEntry.Metrics(10, 200, 300, 420, 500));
+ IoStatsEntry statEntry4 = new IoStatsEntry(11, 6541,
+ new IoStatsEntry.Metrics(10, 20, 30, 40, 50),
+ new IoStatsEntry.Metrics(100, 200, 300, 400, 500));
+ IoStatsEntry statEntry5 = new IoStatsEntry(10, 1234,
+ new IoStatsEntry.Metrics(10, 20, 30, 40, 0),
+ new IoStatsEntry.Metrics(100, 200, 300, 400, 500));
+
+ assertEquals(statEntry1, statEntry1);
+ assertEquals(statEntry1, statEntry2);
+ assertNotSame(statEntry1, statEntry3);
+ assertNotSame(statEntry1, statEntry4);
+ assertNotSame(statEntry1, statEntry5);
+ }
+
+ public void testUidIoStatEntryParcel() throws Exception {
+ IoStatsEntry statEntry = new IoStatsEntry(10, 5000,
+ new IoStatsEntry.Metrics(10, 20, 30, 40, 50),
+ new IoStatsEntry.Metrics(100, 200, 300, 400, 500));
+ Parcel p = Parcel.obtain();
+ statEntry.writeToParcel(p, 0);
+ p.setDataPosition(0);
+ IoStatsEntry other = new IoStatsEntry(p);
+ assertEquals(other, statEntry);
+ }
+
+ public void testUidIoStatEntryJson() throws Exception {
+ try (TemporaryFile temporaryFile = new TemporaryFile(TAG)) {
+ IoStatsEntry statEntry = new IoStatsEntry(10, 1200,
+ new IoStatsEntry.Metrics(10, 20, 30, 40, 50),
+ new IoStatsEntry.Metrics(100, 200, 300, 400, 500));
+ try (JsonWriter jsonWriter = new JsonWriter(new FileWriter(temporaryFile.getFile()))) {
+ statEntry.writeToJson(jsonWriter);
+ }
+ JSONObject jsonObject = new JSONObject(
+ new String(Files.readAllBytes(temporaryFile.getPath())));
+ IoStatsEntry other = new IoStatsEntry(jsonObject);
+ assertEquals(statEntry, other);
+ }
+ }
+
+
+ public void testUidIoStatEntryDelta() throws Exception {
+ IoStatsEntry statEntry1 = new IoStatsEntry(10, 1000,
+ new IoStatsEntry.Metrics(10, 20, 30, 40, 50),
+ new IoStatsEntry.Metrics(60, 70, 80, 90, 100));
+
+ IoStatsEntry statEntry2 = new IoStatsEntry(10,2000,
+ new IoStatsEntry.Metrics(110, 120, 130, 140, 150),
+ new IoStatsEntry.Metrics(260, 370, 480, 500, 110));
+
+ IoStatsEntry statEntry3 = new IoStatsEntry(30, 3000,
+ new IoStatsEntry.Metrics(10, 20, 30, 40, 50),
+ new IoStatsEntry.Metrics(100, 200, 300, 400, 500));
+
+
+ IoStatsEntry delta21 = statEntry2.delta(statEntry1);
+ assertNotNull(delta21);
+ assertEquals(statEntry1.uid, delta21.uid);
+
+ assertEquals(1000, delta21.runtimeMillis);
+ assertEquals(100, delta21.foreground.bytesRead);
+ assertEquals(100, delta21.foreground.bytesWritten);
+ assertEquals(100, delta21.foreground.bytesReadFromStorage);
+ assertEquals(100, delta21.foreground.bytesWrittenToStorage);
+ assertEquals(100, delta21.foreground.fsyncCalls);
+
+ assertEquals(200, delta21.background.bytesRead);
+ assertEquals(300, delta21.background.bytesWritten);
+ assertEquals(400, delta21.background.bytesReadFromStorage);
+ assertEquals(410, delta21.background.bytesWrittenToStorage);
+ assertEquals(10, delta21.background.fsyncCalls);
+
+ try {
+ IoStatsEntry delta31 = statEntry3.delta(statEntry1);
+ fail("delta only allowed on stats for matching user ID");
+ } catch (IllegalArgumentException e) {
+ // test passed
+ }
+ }
+
+ public void testUidIoStatsRecordDelta() throws Exception {
+ IoStatsEntry statEntry = new IoStatsEntry(10, 1000,
+ new IoStatsEntry.Metrics(10, 20, 30, 40, 50),
+ new IoStatsEntry.Metrics(60, 70, 80, 90, 100));
+
+ UidIoRecord statRecord = new UidIoRecord(10,
+ 20, 20, 30, 50, 70,
+ 80, 70, 80, 100, 110);
+
+ UidIoRecord delta = statRecord.delta(statEntry);
+
+ assertNotNull(delta);
+ assertEquals(statRecord.uid, delta.uid);
+
+ assertEquals(10, delta.foreground_rchar);
+ assertEquals(0, delta.foreground_wchar);
+ assertEquals(0, delta.foreground_read_bytes);
+ assertEquals(10, delta.foreground_write_bytes);
+ assertEquals(20, delta.foreground_fsync);
+
+ assertEquals(20, delta.background_rchar);
+ assertEquals(0, delta.background_wchar);
+ assertEquals(0, delta.background_read_bytes);
+ assertEquals(10, delta.background_write_bytes);
+ assertEquals(10, delta.background_fsync);
+
+ statRecord = new UidIoRecord(30,
+ 20, 20, 30, 50, 70,
+ 80, 70, 80, 100, 110);
+
+ try {
+ statRecord.delta(statEntry);
+ fail("delta only allowed on records for matching user ID");
+ } catch (IllegalArgumentException e) {
+ // test passed
+ }
+ }
+
+ public void testUidIoStatsDelta() throws Exception {
+ IoStatsEntry entry10 = new IoStatsEntry(10, 1000,
+ new IoStatsEntry.Metrics(10, 20, 30, 40, 50),
+ new IoStatsEntry.Metrics(60, 70, 80, 90, 100));
+
+ IoStatsEntry entry20 = new IoStatsEntry(20, 2000,
+ new IoStatsEntry.Metrics(200, 60, 100, 30, 40),
+ new IoStatsEntry.Metrics(20, 10, 20, 0, 0));
+
+ IoStatsEntry entry30 = new IoStatsEntry(30, 2000,
+ new IoStatsEntry.Metrics(50, 100, 100, 30, 40),
+ new IoStatsEntry.Metrics(30, 0, 0, 0, 0));
+
+ ArrayList<IoStatsEntry> statsEntries1 = new ArrayList<IoStatsEntry>() {{
+ add(entry10);
+ add(entry20);
+ }};
+
+ ArrayList<IoStatsEntry> statsEntries2 = new ArrayList<IoStatsEntry>() {{
+ add(entry20);
+ add(entry30);
+ }};
+
+ IoStats delta1 = new IoStats(statsEntries1, 5000);
+ IoStats delta2 = new IoStats(statsEntries1, 5000);
+ IoStats delta3 = new IoStats(statsEntries2, 3000);
+ IoStats delta4 = new IoStats(statsEntries1, 5000);
+
+ assertEquals(delta1, delta1);
+ assertEquals(delta1, delta2);
+ assertNotSame(delta1, delta3);
+ assertNotSame(delta3, delta4);
+ }
+
+ public void testUidIoStatsTotals() throws Exception {
+ IoStatsEntry entry10 = new IoStatsEntry(10, 1000,
+ new IoStatsEntry.Metrics(20, 0, 10, 0, 0),
+ new IoStatsEntry.Metrics(10, 50, 0, 20, 2));
+
+ IoStatsEntry entry20 = new IoStatsEntry(20, 1000,
+ new IoStatsEntry.Metrics(100, 200, 50, 200, 1),
+ new IoStatsEntry.Metrics(0, 30, 10, 0, 1));
+
+ ArrayList<IoStatsEntry> statsEntries = new ArrayList<IoStatsEntry>() {{
+ add(entry10);
+ add(entry20);
+ }};
+
+ IoStats delta = new IoStats(statsEntries, 5000);
+
+ IoStatsEntry.Metrics foregroundTotals = delta.getForegroundTotals();
+ IoStatsEntry.Metrics backgroundTotals = delta.getBackgroundTotals();
+ IoStatsEntry.Metrics overallTotals = delta.getTotals();
+
+ assertEquals(120, foregroundTotals.bytesRead);
+ assertEquals(200, foregroundTotals.bytesWritten);
+ assertEquals(60, foregroundTotals.bytesReadFromStorage);
+ assertEquals(200, foregroundTotals.bytesWrittenToStorage);
+ assertEquals(1, foregroundTotals.fsyncCalls);
+
+
+ assertEquals(10, backgroundTotals.bytesRead);
+ assertEquals(80, backgroundTotals.bytesWritten);
+ assertEquals(10, backgroundTotals.bytesReadFromStorage);
+ assertEquals(20, backgroundTotals.bytesWrittenToStorage);
+ assertEquals(3, backgroundTotals.fsyncCalls);
+
+ assertEquals(130, overallTotals.bytesRead);
+ assertEquals(280, overallTotals.bytesWritten);
+ assertEquals(70, overallTotals.bytesReadFromStorage);
+ assertEquals(220, overallTotals.bytesWrittenToStorage);
+ assertEquals(4, overallTotals.fsyncCalls);
+ }
+
+ public void testUidIoStatsDeltaParcel() throws Exception {
+ IoStatsEntry entry10 = new IoStatsEntry(10, 1000,
+ new IoStatsEntry.Metrics(10, 20, 30, 40, 50),
+ new IoStatsEntry.Metrics(60, 70, 80, 90, 100));
+
+ IoStatsEntry entry20 = new IoStatsEntry(20, 2000,
+ new IoStatsEntry.Metrics(200, 60, 100, 30, 40),
+ new IoStatsEntry.Metrics(20, 10, 20, 0, 0));
+
+ ArrayList<IoStatsEntry> statsEntries = new ArrayList<IoStatsEntry>() {{
+ add(entry10);
+ add(entry20);
+ }};
+
+ IoStats statsDelta = new IoStats(statsEntries, 5000);
+
+ Parcel p = Parcel.obtain();
+ statsDelta.writeToParcel(p, 0);
+ p.setDataPosition(0);
+
+ IoStats parceledStatsDelta = new IoStats(p);
+
+ assertEquals(statsDelta.getTimestamp(), parceledStatsDelta.getTimestamp());
+
+ assertEquals(2, parceledStatsDelta.getStats().stream()
+ .filter(e -> e.equals(entry10) || e.equals(entry20))
+ .count());
+ }
+
+ public void testUidIoStatsDeltaJson() throws Exception {
+ try (TemporaryFile temporaryFile = new TemporaryFile(TAG)) {
+ IoStatsEntry entry10 = new IoStatsEntry(10, 1000,
+ new IoStatsEntry.Metrics(10, 20, 30, 40, 50),
+ new IoStatsEntry.Metrics(60, 70, 80, 90, 100));
+
+ IoStatsEntry entry20 = new IoStatsEntry(20, 2000,
+ new IoStatsEntry.Metrics(200, 60, 100, 30, 40),
+ new IoStatsEntry.Metrics(20, 10, 20, 0, 0));
+
+ ArrayList<IoStatsEntry> statsEntries = new ArrayList<IoStatsEntry>() {{
+ add(entry10);
+ add(entry20);
+ }};
+
+ IoStats statsDelta = new IoStats(statsEntries, 5000);
+ try (JsonWriter jsonWriter = new JsonWriter(new FileWriter(temporaryFile.getFile()))) {
+ statsDelta.writeToJson(jsonWriter);
+ }
+ JSONObject jsonObject = new JSONObject(
+ new String(Files.readAllBytes(temporaryFile.getPath())));
+ IoStats other = new IoStats(jsonObject);
+ assertEquals(statsDelta, other);
+ }
+ }
+
+ public void testLifetimeWriteInfo() throws Exception {
+ try (TemporaryDirectory temporaryDirectory = new TemporaryDirectory(TAG)) {
+ try (TemporaryDirectory ext4 = temporaryDirectory.getSubdirectory("ext4");
+ TemporaryDirectory f2fs = temporaryDirectory.getSubdirectory("f2fs")) {
+ try(TemporaryDirectory ext4_part1 = ext4.getSubdirectory("part1");
+ TemporaryDirectory f2fs_part1 = f2fs.getSubdirectory("part1");
+ TemporaryDirectory ext4_part2 = ext4.getSubdirectory("part2");
+ TemporaryDirectory f2f2_notpart = f2fs.getSubdirectory("nopart")) {
+ Files.write(ext4_part1.getPath().resolve("lifetime_write_kbytes"),
+ Collections.singleton("123"));
+ Files.write(f2fs_part1.getPath().resolve("lifetime_write_kbytes"),
+ Collections.singleton("250"));
+ Files.write(ext4_part2.getPath().resolve("lifetime_write_kbytes"),
+ Collections.singleton("2147483660"));
+
+ LifetimeWriteInfo expected_ext4_part1 =
+ new LifetimeWriteInfo("part1", "ext4", 123*1024);
+ LifetimeWriteInfo expected_f2fs_part1 =
+ new LifetimeWriteInfo("part1", "f2fs", 250*1024);
+ LifetimeWriteInfo expected_ext4_part2 =
+ new LifetimeWriteInfo("part2", "ext4", 2147483660L*1024);
+
+ SysfsLifetimeWriteInfoProvider sysfsLifetimeWriteInfoProvider =
+ new SysfsLifetimeWriteInfoProvider(temporaryDirectory.getDirectory());
+
+ LifetimeWriteInfo[] writeInfos = sysfsLifetimeWriteInfoProvider.load();
+
+ assertNotNull(writeInfos);
+ assertEquals(3, writeInfos.length);
+ assertTrue(Arrays.stream(writeInfos).anyMatch(
+ li -> li.equals(expected_ext4_part1)));
+ assertTrue(Arrays.stream(writeInfos).anyMatch(
+ li -> li.equals(expected_ext4_part2)));
+ assertTrue(Arrays.stream(writeInfos).anyMatch(
+ li -> li.equals(expected_f2fs_part1)));
+ }
+ }
+ }
+ }
+
+ public void testLifetimeWriteInfoEquality() throws Exception {
+ LifetimeWriteInfo writeInfo = new LifetimeWriteInfo("part1", "ext4", 123);
+ LifetimeWriteInfo writeInfoEq = new LifetimeWriteInfo("part1", "ext4", 123);
+
+ LifetimeWriteInfo writeInfoNeq1 = new LifetimeWriteInfo("part2", "ext4", 123);
+ LifetimeWriteInfo writeInfoNeq2 = new LifetimeWriteInfo("part1", "f2fs", 123);
+ LifetimeWriteInfo writeInfoNeq3 = new LifetimeWriteInfo("part1", "ext4", 100);
+
+ assertEquals(writeInfo, writeInfo);
+ assertEquals(writeInfo, writeInfoEq);
+ assertNotSame(writeInfo, writeInfoNeq1);
+ assertNotSame(writeInfo, writeInfoNeq2);
+ assertNotSame(writeInfo, writeInfoNeq3);
+ }
+
+ public void testLifetimeWriteInfoParcel() throws Exception {
+ LifetimeWriteInfo lifetimeWriteInfo = new LifetimeWriteInfo("part1", "ext4", 1024);
+
+ Parcel p = Parcel.obtain();
+ lifetimeWriteInfo.writeToParcel(p, 0);
+ p.setDataPosition(0);
+
+ LifetimeWriteInfo parceled = new LifetimeWriteInfo(p);
+
+ assertEquals(lifetimeWriteInfo, parceled);
+ }
+
+ public void testLifetimeWriteInfoJson() throws Exception {
+ try (TemporaryFile temporaryFile = new TemporaryFile(TAG)) {
+ LifetimeWriteInfo lifetimeWriteInfo = new LifetimeWriteInfo("part1", "ext4", 1024);
+
+ try (JsonWriter jsonWriter = new JsonWriter(new FileWriter(temporaryFile.getFile()))) {
+ lifetimeWriteInfo.writeToJson(jsonWriter);
+ }
+ JSONObject jsonObject = new JSONObject(
+ new String(Files.readAllBytes(temporaryFile.getPath())));
+ LifetimeWriteInfo other = new LifetimeWriteInfo(jsonObject);
+ assertEquals(lifetimeWriteInfo, other);
+ }
+ }
+}
diff --git a/tests/carservice_unit_test/src/com/android/car/storagemonitoring/IoStatsTrackerTest.java b/tests/carservice_unit_test/src/com/android/car/storagemonitoring/IoStatsTrackerTest.java
new file mode 100644
index 0000000..c7b2a0b
--- /dev/null
+++ b/tests/carservice_unit_test/src/com/android/car/storagemonitoring/IoStatsTrackerTest.java
@@ -0,0 +1,343 @@
+/*
+ * 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.android.car.storagemonitoring;
+
+import android.car.storagemonitoring.IoStatsEntry;
+import android.car.storagemonitoring.UidIoRecord;
+import android.test.suitebuilder.annotation.MediumTest;
+import android.util.SparseArray;
+import com.android.car.procfsinspector.ProcessInfo;
+import com.android.car.systeminterface.SystemStateInterface;
+import java.time.Duration;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.stream.Collectors;
+import junit.framework.TestCase;
+
+/**
+ * Tests IoStatsTracker functionality.
+ */
+@MediumTest
+public class IoStatsTrackerTest extends TestCase {
+ private static final int SAMPLE_WINDOW_MS = 1000;
+ private static final List<IoStatsEntry> EMPTY = Collections.emptyList();
+ private static final String TAG = IoStatsTrackerTest.class.getSimpleName();
+
+ public void testNewUsersAppear() throws Exception {
+ final MockSystemStateInterface mockSystemStateInterface = new MockSystemStateInterface();
+ IoStatsTracker ioStatsTracker = new IoStatsTracker(EMPTY,
+ SAMPLE_WINDOW_MS, mockSystemStateInterface);
+
+ assertEquals(0, ioStatsTracker.getCurrentSample().size());
+ assertEquals(0, ioStatsTracker.getTotal().size());
+
+ UserActivity user0 = new UserActivity(0);
+ user0.foreground_rchar = 50;
+ user0.background_wchar = 10;
+
+ UserActivity user1 = new UserActivity(1);
+ user1.foreground_rchar = 30;
+ user1.background_wchar = 50;
+
+ UidIoRecord process0 = user0.updateSystemState(mockSystemStateInterface);
+ UidIoRecord process1 = user1.updateSystemState(mockSystemStateInterface);
+
+ ioStatsTracker.update(mockSystemStateInterface.mIoRecords);
+
+ assertEquals(2, ioStatsTracker.getCurrentSample().size());
+ assertEquals(2, ioStatsTracker.getTotal().size());
+
+ assertTrue(ioStatsTracker.getCurrentSample().get(0).representsSameMetrics(process0));
+ assertTrue(ioStatsTracker.getCurrentSample().get(1).representsSameMetrics(process1));
+
+ assertTrue(ioStatsTracker.getTotal().get(0).representsSameMetrics(process0));
+ assertTrue(ioStatsTracker.getTotal().get(1).representsSameMetrics(process1));
+ }
+
+ public void testUserMetricsChange() throws Exception {
+ final MockSystemStateInterface mockSystemStateInterface = new MockSystemStateInterface();
+ IoStatsTracker ioStatsTracker = new IoStatsTracker(EMPTY,
+ SAMPLE_WINDOW_MS, mockSystemStateInterface);
+
+ UserActivity user0 = new UserActivity(0);
+ user0.foreground_rchar = 50;
+ user0.background_wchar = 10;
+
+ user0.updateSystemState(mockSystemStateInterface);
+ ioStatsTracker.update(mockSystemStateInterface.mIoRecords);
+
+ user0.foreground_rchar = 60;
+ user0.foreground_wchar = 10;
+ UidIoRecord process0 = user0.updateSystemState(mockSystemStateInterface);
+ ioStatsTracker.update(mockSystemStateInterface.mIoRecords);
+
+ assertEquals(1, ioStatsTracker.getCurrentSample().size());
+ assertEquals(1, ioStatsTracker.getTotal().size());
+
+ IoStatsEntry sample0 = ioStatsTracker.getCurrentSample().get(0);
+ IoStatsEntry total0 = ioStatsTracker.getTotal().get(0);
+
+ assertNotNull(sample0);
+ assertNotNull(total0);
+
+ assertTrue(total0.representsSameMetrics(process0));
+
+ assertEquals(10, sample0.foreground.bytesRead);
+ assertEquals(10, sample0.foreground.bytesWritten);
+ assertEquals(0, sample0.background.bytesWritten);
+ }
+
+ public void testUpdateNoIoProcessActive() throws Exception {
+ final MockSystemStateInterface mockSystemStateInterface = new MockSystemStateInterface();
+ IoStatsTracker ioStatsTracker = new IoStatsTracker(EMPTY,
+ SAMPLE_WINDOW_MS, mockSystemStateInterface);
+
+ UserActivity user0 = new UserActivity(0);
+ user0.foreground_rchar = 50;
+ user0.background_wchar = 10;
+
+ user0.updateSystemState(mockSystemStateInterface);
+ ioStatsTracker.update(mockSystemStateInterface.mIoRecords);
+
+ user0.spawnProcess();
+ user0.updateSystemState(mockSystemStateInterface);
+ ioStatsTracker.update(mockSystemStateInterface.mIoRecords);
+
+ assertEquals(1, ioStatsTracker.getCurrentSample().size());
+ assertEquals(1, ioStatsTracker.getTotal().size());
+
+ IoStatsEntry sample0 = ioStatsTracker.getCurrentSample().get(0);
+ IoStatsEntry total0 = ioStatsTracker.getTotal().get(0);
+
+ assertEquals(2 * SAMPLE_WINDOW_MS, sample0.runtimeMillis);
+ assertEquals(2 * SAMPLE_WINDOW_MS, total0.runtimeMillis);
+
+ assertEquals(0, sample0.foreground.bytesRead);
+ assertEquals(0, sample0.background.bytesWritten);
+ }
+
+ public void testUpdateNoIoProcessInactive() throws Exception {
+ final MockSystemStateInterface mockSystemStateInterface = new MockSystemStateInterface();
+ IoStatsTracker ioStatsTracker = new IoStatsTracker(EMPTY,
+ SAMPLE_WINDOW_MS, mockSystemStateInterface);
+
+ UserActivity user0 = new UserActivity(0);
+ user0.foreground_rchar = 50;
+ user0.background_wchar = 10;
+
+ user0.updateSystemState(mockSystemStateInterface);
+ ioStatsTracker.update(mockSystemStateInterface.mIoRecords);
+
+ user0.killProcess();
+ UidIoRecord record0 = user0.updateSystemState(mockSystemStateInterface);
+ ioStatsTracker.update(mockSystemStateInterface.mIoRecords);
+
+ assertEquals(0, ioStatsTracker.getCurrentSample().size());
+ assertEquals(1, ioStatsTracker.getTotal().size());
+
+ IoStatsEntry total0 = ioStatsTracker.getTotal().get(0);
+ assertEquals(SAMPLE_WINDOW_MS, total0.runtimeMillis);
+ assertTrue(total0.representsSameMetrics(record0));
+ }
+
+ public void testUpdateIoHappens() throws Exception {
+ final MockSystemStateInterface mockSystemStateInterface = new MockSystemStateInterface();
+ IoStatsTracker ioStatsTracker = new IoStatsTracker(EMPTY,
+ SAMPLE_WINDOW_MS, mockSystemStateInterface);
+
+ UserActivity user0 = new UserActivity(0);
+ user0.foreground_rchar = 50;
+ user0.background_wchar = 10;
+
+ user0.updateSystemState(mockSystemStateInterface);
+ ioStatsTracker.update(mockSystemStateInterface.mIoRecords);
+
+ user0.foreground_rchar = 60;
+ UidIoRecord record0 = user0.updateSystemState(mockSystemStateInterface);
+ ioStatsTracker.update(mockSystemStateInterface.mIoRecords);
+
+ assertEquals(1, ioStatsTracker.getCurrentSample().size());
+ assertEquals(1, ioStatsTracker.getTotal().size());
+
+ IoStatsEntry sample0 = ioStatsTracker.getCurrentSample().get(0);
+ IoStatsEntry total0 = ioStatsTracker.getTotal().get(0);
+
+ assertTrue(total0.representsSameMetrics(record0));
+ assertEquals(2 * SAMPLE_WINDOW_MS, total0.runtimeMillis);
+ assertEquals(2 * SAMPLE_WINDOW_MS, sample0.runtimeMillis);
+ assertEquals(10, sample0.foreground.bytesRead);
+ assertEquals(0, sample0.background.bytesWritten);
+ }
+
+ public void testUpdateGoAwayComeBackProcess() throws Exception {
+ final MockSystemStateInterface mockSystemStateInterface = new MockSystemStateInterface();
+ IoStatsTracker ioStatsTracker = new IoStatsTracker(EMPTY,
+ SAMPLE_WINDOW_MS, mockSystemStateInterface);
+
+ UserActivity user0 = new UserActivity(0);
+ user0.foreground_rchar = 50;
+ user0.background_wchar = 10;
+
+ user0.updateSystemState(mockSystemStateInterface);
+ ioStatsTracker.update(mockSystemStateInterface.mIoRecords);
+
+ ioStatsTracker.update(mockSystemStateInterface.mIoRecords);
+
+ assertEquals(0, ioStatsTracker.getCurrentSample().size());
+ assertEquals(1, ioStatsTracker.getTotal().size());
+
+ user0.spawnProcess();
+ user0.updateSystemState(mockSystemStateInterface);
+ ioStatsTracker.update(mockSystemStateInterface.mIoRecords);
+
+ assertEquals(1, ioStatsTracker.getCurrentSample().size());
+ IoStatsEntry sample0 = ioStatsTracker.getCurrentSample().get(0);
+ assertEquals(2 * SAMPLE_WINDOW_MS, sample0.runtimeMillis);
+ }
+
+ public void testUpdateGoAwayComeBackIo() throws Exception {
+ final MockSystemStateInterface mockSystemStateInterface = new MockSystemStateInterface();
+ IoStatsTracker ioStatsTracker = new IoStatsTracker(EMPTY,
+ SAMPLE_WINDOW_MS, mockSystemStateInterface);
+
+ UserActivity user0 = new UserActivity(0);
+ user0.foreground_rchar = 50;
+ user0.background_wchar = 10;
+
+ user0.updateSystemState(mockSystemStateInterface);
+ ioStatsTracker.update(mockSystemStateInterface.mIoRecords);
+
+ ioStatsTracker.update(mockSystemStateInterface.mIoRecords);
+
+ assertEquals(0, ioStatsTracker.getCurrentSample().size());
+ assertEquals(1, ioStatsTracker.getTotal().size());
+
+ user0.foreground_fsync = 1;
+
+ user0.updateSystemState(mockSystemStateInterface);
+ ioStatsTracker.update(mockSystemStateInterface.mIoRecords);
+
+ assertEquals(1, ioStatsTracker.getCurrentSample().size());
+
+ IoStatsEntry sample0 = ioStatsTracker.getCurrentSample().get(0);
+ assertEquals(2 * SAMPLE_WINDOW_MS, sample0.runtimeMillis);
+ assertEquals(1, sample0.foreground.fsyncCalls);
+ }
+
+ private static final class UserActivity {
+ private final int mUid;
+ private boolean mHasProcess;
+
+ private long foreground_rchar;
+ private long foreground_wchar;
+ private long foreground_read_bytes;
+ private long foreground_write_bytes;
+ private long foreground_fsync;
+
+ private long background_rchar;
+ private long background_wchar;
+ private long background_read_bytes;
+ private long background_write_bytes;
+ private long background_fsync;
+
+ UserActivity(int uid) {
+ mUid = uid;
+ }
+
+ void spawnProcess() {
+ mHasProcess = true;
+ }
+ void killProcess() {
+ mHasProcess = false;
+ }
+
+ UidIoRecord updateSystemState(MockSystemStateInterface systemState) {
+ UidIoRecord uidIoRecord = new UidIoRecord(mUid,
+ foreground_rchar,
+ foreground_wchar,
+ foreground_read_bytes,
+ foreground_write_bytes,
+ foreground_fsync,
+ background_rchar,
+ background_wchar,
+ background_read_bytes,
+ background_write_bytes,
+ background_fsync);
+
+ systemState.addIoRecord(uidIoRecord);
+ if (mHasProcess) {
+ systemState.addProcess(new ProcessInfo(1, mUid));
+ } else {
+ systemState.removeUserProcesses(mUid);
+ }
+
+ return uidIoRecord;
+ }
+ }
+
+ private final class MockSystemStateInterface implements SystemStateInterface {
+ private final List<ProcessInfo> mProcesses = new ArrayList<>();
+ private final SparseArray<UidIoRecord> mIoRecords = new SparseArray<>();
+
+ @Override
+ public void shutdown() {
+ }
+
+ @Override
+ public boolean enterDeepSleep(int wakeupTimeSec) {
+ return true;
+ }
+
+ @Override
+ public void scheduleActionForBootCompleted(Runnable action, Duration delay) {
+ }
+
+ @Override
+ public boolean isWakeupCausedByTimer() {
+ return false;
+ }
+
+ @Override
+ public boolean isSystemSupportingDeepSleep() {
+ return false;
+ }
+
+ @Override
+ public synchronized List<ProcessInfo> getRunningProcesses() {
+ return mProcesses;
+ }
+
+ synchronized void addProcess(ProcessInfo processInfo) {
+ mProcesses.add(processInfo);
+ }
+
+ synchronized void removeUserProcesses(int uid) {
+ mProcesses.removeAll(
+ mProcesses.stream().filter(pi -> pi.uid == uid).collect(Collectors.toList()));
+ }
+
+ synchronized void addIoRecord(UidIoRecord record) {
+ mIoRecords.put(record.uid, record);
+ }
+
+ synchronized void clear() {
+ mProcesses.clear();
+ mIoRecords.clear();
+ }
+ }
+}
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
new file mode 100644
index 0000000..faa7bd0
--- /dev/null
+++ b/tests/carservice_unit_test/src/com/android/car/user/CarUserServiceTest.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.android.car.user;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import android.car.user.CarUserManagerHelper;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.content.pm.UserInfo;
+import android.support.test.runner.AndroidJUnit4;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.ArgumentCaptor;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+
+/**
+ * This class contains unit tests for the {@link CarUserService}.
+ *
+ * The following mocks are used:
+ * <ol>
+ * <li> {@link Context} provides system services and resources.
+ * <li> {@link CarUserManagerHelper} provides user info and actions.
+ * <ol/>
+ */
+@RunWith(AndroidJUnit4.class)
+public class CarUserServiceTest {
+ private CarUserService mCarUserService;
+
+ @Mock
+ private Context mMockContext;
+
+ @Mock
+ private Context mApplicationContext;
+
+ @Mock
+ private CarUserManagerHelper mCarUserManagerHelper;
+
+ /**
+ * Initialize all of the objects with the @Mock annotation.
+ */
+ @Before
+ public void setUp() throws Exception {
+ MockitoAnnotations.initMocks(this);
+ when(mMockContext.getApplicationContext()).thenReturn(mApplicationContext);
+
+ mCarUserService = new CarUserService(mMockContext, mCarUserManagerHelper);
+ }
+
+ /**
+ * Test that the {@link CarUserService} registers to receive the locked boot completed
+ * intent.
+ */
+ @Test
+ public void testRegistersToReceiveEvents() {
+ ArgumentCaptor<IntentFilter> argument = ArgumentCaptor.forClass(IntentFilter.class);
+ mCarUserService.init();
+ verify(mMockContext).registerReceiver(eq(mCarUserService), argument.capture());
+ IntentFilter intentFilter = argument.getValue();
+ assertThat(intentFilter.countActions()).isEqualTo(1);
+
+ assertThat(intentFilter.getAction(0)).isEqualTo(Intent.ACTION_LOCKED_BOOT_COMPLETED);
+ }
+
+ /**
+ * Test that the {@link CarUserService} unregisters its event receivers.
+ */
+ @Test
+ public void testUnregistersEventReceivers() {
+ mCarUserService.release();
+ verify(mMockContext).unregisterReceiver(mCarUserService);
+ }
+
+ /**
+ * Test that the {@link CarUserService} starts up a secondary admin user upon first run.
+ */
+ @Test
+ public void testStartsSecondaryAdminUserOnFirstRun() {
+ List<UserInfo> users = new ArrayList<>();
+
+ int adminUserId = 10;
+ UserInfo admin = new UserInfo(adminUserId, CarUserService.OWNER_NAME, UserInfo.FLAG_ADMIN);
+
+ doReturn(users).when(mCarUserManagerHelper).getAllUsers();
+ // doReturn(users).when(mCarUserManagerHelper.getAllUsers());
+ doReturn(admin).when(mCarUserManagerHelper).createNewAdminUser(CarUserService.OWNER_NAME);
+ doReturn(true).when(mCarUserManagerHelper).switchToUser(admin);
+
+ mCarUserService.onReceive(mMockContext,
+ new Intent(Intent.ACTION_LOCKED_BOOT_COMPLETED));
+
+ verify(mCarUserManagerHelper).createNewAdminUser(CarUserService.OWNER_NAME);
+ verify(mCarUserManagerHelper).switchToUser(admin);
+ }
+}
diff --git a/tools/bootanalyze/stressfs/Android.mk b/tests/common_utils/Android.mk
similarity index 78%
rename from tools/bootanalyze/stressfs/Android.mk
rename to tests/common_utils/Android.mk
index 2e54e64..19302c6 100644
--- a/tools/bootanalyze/stressfs/Android.mk
+++ b/tests/common_utils/Android.mk
@@ -12,18 +12,15 @@
# See the License for the specific language governing permissions and
# limitations under the License.
#
-#
-LOCAL_PATH := $(call my-dir)
+LOCAL_PATH:= $(call my-dir)
include $(CLEAR_VARS)
-LOCAL_PACKAGE_NAME := StressFS
+LOCAL_MODULE := com.android.car.test.utils
+
+LOCAL_MODULE_TAGS := optional
+
LOCAL_SRC_FILES := $(call all-java-files-under, src)
-LOCAL_MODULE_TAGS := tests
-LOCAL_SDK_VERSION := current
-
-LOCAL_PROGUARD_FLAG_FILES := proguard.flags
-
-include $(BUILD_PACKAGE)
+include $(BUILD_STATIC_JAVA_LIBRARY)
diff --git a/tests/common_utils/src/com/android/car/test/utils/TemporaryDirectory.java b/tests/common_utils/src/com/android/car/test/utils/TemporaryDirectory.java
new file mode 100644
index 0000000..e1c4735
--- /dev/null
+++ b/tests/common_utils/src/com/android/car/test/utils/TemporaryDirectory.java
@@ -0,0 +1,90 @@
+/*
+ * 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.android.car.test.utils;
+
+import android.annotation.Nullable;
+import android.os.SystemClock;
+import java.io.File;
+import java.io.IOException;
+import java.nio.file.FileVisitResult;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.SimpleFileVisitor;
+import java.nio.file.attribute.BasicFileAttributes;
+
+/**
+ * A utility class that creates a temporary directory.
+ * The directory, and any files contained within, are automatically deleted when calling close().
+ *
+ * Example usage:
+ *
+ * try (TemporaryDirectory tf = new TemporaryDirectory("myTest")) {
+ * ...
+ * } // directory gets deleted here
+ */
+public class TemporaryDirectory implements AutoCloseable {
+ private Path mDirectory;
+
+ private static final class DeletingVisitor extends SimpleFileVisitor<Path> {
+ FileVisitResult consume(Path path) throws IOException {
+ Files.delete(path);
+ return FileVisitResult.CONTINUE;
+ }
+
+ @Override
+ public FileVisitResult visitFile(Path path, BasicFileAttributes basicFileAttributes)
+ throws IOException {
+ return consume(path);
+ }
+
+ @Override
+ public FileVisitResult postVisitDirectory(Path path, IOException e)
+ throws IOException {
+ return consume(path);
+ }
+ }
+
+ private static final SimpleFileVisitor<Path> DELETE = new DeletingVisitor();
+
+ TemporaryDirectory(Path directory) throws IOException {
+ mDirectory = Files.createDirectory(directory);
+ }
+
+ public TemporaryDirectory(@Nullable String prefix) throws IOException {
+ if (prefix == null) {
+ prefix = TemporaryDirectory.class.getSimpleName();
+ }
+ prefix += String.valueOf(SystemClock.elapsedRealtimeNanos());
+
+ mDirectory = Files.createTempDirectory(prefix);
+ }
+
+ @Override
+ public void close() throws Exception {
+ Files.walkFileTree(mDirectory, DELETE);
+ }
+
+ public File getDirectory() {
+ return mDirectory.toFile();
+ }
+
+ public Path getPath() { return mDirectory; }
+
+ public TemporaryDirectory getSubdirectory(String name) throws IOException {
+ return new TemporaryDirectory(mDirectory.resolve(name));
+ }
+}
diff --git a/tests/common_utils/src/com/android/car/test/utils/TemporaryFile.java b/tests/common_utils/src/com/android/car/test/utils/TemporaryFile.java
new file mode 100644
index 0000000..cd0f323
--- /dev/null
+++ b/tests/common_utils/src/com/android/car/test/utils/TemporaryFile.java
@@ -0,0 +1,73 @@
+/*
+ * 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.android.car.test.utils;
+
+import android.annotation.Nullable;
+import android.os.SystemClock;
+
+import java.io.BufferedWriter;
+import java.io.File;
+import java.io.FileWriter;
+import java.io.IOException;
+import java.nio.file.Files;
+import java.nio.file.Path;
+
+/**
+ * A utility class that creates a temporary file.
+ * The file is automatically deleted when calling close().
+ *
+ * Example usage:
+ *
+ * try (TemporaryFile tf = new TemporaryFile("myTest")) {
+ * ...
+ * } // file gets deleted here
+ */
+public final class TemporaryFile implements AutoCloseable {
+ private File mFile;
+
+ public TemporaryFile(@Nullable String prefix) throws IOException {
+ if (prefix == null) {
+ prefix = TemporaryFile.class.getSimpleName();
+ }
+ mFile = File.createTempFile(prefix, String.valueOf(SystemClock.elapsedRealtimeNanos()));
+ }
+
+ public TemporaryFile(File path) {
+ mFile = path;
+ }
+
+ @Override
+ public void close() throws Exception {
+ Files.delete(mFile.toPath());
+ }
+
+ public void write(String s) throws IOException {
+ BufferedWriter writer = new BufferedWriter(new FileWriter(mFile));
+ writer.write(s);
+ writer.close();
+ }
+
+ public FileWriter newFileWriter() throws IOException {
+ return new FileWriter(mFile);
+ }
+
+ public File getFile() {
+ return mFile;
+ }
+
+ public Path getPath() { return mFile.toPath(); }
+}
diff --git a/tests/obd2_app/AndroidManifest.xml b/tests/obd2_app/AndroidManifest.xml
index 184d939..be6efa4 100644
--- a/tests/obd2_app/AndroidManifest.xml
+++ b/tests/obd2_app/AndroidManifest.xml
@@ -25,6 +25,8 @@
android:label="@string/app_name"
android:supportsRtl="true"
android:theme="@style/AppTheme">
+ <uses-library android:name="android.test.runner" />
+
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
diff --git a/tests/robotests/Android.mk b/tests/robotests/Android.mk
new file mode 100644
index 0000000..3152109
--- /dev/null
+++ b/tests/robotests/Android.mk
@@ -0,0 +1,42 @@
+# 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.
+
+LOCAL_PATH:= $(call my-dir)
+
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES := $(call all-java-files-under, src)
+
+LOCAL_PACKAGE_NAME := CarServiceRoboTests
+LOCAL_PRIVATE_PLATFORM_APIS := true
+
+LOCAL_CERTIFICATE := platform
+
+LOCAL_MODULE_TAGS := tests
+
+# When built explicitly put it in the data partition
+LOCAL_MODULE_PATH := $(TARGET_OUT_DATA_APPS)
+
+LOCAL_PROGUARD_ENABLED := disabled
+
+LOCAL_INSTRUMENTATION_FOR := CarService
+
+LOCAL_JAVA_LIBRARIES := \
+ android.car \
+ robolectric_android-all-stub \
+ Robolectric_all-target \
+ mockito-robolectric-prebuilt \
+ truth-prebuilt
+
+include $(BUILD_PACKAGE)
\ No newline at end of file
diff --git a/tests/robotests/AndroidManifest.xml b/tests/robotests/AndroidManifest.xml
new file mode 100644
index 0000000..d160175
--- /dev/null
+++ b/tests/robotests/AndroidManifest.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.
+ -->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ coreApp="true"
+ package="com.android.car.robotests">
+
+ <application/>
+
+</manifest>
\ No newline at end of file
diff --git a/tools/emulator/vhal_consts_2_1.py b/tests/robotests/config/robolectric.properties
similarity index 76%
rename from tools/emulator/vhal_consts_2_1.py
rename to tests/robotests/config/robolectric.properties
index e5dbcff..b4e3b78 100644
--- a/tools/emulator/vhal_consts_2_1.py
+++ b/tests/robotests/config/robolectric.properties
@@ -1,4 +1,5 @@
-# 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.
@@ -12,6 +13,5 @@
# See the License for the specific language governing permissions and
# limitations under the License.
#
-# DO NOT EDIT MANUALLY
-# This file was autogenerated by vhal_const_generate.py
-from vhal_consts_2_0 import *
+manifest=packages/services/Car/tests/robotests/AndroidManifest.xml
+sdk=NEWEST_SDK
\ No newline at end of file
diff --git a/tests/robotests/src/com/android/car/CarServiceRobolectricTestRunner.java b/tests/robotests/src/com/android/car/CarServiceRobolectricTestRunner.java
new file mode 100644
index 0000000..92b3cd8
--- /dev/null
+++ b/tests/robotests/src/com/android/car/CarServiceRobolectricTestRunner.java
@@ -0,0 +1,70 @@
+/*
+ * 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;
+
+import android.annotation.NonNull;
+
+import org.junit.runners.model.InitializationError;
+import org.robolectric.RobolectricTestRunner;
+import org.robolectric.annotation.Config;
+import org.robolectric.manifest.AndroidManifest;
+import org.robolectric.res.Fs;
+import org.robolectric.res.ResourcePath;
+
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.util.List;
+
+public class CarServiceRobolectricTestRunner extends RobolectricTestRunner {
+ public CarServiceRobolectricTestRunner(Class<?> testClass) throws InitializationError {
+ super(testClass);
+ }
+
+ /**
+ * We are going to create our own custom manifest so we can add multiple resource paths to it.
+ */
+ @Override
+ protected AndroidManifest getAppManifest(Config config) {
+ try {
+ // Using the manifest file's relative path, we can figure out the application directory.
+ final URL appRoot =
+ new URL("file:packages/services/Car/tests/robotests");
+ final URL manifestPath = new URL(appRoot, "AndroidManifest.xml");
+ final URL resDir = new URL(appRoot, "res");
+ final URL assetsDir = new URL(appRoot, "assets");
+
+ return new AndroidManifest(Fs.fromURL(manifestPath), Fs.fromURL(resDir),
+ Fs.fromURL(assetsDir), "com.android.car") {
+ @Override
+ public List<ResourcePath> getIncludedResourcePaths() {
+ final List<ResourcePath> paths = super.getIncludedResourcePaths();
+ return paths;
+ }
+ };
+ } catch (MalformedURLException e) {
+ throw new RuntimeException("CarServiceRobolectricTestRunner failure", e);
+ }
+ }
+
+ private static ResourcePath resourcePath(@NonNull String spec) {
+ try {
+ return new ResourcePath(null, Fs.fromURL(new URL(spec)), null);
+ } catch (MalformedURLException e) {
+ throw new RuntimeException("CarServiceRobolectricTestRunner failure", e);
+ }
+ }
+}
diff --git a/tests/robotests/src/com/android/car/testutils/shadow/ShadowActivityManager.java b/tests/robotests/src/com/android/car/testutils/shadow/ShadowActivityManager.java
new file mode 100644
index 0000000..e213c4e
--- /dev/null
+++ b/tests/robotests/src/com/android/car/testutils/shadow/ShadowActivityManager.java
@@ -0,0 +1,65 @@
+/*
+ * 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.testutils.shadow;
+
+import android.app.ActivityManager;
+
+import org.robolectric.RuntimeEnvironment;
+import org.robolectric.annotation.Implementation;
+import org.robolectric.annotation.Implements;
+import org.robolectric.annotation.Resetter;
+import org.robolectric.shadow.api.Shadow;
+
+@Implements(ActivityManager.class)
+public class ShadowActivityManager {
+ private static int sCurrentUserId = 0;
+ private int mUserSwitchedTo = -1;
+
+ @Resetter
+ public void reset() {
+ sCurrentUserId = 0;
+ mUserSwitchedTo = 0;
+ }
+
+ @Implementation
+ public static int getCurrentUser() {
+ return sCurrentUserId;
+ }
+
+ @Implementation
+ public boolean switchUser(int userId) {
+ mUserSwitchedTo = userId;
+ return true;
+ }
+
+ public boolean getSwitchUserCalled() {
+ return mUserSwitchedTo != -1;
+ }
+
+ public int getUserSwitchedTo() {
+ return mUserSwitchedTo;
+ }
+
+ public static void setCurrentUser(int userId) {
+ sCurrentUserId = userId;
+ }
+
+ public static ShadowActivityManager getShadow() {
+ return (ShadowActivityManager) Shadow.extract(
+ RuntimeEnvironment.application.getSystemService(ActivityManager.class));
+ }
+}
diff --git a/tests/robotests/src/com/android/car/testutils/shadow/ShadowUserHandle.java b/tests/robotests/src/com/android/car/testutils/shadow/ShadowUserHandle.java
new file mode 100644
index 0000000..656fa97
--- /dev/null
+++ b/tests/robotests/src/com/android/car/testutils/shadow/ShadowUserHandle.java
@@ -0,0 +1,36 @@
+/*
+ * 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.testutils.shadow;
+
+import android.os.UserHandle;
+
+import org.robolectric.annotation.Implementation;
+import org.robolectric.annotation.Implements;
+
+@Implements(UserHandle.class)
+public class ShadowUserHandle {
+ @Implementation
+ public static int myUserId() {
+ try {
+ return ShadowUserManager.getShadow().getCurrentUser();
+ } catch (Throwable t) {
+ // This method may be called before ShadowUserManager is properly initialized. Just
+ // return the default 0 in those cases.
+ return 0;
+ }
+ }
+}
diff --git a/tests/robotests/src/com/android/car/testutils/shadow/ShadowUserManager.java b/tests/robotests/src/com/android/car/testutils/shadow/ShadowUserManager.java
new file mode 100644
index 0000000..bf9cf62
--- /dev/null
+++ b/tests/robotests/src/com/android/car/testutils/shadow/ShadowUserManager.java
@@ -0,0 +1,147 @@
+/*
+ * 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.testutils.shadow;
+
+import android.content.Context;
+import android.content.pm.UserInfo;
+import android.os.UserHandle;
+import android.os.UserManager;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.robolectric.RuntimeEnvironment;
+import org.robolectric.annotation.HiddenApi;
+import org.robolectric.annotation.Implementation;
+import org.robolectric.annotation.Implements;
+import org.robolectric.shadow.api.Shadow;
+
+@Implements(UserManager.class)
+public class ShadowUserManager extends org.robolectric.shadows.ShadowUserManager {
+ private final Map<Integer, UserInfo> mUserInfos = new HashMap<>();
+ private int mCurrentUser = UserHandle.USER_SYSTEM;
+ public boolean isSystemUser = true;
+ public boolean isPrimaryUser = true;
+ public boolean isLinkedUser = false;
+ public boolean isDemoUser = false;
+ public boolean isManagedProfile = false;
+ public boolean isGuestUser = false;
+ public boolean canSwitchUser = true;
+
+ {
+ addUserInfo(new UserInfo(UserHandle.USER_SYSTEM, "system_user", 0));
+ }
+
+ /**
+ * Used by BaseActivity when creating intents.
+ */
+ @Implementation
+ @HiddenApi
+ public List<UserInfo> getUsers() {
+ return new ArrayList<>(mUserInfos.values());
+ }
+
+ @Implementation
+ public boolean isSystemUser() {
+ return isSystemUser;
+ }
+
+ @Implementation
+ public boolean isPrimaryUser() {
+ return isPrimaryUser;
+ }
+
+ @Implementation
+ public boolean isLinkedUser() {
+ return isLinkedUser;
+ }
+
+ @Implementation
+ public boolean isDemoUser() {
+ return isDemoUser;
+ }
+
+ @Implementation
+ public boolean isGuestUser() {
+ return isGuestUser;
+ }
+
+ @Implementation
+ public boolean isManagedProfile(int userId) {
+ return isManagedProfile;
+ }
+
+ @Implementation
+ public static boolean isSplitSystemUser() {
+ return false;
+ }
+
+ @Implementation
+ public UserInfo getUserInfo(int id) {
+ return mUserInfos.get(id);
+ }
+
+ @Implementation
+ public boolean isUserUnlockingOrUnlocked(int userId) {
+ return isUserUnlocked();
+ }
+
+ @Implementation
+ public boolean canSwitchUsers() {
+ return canSwitchUser;
+ }
+
+ @Implementation
+ public boolean removeUser(int userId) {
+ mUserInfos.remove(userId);
+ return true;
+ }
+
+ @Implementation
+ public UserInfo createGuest(Context context, String name) {
+ UserInfo guest = new UserInfo(12, name, UserInfo.FLAG_GUEST);
+
+ addUserInfo(guest);
+ return guest;
+ }
+
+ public void switchUser(int userId) {
+ if (!mUserInfos.containsKey(userId)) {
+ throw new UnsupportedOperationException("Must add user before switching to it");
+ }
+ mCurrentUser = userId;
+ }
+
+ public int getCurrentUser() {
+ return mCurrentUser;
+ }
+
+ public void setCurrentUser(int userId) {
+ mCurrentUser = userId;
+ }
+
+ public void addUserInfo(UserInfo userInfo) {
+ mUserInfos.put(userInfo.id, userInfo);
+ }
+
+ public static ShadowUserManager getShadow() {
+ return (ShadowUserManager) Shadow.extract(
+ RuntimeEnvironment.application.getSystemService(UserManager.class));
+ }
+}
diff --git a/tests/robotests/src/com/android/car/users/CarUserManagerHelperRoboTest.java b/tests/robotests/src/com/android/car/users/CarUserManagerHelperRoboTest.java
new file mode 100644
index 0000000..9c39445
--- /dev/null
+++ b/tests/robotests/src/com/android/car/users/CarUserManagerHelperRoboTest.java
@@ -0,0 +1,210 @@
+/*
+ * 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.users;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.mockito.Mockito.when;
+
+import android.app.ActivityManager;
+import android.car.user.CarUserManagerHelper;
+import android.content.Context;
+import android.content.pm.UserInfo;
+import android.os.UserManager;
+
+import com.android.car.CarServiceRobolectricTestRunner;
+import com.android.car.testutils.shadow.ShadowActivityManager;
+import com.android.car.testutils.shadow.ShadowUserHandle;
+import com.android.car.testutils.shadow.ShadowUserManager;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import org.robolectric.RuntimeEnvironment;
+import org.robolectric.annotation.Config;
+
+@RunWith(CarServiceRobolectricTestRunner.class)
+@Config(shadows = { ShadowActivityManager.class,
+ ShadowUserHandle.class, ShadowUserManager.class})
+public class CarUserManagerHelperRoboTest {
+ @Mock
+ private Context mContext;
+
+ private CarUserManagerHelper mHelper;
+
+ @Before
+ public void setUp() {
+ MockitoAnnotations.initMocks(this);
+ when(mContext.getSystemService(Context.USER_SERVICE)).thenReturn(
+ RuntimeEnvironment.application.getSystemService(UserManager.class));
+ when(mContext.getSystemService(Context.ACTIVITY_SERVICE)).thenReturn(
+ RuntimeEnvironment.application.getSystemService(ActivityManager.class));
+ when(mContext.getApplicationContext()).thenReturn(mContext);
+ mHelper = new CarUserManagerHelper(mContext);
+ }
+
+ @After
+ public void tearDown() {
+ ShadowActivityManager.getShadow().reset();
+ }
+
+ @Test
+ public void testGetForegroundUserId() {
+ ShadowActivityManager.setCurrentUser(15);
+ assertThat(mHelper.getCurrentForegroundUserId()).isEqualTo(15);
+ }
+
+ @Test
+ public void testGetForegroundUserInfo() {
+ int currentForegroundUserId = 17;
+ ShadowActivityManager.setCurrentUser(currentForegroundUserId);
+
+ assertThat(mHelper.getCurrentForegroundUserInfo().id).isEqualTo(currentForegroundUserId);
+ }
+
+ @Test
+ public void testGetCurrentProcessUserId() {
+ int currentProcessUserId = 11;
+ ShadowUserManager.getShadow().setCurrentUser(currentProcessUserId);
+
+ assertThat(mHelper.getCurrentProcessUserId()).isEqualTo(currentProcessUserId);
+ }
+
+ @Test
+ public void testGetCurrentProcessUserInfo() {
+ int currentProcessUserId = 12;
+ ShadowUserManager.getShadow().setCurrentUser(currentProcessUserId);
+ assertThat(mHelper.getCurrentProcessUserInfo().id).isEqualTo(currentProcessUserId);
+ }
+
+ @Test
+ public void testGetAllUsers() {
+ int currentProcessUserId = 12;
+ ShadowUserManager userManager = ShadowUserManager.getShadow();
+ userManager.setCurrentUser(currentProcessUserId);
+
+ UserInfo currentProcessUser = createUserInfoForId(currentProcessUserId);
+ UserInfo systemUser = createUserInfoForId(0);
+
+ UserInfo otherUser1 = createUserInfoForId(13);
+ UserInfo otherUser2 = createUserInfoForId(14);
+
+ userManager.addUserInfo(systemUser);
+ userManager.addUserInfo(currentProcessUser);
+ userManager.addUserInfo(otherUser1);
+ userManager.addUserInfo(otherUser2);
+
+ if (mHelper.isHeadlessSystemUser()) {
+ // Should return 3 users that don't have system user id.
+ assertThat(mHelper.getAllUsers())
+ .containsExactly(currentProcessUser, otherUser1, otherUser2);
+ } else {
+ assertThat(mHelper.getAllUsers())
+ .containsExactly(systemUser, currentProcessUser, otherUser1, otherUser2);
+ }
+ }
+
+ @Test
+ public void testGetAllUsersExcludesForegroundUser() {
+ ShadowActivityManager.setCurrentUser(11);
+ ShadowUserManager userManager = ShadowUserManager.getShadow();
+
+ UserInfo foregroundUser = createUserInfoForId(11);
+ UserInfo otherUser1 = createUserInfoForId(12);
+ UserInfo otherUser2 = createUserInfoForId(13);
+ UserInfo otherUser3 = createUserInfoForId(14);
+
+ userManager.addUserInfo(foregroundUser);
+ userManager.addUserInfo(otherUser1);
+ userManager.addUserInfo(otherUser2);
+ userManager.addUserInfo(otherUser3);
+
+ // Should return 3 users that don't have foregroundUser id.
+ assertThat(mHelper.getAllSwitchableUsers()).hasSize(3);
+ assertThat(mHelper.getAllSwitchableUsers())
+ .containsExactly(otherUser1, otherUser2, otherUser3);
+ }
+
+ @Test
+ public void testCheckForegroundUser() {
+ ShadowActivityManager.setCurrentUser(10);
+ assertThat(mHelper.isForegroundUser(createUserInfoForId(10))).isTrue();
+ assertThat(mHelper.isForegroundUser(createUserInfoForId(11))).isFalse();
+
+ ShadowActivityManager.setCurrentUser(11);
+ assertThat(mHelper.isForegroundUser(createUserInfoForId(11))).isTrue();
+ }
+
+ @Test
+ public void testIsUserRunningCurrentProcess() {
+ ShadowUserManager shadowUserManager = ShadowUserManager.getShadow();
+ UserInfo user1 = createUserInfoForId(10);
+ UserInfo user2 = createUserInfoForId(11);
+ shadowUserManager.addUserInfo(user1);
+ shadowUserManager.addUserInfo(user2);
+ shadowUserManager.setCurrentUser(10);
+
+ assertThat(mHelper.isCurrentProcessUser(user1)).isTrue();
+ assertThat(mHelper.isCurrentProcessUser(user2)).isFalse();
+
+ shadowUserManager.setCurrentUser(11);
+ assertThat(mHelper.isCurrentProcessUser(user2)).isTrue();
+ assertThat(mHelper.isCurrentProcessUser(user1)).isFalse();
+ }
+
+ @Test
+ public void testRemoveCurrentProcessUserSwitchesToGuestUser() {
+ // Set currentProcess user to be user 10.
+ ShadowUserManager shadowUserManager = ShadowUserManager.getShadow();
+ UserInfo user1 = createUserInfoForId(10);
+ UserInfo user2 = createUserInfoForId(11);
+ shadowUserManager.addUserInfo(user1);
+ shadowUserManager.addUserInfo(user2);
+ shadowUserManager.setCurrentUser(10);
+
+ // Removing a currentProcess user, calls "switch" to guest user
+ mHelper.removeUser(user1, "testGuest");
+ assertThat(ShadowActivityManager.getShadow().getSwitchUserCalled()).isTrue();
+ assertThat(ShadowActivityManager.getShadow().getUserSwitchedTo()).isEqualTo(0);
+
+ assertThat(shadowUserManager.removeUser(10)).isTrue();
+ }
+
+ @Test
+ public void testSwitchToUser() {
+ ShadowActivityManager.setCurrentUser(20);
+
+ // Switching to foreground user doesn't do anything.
+ mHelper.switchToUser(createUserInfoForId(20));
+ assertThat(ShadowActivityManager.getShadow().getSwitchUserCalled()).isFalse();
+
+ // Switching to non-current, non-guest user, simply calls switchUser.
+ UserInfo userToSwitchTo = new UserInfo(22, "Test User", 0);
+ mHelper.switchToUser(userToSwitchTo);
+ assertThat(ShadowActivityManager.getShadow().getSwitchUserCalled()).isTrue();
+ assertThat(ShadowActivityManager.getShadow().getUserSwitchedTo()).isEqualTo(22);
+ }
+
+ private UserInfo createUserInfoForId(int id) {
+ UserInfo userInfo = new UserInfo();
+ userInfo.id = id;
+ return userInfo;
+ }
+}
diff --git a/tests/usb/AoapHostApp/Android.mk b/tests/usb/AoapHostApp/Android.mk
index e335160..9fc286a 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 legacy-android-test
+LOCAL_STATIC_JAVA_LIBRARIES := junit
include packages/services/Car/car-support-lib/car-support.mk
include $(BUILD_PACKAGE)
diff --git a/tests/usb/AoapHostApp/AndroidManifest.xml b/tests/usb/AoapHostApp/AndroidManifest.xml
index 668fb7a..2cac450 100644
--- a/tests/usb/AoapHostApp/AndroidManifest.xml
+++ b/tests/usb/AoapHostApp/AndroidManifest.xml
@@ -17,6 +17,8 @@
xmlns:androidprv="http://schemas.android.com/apk/prv/res/android"
package="com.google.android.car.usb.aoap.host" >
<application android:label="@string/app_title" >
+ <uses-library android:name="android.test.runner" />
+
<activity android:name=".UsbAoapHostActivity"
android:configChanges="keyboard|keyboardHidden" >
<intent-filter>
diff --git a/tests/usb/AoapPhoneCompanionApp/Android.mk b/tests/usb/AoapPhoneCompanionApp/Android.mk
index 1d0d3b2..7e0ba18 100644
--- a/tests/usb/AoapPhoneCompanionApp/Android.mk
+++ b/tests/usb/AoapPhoneCompanionApp/Android.mk
@@ -31,7 +31,6 @@
LOCAL_MODULE_TAGS := optional
LOCAL_MODULE_PATH := $(TARGET_OUT_DATA_APPS)
-LOCAL_JAVA_LIBRARIES := core-libart
LOCAL_PROGUARD_ENABLED := disabled
diff --git a/tests/usb/AoapPhoneCompanionApp/src/com/google/android/car/usb/aoap/companion/AoapPhoneCompanionActivity.java b/tests/usb/AoapPhoneCompanionApp/src/com/google/android/car/usb/aoap/companion/AoapPhoneCompanionActivity.java
index c6a6634..f71a575 100644
--- a/tests/usb/AoapPhoneCompanionApp/src/com/google/android/car/usb/aoap/companion/AoapPhoneCompanionActivity.java
+++ b/tests/usb/AoapPhoneCompanionApp/src/com/google/android/car/usb/aoap/companion/AoapPhoneCompanionActivity.java
@@ -29,8 +29,6 @@
import android.view.View;
import android.widget.Button;
-import libcore.io.IoUtils;
-
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
@@ -97,7 +95,15 @@
protected void onDestroy() {
super.onDestroy();
unregisterReceiver(mReceiver);
- IoUtils.closeQuietly(mFd);
+ // close quietly
+ if (mFd != null) {
+ try {
+ mFd.close();
+ } catch (RuntimeException e) {
+ throw e;
+ } catch (Exception e) {
+ }
+ }
if (mProcessorThread != null) {
mProcessorThread.requestToQuit();
try {
diff --git a/tests/vehiclehal_test/Android.mk b/tests/vehiclehal_test/Android.mk
index 57afcf1..d5adc65 100644
--- a/tests/vehiclehal_test/Android.mk
+++ b/tests/vehiclehal_test/Android.mk
@@ -37,6 +37,6 @@
android.hidl.base-V1.0-java \
android.hardware.automotive.vehicle-V2.0-java
-LOCAL_JAVA_LIBRARIES := android.car android.test.runner
+LOCAL_JAVA_LIBRARIES := android.car android.test.runner android.test.base
include $(BUILD_PACKAGE)
diff --git a/tests/vehiclehal_test/AndroidManifest.xml b/tests/vehiclehal_test/AndroidManifest.xml
index 765d099..c03406d 100644
--- a/tests/vehiclehal_test/AndroidManifest.xml
+++ b/tests/vehiclehal_test/AndroidManifest.xml
@@ -18,6 +18,8 @@
package="com.android.car.vehiclehal.test"
android:sharedUserId="android.uid.system" >
+ <uses-permission android:name="android.car.permission.CONTROL_CAR_CLIMATE" />
+
<instrumentation android:name="android.support.test.runner.AndroidJUnitRunner"
android:targetPackage="com.android.car.vehiclehal.test"
android:label="Tests for Vehicle HAL APIs"/>
diff --git a/tests/vehiclehal_test/assets/car_hvac_test.json b/tests/vehiclehal_test/assets/car_hvac_test.json
new file mode 100644
index 0000000..7f6c0bb
--- /dev/null
+++ b/tests/vehiclehal_test/assets/car_hvac_test.json
@@ -0,0 +1,518 @@
+[
+ {
+ "timestamp": 1526063903356950016,
+ "areaId": 1,
+ "value": 1,
+ "prop": 354419984
+ },
+ {
+ "timestamp": 1526063903357100032,
+ "areaId": 4,
+ "value": 1,
+ "prop": 354419984
+ },
+ {
+ "timestamp": 1526063903757636096,
+ "areaId": 0,
+ "value": 1,
+ "prop": 356517121
+ },
+ {
+ "timestamp": 1526063904959113984,
+ "areaId": 0,
+ "value": 28,
+ "prop": 358614275
+ },
+ {
+ "timestamp": 1526063905159528960,
+ "areaId": 0,
+ "value": 27,
+ "prop": 358614275
+ },
+ {
+ "timestamp": 1526063905359936000,
+ "areaId": 0,
+ "value": 26,
+ "prop": 358614275
+ },
+ {
+ "timestamp": 1526063905560376832,
+ "areaId": 0,
+ "value": 25,
+ "prop": 358614275
+ },
+ {
+ "timestamp": 1526063905760837120,
+ "areaId": 0,
+ "value": 24,
+ "prop": 358614275
+ },
+ {
+ "timestamp": 1526063905961300992,
+ "areaId": 0,
+ "value": 23,
+ "prop": 358614275
+ },
+ {
+ "timestamp": 1526063906362006016,
+ "areaId": 0,
+ "value": 1,
+ "prop": 356517120
+ },
+ {
+ "timestamp": 1526063906562436096,
+ "areaId": 0,
+ "value": 2,
+ "prop": 356517120
+ },
+ {
+ "timestamp": 1526063906762857984,
+ "areaId": 0,
+ "value": 3,
+ "prop": 356517120
+ },
+ {
+ "timestamp": 1526063906963272960,
+ "areaId": 0,
+ "value": 4,
+ "prop": 356517120
+ },
+ {
+ "timestamp": 1526063908364721920,
+ "areaId": 0,
+ "value": 1,
+ "prop": 356517121
+ },
+ {
+ "timestamp": 1526063910066729984,
+ "areaId": 0,
+ "value": 4,
+ "prop": 356517121
+ },
+ {
+ "timestamp": 1526063911268203008,
+ "areaId": 0,
+ "value": 22,
+ "prop": 358614275
+ },
+ {
+ "timestamp": 1526063911468478976,
+ "areaId": 0,
+ "value": 23,
+ "prop": 358614275
+ },
+ {
+ "timestamp": 1526063911668872192,
+ "areaId": 0,
+ "value": 24,
+ "prop": 358614275
+ },
+ {
+ "timestamp": 1526063911869281024,
+ "areaId": 0,
+ "value": 25,
+ "prop": 358614275
+ },
+ {
+ "timestamp": 1526063912069678080,
+ "areaId": 0,
+ "value": 26,
+ "prop": 358614275
+ },
+ {
+ "timestamp": 1526063912270088960,
+ "areaId": 0,
+ "value": 27,
+ "prop": 358614275
+ },
+ {
+ "timestamp": 1526063912670825984,
+ "areaId": 0,
+ "value": 5,
+ "prop": 356517120
+ },
+ {
+ "timestamp": 1526063912871236096,
+ "areaId": 0,
+ "value": 4,
+ "prop": 356517120
+ },
+ {
+ "timestamp": 1526063913071654912,
+ "areaId": 0,
+ "value": 3,
+ "prop": 356517120
+ },
+ {
+ "timestamp": 1526063913272064000,
+ "areaId": 0,
+ "value": 2,
+ "prop": 356517120
+ },
+ {
+ "timestamp": 1526063914373497856,
+ "areaId": 0,
+ "value": 1,
+ "prop": 356517121
+ },
+ {
+ "timestamp": 1526063915574942976,
+ "areaId": 0,
+ "value": 28,
+ "prop": 358614275
+ },
+ {
+ "timestamp": 1526063915775356928,
+ "areaId": 0,
+ "value": 27,
+ "prop": 358614275
+ },
+ {
+ "timestamp": 1526063915975784960,
+ "areaId": 0,
+ "value": 26,
+ "prop": 358614275
+ },
+ {
+ "timestamp": 1526063916176208128,
+ "areaId": 0,
+ "value": 25,
+ "prop": 358614275
+ },
+ {
+ "timestamp": 1526063916376483840,
+ "areaId": 0,
+ "value": 24,
+ "prop": 358614275
+ },
+ {
+ "timestamp": 1526063916576890880,
+ "areaId": 0,
+ "value": 23,
+ "prop": 358614275
+ },
+ {
+ "timestamp": 1526063916977551872,
+ "areaId": 0,
+ "value": 1,
+ "prop": 356517120
+ },
+ {
+ "timestamp": 1526063917177978112,
+ "areaId": 0,
+ "value": 2,
+ "prop": 356517120
+ },
+ {
+ "timestamp": 1526063917378403072,
+ "areaId": 0,
+ "value": 3,
+ "prop": 356517120
+ },
+ {
+ "timestamp": 1526063917578809856,
+ "areaId": 0,
+ "value": 4,
+ "prop": 356517120
+ },
+ {
+ "timestamp": 1526063918980086016,
+ "areaId": 0,
+ "value": 1,
+ "prop": 356517121
+ },
+ {
+ "timestamp": 1526063920681338112,
+ "areaId": 0,
+ "value": 4,
+ "prop": 356517121
+ },
+ {
+ "timestamp": 1526063921882802944,
+ "areaId": 0,
+ "value": 22,
+ "prop": 358614275
+ },
+ {
+ "timestamp": 1526063922083273984,
+ "areaId": 0,
+ "value": 23,
+ "prop": 358614275
+ },
+ {
+ "timestamp": 1526063922283792896,
+ "areaId": 0,
+ "value": 24,
+ "prop": 358614275
+ },
+ {
+ "timestamp": 1526063922484265984,
+ "areaId": 0,
+ "value": 25,
+ "prop": 358614275
+ },
+ {
+ "timestamp": 1526063922684783872,
+ "areaId": 0,
+ "value": 26,
+ "prop": 358614275
+ },
+ {
+ "timestamp": 1526063922885256960,
+ "areaId": 0,
+ "value": 27,
+ "prop": 358614275
+ },
+ {
+ "timestamp": 1526063923285954048,
+ "areaId": 0,
+ "value": 5,
+ "prop": 356517120
+ },
+ {
+ "timestamp": 1526063923486427136,
+ "areaId": 0,
+ "value": 4,
+ "prop": 356517120
+ },
+ {
+ "timestamp": 1526063923686938880,
+ "areaId": 0,
+ "value": 3,
+ "prop": 356517120
+ },
+ {
+ "timestamp": 1526063923887389952,
+ "areaId": 0,
+ "value": 2,
+ "prop": 356517120
+ },
+ {
+ "timestamp": 1526063924988778240,
+ "areaId": 0,
+ "value": 1,
+ "prop": 356517121
+ },
+ {
+ "timestamp": 1526063926190287104,
+ "areaId": 0,
+ "value": 28,
+ "prop": 358614275
+ },
+ {
+ "timestamp": 1526063926390775040,
+ "areaId": 0,
+ "value": 27,
+ "prop": 358614275
+ },
+ {
+ "timestamp": 1526063926591278080,
+ "areaId": 0,
+ "value": 26,
+ "prop": 358614275
+ },
+ {
+ "timestamp": 1526063926791796992,
+ "areaId": 0,
+ "value": 25,
+ "prop": 358614275
+ },
+ {
+ "timestamp": 1526063926992291840,
+ "areaId": 0,
+ "value": 24,
+ "prop": 358614275
+ },
+ {
+ "timestamp": 1526063927192840960,
+ "areaId": 0,
+ "value": 23,
+ "prop": 358614275
+ },
+ {
+ "timestamp": 1526063927593507072,
+ "areaId": 0,
+ "value": 1,
+ "prop": 356517120
+ },
+ {
+ "timestamp": 1526063927793946112,
+ "areaId": 0,
+ "value": 2,
+ "prop": 356517120
+ },
+ {
+ "timestamp": 1526063927994479872,
+ "areaId": 0,
+ "value": 3,
+ "prop": 356517120
+ },
+ {
+ "timestamp": 1526063928194946048,
+ "areaId": 0,
+ "value": 4,
+ "prop": 356517120
+ },
+ {
+ "timestamp": 1526063929596730112,
+ "areaId": 0,
+ "value": 1,
+ "prop": 356517121
+ },
+ {
+ "timestamp": 1526063931298659072,
+ "areaId": 0,
+ "value": 4,
+ "prop": 356517121
+ },
+ {
+ "timestamp": 1526063932500180992,
+ "areaId": 0,
+ "value": 22,
+ "prop": 358614275
+ },
+ {
+ "timestamp": 1526063932700491008,
+ "areaId": 0,
+ "value": 23,
+ "prop": 358614275
+ },
+ {
+ "timestamp": 1526063932900928000,
+ "areaId": 0,
+ "value": 24,
+ "prop": 358614275
+ },
+ {
+ "timestamp": 1526063933101340928,
+ "areaId": 0,
+ "value": 25,
+ "prop": 358614275
+ },
+ {
+ "timestamp": 1526063933301820160,
+ "areaId": 0,
+ "value": 26,
+ "prop": 358614275
+ },
+ {
+ "timestamp": 1526063933502290944,
+ "areaId": 0,
+ "value": 27,
+ "prop": 358614275
+ },
+ {
+ "timestamp": 1526063933903042048,
+ "areaId": 0,
+ "value": 5,
+ "prop": 356517120
+ },
+ {
+ "timestamp": 1526063934103492864,
+ "areaId": 0,
+ "value": 4,
+ "prop": 356517120
+ },
+ {
+ "timestamp": 1526063934303913984,
+ "areaId": 0,
+ "value": 3,
+ "prop": 356517120
+ },
+ {
+ "timestamp": 1526063934504412928,
+ "areaId": 0,
+ "value": 2,
+ "prop": 356517120
+ },
+ {
+ "timestamp": 1526063935606041856,
+ "areaId": 0,
+ "value": 1,
+ "prop": 356517121
+ },
+ {
+ "timestamp": 1526063936807610880,
+ "areaId": 0,
+ "value": 28,
+ "prop": 358614275
+ },
+ {
+ "timestamp": 1526063937008130048,
+ "areaId": 0,
+ "value": 27,
+ "prop": 358614275
+ },
+ {
+ "timestamp": 1526063937208636160,
+ "areaId": 0,
+ "value": 26,
+ "prop": 358614275
+ },
+ {
+ "timestamp": 1526063937409096960,
+ "areaId": 0,
+ "value": 25,
+ "prop": 358614275
+ },
+ {
+ "timestamp": 1526063937609554176,
+ "areaId": 0,
+ "value": 24,
+ "prop": 358614275
+ },
+ {
+ "timestamp": 1526063937810017024,
+ "areaId": 0,
+ "value": 23,
+ "prop": 358614275
+ },
+ {
+ "timestamp": 1526063938210696960,
+ "areaId": 0,
+ "value": 1,
+ "prop": 356517120
+ },
+ {
+ "timestamp": 1526063938411200000,
+ "areaId": 0,
+ "value": 2,
+ "prop": 356517120
+ },
+ {
+ "timestamp": 1526063938611734016,
+ "areaId": 0,
+ "value": 3,
+ "prop": 356517120
+ },
+ {
+ "timestamp": 1526063938812249856,
+ "areaId": 0,
+ "value": 4,
+ "prop": 356517120
+ },
+ {
+ "timestamp": 1526063940214057984,
+ "areaId": 0,
+ "value": 1,
+ "prop": 356517121
+ },
+ {
+ "timestamp": 1526063941916071936,
+ "areaId": 0,
+ "value": 4,
+ "prop": 356517121
+ },
+ {
+ "timestamp": 1526063943123698944,
+ "areaId": 0,
+ "value": 22,
+ "prop": 358614275
+ },
+ {
+ "timestamp": 1526063943323981056,
+ "areaId": 0,
+ "value": 23,
+ "prop": 358614275
+ }
+]
\ No newline at end of file
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
new file mode 100644
index 0000000..08544bd
--- /dev/null
+++ b/tests/vehiclehal_test/src/com/android/car/vehiclehal/test/CarHvacTest.java
@@ -0,0 +1,138 @@
+/*
+ * 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/E2eCarTestBase.java b/tests/vehiclehal_test/src/com/android/car/vehiclehal/test/E2eCarTestBase.java
new file mode 100644
index 0000000..5960422
--- /dev/null
+++ b/tests/vehiclehal_test/src/com/android/car/vehiclehal/test/E2eCarTestBase.java
@@ -0,0 +1,137 @@
+/*
+ * 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.Assume.assumeTrue;
+
+import android.car.Car;
+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;
+import android.support.test.InstrumentationRegistry;
+import android.util.Log;
+
+import com.google.android.collect.Lists;
+
+import org.json.JSONException;
+import org.junit.After;
+import org.junit.Before;
+
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.util.List;
+
+
+public class E2eCarTestBase {
+ private static final String TAG = Utils.concatTag(E2eCarTestBase.class);
+ private static final int DEFAULT_WAIT_TIMEOUT_MS = 1000;
+
+ protected IVehicle mVehicle;
+ protected Car mCar;
+ protected Context mContext;
+ private final CarConnectionListener mConnectionListener = new CarConnectionListener();
+
+ @Before
+ public void connectToVehicleHal() throws Exception {
+ mVehicle = Utils.getVehicle();
+ mVehicle.getPropConfigs(
+ Lists.newArrayList(VhalEventGenerator.GENERATE_FAKE_DATA_CONTROLLING_PROPERTY),
+ (status, propConfigs) -> assumeTrue(status == StatusCode.OK));
+ }
+
+ @Before
+ public void connectToCarService() {
+ mContext = InstrumentationRegistry.getContext();
+ mCar = Car.createCar(mContext, mConnectionListener);
+ assertNotNull(mCar);
+ mCar.connect();
+ mConnectionListener.waitForConnection(DEFAULT_WAIT_TIMEOUT_MS);
+ }
+
+ @After
+ public void disconnect() {
+ if (mVehicle != null) {
+ mVehicle = null;
+ }
+ if (mCar != null) {
+ mCar.disconnect();
+ mCar = null;
+ }
+ }
+
+ protected List<VehiclePropValue> getExpectedEvents(String fileName)
+ throws IOException, JSONException {
+ try (InputStream in = mContext.getAssets().open(fileName)) {
+ Log.d(TAG, "Reading golden test data" + fileName);
+ return VhalJsonReader.readFromJson(in);
+ }
+ }
+
+ /**
+ * The method copies the test data from assets/ to internal storage and make it publicly
+ * readable, so that default VHAL can access and read the test data.
+ */
+ protected File makeShareable(String fileName) throws IOException {
+ File filesDir = mContext.getFilesDir();
+ // Set publicly executable permission to make sure app internal storage:
+ // /data/user/0/<package> is accessible for default VHAL service
+ if (!filesDir.getParentFile().setExecutable(true, false)) {
+ Log.w(TAG, "Failed to set parent directory +x permission"
+ + filesDir.getParentFile().getAbsolutePath());
+ }
+ File internalFile = new File(filesDir, fileName);
+
+ try (
+ InputStream in = mContext.getAssets().open(fileName);
+ OutputStream out = new FileOutputStream(internalFile)
+ ) {
+ Log.d(TAG, "Copying golden test data to " + internalFile.getAbsolutePath());
+ FileUtils.copy(in, out);
+ }
+ // Make sure the copied test file is publicly readable for default VHAL service. This
+ // operation is risky with security holes and should only be used for testing scenarios.
+ if (!internalFile.setReadable(true, false)) {
+ Log.w(TAG, "Failed to set read permission for " + internalFile.getAbsolutePath());
+ }
+ return internalFile;
+ }
+
+ private static class CarConnectionListener implements ServiceConnection {
+ private final ConditionVariable mConnectionWait = new ConditionVariable();
+
+ void waitForConnection(long timeoutMs) {
+ mConnectionWait.block(timeoutMs);
+ }
+
+ @Override
+ public void onServiceConnected(ComponentName name, IBinder service) {
+ mConnectionWait.open();
+ }
+
+ @Override
+ public void onServiceDisconnected(ComponentName name) {}
+ }
+}
diff --git a/tests/vehiclehal_test/src/com/android/car/vehiclehal/test/E2ePerformanceTest.java b/tests/vehiclehal_test/src/com/android/car/vehiclehal/test/E2ePerformanceTest.java
index 6675713..6427a07 100644
--- a/tests/vehiclehal_test/src/com/android/car/vehiclehal/test/E2ePerformanceTest.java
+++ b/tests/vehiclehal_test/src/com/android/car/vehiclehal/test/E2ePerformanceTest.java
@@ -15,12 +15,13 @@
*/
package com.android.car.vehiclehal.test;
-import static java.lang.Integer.toHexString;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
-import static org.junit.Assume.assumeTrue;
+import static org.junit.Assert.fail;
+
+import static java.lang.Integer.toHexString;
import android.annotation.Nullable;
import android.car.Car;
@@ -29,41 +30,22 @@
import android.car.hardware.CarSensorManager;
import android.car.hardware.CarSensorManager.OnSensorChangedListener;
import android.car.hardware.hvac.CarHvacManager;
-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.VehicleArea;
-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.VehiclePropertyType;
-import android.os.Handler;
-import android.os.HandlerThread;
-import android.os.IBinder;
-import android.os.RemoteException;
import android.os.SystemClock;
-import android.support.test.InstrumentationRegistry;
+import android.support.test.filters.MediumTest;
import android.support.test.runner.AndroidJUnit4;
-import android.test.suitebuilder.annotation.MediumTest;
+import android.util.Log;
import android.util.SparseArray;
import android.util.SparseIntArray;
import com.google.android.collect.Lists;
-import com.android.car.vehiclehal.VehiclePropValueBuilder;
-
-import org.junit.After;
-import org.junit.Before;
-import org.junit.BeforeClass;
import org.junit.Test;
import org.junit.runner.RunWith;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.CountDownLatch;
-import java.util.concurrent.Semaphore;
import java.util.concurrent.TimeUnit;
/**
@@ -76,67 +58,9 @@
*/
@MediumTest
@RunWith(AndroidJUnit4.class)
-public class E2ePerformanceTest {
+public class E2ePerformanceTest extends E2eCarTestBase {
private static String TAG = Utils.concatTag(E2ePerformanceTest.class);
- private IVehicle mVehicle;
- private final CarConnectionListener mConnectionListener = new CarConnectionListener();
- private Context mContext;
- private Car mCar;
-
- private static Handler sEventHandler;
- private static final HandlerThread sHandlerThread = new HandlerThread(TAG);
-
- private static final int DEFAULT_WAIT_TIMEOUT_MS = 1000;
-
- private static final int GENERATE_FAKE_DATA_CONTROLLING_PROPERTY = 0x0666
- | VehiclePropertyGroup.VENDOR
- | VehicleArea.GLOBAL
- | VehiclePropertyType.COMPLEX;
-
- private static final int CMD_START = 1;
- private static final int CMD_STOP = 0;
-
- private HalEventsGenerator mEventsGenerator;
-
- @BeforeClass
- public static void setupEventHandler() {
- sHandlerThread.start();
- sEventHandler = new Handler(sHandlerThread.getLooper());
- }
-
- @Before
- public void connectToVehicleHal() throws Exception {
- mVehicle = Utils.getVehicle();
-
- mVehicle.getPropConfigs(Lists.newArrayList(GENERATE_FAKE_DATA_CONTROLLING_PROPERTY),
- (status, propConfigs) -> assumeTrue(status == StatusCode.OK));
-
- mEventsGenerator = new HalEventsGenerator(mVehicle);
- }
-
- @Before
- public void connectToCarService() throws Exception {
- mContext = InstrumentationRegistry.getContext();
- mCar = Car.createCar(mContext, mConnectionListener, sEventHandler);
- assertNotNull(mCar);
- mCar.connect();
- mConnectionListener.waitForConnection(DEFAULT_WAIT_TIMEOUT_MS);
- }
-
- @After
- public void disconnect() throws Exception {
- if (mVehicle != null) {
- mEventsGenerator.stop();
- mVehicle = null;
- mEventsGenerator = null;
- }
- if (mCar != null) {
- mCar.disconnect();
- mCar = null;
- }
- }
-
@Test
public void singleOnChangeProperty() throws Exception {
verifyEventsFromSingleProperty(
@@ -146,14 +70,13 @@
@Test
public void singleContinuousProperty() throws Exception {
verifyEventsFromSingleProperty(
- CarSensorManager.SENSOR_TYPE_RPM, VehicleProperty.ENGINE_RPM);
+ CarSensorManager.SENSOR_TYPE_CAR_SPEED, VehicleProperty.PERF_VEHICLE_SPEED);
}
@Test
public void benchmarkEventBandwidthThroughCarService() throws Exception {
int[] mgrProperties = new int[] {
CarSensorManager.SENSOR_TYPE_ODOMETER,
- CarSensorManager.SENSOR_TYPE_RPM,
CarSensorManager.SENSOR_TYPE_CAR_SPEED
};
// Expecting to receive at least 10 events within 150ms.
@@ -168,23 +91,23 @@
mgr.isSensorSupported(mgrPropId));
}
- mEventsGenerator
- .reset()
+ VhalEventGenerator odometerGenerator = new LinearVhalEventGenerator(mVehicle)
+ .setProp(VehicleProperty.PERF_ODOMETER)
.setIntervalMs(EVENT_INTERVAL_MS)
.setInitialValue(1000)
.setIncrement(1.0f)
- .setDispersion(100)
- .start(VehicleProperty.PERF_ODOMETER);
+ .setDispersion(100);
- mEventsGenerator
- .start(VehicleProperty.ENGINE_RPM);
- mEventsGenerator
+ VhalEventGenerator speedGenerator = new LinearVhalEventGenerator(mVehicle)
+ .setProp(VehicleProperty.PERF_VEHICLE_SPEED)
.setIntervalMs(EVENT_INTERVAL_MS)
.setInitialValue(20.0f)
.setIncrement(0.1f)
- .setDispersion(10)
- .start(VehicleProperty.PERF_VEHICLE_SPEED);
+ .setDispersion(10);
+
+ odometerGenerator.start();
+ speedGenerator.start();
SparseArray<CountDownLatch> eventsCounters = new SparseArray<>();
for (int i = 0; i < mgrProperties.length; i++) {
@@ -202,7 +125,9 @@
}
boolean allEventsReceived = awaitCountDownLatches(latches, WAIT_TIME);
mgr.unregisterListener(listener);
- mEventsGenerator.stop();
+
+ odometerGenerator.stop();
+ speedGenerator.stop();
if (!allEventsReceived) {
SparseIntArray missingEventsPerProperty = new SparseIntArray();
@@ -233,8 +158,8 @@
boolean value = false;
long actualIterations = 0;
while (SystemClock.elapsedRealtimeNanos() < start + TEST_DURATION_NANO) {
- mgr.setBooleanProperty(PROP, 0, value);
- boolean actualValue = mgr.getBooleanProperty(PROP, 0);
+ mgr.setBooleanProperty(PROP, 1, value);
+ boolean actualValue = mgr.getBooleanProperty(PROP, 1);
assertEquals(value, actualValue);
value = !value;
actualIterations++;
@@ -259,6 +184,27 @@
final int EXPECTED_INVOCATIONS = 1000; // How many time get/set will be called.
final int EXPECTED_DURATION_MS = 2500;
+ // This is a stress test and it can be flaky because it shares resources with all currently
+ // running process. Let's have this number of attempt before giving up.
+ final int ATTEMPTS = 3;
+
+ for (int curAttempt = 0; curAttempt < ATTEMPTS; curAttempt++) {
+ long missingInvocations = stressTestHvacProperties(mgr, cfg,
+ EXPECTED_INVOCATIONS, EXPECTED_DURATION_MS);
+ if (missingInvocations == 0) return; // All done.
+
+ Log.w(TAG, "Failed to invoke get/set " + EXPECTED_INVOCATIONS
+ + " within " + EXPECTED_DURATION_MS + "ms"
+ + ", actually invoked: "
+ + (EXPECTED_INVOCATIONS - missingInvocations));
+ }
+ fail("Failed to invoke get/set " + EXPECTED_INVOCATIONS + " within "
+ + EXPECTED_DURATION_MS + "ms. Number of attempts: " + ATTEMPTS
+ + ". See logs for details.");
+ }
+
+ private long stressTestHvacProperties(CarHvacManager mgr, CarPropertyConfig<Float> cfg,
+ int EXPECTED_INVOCATIONS, int EXPECTED_DURATION_MS) throws InterruptedException {
CountDownLatch counter = new CountDownLatch(EXPECTED_INVOCATIONS);
List<Thread> threads = new ArrayList<>(Lists.newArrayList(
@@ -271,15 +217,12 @@
counter.await(EXPECTED_DURATION_MS, TimeUnit.MILLISECONDS);
long missingInvocations = counter.getCount();
- assertTrue("Failed to invoke get/set " + EXPECTED_INVOCATIONS
- + " within " + EXPECTED_DURATION_MS + "ms"
- + ", actually invoked: " + (EXPECTED_INVOCATIONS - missingInvocations),
- missingInvocations == 0);
for (Thread t : threads) {
t.join(10000); // Let thread join to not interfere with other test.
assertFalse(t.isAlive());
}
+ return missingInvocations;
}
private void invokeSetAndGetForHvacFloat(CarHvacManager mgr,
@@ -329,12 +272,14 @@
assertNotNull(mgr);
assertTrue(mgr.isSensorSupported(mgrPropId));
- mEventsGenerator
+ VhalEventGenerator generator = new LinearVhalEventGenerator(mVehicle)
+ .setProp(halPropId)
.setIntervalMs(10)
.setInitialValue(INITIAL_VALUE)
.setIncrement(INCREMENT)
- .setDispersion(100)
- .start(halPropId);
+ .setDispersion(100);
+
+ generator.start();
CountDownLatch latch = new CountDownLatch(EXPECTED_EVENTS);
OnSensorChangedListener listener = event -> latch.countDown();
@@ -343,25 +288,11 @@
try {
assertTrue(latch.await(EXPECTED_TIME_DURATION_MS, TimeUnit.MILLISECONDS));
} finally {
+ generator.stop();
mgr.unregisterListener(listener);
}
}
- private static class CarConnectionListener implements ServiceConnection {
- private final Semaphore mConnectionWait = new Semaphore(0);
-
- void waitForConnection(long timeoutMs) throws InterruptedException {
- mConnectionWait.tryAcquire(timeoutMs, TimeUnit.MILLISECONDS);
- }
-
- @Override
- public void onServiceConnected(ComponentName name, IBinder service) {
- mConnectionWait.release();
- }
-
- @Override
- public void onServiceDisconnected(ComponentName name) { }
- }
private static boolean awaitCountDownLatches(CountDownLatch[] latches, long timeoutMs)
throws InterruptedException {
@@ -375,68 +306,4 @@
return true;
}
-
- static class HalEventsGenerator {
- private final IVehicle mVehicle;
-
- private long mIntervalMs;
- private float mInitialValue;
- private float mDispersion;
- private float mIncrement;
-
- HalEventsGenerator(IVehicle vehicle) {
- mVehicle = vehicle;
- reset();
- }
-
- HalEventsGenerator reset() {
- mIntervalMs = 1000;
- mInitialValue = 1000;
- mDispersion = 0;
- mInitialValue = 0;
- return this;
- }
-
- HalEventsGenerator setIntervalMs(long intervalMs) {
- mIntervalMs = intervalMs;
- return this;
- }
-
- HalEventsGenerator setInitialValue(float initialValue) {
- mInitialValue = initialValue;
- return this;
- }
-
- HalEventsGenerator setDispersion(float dispersion) {
- mDispersion = dispersion;
- return this;
- }
-
- HalEventsGenerator setIncrement(float increment) {
- mIncrement = increment;
- return this;
- }
-
- void start(int propId) throws RemoteException {
- VehiclePropValue request =
- VehiclePropValueBuilder.newBuilder(GENERATE_FAKE_DATA_CONTROLLING_PROPERTY)
- .addIntValue(CMD_START, propId)
- .setInt64Value(mIntervalMs * 1000_000)
- .addFloatValue(mInitialValue, mDispersion, mIncrement)
- .build();
- assertEquals(StatusCode.OK, mVehicle.set(request));
- }
-
- void stop() throws RemoteException {
- stop(0);
- }
-
- void stop(int propId) throws RemoteException {
- VehiclePropValue request =
- VehiclePropValueBuilder.newBuilder(GENERATE_FAKE_DATA_CONTROLLING_PROPERTY)
- .addIntValue(CMD_STOP, propId)
- .build();
- assertEquals(StatusCode.OK, mVehicle.set(request));
- }
- }
}
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
new file mode 100644
index 0000000..702f5f0
--- /dev/null
+++ b/tests/vehiclehal_test/src/com/android/car/vehiclehal/test/JsonVhalEventGenerator.java
@@ -0,0 +1,64 @@
+/*
+ * 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.assertEquals;
+
+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.RemoteException;
+
+import com.android.car.vehiclehal.VehiclePropValueBuilder;
+
+import java.io.File;
+
+class JsonVhalEventGenerator implements VhalEventGenerator {
+
+ private IVehicle mVehicle;
+ private File mFile;
+
+ JsonVhalEventGenerator(IVehicle vehicle) {
+ mVehicle = vehicle;
+ }
+
+ public JsonVhalEventGenerator setJsonFile(File file) throws Exception {
+ if (!file.exists()) {
+ throw new Exception("JSON test data file does not exist: " + file.getAbsolutePath());
+ }
+ mFile = file;
+ return this;
+ }
+
+ @Override
+ public void start() throws RemoteException {
+ VehiclePropValue request =
+ VehiclePropValueBuilder.newBuilder(GENERATE_FAKE_DATA_CONTROLLING_PROPERTY)
+ .addIntValue(CMD_START_JSON)
+ .setStringValue(mFile.getAbsolutePath())
+ .build();
+ assertEquals(StatusCode.OK, mVehicle.set(request));
+ }
+
+ @Override
+ public void stop() throws RemoteException {
+ VehiclePropValue request =
+ VehiclePropValueBuilder.newBuilder(GENERATE_FAKE_DATA_CONTROLLING_PROPERTY)
+ .addIntValue(CMD_STOP_JSON)
+ .build();
+ assertEquals(StatusCode.OK, mVehicle.set(request));
+ }
+}
diff --git a/tests/vehiclehal_test/src/com/android/car/vehiclehal/test/LinearVhalEventGenerator.java b/tests/vehiclehal_test/src/com/android/car/vehiclehal/test/LinearVhalEventGenerator.java
new file mode 100644
index 0000000..856e1fc
--- /dev/null
+++ b/tests/vehiclehal_test/src/com/android/car/vehiclehal/test/LinearVhalEventGenerator.java
@@ -0,0 +1,97 @@
+/*
+ * 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.assertEquals;
+
+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.RemoteException;
+
+import com.android.car.vehiclehal.VehiclePropValueBuilder;
+
+import java.time.Duration;
+
+class LinearVhalEventGenerator implements VhalEventGenerator {
+
+ private final IVehicle mVehicle;
+
+ private int mProp;
+ private Duration mInterval;
+ private float mInitialValue;
+ private float mDispersion;
+ private float mIncrement;
+
+ LinearVhalEventGenerator(IVehicle vehicle) {
+ mVehicle = vehicle;
+ reset();
+ }
+
+ LinearVhalEventGenerator reset() {
+ mProp = 0;
+ mInterval = Duration.ofSeconds(1);
+ mInitialValue = 1000;
+ mDispersion = 0;
+ mInitialValue = 0;
+ return this;
+ }
+
+ LinearVhalEventGenerator setIntervalMs(long intervalMs) {
+ mInterval = Duration.ofMillis(intervalMs);
+ return this;
+ }
+
+ LinearVhalEventGenerator setInitialValue(float initialValue) {
+ mInitialValue = initialValue;
+ return this;
+ }
+
+ LinearVhalEventGenerator setDispersion(float dispersion) {
+ mDispersion = dispersion;
+ return this;
+ }
+
+ LinearVhalEventGenerator setIncrement(float increment) {
+ mIncrement = increment;
+ return this;
+ }
+
+ LinearVhalEventGenerator setProp(int prop) {
+ mProp = prop;
+ return this;
+ }
+
+ @Override
+ public void start() throws RemoteException {
+ VehiclePropValue request =
+ VehiclePropValueBuilder.newBuilder(GENERATE_FAKE_DATA_CONTROLLING_PROPERTY)
+ .addIntValue(CMD_START_LINEAR, mProp)
+ .setInt64Value(mInterval.toNanos())
+ .addFloatValue(mInitialValue, mDispersion, mIncrement)
+ .build();
+ assertEquals(StatusCode.OK, mVehicle.set(request));
+ }
+
+ @Override
+ public void stop() throws RemoteException {
+ VehiclePropValue request =
+ VehiclePropValueBuilder.newBuilder(GENERATE_FAKE_DATA_CONTROLLING_PROPERTY)
+ .addIntValue(CMD_STOP_LINEAR, mProp)
+ .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 e1ee963..6a4b496 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,10 +16,13 @@
package com.android.car.vehiclehal.test;
-import android.annotation.Nullable;
+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;
@@ -81,16 +84,73 @@
return readVhalProperty(vehicle, request, f);
}
- @Nullable
static IVehicle getVehicle() throws RemoteException {
IVehicle service;
try {
- service = android.hardware.automotive.vehicle.V2_0.IVehicle.getService();
+ service = IVehicle.getService();
} catch (NoSuchElementException ex) {
- Log.d(TAG, "Couldn't connect to vehicle@2.1, connecting to vehicle@2.0...");
- service = IVehicle.getService();
+ throw new RuntimeException("Couldn't connect to vehicle@2.0", ex);
}
Log.d(TAG, "Connected to IVehicle service: " + service);
return service;
}
+
+ /**
+ * Check the equality of two VehiclePropValue object ignoring timestamp and status.
+ *
+ * @param value1
+ * @param value2
+ * @return true if equal
+ */
+ static boolean areVehiclePropValuesEqual(final VehiclePropValue value1,
+ final VehiclePropValue 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();
+ }
}
diff --git a/tests/vehiclehal_test/src/com/android/car/vehiclehal/test/VhalEventGenerator.java b/tests/vehiclehal_test/src/com/android/car/vehiclehal/test/VhalEventGenerator.java
new file mode 100644
index 0000000..b71bf6c
--- /dev/null
+++ b/tests/vehiclehal_test/src/com/android/car/vehiclehal/test/VhalEventGenerator.java
@@ -0,0 +1,58 @@
+/*
+ * 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.hardware.automotive.vehicle.V2_0.VehicleArea;
+import android.hardware.automotive.vehicle.V2_0.VehiclePropertyGroup;
+import android.hardware.automotive.vehicle.V2_0.VehiclePropertyType;
+import android.os.RemoteException;
+
+interface VhalEventGenerator {
+
+ /**
+ * The following property controls VHAL to start/stop linear fake data generation process.
+ * It must match kGenerateFakeDataControllingProperty that is defined in default VHAL
+ * implementation:
+ *
+ * hardware/interfaces/automotive/vehicle/2.0/default/impl/vhal_v2_0/DefaultConfig.h
+ */
+ int GENERATE_FAKE_DATA_CONTROLLING_PROPERTY = 0x0666
+ | VehiclePropertyGroup.VENDOR
+ | VehicleArea.GLOBAL
+ | VehiclePropertyType.MIXED;
+
+ // Command bits sent via GENERATE_FAKE_DATA_CONTROLLING_PROPERTY to control fake data generation
+ int CMD_START_LINEAR = 0; // Start linear fake data generation
+ int CMD_STOP_LINEAR = 1; // Stop linear fake data generation
+ int CMD_START_JSON = 2; // Start JSON-based fake data generation
+ int CMD_STOP_JSON = 3; // Stop JSON-based fake data generation
+
+ /**
+ * Asynchronous call to tell VHAL to start fake event generation. VHAL will start generating
+ * data after this call
+ *
+ * @throws RemoteException
+ */
+ void start() throws RemoteException;
+
+ /**
+ * Synchronous call to tell VHAL to stop fake event generation. VHAL should always stopped
+ * generating data after this call.
+ *
+ * @throws RemoteException
+ */
+ void stop() throws RemoteException;
+}
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
new file mode 100644
index 0000000..5ac92ca
--- /dev/null
+++ b/tests/vehiclehal_test/src/com/android/car/vehiclehal/test/VhalEventVerifier.java
@@ -0,0 +1,95 @@
+/*
+ * 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.hardware.automotive.vehicle.V2_0.VehiclePropValue;
+import android.os.ConditionVariable;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * The verifier class is used to verify received VHAL events against expected events on-the-fly.
+ * It is initialized with a list of expected events and moving down the list to verify received
+ * events. The verifier object not reusable and should be discarded once the verification is done.
+ * The verifier will provide formatted result for all mismatched events in sequence.
+ */
+class VhalEventVerifier {
+ private List<VehiclePropValue> mExpectedEvents;
+ // A pointer to keep track of the next expected event in the list
+ private int mIdx;
+ private List<MismatchedEventPair> mMismatchedEvents;
+ // Condition variable to notify waiting threads when verification is done or timeout.
+ private ConditionVariable mCond;
+
+ static class MismatchedEventPair {
+ public final int idx;
+ public final VehiclePropValue expectedEvent;
+ public final VehiclePropValue mismatchedEvent;
+
+ MismatchedEventPair(VehiclePropValue expectedEvent, VehiclePropValue mismatchedEvent,
+ int idx) {
+ this.idx = idx;
+ this.expectedEvent = expectedEvent;
+ this.mismatchedEvent = mismatchedEvent;
+ }
+ }
+
+ VhalEventVerifier(List<VehiclePropValue> expectedEvents) {
+ mExpectedEvents = expectedEvents;
+ mIdx = 0;
+ mMismatchedEvents = new ArrayList<>();
+ mCond = new ConditionVariable(expectedEvents.isEmpty());
+ }
+
+ /**
+ * Verification method that checks the equality of received event against expected event. Once
+ * it reaches to the end of list, it will unblock the waiting threads. Note, the verification
+ * method is not thread-safe. It assumes only a single thread is calling the method at all time.
+ *
+ * @param nextEvent to be verified
+ */
+ public void verify(VehiclePropValue nextEvent) {
+ if (mIdx >= mExpectedEvents.size()) {
+ return;
+ }
+ VehiclePropValue expectedEvent = mExpectedEvents.get(mIdx);
+ if (!Utils.areVehiclePropValuesEqual(expectedEvent, nextEvent)) {
+ mMismatchedEvents.add(new MismatchedEventPair(expectedEvent, nextEvent, mIdx));
+ }
+ if (++mIdx == mExpectedEvents.size()) {
+ mCond.open();
+ }
+ }
+
+ public List<MismatchedEventPair> getMismatchedEvents() {
+ return mMismatchedEvents;
+ }
+
+ public void waitForEnd(long timeout) {
+ mCond.block(timeout);
+ }
+
+ public String getResultString() {
+ StringBuilder resultBuilder = new StringBuilder();
+ for (MismatchedEventPair pair : mMismatchedEvents) {
+ resultBuilder.append("Index " + pair.idx + ": Expected "
+ + Utils.vehiclePropValueToString(pair.expectedEvent) + ", Received "
+ + Utils.vehiclePropValueToString(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
new file mode 100644
index 0000000..bf4e32f
--- /dev/null
+++ b/tests/vehiclehal_test/src/com/android/car/vehiclehal/test/VhalJsonReader.java
@@ -0,0 +1,95 @@
+/*
+ * 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 java.lang.Integer.toHexString;
+
+import android.hardware.automotive.vehicle.V2_0.VehiclePropValue;
+import android.hardware.automotive.vehicle.V2_0.VehiclePropertyType;
+
+import com.android.car.vehiclehal.VehiclePropValueBuilder;
+
+import org.json.JSONArray;
+import org.json.JSONException;
+import org.json.JSONObject;
+
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.nio.charset.StandardCharsets;
+import java.util.ArrayList;
+import java.util.List;
+
+
+class VhalJsonReader {
+
+ /**
+ * Name of fields presented in JSON file. All of them are required.
+ */
+ private static final String JSON_FIELD_PROP = "prop";
+ 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";
+
+ public static List<VehiclePropValue> readFromJson(InputStream in)
+ throws IOException, JSONException {
+ JSONArray rawEvents = new JSONArray(readJsonString(in));
+ List<VehiclePropValue> events = new ArrayList<>();
+ for (int i = 0; i < rawEvents.length(); i++) {
+ events.add(getEvent(rawEvents.getJSONObject(i)));
+ }
+ return events;
+ }
+
+ private static String readJsonString(InputStream in) throws IOException {
+ StringBuilder builder = new StringBuilder();
+ try (BufferedReader reader = new BufferedReader(
+ new InputStreamReader(in, StandardCharsets.UTF_8))) {
+ reader.lines().forEach(builder::append);
+ }
+ return builder.toString();
+ }
+
+ private static VehiclePropValue 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));
+
+ switch (prop & VehiclePropertyType.MASK) {
+ case VehiclePropertyType.BOOLEAN:
+ case VehiclePropertyType.INT32:
+ builder.addIntValue(rawEvent.getInt(JSON_FIELD_VALUE));
+ break;
+ case VehiclePropertyType.INT64:
+ builder.setInt64Value(rawEvent.getLong(JSON_FIELD_VALUE));
+ break;
+ case VehiclePropertyType.FLOAT:
+ builder.addFloatValue((float) rawEvent.getDouble(JSON_FIELD_VALUE));
+ break;
+ case VehiclePropertyType.STRING:
+ builder.setStringValue(rawEvent.getString(JSON_FIELD_VALUE));
+ break;
+ //TODO: Add VehiclePropertyType.MIXED type support
+ default:
+ throw new IllegalArgumentException("Property type 0x"
+ + toHexString(prop & VehiclePropertyType.MASK)
+ + " is not supported in the test.");
+ }
+ return builder.build();
+ }
+}
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
new file mode 100644
index 0000000..f24cad6
--- /dev/null
+++ b/tests/vehiclehal_test/src/com/android/car/vehiclehal/test/VhalPropMaps.java
@@ -0,0 +1,73 @@
+/*
+ * 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/bootanalyze/README.md b/tools/bootanalyze/README.md
deleted file mode 100644
index d6e0412..0000000
--- a/tools/bootanalyze/README.md
+++ /dev/null
@@ -1,15 +0,0 @@
-# bootanalyze #
-
-The bootanalyze tool helps to profile boot timing.
-
-Per specific product modify config.yaml file to include
-events you are looking for. Config should look like:
-
- stop_event: <logcat log message which will terminate log collection after reboot>
- events:
- event1_name: <pattern that matches log message>
- event2_.....
-
-On some devise clock is showing incorrect time for first couple of seconds after boot.
-To ensure correct adjustment of time, one has to include event in config that will
-be present in dmesg log after clock correction.
diff --git a/tools/bootanalyze/bootanalyze.py b/tools/bootanalyze/bootanalyze.py
deleted file mode 100755
index b878358..0000000
--- a/tools/bootanalyze/bootanalyze.py
+++ /dev/null
@@ -1,818 +0,0 @@
-#!/usr/bin/python
-
-# 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.
-#
-"""Tool to analyze logcat and dmesg logs.
-
-bootanalyze read logcat and dmesg loga and determines key points for boot.
-"""
-
-import argparse
-import collections
-import datetime
-import math
-import operator
-import os
-import re
-import select
-import subprocess
-import sys
-import time
-import threading
-import yaml
-
-from datetime import datetime, date
-
-
-TIME_DMESG = "\[\s*(\d+\.\d+)\]"
-TIME_LOGCAT = "[0-9]+\.?[0-9]*"
-KERNEL_TIME_KEY = "kernel"
-BOOT_ANIM_END_TIME_KEY = "BootAnimEnd"
-KERNEL_BOOT_COMPLETE = "BootComplete_kernel"
-LOGCAT_BOOT_COMPLETE = "BootComplete"
-LAUNCHER_START = "LauncherStart"
-BOOT_TIME_TOO_BIG = 200.0
-MAX_RETRIES = 5
-DEBUG = False
-ADB_CMD = "adb"
-TIMING_THRESHOLD = 5.0
-BOOT_PROP = "\[ro\.boottime\.([^\]]+)\]:\s+\[(\d+)\]"
-BOOTLOADER_TIME_PROP = "\[ro\.boot\.boottime\]:\s+\[([^\]]+)\]"
-
-max_wait_time = BOOT_TIME_TOO_BIG
-
-def main():
- global ADB_CMD
-
- args = init_arguments()
-
- if args.iterate < 1:
- raise Exception('Number of iteration must be >=1');
-
- if args.iterate > 1 and not args.reboot:
- print "Forcing reboot flag"
- args.reboot = True
-
- if args.serial:
- ADB_CMD = "%s %s" % ("adb -s", args.serial)
-
- error_time = BOOT_TIME_TOO_BIG * 10
- if args.errortime:
- error_time = float(args.errortime)
- if args.maxwaittime:
- global max_wait_time
- max_wait_time = float(args.maxwaittime)
-
- components_to_monitor = {}
- if args.componentmonitor:
- items = args.componentmonitor.split(",")
- for item in items:
- kv = item.split("=")
- key = kv[0]
- value = float(kv[1])
- components_to_monitor[key] = value
-
- cfg = yaml.load(args.config)
-
- if args.stressfs:
- if run_adb_cmd('install -r -g ' + args.stressfs) != 0:
- raise Exception('StressFS APK not installed');
-
- if args.iterate > 1 and args.bootchart:
- run_adb_shell_cmd_as_root('touch /data/bootchart/enabled')
-
- search_events_pattern = {key: re.compile(pattern)
- for key, pattern in cfg['events'].iteritems()}
- timing_events_pattern = {key: re.compile(pattern)
- for key, pattern in cfg['timings'].iteritems()}
- shutdown_events_pattern = {key: re.compile(pattern)
- for key, pattern in cfg['shutdown_events'].iteritems()}
-
- data_points = {}
- kernel_timing_points = collections.OrderedDict()
- logcat_timing_points = collections.OrderedDict()
- boottime_points = collections.OrderedDict()
- boot_chart_file_name_prefix = "bootchart-" + datetime.now().strftime("%Y-%m-%d-%H-%M-%S")
- systrace_file_name_prefix = "systrace-" + datetime.now().strftime("%Y-%m-%d-%H-%M-%S")
- shutdown_event_all = collections.OrderedDict()
- shutdown_timing_event_all = collections.OrderedDict()
- for it in range(0, args.iterate):
- if args.iterate > 1:
- print "Run: {0}".format(it)
- attempt = 1
- processing_data = None
- timings = None
- boottime_events = None
- while attempt <= MAX_RETRIES and processing_data is None:
- attempt += 1
- processing_data, kernel_timings, logcat_timings, boottime_events, shutdown_events,\
- shutdown_timing_events = iterate(\
- args, search_events_pattern, timing_events_pattern, shutdown_events_pattern, cfg,\
- error_time, components_to_monitor)
- if shutdown_events:
- for k, v in shutdown_events.iteritems():
- events = shutdown_event_all.get(k)
- if not events:
- events = []
- shutdown_event_all[k] = events
- events.append(v)
- if shutdown_timing_events:
- for k, v in shutdown_timing_events.iteritems():
- events = shutdown_timing_event_all.get(k)
- if not events:
- events = []
- shutdown_timing_event_all[k] = events
- events.append(v)
- if not processing_data or not boottime_events:
- # Processing error
- print "Failed to collect valid samples for run {0}".format(it)
- continue
- if args.bootchart:
- grab_bootchart(boot_chart_file_name_prefix + "_run_" + str(it))
-
- if args.systrace:
- grab_systrace(systrace_file_name_prefix + "_run_" + str(it))
- for k, v in processing_data.iteritems():
- if k not in data_points:
- data_points[k] = []
- data_points[k].append(v['value'])
-
- if kernel_timings is not None:
- for k, v in kernel_timings.iteritems():
- if k not in kernel_timing_points:
- kernel_timing_points[k] = []
- kernel_timing_points[k].append(v)
- if logcat_timings is not None:
- for k, v in logcat_timings.iteritems():
- if k not in logcat_timing_points:
- logcat_timing_points[k] = []
- logcat_timing_points[k].append(v)
-
- for k, v in boottime_events.iteritems():
- if not k in boottime_points:
- boottime_points[k] = []
- boottime_points[k].append(v)
-
- if args.stressfs:
- run_adb_cmd('uninstall com.android.car.test.stressfs')
- run_adb_shell_cmd('"rm -rf /storage/emulated/0/stressfs_data*"')
-
- if args.iterate > 1:
- print "-----------------"
- print "\nshutdown events after {0} runs".format(args.iterate)
- print '{0:30}: {1:<7} {2:<7} {3}'.format("Event", "Mean", "stddev", "#runs")
- for item in shutdown_event_all.items():
- num_runs = len(item[1])
- print '{0:30}: {1:<7.5} {2:<7.5} {3} {4}'.format(
- item[0], sum(item[1])/num_runs, stddev(item[1]),\
- "*time taken" if item[0].startswith("init.") else "",\
- num_runs if num_runs != args.iterate else "")
- print "\nshutdown timing events after {0} runs".format(args.iterate)
- print '{0:30}: {1:<7} {2:<7} {3}'.format("Event", "Mean", "stddev", "#runs")
- for item in shutdown_timing_event_all.items():
- num_runs = len(item[1])
- print '{0:30}: {1:<7.5} {2:<7.5} {3} {4}'.format(
- item[0], sum(item[1])/num_runs, stddev(item[1]),\
- "*time taken" if item[0].startswith("init.") else "",\
- num_runs if num_runs != args.iterate else "")
-
- print "-----------------"
- print "ro.boottime.* after {0} runs".format(args.iterate)
- print '{0:30}: {1:<7} {2:<7} {3}'.format("Event", "Mean", "stddev", "#runs")
- for item in boottime_points.items():
- num_runs = len(item[1])
- print '{0:30}: {1:<7.5} {2:<7.5} {3} {4}'.format(
- item[0], sum(item[1])/num_runs, stddev(item[1]),\
- "*time taken" if item[0].startswith("init.") else "",\
- num_runs if num_runs != args.iterate else "")
-
- if args.timings:
- dump_timings_points_summary("Kernel", kernel_timing_points, args)
- dump_timings_points_summary("Logcat", logcat_timing_points, args)
-
-
- print "-----------------"
- print "Avg values after {0} runs".format(args.iterate)
- print '{0:30}: {1:<7} {2:<7} {3}'.format("Event", "Mean", "stddev", "#runs")
-
- average_with_stddev = []
- for item in data_points.items():
- average_with_stddev.append((item[0], sum(item[1])/len(item[1]), stddev(item[1]),\
- len(item[1])))
- for item in sorted(average_with_stddev, key=lambda entry: entry[1]):
- print '{0:30}: {1:<7.5} {2:<7.5} {3}'.format(
- item[0], item[1], item[2], item[3] if item[3] != args.iterate else "")
-
- run_adb_shell_cmd_as_root('rm /data/bootchart/enabled')
-
-
-def dump_timings_points_summary(msg_header, timing_points, args):
- averaged_timing_points = []
- for item in timing_points.items():
- average = sum(item[1])/len(item[1])
- std_dev = stddev(item[1])
- averaged_timing_points.append((item[0], average, std_dev, len(item[1])))
-
- print "-----------------"
- print msg_header + " timing in order, Avg time values after {0} runs".format(args.iterate)
- print '{0:30}: {1:<7} {2:<7} {3}'.format("Event", "Mean", "stddev", "#runs")
- for item in averaged_timing_points:
- print '{0:30}: {1:<7.5} {2:<7.5} {3}'.format(
- item[0], item[1], item[2], item[3] if item[3] != args.iterate else "")
-
- print "-----------------"
- print msg_header + " timing top items, Avg time values after {0} runs".format(args.iterate)
- print '{0:30}: {1:<7} {2:<7} {3}'.format("Event", "Mean", "stddev", "#runs")
- for item in sorted(averaged_timing_points, key=lambda entry: entry[1], reverse=True):
- if item[1] < TIMING_THRESHOLD:
- break
- print '{0:30}: {1:<7.5} {2:<7.5} {3}'.format(
- item[0], item[1], item[2], item[3] if item[3] != args.iterate else "")
-
-def capture_bugreport(bugreport_hint, boot_complete_time):
- now = datetime.now()
- bugreport_file = ("bugreport-%s-" + bugreport_hint + "-%s.zip") \
- % (now.strftime("%Y-%m-%d-%H-%M-%S"), str(boot_complete_time))
- print "Boot up time too big, will capture bugreport %s" % (bugreport_file)
- os.system(ADB_CMD + " bugreport " + bugreport_file)
-
-def generate_timing_points(timing_events, timings):
- timing_points = collections.OrderedDict()
- for k, l in timing_events.iteritems():
- for v in l:
- name, time_v = extract_timing(v, timings)
- if name and time_v:
- if v.find("SystemServerTimingAsync") > 0:
- name = "(" + name + ")"
- new_name = name
- name_index = 0
- while timing_points.get(new_name): # if the name is already taken, append #digit
- name_index += 1
- new_name = name + "#" + str(name_index)
- name = new_name
- if k.endswith("_secs"):
- timing_points[name] = time_v * 1000.0
- else:
- timing_points[name] = time_v
- return timing_points
-
-def dump_timing_points(msg_header, timing_points):
- print msg_header + " event timing in time order, key: time"
- for item in timing_points.items():
- print '{0:30}: {1:<7.5}'.format(item[0], item[1])
- print "-----------------"
- print msg_header + " event timing top items"
- for item in sorted(timing_points.items(), key=operator.itemgetter(1), reverse = True):
- if item[1] < TIMING_THRESHOLD:
- break
- print '{0:30}: {1:<7.5}'.format(
- item[0], item[1])
- print "-----------------"
-
-def handle_reboot_log(capture_log_on_error, shutdown_events_pattern, components_to_monitor):
- shutdown_events, shutdown_timing_events = collect_logcat_for_shutdown(capture_log_on_error,\
- shutdown_events_pattern, components_to_monitor)
- print "\nshutdown events: time"
- for item in shutdown_events.items():
- print '{0:30}: {1:<7.5}'.format(item[0], item[1])
- print "\nshutdown timing events: time"
- for item in shutdown_timing_events.items():
- print '{0:30}: {1:<7.5}'.format(item[0], item[1])
- return shutdown_events, shutdown_timing_events
-
-def iterate(args, search_events_pattern, timings_pattern, shutdown_events_pattern, cfg, error_time,\
- components_to_monitor):
- shutdown_events = None
- shutdown_timing_events = None
- if args.reboot:
- # sleep to make sure that logcat reader is reading before adb is gone by reboot. ugly but make
- # impl simple.
- t = threading.Thread(target = lambda : (time.sleep(2), reboot(args.serial, args.stressfs != '',\
- args.permissive, args.adb_reboot)))
- t.start()
- shutdown_events, shutdown_timing_events = handle_reboot_log(True, shutdown_events_pattern,\
- components_to_monitor)
- t.join()
-
- dmesg_events, kernel_timing_events = collect_events(search_events_pattern, ADB_CMD +\
- ' shell su root dmesg -w', timings_pattern,\
- [ KERNEL_BOOT_COMPLETE ], True)
-
- logcat_stop_events = [ LOGCAT_BOOT_COMPLETE, KERNEL_BOOT_COMPLETE, LAUNCHER_START]
- if args.fs_check:
- logcat_stop_events.append("FsStat")
- logcat_events, logcat_timing_events = collect_events(
- search_events_pattern, ADB_CMD + ' logcat -b all -v epoch', timings_pattern,\
- logcat_stop_events, False)
- logcat_event_time = extract_time(
- logcat_events, TIME_LOGCAT, float);
- logcat_original_time = extract_time(
- logcat_events, TIME_LOGCAT, str);
- dmesg_event_time = extract_time(
- dmesg_events, TIME_DMESG, float);
- boottime_events = fetch_boottime_property()
- events = {}
- diff_time = 0
- max_time = 0
- events_to_correct = []
- replaced_from_dmesg = set()
-
- time_correction_delta = 0
- time_correction_time = 0
- if ('time_correction_key' in cfg
- and cfg['time_correction_key'] in logcat_events):
- match = search_events[cfg['time_correction_key']].search(
- logcat_events[cfg['time_correction_key']])
- if match and logcat_event_time[cfg['time_correction_key']]:
- time_correction_delta = float(match.group(1))
- time_correction_time = logcat_event_time[cfg['time_correction_key']]
-
- debug("time_correction_delta = {0}, time_correction_time = {1}".format(
- time_correction_delta, time_correction_time))
-
- for k, v in logcat_event_time.iteritems():
- if v <= time_correction_time:
- logcat_event_time[k] += time_correction_delta
- v = v + time_correction_delta
- debug("correcting event to event[{0}, {1}]".format(k, v))
-
- if not logcat_event_time.get(KERNEL_TIME_KEY):
- print "kernel time not captured in logcat, cannot get time diff"
- return None, None, None, None
- diffs = []
- diffs.append((logcat_event_time[KERNEL_TIME_KEY], logcat_event_time[KERNEL_TIME_KEY]))
- if logcat_event_time.get(BOOT_ANIM_END_TIME_KEY) and dmesg_event_time.get(BOOT_ANIM_END_TIME_KEY):
- diffs.append((logcat_event_time[BOOT_ANIM_END_TIME_KEY],\
- logcat_event_time[BOOT_ANIM_END_TIME_KEY] -\
- dmesg_event_time[BOOT_ANIM_END_TIME_KEY]))
- if not dmesg_event_time.get(KERNEL_BOOT_COMPLETE):
- print "BootAnimEnd time or BootComplete-kernel not captured in both log" +\
- ", cannot get time diff"
- return None, None, None, None
- diffs.append((logcat_event_time[KERNEL_BOOT_COMPLETE],\
- logcat_event_time[KERNEL_BOOT_COMPLETE] - dmesg_event_time[KERNEL_BOOT_COMPLETE]))
-
- for k, v in logcat_event_time.iteritems():
- debug("event[{0}, {1}]".format(k, v))
- events[k] = v
- if k in dmesg_event_time:
- debug("{0} is in dmesg".format(k))
- events[k] = dmesg_event_time[k]
- replaced_from_dmesg.add(k)
- else:
- events_to_correct.append(k)
-
- diff_prev = diffs[0]
- for k in events_to_correct:
- diff = diffs[0]
- while diff[0] < events[k] and len(diffs) > 1:
- diffs.pop(0)
- diff_prev = diff
- diff = diffs[0]
- events[k] = events[k] - diff[1]
- if events[k] < 0.0:
- if events[k] < -0.1: # maybe previous one is better fit
- events[k] = events[k] + diff[1] - diff_prev[1]
- else:
- events[k] = 0.0
-
- data_points = collections.OrderedDict()
-
- print "-----------------"
- print "ro.boottime.*: time"
- for item in boottime_events.items():
- print '{0:30}: {1:<7.5} {2}'.format(item[0], item[1],\
- "*time taken" if item[0].startswith("init.") else "")
- print "-----------------"
-
- if args.timings:
- kernel_timing_points = generate_timing_points(kernel_timing_events, timings_pattern)
- logcat_timing_points = generate_timing_points(logcat_timing_events, timings_pattern)
- dump_timing_points("Kernel", kernel_timing_points)
- dump_timing_points("Logcat", logcat_timing_points)
-
- for item in sorted(events.items(), key=operator.itemgetter(1)):
- data_points[item[0]] = {
- 'value': item[1],
- 'from_dmesg': item[0] in replaced_from_dmesg,
- 'logcat_value': logcat_original_time[item[0]]
- }
- # add times with bootloader
- if events.get("BootComplete") and boottime_events.get("bootloader"):
- total = events["BootComplete"] + boottime_events["bootloader"]
- data_points["*BootComplete+Bootloader"] = {
- 'value': total,
- 'from_dmesg': False,
- 'logcat_value': 0.0
- }
- if events.get("LauncherStart") and boottime_events.get("bootloader"):
- total = events["LauncherStart"] + boottime_events["bootloader"]
- data_points["*LauncherStart+Bootloader"] = {
- 'value': total,
- 'from_dmesg': False,
- 'logcat_value': 0.0
- }
- for k, v in data_points.iteritems():
- print '{0:30}: {1:<7.5} {2:1} ({3})'.format(
- k, v['value'], '*' if v['from_dmesg'] else '', v['logcat_value'])
-
- print '\n* - event time was obtained from dmesg log\n'
-
- if events[LOGCAT_BOOT_COMPLETE] > error_time and not args.ignore:
- capture_bugreport("bootuptoolong", events[LOGCAT_BOOT_COMPLETE])
-
- for k, v in components_to_monitor.iteritems():
- logcat_value_measured = logcat_timing_points.get(k)
- kernel_value_measured = kernel_timing_points.get(k)
- data_from_data_points = data_points.get(k)
- if logcat_value_measured and logcat_value_measured > v:
- capture_bugreport(k + "-" + str(logcat_value_measured), events[LOGCAT_BOOT_COMPLETE])
- break
- elif kernel_value_measured and kernel_value_measured > v:
- capture_bugreport(k + "-" + str(kernel_value_measured), events[LOGCAT_BOOT_COMPLETE])
- break
- elif data_from_data_points and data_from_data_points['value'] * 1000.0 > v:
- capture_bugreport(k + "-" + str(data_from_data_points['value']), events[LOGCAT_BOOT_COMPLETE])
- break
-
- if args.fs_check:
- fs_stat = None
- if logcat_events.get("FsStat"):
- fs_stat_pattern = cfg["events"]["FsStat"]
- m = re.search(fs_stat_pattern, logcat_events.get("FsStat"))
- if m:
- fs_stat = m.group(1)
- print 'fs_stat:', fs_stat
-
- if fs_stat:
- fs_stat_val = int(fs_stat, 0)
- if (fs_stat_val & ~0x17) != 0:
- capture_bugreport("fs_stat_" + fs_stat, events[LOGCAT_BOOT_COMPLETE])
-
- return data_points, kernel_timing_points, logcat_timing_points, boottime_events, shutdown_events,\
- shutdown_timing_events
-
-def debug(string):
- if DEBUG:
- print string
-
-def extract_timing(s, patterns):
- for k, p in patterns.iteritems():
- m = p.search(s)
- if m:
- g_dict = m.groupdict()
- return g_dict['name'], float(g_dict['time'])
- return None, None
-
-def init_arguments():
- parser = argparse.ArgumentParser(description='Measures boot time.')
- parser.add_argument('-r', '--reboot', dest='reboot',
- action='store_true',
- help='reboot device for measurement', )
- parser.add_argument('-c', '--config', dest='config',
- default='config.yaml', type=argparse.FileType('r'),
- help='config file for the tool', )
- parser.add_argument('-s', '--stressfs', dest='stressfs',
- default='', type=str,
- help='APK file for the stressfs tool used to write to the data partition ' +\
- 'during shutdown')
- parser.add_argument('-n', '--iterate', dest='iterate', type=int, default=1,
- help='number of time to repeat the measurement', )
- parser.add_argument('-g', '--ignore', dest='ignore', action='store_true',
- help='ignore too big values error', )
- parser.add_argument('-t', '--timings', dest='timings', action='store_true',
- help='print individual component times', default=True, )
- parser.add_argument('-p', '--serial', dest='serial', action='store',
- help='android device serial number')
- parser.add_argument('-e', '--errortime', dest='errortime', action='store',
- help='handle bootup time bigger than this as error')
- parser.add_argument('-w', '--maxwaittime', dest='maxwaittime', action='store',
- help='wait for up to this time to collect logs. Retry after this time.' +\
- ' Default is 200 sec.')
- parser.add_argument('-f', '--fs_check', dest='fs_check',
- action='store_true',
- help='check fs_stat after reboot', )
- parser.add_argument('-a', '--adb_reboot', dest='adb_reboot',
- action='store_true',
- help='reboot with adb reboot', )
- parser.add_argument('-v', '--permissive', dest='permissive',
- action='store_true',
- help='set selinux into permissive before reboot', )
- parser.add_argument('-m', '--componentmonitor', dest='componentmonitor', action='store',
- help='capture bugreport if specified timing component is taking more than ' +\
- 'certain time. Unlike errortime, the result will not be rejected in' +\
- 'averaging. Format is key1=time1,key2=time2...')
- parser.add_argument('-b', '--bootchart', dest='bootchart',
- action='store_true',
- help='collect bootchart from the device.', )
- parser.add_argument('-y', '--systrace', dest='systrace',
- action='store_true',
- help='collect systrace from the device. kernel trace should be already enabled', )
- return parser.parse_args()
-
-def handle_zygote_event(zygote_pids, events, event, line):
- words = line.split()
- if len(words) > 1:
- pid = int(words[1])
- if len(zygote_pids) == 2:
- if pid == zygote_pids[1]: # secondary
- event = event + "-secondary"
- elif len(zygote_pids) == 1:
- if zygote_pids[0] != pid: # new pid, need to decide if old ones were secondary
- primary_pid = min(pid, zygote_pids[0])
- secondary_pid = max(pid, zygote_pids[0])
- zygote_pids.pop()
- zygote_pids.append(primary_pid)
- zygote_pids.append(secondary_pid)
- if pid == primary_pid: # old one was secondary:
- move_to_secondary = []
- for k, l in events.iteritems():
- if k.startswith("zygote"):
- move_to_secondary.append((k, l))
- for item in move_to_secondary:
- del events[item[0]]
- if item[0].endswith("-secondary"):
- print "Secondary already exists for event %s while found new pid %d, primary %d "\
- % (item[0], secondary_pid, primary_pid)
- else:
- events[item[0] + "-secondary"] = item[1]
- else:
- event = event + "-secondary"
- else:
- zygote_pids.append(pid)
- events[event] = line
-
-def update_name_if_already_exist(events, name):
- existing_event = events.get(name)
- i = 0
- new_name = name
- while existing_event:
- i += 1
- new_name = name + "_" + str(i)
- existing_event = events.get(new_name)
- return new_name
-
-def collect_logcat_for_shutdown(capture_log_on_error, shutdown_events_pattern,\
- log_capture_conditions):
- events = collections.OrderedDict()
- # shutdown does not have timing_events but calculated from checking Xyz - XyzDone / XyzTimeout
- timing_events = collections.OrderedDict()
- process = subprocess.Popen(ADB_CMD + ' logcat -b all -v epoch', shell=True,
- stdout=subprocess.PIPE);
- lines = []
- capture_log = False
- shutdown_start_time = 0
- while (True):
- line = process.stdout.readline().lstrip().rstrip()
- if not line:
- break
- lines.append(line)
- event = get_boot_event(line, shutdown_events_pattern);
- if not event:
- continue
- time = extract_a_time(line, TIME_LOGCAT, float)
- if not time:
- print "cannot get time from: " + line
- continue
- if shutdown_start_time == 0:
- shutdown_start_time = time
- time = time - shutdown_start_time
- events[event] = time
- time_limit1 = log_capture_conditions.get(event)
- if time_limit1 and time_limit1 <= time:
- capture_log = True
- pair_event = None
- if event.endswith('Done'):
- pair_event = event[:-4]
- elif event.endswith('Timeout'):
- pair_event = event[:-7]
- if capture_log_on_error:
- capture_log = True
- if not pair_event:
- continue
- start_time = events.get(pair_event)
- if not start_time:
- print "No start event for " + event
- continue
- time_spent = time - start_time
- timing_event_name = pair_event + "Duration"
- timing_events[timing_event_name] = time_spent
- time_limit2 = log_capture_conditions.get(timing_event_name)
- if time_limit2 and time_limit2 <= time_spent:
- capture_log = True
-
- if capture_log:
- now = datetime.now()
- log_file = ("shutdownlog-error-%s.txt") % (now.strftime("%Y-%m-%d-%H-%M-%S"))
- print "Shutdown error, capture log to %s" % (log_file)
- with open(log_file, 'w') as f:
- f.write('\n'.join(lines))
- return events, timing_events
-
-
-def collect_events(search_events, command, timings, stop_events, disable_timing_after_zygote):
- events = collections.OrderedDict()
- timing_events = {}
- process = subprocess.Popen(command, shell=True,
- stdout=subprocess.PIPE);
- data_available = stop_events is None
- zygote_pids = []
- start_time = time.time()
- zygote_found = False
-
- line = None
- read_poll = select.poll()
- read_poll.register(process.stdout, select.POLLIN)
- while True:
- time_left = start_time + max_wait_time - time.time()
- if time_left <= 0:
- print "timeout waiting for event, continue", time_left
- break
- read_r = read_poll.poll(time_left * 1000.0)
- if len(read_r) > 0 and read_r[0][1] == select.POLLIN:
- line = process.stdout.readline()
- else:
- print "poll timeout waiting for event, continue", time_left
- break
- if not data_available:
- print "Collecting data samples from '%s'. Please wait...\n" % command
- data_available = True
- event = get_boot_event(line, search_events);
- if event:
- debug("event[{0}] captured: {1}".format(event, line))
- if event == "starting_zygote":
- events[event] = line
- zygote_found = True
- elif event.startswith("zygote"):
- handle_zygote_event(zygote_pids, events, event, line)
- else:
- new_event = update_name_if_already_exist(events, event)
- events[new_event] = line
- if event in stop_events:
- stop_events.remove(event)
- print "remaining stop_events:", stop_events
- if len(stop_events) == 0:
- break;
-
- timing_event = get_boot_event(line, timings);
- if timing_event and (not disable_timing_after_zygote or not zygote_found):
- if timing_event not in timing_events:
- timing_events[timing_event] = []
- timing_events[timing_event].append(line)
- debug("timing_event[{0}] captured: {1}".format(timing_event, line))
-
- process.terminate()
- return events, timing_events
-
-def fetch_boottime_property():
- cmd = ADB_CMD + ' shell su root getprop'
- events = {}
- process = subprocess.Popen(cmd, shell=True,
- stdout=subprocess.PIPE);
- out = process.stdout
- pattern = re.compile(BOOT_PROP)
- pattern_bootloader = re.compile(BOOTLOADER_TIME_PROP)
- bootloader_time = 0.0
- for line in out:
- match = pattern.match(line)
- if match:
- if match.group(1).startswith("init."):
- events[match.group(1)] = float(match.group(2)) / 1000.0 #ms to s
- else:
- events[match.group(1)] = float(match.group(2)) / 1000000000.0 #ns to s
- match = pattern_bootloader.match(line)
- if match:
- items = match.group(1).split(",")
- for item in items:
- entry_pair = item.split(":")
- entry_name = entry_pair[0]
- time_spent = float(entry_pair[1]) / 1000 #ms to s
- if entry_name != "SW":
- bootloader_time = bootloader_time + time_spent
- ordered_event = collections.OrderedDict()
- if bootloader_time != 0.0:
- ordered_event["bootloader"] = bootloader_time;
- for item in sorted(events.items(), key=operator.itemgetter(1)):
- ordered_event[item[0]] = item[1]
- return ordered_event
-
-
-def get_boot_event(line, events):
- for event_key, event_pattern in events.iteritems():
- if event_pattern.search(line):
- return event_key
- return None
-
-def extract_a_time(line, pattern, date_transform_function):
- found = re.findall(pattern, line)
- if len(found) > 0:
- return date_transform_function(found[0])
- else:
- return None
-
-def extract_time(events, pattern, date_transform_function):
- result = collections.OrderedDict()
- for event, data in events.iteritems():
- time = extract_a_time(data, pattern, date_transform_function)
- if time:
- result[event] = time
- else:
- print "Failed to find time for event: ", event, data
- return result
-
-
-def do_reboot(serial, use_adb_reboot):
- original_devices = subprocess.check_output("adb devices", shell=True)
- if use_adb_reboot:
- print 'Rebooting the device using adb reboot'
- run_adb_cmd('reboot')
- else:
- print 'Rebooting the device using svc power reboot'
- run_adb_shell_cmd_as_root('svc power reboot')
- # Wait for the device to go away
- retry = 0
- while retry < 20:
- current_devices = subprocess.check_output("adb devices", shell=True)
- if original_devices != current_devices:
- if not serial or (serial and current_devices.find(serial) < 0):
- return True
- time.sleep(1)
- retry += 1
- return False
-
-def reboot(serial, use_stressfs, permissive, use_adb_reboot):
- if use_stressfs:
- print 'Starting write to data partition'
- run_adb_shell_cmd('am start' +\
- ' -n com.android.car.test.stressfs/.WritingActivity' +\
- ' -a com.android.car.test.stressfs.START')
- # Give this app some time to start.
- time.sleep(1)
- if permissive:
- run_adb_shell_cmd_as_root('setenforce 0')
-
- retry = 0
- while retry < 5:
- if do_reboot(serial, use_adb_reboot):
- break
- retry += 1
-
- print 'Waiting the device'
- run_adb_cmd('wait-for-device')
-
-def run_adb_cmd(cmd):
- return subprocess.call(ADB_CMD + ' ' + cmd, shell=True)
-
-def run_adb_shell_cmd(cmd):
- return subprocess.call(ADB_CMD + ' shell ' + cmd, shell=True)
-
-def run_adb_shell_cmd_as_root(cmd):
- return subprocess.call(ADB_CMD + ' shell su root ' + cmd, shell=True)
-
-def logcat_time_func(offset_year):
- def f(date_str):
- ndate = datetime.datetime.strptime(str(offset_year) + '-' +
- date_str, '%Y-%m-%d %H:%M:%S.%f')
- return datetime_to_unix_time(ndate)
- return f
-
-def datetime_to_unix_time(ndate):
- return time.mktime(ndate.timetuple()) + ndate.microsecond/1000000.0
-
-def stddev(data):
- items_count = len(data)
- avg = sum(data) / items_count
- sq_diffs_sum = sum([(v - avg) ** 2 for v in data])
- variance = sq_diffs_sum / items_count
- return math.sqrt(variance)
-
-def grab_bootchart(boot_chart_file_name):
- subprocess.call("./system/core/init/grab-bootchart.sh", shell=True)
- print "Saving boot chart as " + boot_chart_file_name + ".tgz"
- subprocess.call('cp /tmp/android-bootchart/bootchart.tgz ./' + boot_chart_file_name + '.tgz',\
- shell=True)
- subprocess.call('cp ./bootchart.png ./' + boot_chart_file_name + '.png', shell=True)
-
-def grab_systrace(systrace_file_name):
- trace_file = systrace_file_name + "_trace.txt"
- with open(trace_file, 'w') as f:
- f.write("TRACE:\n")
- run_adb_shell_cmd_as_root("cat /d/tracing/trace >> " + trace_file)
- html_file = systrace_file_name + ".html"
- subprocess.call("./external/chromium-trace/systrace.py --from-file=" + trace_file + " -o " +\
- html_file, shell=True)
-
-if __name__ == '__main__':
- main()
diff --git a/tools/bootanalyze/bugreport_anayze.py b/tools/bootanalyze/bugreport_anayze.py
deleted file mode 100644
index 2575ebf..0000000
--- a/tools/bootanalyze/bugreport_anayze.py
+++ /dev/null
@@ -1,386 +0,0 @@
-#!/usr/bin/python
-
-# 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.
-#
-"""Tool to analyze boot-up time from bugreport."""
-
-import argparse
-import collections
-import datetime
-import math
-import operator
-import os
-import re
-import select
-import subprocess
-import sys
-import time
-import threading
-import yaml
-
-from datetime import datetime, date
-
-DBG = True
-
-LOG_START_PATTERN = r"""\-\-\-\-\-\-\s(.*)\s\-\-\-\-\-\-"""
-LOG_END_PATTERN = r"""\-\-\-\-\-\-\s\S.*\s\-\-\-\-\-\-"""
-
-KERNEL_LOG_TITLE = "KERNEL LOG"
-SYSYEM_LOG_TITLE = "SYSTEM LOG"
-LAST_KMSG_TITLE = "LAST KMSG"
-LAST_LOGCAT_TITLE = "LAST LOGCAT"
-
-SYSTEM_PROPS_TITLE = "SYSTEM PROPERTIES"
-
-TIME_DMESG = "\[\s*(\d+\.\d+)\]"
-TIME_LOGCAT = "(\d+)\-(\d+)\s(\d+):(\d+):(\d+\.\d+)"
-
-NATIVE_CRASH_START_PATTERN = "I\sDEBUG\s+:\s\*\*\*\s\*\*\*"
-NATIVE_CRASH_PATTERN = "I\sDEBUG\s+:"
-JAVA_CRASH_START_PATTERN = "E\sAndroidRuntime:\sFATAL\sEXCEPTION"
-JAVA_CRASH_PATTERN = "E\sAndroidRuntime:\s"
-
-EPOCH = datetime.utcfromtimestamp(0)
-
-def init_arguments():
- parser = argparse.ArgumentParser(description='Measures boot time from bugreport.')
- parser.add_argument('-c', '--config', dest='config',
- default='config.yaml', type=argparse.FileType('r'),
- help='config file for the tool')
- parser.add_argument('bugreport_file', nargs=1, help='bugreport txt file',
- type=argparse.FileType('r'))
- parser.add_argument('-n', '--iterate', dest='iterate', type=int, default=1,
- help='number of time to repeat the measurement', )
- return parser.parse_args()
-
-# Event per each reboot, for distinghishing current boot from last boot
-class Events:
- def __init__(self):
- self.events = collections.OrderedDict() #K: keyword, V:time in ms
- self.timings = collections.OrderedDict()
- self.shutdown_events = collections.OrderedDict()
- self.java_crash = collections.OrderedDict() #K:time, V:list of crash infos, each entry per line
- self.native_crash = collections.OrderedDict()
-
- def reset_events_time(self, delta):
- new_events = collections.OrderedDict()
- for entry in self.events.iteritems():
- new_events[entry[0]] = entry[1] - delta
- self.events = new_events
- if len(self.native_crash) > 0:
- new_crash = collections.OrderedDict()
- for entry in self.native_crash.iteritems():
- new_crash[entry[0] - delta] = entry[1]
- self.native_crash = new_crash
- if len(self.java_crash) > 0:
- new_crash = collections.OrderedDict()
- for entry in self.java_crash.iteritems():
- new_crash[entry[0] - delta] = entry[1]
- self.java_crash = new_crash
-
- def reset_shutdown_events_time(self):
- if len(self.shutdown_events) == 0:
- return
- time_offset = 0
- new_events = collections.OrderedDict()
- for entry in self.shutdown_events.iteritems():
- if time_offset == 0:
- time_offset = entry[1]
- new_events[entry[0]] = entry[1] - time_offset
- self.shutdown_events = new_events
-
- def dump_dict(self, d):
- for entry in d.iteritems():
- print ' {0:30}: {1}'.format(entry[0], entry[1])
-
- def dump_crash(self, time, stack):
- print " Crash time:", time, " stack:"
- print ' '.join(stack)
-
- def dump(self):
- if len(self.events) > 0:
- print "\n***Events:"
- self.dump_dict(self.events)
- if len(self.timings) > 0:
- print "\n***Timings top 20"
- timings_sorted = sorted(self.timings.items(), key = lambda item: item[1], reverse=True)
- nums_to_dump = min(20, len(timings_sorted))
- for i in range(nums_to_dump):
- print ' {0:30}: {1}'.format(timings_sorted[i][0], timings_sorted[i][1])
- print "\n***Timings:"
- self.dump_dict(self.timings)
- if len(self.shutdown_events) > 0:
- print "\n***Shutdown Events (time relative to the begining of shutdown) :"
- self.dump_dict(self.shutdown_events)
- if len(self.native_crash) > 0:
- print "\n***Native crash founds:", len(self.native_crash)
- for entry in self.native_crash.iteritems():
- self.dump_crash(entry[0], entry[1])
- if len(self.java_crash) > 0:
- print "\n***Java crash founds:", len(self.java_crash)
- for entry in self.java_crash.iteritems():
- self.dump_crash(entry[0], entry[1])
-
-class Parser:
- def __init__(self, config_file, bugreport_file):
- self.re_log_start = re.compile(LOG_START_PATTERN)
- self.re_log_end = re.compile(LOG_END_PATTERN)
- self.f = bugreport_file
- cfg = yaml.load(config_file)
- self.event_patterns = {key: re.compile(pattern)
- for key, pattern in cfg['events'].iteritems()}
- self.timing_patterns = {key: re.compile(pattern)
- for key, pattern in cfg['timings'].iteritems()}
- self.shutdown_event_patterns = {key: re.compile(pattern)
- for key, pattern in cfg['shutdown_events'].iteritems()}
- self.current_boot_kernel = Events()
- self.current_boot_logcat = Events()
- self.last_boot_kernel = Events()
- self.last_boot_logcat = Events()
- self.boottime_props = collections.OrderedDict() # K:prop, V:boot time, added in boot time order
- self.bootloader_time = 0
- self.re_time_dmesg = re.compile(TIME_DMESG)
- self.re_time_logcat = re.compile(TIME_LOGCAT)
- self.re_native_crash_start = re.compile(NATIVE_CRASH_START_PATTERN)
- self.re_native_crash = re.compile(NATIVE_CRASH_PATTERN)
- self.re_java_crash_start = re.compile(JAVA_CRASH_START_PATTERN)
- self.re_java_crash = re.compile(JAVA_CRASH_PATTERN)
-
- def match_an_event(self, event_patterns, line):
- for event_key, event_pattern in event_patterns.iteritems():
- m = event_pattern.search(line)
- if m:
- return event_key, m
- return None, None
-
- def get_event_time(self, line, is_kernel):
- if is_kernel:
- m = self.re_time_dmesg.search(line)
- if not m:
- print "Cannot get time from log:", line
- return -1
- return int(float(m.group(1)) * 1000)
- else:
- m = self.re_time_logcat.search(line)
- if not m:
- print "Cannot get time from log:", line
- return -1
- mm = int(m.group(1))
- dd = int(m.group(2))
- hh = int(m.group(3))
- min = int(m.group(4))
- usecs = int(float(m.group(5)) * 1000000)
- secs = usecs / 1000000
- usecs = usecs - 1000000 * secs
- dt = datetime(2017, mm, dd, hh, min, secs, usecs)
- return int((dt - EPOCH).total_seconds() * 1000)
-
- def queue_crash(self, event, crash_time, crash_stacks, is_native_crash):
- stacks = list(crash_stacks)
- if is_native_crash:
- event.native_crash[crash_time] = stacks
- else:
- event.java_crash[crash_time] = stacks
-
- def check_crash(self, event, orig_line):
- line = orig_line
- crash_time = 0
- crash_stacks = []
- is_native_crash = True
- while len(line) > 0:
- m = self.re_native_crash_start.search(line)
- if m:
- if len(crash_stacks) > 0:
- self.queue_crash(event, crash_time, crash_stacks, is_native_crash)
- crash_stacks = []
- is_native_crash = True
- crash_stacks.append(line)
- crash_time = self.get_event_time(line, False)
- line = self.f.readline()
- continue
- m = self.re_native_crash.search(line)
- if m:
- crash_stacks.append(line)
- line = self.f.readline()
- continue
- m = self.re_java_crash_start.search(line)
- if m:
- if len(crash_stacks) > 0:
- self.queue_crash(event, crash_time, crash_stacks, is_native_crash)
- crash_stacks = []
- is_native_crash = False
- crash_stacks.append(line)
- crash_time = self.get_event_time(line, False)
- line = self.f.readline()
- continue
- m = self.re_java_crash.search(line)
- if m:
- crash_stacks.append(line)
- line = self.f.readline()
- continue
- # reaching here means not crash, so return new line
- if line != orig_line:
- return line
- else:
- return self.f.readline()
-
-
-
- def handle_events(self, event, is_kernel):
- line = self.f.readline()
- while len(line) > 0 and not self.re_log_end.match(line):
- key, m = self.match_an_event(self.event_patterns, line)
- if m:
- event.events[key] = self.get_event_time(line, is_kernel)
- line = self.f.readline()
- continue
- key, m = self.match_an_event(self.timing_patterns, line)
- if m:
- name = m.group('name')
- time = float(m.group('time'))
- if key.endswith('_secs'):
- time = time * 1000
- event.timings[name] = int(time)
- line = self.f.readline()
- continue
- key, m = self.match_an_event(self.shutdown_event_patterns, line)
- if m:
- event.shutdown_events[key] = self.get_event_time(line, is_kernel)
- line = self.f.readline()
- continue
- if not is_kernel: # collect crash
- line = self.check_crash(event, line)
- continue
- line = self.f.readline()
-
- def handle_kernel_log(self):
- if DBG:
- print "start " + KERNEL_LOG_TITLE
- self.handle_events(self.current_boot_kernel, True)
-
- def handle_system_log(self):
- if DBG:
- print "start " + SYSYEM_LOG_TITLE
- self.handle_events(self.current_boot_logcat, False)
-
- def handle_last_kernel_log(self):
- if DBG:
- print "start " + LAST_KMSG_TITLE
- self.handle_events(self.last_boot_kernel, True)
-
- def handle_last_system_log(self):
- if DBG:
- print "start " + LAST_LOGCAT_TITLE
- self.handle_events(self.last_boot_logcat, False)
-
- def handle_system_props(self):
- if DBG:
- print "start " + SYSTEM_PROPS_TITLE
- re_prop = re.compile(r"""\[(.+)\].*\[(.*)\]""")
- RO_BOOTTIME_PROP = "ro.boottime."
- boottime_props = {} # K: prop name, V: boot time in ms
- line = self.f.readline()
- while len(line) > 0 and not self.re_log_end.match(line):
- m = re_prop.match(line)
- if not m:
- print "Cannot parse prop:", line
- line = self.f.readline()
- continue
- if m.group(1).startswith(RO_BOOTTIME_PROP):
- name = m.group(1)[len(RO_BOOTTIME_PROP):]
- time = int(m.group(2)) / 1000000 # ns to ms
- boottime_props[name] = time
- elif m.group(1) == "ro.boot.boottime":
- print "Found bootloader boottime ", line
- entries = m.group(2).split(",")
- for entry in entries:
- values = entry.split(":")
- if values[0] != "SW":
- self.bootloader_time += int(values[1])
- line = self.f.readline()
- self.boottime_props = collections.OrderedDict(sorted(
- boottime_props.items(), key = lambda item: item[1]))
-
- def parse(self):
- while (True):
- l = self.f.readline()
- if len(l) == 0: # EOF
- return
- m = self.re_log_start.match(l)
- if not m:
- continue
- #print m.group(1)
- if m.group(1).startswith(KERNEL_LOG_TITLE):
- self.handle_kernel_log()
- elif m.group(1).startswith(SYSYEM_LOG_TITLE):
- self.handle_system_log()
- elif m.group(1).startswith(SYSTEM_PROPS_TITLE):
- self.handle_system_props()
- elif m.group(1).startswith(LAST_KMSG_TITLE):
- self.handle_last_kernel_log()
- elif m.group(1).startswith(LAST_LOGCAT_TITLE):
- self.handle_last_system_log()
-
- def dump_props(self):
- if self.bootloader_time != 0:
- print "*bootloader time:", self.bootloader_time
- if self.boottime_props:
- print "*ro.boottime.*:"
- for name, t in self.boottime_props.iteritems():
- print ' {0:30}: {1}'.format(name, t)
-
- def reset_event_times(self, kernel_event, logcat_event):
- has_boot_complete = True
- kernel_bootcomplete_time = kernel_event.events.get("BootComplete_kernel")
- if not kernel_bootcomplete_time:
- has_boot_complete = False
- logcat_bootcomplete_time = logcat_event.events.get("BootComplete")
- if not logcat_bootcomplete_time:
- has_boot_complete = False
- time_delta = 0
- if has_boot_complete:
- time_delta = logcat_bootcomplete_time - kernel_bootcomplete_time
- else:
- time_delta = logcat_event.events.values()[0] if len(logcat_event.events) > 0 else 0
- logcat_event.reset_events_time(time_delta)
- logcat_event.reset_shutdown_events_time()
- kernel_event.reset_shutdown_events_time()
- return has_boot_complete
-
- def dump(self):
- self.dump_props()
- boot_complete_found = self.reset_event_times(self.current_boot_kernel, self.current_boot_logcat)
- print "* Kernel dmesg:"
- self.current_boot_kernel.dump()
- print "\n\n* Logcat " + ("(time matched with kernel dmesg):" if boot_complete_found\
- else "(time set relative to the first event):")
- self.current_boot_logcat.dump()
- print "\n\n\n==== Data from last boot ==="
- boot_complete_found = self.reset_event_times(self.last_boot_kernel, self.last_boot_logcat)
- print "\n\n* Last Kernel dmesg:"
- self.last_boot_kernel.dump()
- print "\n\n* Last Logcat " + ("(time matched with kernel dmesg):" if boot_complete_found \
- else "(time set relative to the first event):")
- self.last_boot_logcat.dump()
-
-def main():
- args = init_arguments()
-
- parser = Parser(args.config, args.bugreport_file[0])
- parser.parse()
- parser.dump()
-
-if __name__ == '__main__':
- main()
diff --git a/tools/bootanalyze/config.yaml b/tools/bootanalyze/config.yaml
deleted file mode 100644
index 37f2891..0000000
--- a/tools/bootanalyze/config.yaml
+++ /dev/null
@@ -1,78 +0,0 @@
-#YAML
-time_correction_key: correction
-timings:
- system_server: SystemServerTiming(Async)?\s*:\s*(?P<name>\S+) took to complete:\s(?P<time>[0-9]+)ms
- fs_shutdown: (?P<name>boot_fs_shutdown),(?P<time>[0-9]+),([0-9]+)
- ueventd_secs: ueventd:\s(?P<name>\S.+)\stook\s(?P<time>[.0-9]+)\sseconds
- init_command_ms: init:\sCommand\s(?P<name>\S.+)\sreturned.*took\s(?P<time>[.0-9]+)ms
- init_service_exec_secs: init:\sService\s.*exec\s\S+\s\((?P<name>\S.+)\).*pid.*\swaiting\stook\s(?P<time>[.0-9]+)\sseconds
- zygote64_timing: (?P<name>Zygote64Timing\:\s\S+)\stook\sto\scomplete\:\s(?P<time>[0-9]+)ms
- zygote32_timing: (?P<name>Zygote32Timing\:\s\S+)\stook\sto\scomplete\:\s(?P<time>[0-9]+)ms
-events:
- kernel: Linux version
- android_init_1st_stage: init first stage started
- android_init_2st_stage: init second stage started
- late_init: processing action \(late-init\)
- fs: processing action \(fs\)
- post-fs: processing action \(post-fs\)
- late-fs: processing action \(late-fs\)
- post-fs-data: processing action \(post-fs-data\)
- nonencrypted: processing action \(nonencrypted\)
- vold: starting service 'vold'
- starting_zygote: starting service 'zygote'
- starting_zygote_secondary: starting service 'zygote_secondary'
- load_persist_props_action: processing action \(load_persist_props_action\)
- early-boot: processing action \(early-boot\)
- boot: processing action \(boot\)
- ueventd: Starting service 'ueventd'
- system_mounted: target=/system
- data_mounted: target=/data
- correction: Updating system time diff=([0-9]+\.?[0-9]*), cuttime=([0-9]+)
- servicemanager_start_by_init: starting service 'servicemanager'
- zygoteInit: START com.android.internal.os.ZygoteInit
- ZygoteMainSystemServer: app_process\smain\swith\sargv.*\-\-start\-system\-server
- ZygoteMainOthers: app_process\smain\swith\sargv
- zygote_preload_start: Zygote\s*:\s*begin preload
- zygote_preload_classes_start: Zygote\s*:\s*Preloading classes...
- zygote_preload_res_start: Zygote\s*:\s*Preloading resources...
- zygote_preload_end: Zygote\s*:\s*end preload
- zygote_create_system_server: Zygote\s*:\s*System server process [0-9]* has been created
- SystemServer_start: Entered the Android system server!
- system_server_ready: Enabled StrictMode for system server main
- PackageManagerInit_start: SystemServer\s*:\s*StartPackageManagerService
- BluetoothService_start: Starting com.android.server.BluetoothService
- SystemUi_start: for service com.android.systemui/.
- CarLauncherReady: Em.Overview:\s*onResume
- CarService_start: for service com.android.car/.CarService
- BootAnimStart: starting service 'bootanim'
- BootAnimSfWait: BootAnimation:\sWaiting\sfor\sSurfaceFlinger\stook\s
- BootAnimShowStart: BootAnimation:\sBootAnimationShownTiming\sstart\stime
- BootAnimStopRequest: TELLING SURFACE FLINGER WE ARE BOOTED
- BootAnimEnd: Service 'bootanim'
- KeyguardStart: KeyguardServiceDelegate.*\*\*\* Keyguard started
- KeyguardConnected: KeyguardServiceDelegate.*\*\*\* Keyguard connected
- KeyguardShown: KeyguardServiceDelegate.*\*\*\*\* SHOWN CALLED \*\*\*\*
- BootComplete: Starting phase 1000
- BootComplete_kernel: processing action \(sys\.boot_completed=1\)
- LauncherStart: START.*HOME.*(NexusLauncherActivity|GEL|LensPickerTrampolineActivity|SetupWizardActivity)
- FsStat: fs_stat, partition:userdata stat:(0x\S+)
-shutdown_events:
- ShutdownStart: ShutdownThread:\sNotifying thread to start shutdown
- ShutdownBroadcast: ShutdownThread:\sSending shutdown broadcast
- ShutdownActivityManagerService: ShutdownThread:\sShutting down activity manager
- ShutdownPackageManagerService: ShutdownThread:\sShutting down package manager
- ShutdownNfc: ShutdownThread:\sTurning off NFC
- ShutdownBt: ShutdownThread:\sDisabling Bluetooth
- ShutdownRadio: ShutdownThread:\sTurning off cellular radios
- ShutdownRadiosWait: ShutdownThread:\sWaiting for NFC, Bluetooth and Radio
- ShutdownBtDone: ShutdownThread:\sBluetooth turned off
- ShutdownRadioDone: ShutdownThread:\sRadio turned off
- ShutdownNfcDone: ShutdownThread:\sNFC turned off
- ShutdownRadiosWaitDone: ShutdownThread:\sNFC, Radio and Bluetooth shutdown complete
- ShutdownRadiosWaitTimeout: ShutdownThread:\sTimed out waiting for NFC, Radio and Bluetooth shutdown
- ShutdownStorageManagerSerivce: ShutdownThread:\sShutting down StorageManagerService
- ShutdownStorageManagerSerivceDone: ShutdownThread:\sResult code [\d]+ from StorageManagerService\.shutdown
- ShutdownStorageManagerSerivceTimeout: ShutdownThread:\sShutdown wait timed out
- ShutdownStartDone: ShutdownThread:\sPerforming low-level shutdown
- ShutdownInitAction: init\s+:\sprocessing action \(sys\.shutdown\.requested
- ShutdownInitFsShutdown: init\s+:\sShutdown timeout
diff --git a/tools/bootanalyze/stressfs/AndroidManifest.xml b/tools/bootanalyze/stressfs/AndroidManifest.xml
deleted file mode 100644
index 8713c51..0000000
--- a/tools/bootanalyze/stressfs/AndroidManifest.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.
--->
-
-<manifest xmlns:android="http://schemas.android.com/apk/res/android"
- package="com.android.car.test.stressfs">
-
- <original-package android:name="com.android.car.test.stressfs" />
-
- <uses-sdk android:minSdkVersion="25"
- android:targetSdkVersion="25" />
- <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
-
- <application android:label="Stress Filesystem"
- android:directBootAware="true"
- android:allowBackup="false">
-
- <activity android:name=".WritingActivity">
- <intent-filter>
- <action android:name="com.android.car.test.stressfs.START" />
- </intent-filter>
- </activity>
- <service android:name=".WritingService">
- </service>
- </application>
-</manifest>
diff --git a/tools/bootanalyze/stressfs/proguard.flags b/tools/bootanalyze/stressfs/proguard.flags
deleted file mode 100644
index 1e5ff3d..0000000
--- a/tools/bootanalyze/stressfs/proguard.flags
+++ /dev/null
@@ -1,3 +0,0 @@
--verbose
--keep public class * extends android.app.Activity
--keep public class * extends android.app.Service
diff --git a/tools/bootanalyze/stressfs/src/com/android/car/test/stressfs/WritingActivity.java b/tools/bootanalyze/stressfs/src/com/android/car/test/stressfs/WritingActivity.java
deleted file mode 100644
index 6fe5cc6..0000000
--- a/tools/bootanalyze/stressfs/src/com/android/car/test/stressfs/WritingActivity.java
+++ /dev/null
@@ -1,61 +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.android.car.test.stressfs;
-
-import android.app.Activity;
-import android.content.ComponentName;
-import android.content.Context;
-import android.content.Intent;
-import android.content.ServiceConnection;
-import android.os.Bundle;
-import android.os.IBinder;
-
-/**
- * Used to instantiate the WritingService service at a high priority.
- */
-public class WritingActivity extends Activity {
-
- private static final String TAG = "StressFS";
-
- /**
- * Activity-wide connection to keep the service going.
- * Not used for any specific interaction.
- */
- private ServiceConnection mConnection = new ServiceConnection() {
- /** No-op */
- public void onServiceConnected(ComponentName className, IBinder service) {
- // Nothing to do.
- }
-
- /** No-op */
- public void onServiceDisconnected(ComponentName className) {
- // Nothing to do.
- }
- };
-
- @Override
- public void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- bindService(
- new Intent(
- getIntent().getAction(),
- getIntent().getData(),
- this,
- WritingService.class),
- mConnection,
- Context.BIND_AUTO_CREATE);
- }
-}
diff --git a/tools/bootanalyze/stressfs/src/com/android/car/test/stressfs/WritingService.java b/tools/bootanalyze/stressfs/src/com/android/car/test/stressfs/WritingService.java
deleted file mode 100644
index 0db75d4..0000000
--- a/tools/bootanalyze/stressfs/src/com/android/car/test/stressfs/WritingService.java
+++ /dev/null
@@ -1,186 +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.android.car.test.stressfs;
-
-import android.app.Service;
-import android.app.Notification;
-import android.app.NotificationChannel;
-import android.content.Context;
-import android.content.Intent;
-import android.net.Uri;
-import android.os.Binder;
-import android.os.Bundle;
-import android.os.Environment;
-import android.os.IBinder;
-import android.util.Log;
-import android.R.drawable;
-
-import java.io.*;
-import java.util.*;
-
-/**
- * Used to stress the file writing before and during shutdown to help ensure
- * that the filesystem shuts down at the right time, in a consistent manner,
- * and does not get corrupted.
- *
- * Writes to two files - one on the data partition, one on the external storage
- * partition - simultaneous in two separate threads; starting over after a
- * certain amount of data is written.
- *
- * This class is intended to be invoked from the shell. For a 64KB file
- * written in 1KB chunks, invoke from the host workstation:
- * adb install -g StressFS.apk
- * adb shell am start \
- * -n com.android.car.test.stressfs/.WritingActivity \
- * -a com.android.car.test.stressfs.START
- * -d "stressfs://start?block=1024\&file=65536"
- *
- * After reboot:
- * adb uninstall com.android.car.test.stressfs
- * adb shell "rm -rf /storage/emulated/0/stressfs_data*"
- *
- * On boot after running this while shutting down, fsck should flag any
- * corruption that it sees resulting from this running. The goal is to set the
- * shutdown sequence in a manner that does not corrupt so that this check can
- * be avoided.
- */
-public class WritingService extends Service {
-
- private static final String TAG = "StressFS";
-
- private static final String ACTION_START = "com.android.car.test.stressfs.START";
-
- private static final int DEFAULT_BLOCK_SIZE = 4096;
- private static final int DEFAULT_FILE_SIZE = 16 * 1024 * 1024;
-
- private static final String FILENAME_PREFIX = "stressfs_data_";
-
- private static final int NOTIFICATION_ID = 100;
-
- /** Continuously writes test data to a specified file. */
- private static class WriteToDisk extends Thread {
- private final String mLogTag;
- private final File mFile;
- private final int mFileSize;
- private final byte[] mTestData;
-
- public WriteToDisk(
- String logTag,
- File file,
- int fileSize,
- byte[] testData) {
- mLogTag = logTag;
- mFile = file;
- mFileSize = fileSize;
- mTestData = testData;
- }
-
- /** Writes data to a file, restarting once the maximum amount of data is reached.*/
- @Override
- public void run() {
- Log.d(TAG, mLogTag + " thread started");
- while (true) {
- try {
- FileOutputStream fos = new FileOutputStream(mFile);
- // Write in chunks until the amount of data requested
- // is written.
- for (int j = 0; j < mFileSize; j += mTestData.length) {
- fos.write(mTestData);
- }
- fos.close();
- } catch (FileNotFoundException e) {
- Log.e(TAG, "File not found: ", e);
- } catch (IOException e) {
- Log.e(TAG, "IO error: ", e);
- }
- }
- }
- }
-
- /** Raises service priority and starts the writing threads. */
- @Override
- public IBinder onBind(Intent intent) {
- Notification notification =
- new Notification.Builder(this, NotificationChannel.DEFAULT_CHANNEL_ID)
- .setContentTitle("Stress Filesystem service running.")
- .setSmallIcon(drawable.ic_menu_save)
- .build();
-
- // Raise priority of this service.
- startForeground(NOTIFICATION_ID, notification);
-
- File dataPartitionFile = getFileStreamPath(FILENAME_PREFIX + UUID.randomUUID());
- File externalPartitionFile = new File(
- Environment.getExternalStorageDirectory(), FILENAME_PREFIX + UUID.randomUUID());
-
- Log.i(TAG, "External storage state: " +
- Environment.getExternalStorageState(externalPartitionFile));
-
- Uri data = intent.getData();
- if (data != null) {
- Log.i(TAG, "Data: " + data.toString());
- }
- int blockSize = getQueryParam(data, "block", DEFAULT_BLOCK_SIZE);
- int fileSize = getQueryParam(data, "file", DEFAULT_FILE_SIZE);
- Log.i(TAG, "Block Size: " + blockSize);
- Log.i(TAG, "File Size: " + fileSize);
-
- if (fileSize % blockSize != 0) {
- Log.w(TAG, "File size should be a multiple of block size.");
- }
-
- // Populate some test data.
- StringBuilder builder = new StringBuilder(blockSize);
- for (int i = 0; i < builder.capacity(); i++) {
- builder.append((char)(i % 26 + 'A'));
- }
- byte[] testData = new String(builder).getBytes();
-
- // Spawn two threads - one to write to the /data partition, one to
- // write to the SD card.
- new WriteToDisk("data", dataPartitionFile, fileSize, testData).start();
- new WriteToDisk("external", externalPartitionFile, fileSize, testData).start();
-
- // No need to return a binder interface, since there is no more
- // interaction needed from the activity starting the service.
- return null;
- }
-
- /** Keeps service alive once started. */
- @Override
- public int onStartCommand(Intent intent, int flags, int startId) {
- return START_STICKY;
- }
-
- /** Parses an integer query parameter from the input Uri. */
- private int getQueryParam(Uri data, String key, int defaultValue) {
- if (data == null) {
- return defaultValue;
- }
- String inValString = data.getQueryParameter(key);
- if (inValString != null) {
- try {
- int inVal = Integer.parseInt(inValString);
- if (inVal != 0) {
- return inVal;
- }
- } catch (NumberFormatException e) {
- return defaultValue;
- }
- }
- return defaultValue;
- }
-}
diff --git a/tools/bootio/Android.mk b/tools/bootio/Android.mk
deleted file mode 100644
index e4db835..0000000
--- a/tools/bootio/Android.mk
+++ /dev/null
@@ -1,76 +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.
-#
-
-LOCAL_PATH := $(call my-dir)
-
-bootio_lib_src_files := \
- protos.proto \
- bootio_collector.cpp \
-
-bootio_src_files := \
- bootio.cpp \
-
-bootio_shared_libs := \
- libbase \
- libcutils \
- liblog \
- libprotobuf-cpp-lite \
-
-bootio_cflags := \
- -Wall \
- -Werror \
- -Wextra \
-
-define bootio_proto_include
-$(call local-generated-sources-dir)/proto/$(LOCAL_PATH)
-endef
-
-# bootio static library
-# -----------------------------------------------------------------------------
-
-include $(CLEAR_VARS)
-
-LOCAL_MODULE := libbootio
-LOCAL_MODULE_CLASS := SHARED_LIBRARIES
-
-LOCAL_C_INCLUDES := \
- $(LOCAL_PATH)/.. \
- $(call bootio_proto_include) \
-
-LOCAL_EXPORT_C_INCLUDE_DIRS := $(LOCAL_PATH)
-LOCAL_CFLAGS := $(bootio_cflags)
-LOCAL_SHARED_LIBRARIES := $(bootio_shared_libs)
-LOCAL_PROTOC_OPTIMIZE_TYPE := lite
-LOCAL_SRC_FILES := $(bootio_lib_src_files)
-
-include $(BUILD_SHARED_LIBRARY)
-
-
-# bootio binary
-# -----------------------------------------------------------------------------
-
-include $(CLEAR_VARS)
-
-LOCAL_MODULE := bootio
-LOCAL_CFLAGS := $(bootio_cflags)
-LOCAL_SHARED_LIBRARIES := \
- $(bootio_shared_libs) \
- libbootio \
-
-LOCAL_INIT_RC := bootio.rc
-LOCAL_SRC_FILES := $(bootio_src_files)
-
-include $(BUILD_EXECUTABLE)
diff --git a/tools/bootio/README.md b/tools/bootio/README.md
deleted file mode 100644
index ca075de..0000000
--- a/tools/bootio/README.md
+++ /dev/null
@@ -1,24 +0,0 @@
-# bootio #
-
-The bootio tool records I/O for processes during boot.
-To use bootio kernel must be compiled with this flags:
-
- CONFIG_TASKSTATS=y
- CONFIG_TASK_DELAY_ACCT=y
- CONFIG_TASK_XACCT=y
- CONFIG_TASK_IO_ACCOUNTING=y
-
-To use bootio make sure it's included in product config for the board.
-Create file /data/misc/bootio/start with a command like the following:
-
- adb shell 'echo "$TIMEOUT $SAMPLES" > /data/misc/bootio/start'
-
-Where the value of $TIMEOUT corresponds to the desired bootio period in
-seconds and $SAMPLES corresponds to the desired number of samples.
-
-Note: /data/misc/bootio/start is not deleted automatically, so don't
-forget to delete it when you're done collecting data.
-
-To see collected logs run:
-
- adb shell bootio -p
diff --git a/tools/bootio/bootio.cpp b/tools/bootio/bootio.cpp
deleted file mode 100644
index 629d04a..0000000
--- a/tools/bootio/bootio.cpp
+++ /dev/null
@@ -1,162 +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.
- */
-
-// The bootio tool provides options to collect I/O stats for processes during boot.
-
-#include <vector>
-#include <getopt.h>
-#include <unistd.h>
-#include <android-base/file.h>
-#include <android-base/logging.h>
-#include <android-base/strings.h>
-#include <log/log.h>
-
-#include "bootio_collector.h"
-
-namespace android {
-
-#define LOG_ROOT "/data/misc/bootio"
-#define LOG_START_FILE LOG_ROOT"/start"
-#define SELF_IO "/proc/self/io"
-
-static const int LOG_TIMEOUT_INDEX = 0;
-static const int LOG_SAMPLES_INDEX = 1;
-static const int LOG_MAX_TIMEOUT = 120;
-static const int LOG_MAX_SAMPLES = 30;
-
-void ShowHelp(const char *cmd) {
- fprintf(stderr, "Usage: %s [options]\n", cmd);
- fprintf(stderr,
- "options include:\n"
- " -h, --help Show this help\n"
- " -p, --print Dump the boot io data to the console\n"
- "\nNo options will start data collection process.\n");
-}
-
-void PrintBootIo() {
- printf("Boot I/O:\n");
- printf("------------\n");
- std::unique_ptr <BootioCollector> collector(new BootioCollector(LOG_ROOT));
- if (collector.get() == NULL) {
- LOG(ERROR) << "Failed to create data collector";
- return;
- }
- collector->Print();
-}
-
-void StartDataCollection() {
- if (access(SELF_IO, F_OK) == -1) {
- LOG(ERROR) << "Kernel doesn't support I/O profiling.";
- printf("Kernel doesn't support I/O profiling.");
- return;
- }
-
- int timeout = 0;
- int samples = 0;
-
- std::string start;
- android::base::ReadFileToString(LOG_START_FILE, &start);
-
- if (!start.empty()) {
- std::vector <std::string> components = android::base::Split(start, " ");
- if (components.size() != 2) {
- LOG(ERROR) << "Invalid value in start file." << start;
- return;
- }
- timeout = atoi(components.at(LOG_TIMEOUT_INDEX).c_str());
- samples = atoi(components.at(LOG_SAMPLES_INDEX).c_str());
- } else {
- LOG(INFO) << "No profiling requested. Exiting";
- printf("Boot I/O: no profiling requested. Exiting.\n");
- return;
- }
- if (timeout <= 0 || samples <= 0) {
- LOG(ERROR) << "Boot I/O: failed to parse string:" << start;
- printf("Boot I/O: failed to parse string: %s\n", start.c_str());
- return;
- }
- if (samples > timeout || samples > LOG_MAX_SAMPLES || timeout > LOG_MAX_TIMEOUT) {
- LOG(ERROR) << "Bad values for bootio. timeout=" << timeout <<
- " samples=" << samples << " Max timeout=" << LOG_MAX_TIMEOUT <<
- " Max samples=" << LOG_MAX_SAMPLES;
- return;
- }
- LOG(INFO) << "Boot I/O: collecting data. samples=" << samples << "timeout=" << timeout;
- printf("Boot I/O: collecting data\ntimeout=%d, samples=%d\n",
- timeout, samples);
- std::unique_ptr <BootioCollector> collector(new BootioCollector(LOG_ROOT));
- if (collector.get() == NULL) {
- LOG(ERROR) << "Failed to create data collector";
- return;
- }
- collector->StartDataCollection(timeout, samples);
-}
-
-}
-
-int main(int argc, char **argv) {
- android::base::InitLogging(argv);
-
- LOG(INFO) << "Bootio started";
-
- int optionIndex = 0;
- static const struct option longOptions[] = {
- {"help", no_argument, NULL, 'h'},
- {"print", no_argument, NULL, 'p'},
- {NULL, 0, NULL, 0}
- };
-
- int opt = 0;
- bool startCollection = true;
- while ((opt = getopt_long(argc, argv, "hlpr:", longOptions, &optionIndex)) != -1) {
- switch (opt) {
- case 0: {
- const std::string option_name = longOptions[optionIndex].name;
- LOG(ERROR) << "Invalid option: " << option_name;
- break;
- }
-
- case 'h': {
- android::ShowHelp(argv[0]);
- startCollection = false;
- break;
- }
-
- case 'p': {
- android::PrintBootIo();
- startCollection = false;
- break;
- }
-
- default: {
- DCHECK_EQ(opt, '?');
-
- // |optopt| is an external variable set by getopt representing
- // the value of the invalid option.
- LOG(ERROR) << "Invalid option: " << optopt;
- android::ShowHelp(argv[0]);
- return EXIT_FAILURE;
- }
- }
- }
-
- if (startCollection) {
- android::StartDataCollection();
- }
-
- return 0;
-}
-
diff --git a/tools/bootio/bootio.rc b/tools/bootio/bootio.rc
deleted file mode 100644
index f0074cb..0000000
--- a/tools/bootio/bootio.rc
+++ /dev/null
@@ -1,10 +0,0 @@
-# This file is the LOCAL_INIT_RC file for the bootio command.
-
-service bootio /system/bin/bootio
- class main
- user root
- group root
- oneshot
-
-on post-fs-data
- mkdir /data/misc/bootio 0755 root shell
diff --git a/tools/bootio/bootio_collector.cpp b/tools/bootio/bootio_collector.cpp
deleted file mode 100644
index 495a9aa..0000000
--- a/tools/bootio/bootio_collector.cpp
+++ /dev/null
@@ -1,381 +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.
- */
-
-#include "bootio_collector.h"
-#include <android-base/logging.h>
-#include <android-base/file.h>
-#include <log/log.h>
-#include "protos.pb.h"
-#include "time.h"
-#include <unordered_map>
-#include <inttypes.h>
-#include <dirent.h>
-
-namespace android {
-
-#define CPU_STAT_FILE "/proc/stat"
-#define SAMPLES_FILE "/samples"
-#define PID_STAT_FILE "/proc/%d/stat"
-#define PID_CMDLINE_FILE "/proc/%d/cmdline"
-#define PID_IO_FILE "/proc/%d/io"
-#define PROC_DIR "/proc"
-
-static const int MAX_LINE = 256;
-
-#define die(...) { LOG(ERROR) << (__VA_ARGS__); exit(EXIT_FAILURE); }
-
-void PopulateCpu(CpuData& cpu) {
- long unsigned utime, ntime, stime, itime;
- long unsigned iowtime, irqtime, sirqtime;
- FILE *file;
- file = fopen(CPU_STAT_FILE, "r");
- if (!file) die("Could not open /proc/stat.\n");
- fscanf(file, "cpu %lu %lu %lu %lu %lu %lu %lu", &utime, &ntime, &stime,
- &itime, &iowtime, &irqtime, &sirqtime);
- fclose(file);
- cpu.set_utime(utime);
- cpu.set_ntime(ntime);
- cpu.set_stime(stime);
- cpu.set_itime(itime);
- cpu.set_iowtime(iowtime);
- cpu.set_irqtime(irqtime);
- cpu.set_sirqtime(sirqtime);
-}
-
-void ClearPreviousResults(std::string path) {
- std::string err;
- if (!android::base::RemoveFileIfExists(path, &err)) {
- LOG(ERROR) << "failed to remove the file " << path << " " << err;
- return;
- }
-}
-
-int ReadIo(char *filename, AppSample *sample) {
- FILE *file;
- char line[MAX_LINE];
- unsigned int rchar, wchar, syscr, syscw, readbytes, writebytes;
-
- file = fopen(filename, "r");
- if (!file) return 1;
- while (fgets(line, MAX_LINE, file)) {
- sscanf(line, "rchar: %u", &rchar);
- sscanf(line, "wchar: %u", &wchar);
- sscanf(line, "syscr: %u", &syscr);
- sscanf(line, "syscw: %u", &syscw);
- sscanf(line, "read_bytes: %u", &readbytes);
- sscanf(line, "write_bytes: %u", &writebytes);
- }
- fclose(file);
- sample->set_rchar(rchar);
- sample->set_wchar(wchar);
- sample->set_syscr(syscr);
- sample->set_syscw(syscw);
- sample->set_readbytes(readbytes);
- sample->set_writebytes(writebytes);
- return 0;
-}
-
-int ReadStatForName(char *filename, AppData *app) {
- FILE *file;
- char buf[MAX_LINE], *open_paren, *close_paren;
-
- file = fopen(filename, "r");
- if (!file) return 1;
- fgets(buf, MAX_LINE, file);
- fclose(file);
-
- /* Split at first '(' and last ')' to get process name. */
- open_paren = strchr(buf, '(');
- close_paren = strrchr(buf, ')');
- if (!open_paren || !close_paren) return 1;
-
- *open_paren = *close_paren = '\0';
- if (!app->has_tname()) {
- app->set_tname(open_paren + 1, close_paren - open_paren - 1);
- }
- return 0;
-}
-
-int ReadStat(char *filename, AppSample *sample) {
- FILE *file;
- char buf[MAX_LINE], *open_paren, *close_paren;
-
- file = fopen(filename, "r");
- if (!file) return 1;
- fgets(buf, MAX_LINE, file);
- fclose(file);
-
- /* Split at first '(' and last ')' to get process name. */
- open_paren = strchr(buf, '(');
- close_paren = strrchr(buf, ')');
- if (!open_paren || !close_paren) return 1;
-
- uint64_t utime;
- uint64_t stime;
- uint64_t rss;
-
- /* Scan rest of string. */
- sscanf(close_paren + 1,
- " %*c " "%*d %*d %*d %*d %*d %*d %*d %*d %*d %*d "
- "%" PRIu64 /*SCNu64*/
- "%" PRIu64 /*SCNu64*/ "%*d %*d %*d %*d %*d %*d %*d %*d "
- "%" PRIu64 /*SCNu64*/ "%*d %*d %*d %*d %*d %*d %*d %*d %*d %*d %*d %*d %*d %*d %*d",
- &utime,
- &stime,
- &rss);
- sample->set_utime(utime);
- sample->set_stime(stime);
- sample->set_rss(rss);
-
- return 0;
-}
-
-int ReadCmdline(char *filename, AppData *app) {
- FILE *file;
- char line[MAX_LINE];
-
- line[0] = '\0';
- file = fopen(filename, "r");
- if (!file) return 1;
- fgets(line, MAX_LINE, file);
- fclose(file);
- if (strlen(line) > 0) {
- app->set_name(line, strlen(line));
- } else {
- app->set_name("N/A");
- }
- return 0;
-};
-
-void ReadProcData(std::unordered_map<int, AppData*>& pidDataMap, DataContainer& dataContainer,
- time_t currentTimeUtc, time_t currentUptime) {
- DIR *procDir;
- struct dirent *pidDir;
- pid_t pid;
- char filename[64];
- procDir = opendir(PROC_DIR);
- if (!procDir) die("Could not open /proc.\n");
- while ((pidDir = readdir(procDir))) {
- if (!isdigit(pidDir->d_name[0])) {
- continue;
- }
- pid = atoi(pidDir->d_name);
- AppData *data;
-
- // TODO: in theory same pid can be shared for multiple processes,
- // might need add extra check.
- if (pidDataMap.count(pid) == 0) {
- data = dataContainer.add_app();
- data->set_pid(pid);
- sprintf(filename, PID_STAT_FILE, pid);
- ReadStatForName(filename, data);
- sprintf(filename, PID_CMDLINE_FILE, pid);
- ReadCmdline(filename, data);
- pidDataMap[pid] = data;
- } else {
- data = pidDataMap[pid];
- }
- AppSample *sample = data->add_samples();
- sample->set_timestamp(currentTimeUtc);
- sample->set_uptime(currentUptime);
-
- sprintf(filename, PID_STAT_FILE, pid);
- ReadStat(filename, sample);
-
- sprintf(filename, PID_IO_FILE, pid);
- ReadIo(filename, sample);
- }
-}
-
-uint64_t SumCpuValues(CpuData& cpu) {
- return cpu.utime() + cpu.ntime() + cpu.stime() + cpu.itime() + cpu.iowtime() +
- cpu.irqtime() + cpu.sirqtime();
-}
-
-time_t GetUptime() {
- std::string uptime_str;
- if (!android::base::ReadFileToString("/proc/uptime", &uptime_str)) {
- LOG(ERROR) << "Failed to read /proc/uptime";
- return -1;
- }
-
- // Cast intentionally rounds down.
- return static_cast<time_t>(strtod(uptime_str.c_str(), NULL));
-}
-
-struct Stats {
- int uptime;
- float cpu;
- uint64_t rbytes;
- uint64_t wbytes;
-};
-
-void PrintPids(DataContainer& data, std::unordered_map<int, uint64_t>& cpuDataMap) {
- printf("rchar: number of bytes the process read, using any read-like system call "
- "(from files, pipes, tty...).\n");
- printf("wchar: number of bytes the process wrote using any write-like system call.\n");
- printf("wchar: number of bytes the process wrote using any write-like system call.\n");
- printf("syscr: number of write-like system call invocations that the process performed.\n");
- printf("rbytes: number of bytes the process directly read from disk.\n");
- printf("wbytes: number of bytes the process originally dirtied in the page-cache "
- "(assuming they will go to disk later).\n\n");
-
- std::unique_ptr<AppSample> bootZeroSample(new AppSample());
- std::map<int, Stats> statsMap;
- // Init stats map
- Stats emptyStat {0, 0., 0, 0};
- for (auto it = cpuDataMap.begin(); it != cpuDataMap.end(); it++) {
- statsMap[it->first] = emptyStat;
- }
- for (int i = 0; i < data.app_size(); i++) {
- const AppData appData = data.app(i);
- printf("\n-----------------------------------------------------------------------------\n");
- printf("PID:\t%u\n", appData.pid());
- printf("Name:\t%s\n", appData.name().c_str());
- printf("ThName:\t%s\n", appData.tname().c_str());
- printf("%-15s%-13s%-13s%-13s%-13s%-13s%-13s%-13s\n", "Uptime inter.", "rchar", "wchar",
- "syscr", "syscw", "rbytes", "wbytes", "cpu%");
- const AppSample *olderSample = NULL;
- const AppSample *newerSample = NULL;
- bool isFirstSample = true;
- for (int j = 0; j < appData.samples_size(); j++) {
- olderSample = newerSample;
- newerSample = &(appData.samples(j));
- if (olderSample == NULL) {
- olderSample = bootZeroSample.get();
- }
- float cpuLoad = 0.;
- uint64_t cpuDelta;
- if (isFirstSample) {
- cpuDelta = cpuDataMap[newerSample->timestamp()];
- } else {
- cpuDelta = cpuDataMap[newerSample->timestamp()] -
- cpuDataMap[olderSample->timestamp()];
- }
- if (cpuDelta != 0) {
- cpuLoad = (newerSample->utime() - olderSample->utime() +
- newerSample->stime() - olderSample->stime()) * 100. / cpuDelta;
- }
- Stats& stats = statsMap[newerSample->timestamp()];
- stats.uptime = newerSample->uptime();
- stats.cpu += cpuLoad;
- stats.rbytes += (newerSample->readbytes() - olderSample->readbytes());
- stats.wbytes += (newerSample->writebytes() - olderSample->writebytes());
-
- // Note that all of these are explicitly `long long`s, not int64_t,
- // so we can't use PRId64 here.
-#define NUMBER "%-13lld"
- printf("%5lld - %-5lld " NUMBER NUMBER NUMBER NUMBER NUMBER NUMBER "%-9.2f\n",
-#undef NUMBER
- olderSample->uptime(),
- newerSample->uptime(),
- newerSample->rchar() - olderSample->rchar(),
- newerSample->wchar() - olderSample->wchar(),
- newerSample->syscr() - olderSample->syscr(),
- newerSample->syscw() - olderSample->syscw(),
- newerSample->readbytes() - olderSample->readbytes(),
- newerSample->writebytes() - olderSample->writebytes(),
- cpuLoad);
- isFirstSample = false;
- }
- printf("-----------------------------------------------------------------------------\n");
-#define NUMBER "%-13lld"
- printf("%-15s" NUMBER NUMBER NUMBER NUMBER NUMBER NUMBER "\n",
-#undef NUMBER
- "Total",
- newerSample->rchar(),
- newerSample->wchar(),
- newerSample->syscr(),
- newerSample->syscw(),
- newerSample->readbytes(),
- newerSample->writebytes());
- }
- printf("\nAggregations\n%-10s%-13s%-13s%-13s\n",
- "Total",
- "rbytes",
- "wbytes",
- "cpu%");
-
- for (auto it = statsMap.begin(); it != statsMap.end(); it++) {
- printf("%-10u%-13" PRIu64 "%-13" PRIu64 "%-9.2f\n",
- it->second.uptime,
- it->second.rbytes,
- it->second.wbytes,
- it->second.cpu);
- }
-}
-
-}
-
-BootioCollector::BootioCollector(std::string path) {
- DCHECK_EQ('/', path.back());
- path_ = path;
-}
-
-void BootioCollector::StartDataCollection(int timeout, int samples) {
- android::ClearPreviousResults(getStoragePath());
- int remaining = samples + 1;
- int delayS = timeout / samples;
-
- std::unordered_map < int, AppData * > pidDataMap;
- std::unique_ptr <DataContainer> data(new DataContainer());
- while (remaining > 0) {
- time_t currentTimeUtc = time(nullptr);
- time_t currentUptime = android::GetUptime();
- CpuData *cpu = data->add_cpu();
- cpu->set_timestamp(currentTimeUtc);
- cpu->set_uptime(currentUptime);
- android::PopulateCpu(*cpu);
- android::ReadProcData(pidDataMap, *data.get(), currentTimeUtc, currentUptime);
- remaining--;
- if (remaining == 0) {
- continue;
- }
- sleep(delayS);
- }
- std::string file_data;
- if (!data->SerializeToString(&file_data)) {
- LOG(ERROR) << "Failed to serialize";
- return;
- }
- if (!android::base::WriteStringToFile(file_data, getStoragePath())) {
- LOG(ERROR) << "Failed to write samples";
- }
-}
-
-void BootioCollector::Print() {
- std::string file_data;
- if (!android::base::ReadFileToString(getStoragePath(), &file_data)) {
- printf("Failed to read data from file.\n");
- return;
- }
- std::unique_ptr <DataContainer> data(new DataContainer());
- if (!data->ParsePartialFromString(file_data)) {
- printf("Failed to parse data.\n");
- return;
- }
- std::unordered_map<int, uint64_t> cpuDataMap;
- for (int i = 0; i < data->cpu_size(); i++) {
- CpuData cpu_data = data->cpu(i);
- cpuDataMap[cpu_data.timestamp()] = android::SumCpuValues(cpu_data);
- }
- android::PrintPids(*data.get(), cpuDataMap);
-}
-
-
-std::string BootioCollector::getStoragePath() {
- return path_ + SAMPLES_FILE;
-}
diff --git a/tools/bootio/bootio_collector.h b/tools/bootio/bootio_collector.h
deleted file mode 100644
index 7296e6f..0000000
--- a/tools/bootio/bootio_collector.h
+++ /dev/null
@@ -1,39 +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.
- */
-
-#ifndef BOOTIO_COLLECTOR_H_
-#define BOOTIO_COLLECTOR_H_
-
-#include <string>
-#include <android-base/macros.h>
-
-class BootioCollector {
-public:
- BootioCollector(std::string path);
-
- void StartDataCollection(int timeout, int samples);
-
- void Print();
-
-private:
- std::string getStoragePath();
-
- std::string path_;
-
- DISALLOW_COPY_AND_ASSIGN(BootioCollector);
-};
-
-#endif // BOOTIO_COLLECTOR_H_
diff --git a/tools/bootio/protos.proto b/tools/bootio/protos.proto
deleted file mode 100644
index d5674ec..0000000
--- a/tools/bootio/protos.proto
+++ /dev/null
@@ -1,55 +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.
-
-syntax = "proto2";
-
-option optimize_for = LITE_RUNTIME;
-
-message DataContainer {
- repeated AppData app = 1;
- repeated CpuData cpu = 2;
-};
-
-message CpuData {
- required int64 timestamp = 1;
- required int64 uptime = 2;
- required int64 utime = 3;
- required int64 ntime = 4;
- required int64 stime = 5;
- required int64 itime = 6;
- required int64 iowtime = 7;
- required int64 irqtime = 9;
- required int64 sirqtime = 10;
-}
-
-message AppData {
- required int32 pid = 1;
- required string tname = 2;
- required string name = 3;
- repeated AppSample samples = 4;
-}
-
-message AppSample {
- required int64 timestamp = 1;
- required int64 uptime = 2;
- required int64 rchar = 3;
- required int64 wchar = 4;
- required int64 syscr = 5;
- required int64 syscw = 6;
- required int64 readbytes = 7;
- required int64 writebytes = 8;
- required int64 utime = 9;
- required int64 stime = 10;
- required int64 rss = 11;
-};
diff --git a/tools/bootio/sepolicy/bootio.te b/tools/bootio/sepolicy/bootio.te
deleted file mode 100644
index 5838386..0000000
--- a/tools/bootio/sepolicy/bootio.te
+++ /dev/null
@@ -1,12 +0,0 @@
-# bootio command
-type bootio, domain;
-type bootio_exec, exec_type, file_type;
-
-init_daemon_domain(bootio)
-
-# Allow persistent storage in /data/misc/bootio.
-allow bootio bootio_data_file:dir rw_dir_perms;
-allow bootio bootio_data_file:file create_file_perms;
-
-# Read access to pseudo filesystems (for /proc/stats, proc/io/io, etc).
-r_dir_file(bootio, proc)
diff --git a/tools/bootio/sepolicy/domain.te b/tools/bootio/sepolicy/domain.te
deleted file mode 100644
index af42fe7..0000000
--- a/tools/bootio/sepolicy/domain.te
+++ /dev/null
@@ -1,2 +0,0 @@
-# dontaudit bootio kernel:system module_request;
-allow bootio kernel:fd use;
\ No newline at end of file
diff --git a/tools/bootio/sepolicy/file.te b/tools/bootio/sepolicy/file.te
deleted file mode 100644
index c68cec7..0000000
--- a/tools/bootio/sepolicy/file.te
+++ /dev/null
@@ -1,2 +0,0 @@
-# /data/misc subdirectories
-type bootio_data_file, file_type, data_file_type;
diff --git a/tools/bootio/sepolicy/file_contexts b/tools/bootio/sepolicy/file_contexts
deleted file mode 100644
index 071227c..0000000
--- a/tools/bootio/sepolicy/file_contexts
+++ /dev/null
@@ -1,5 +0,0 @@
-# System files
-/system/bin/bootio u:object_r:bootio_exec:s0
-
-# Misc data
-/data/misc/bootio(/.*)? u:object_r:bootio_data_file:s0
diff --git a/tools/emulator/VehicleHalProto_pb2.py b/tools/emulator/VehicleHalProto_pb2.py
index aaad547..3278ed7 100644
--- a/tools/emulator/VehicleHalProto_pb2.py
+++ b/tools/emulator/VehicleHalProto_pb2.py
@@ -14,7 +14,7 @@
DESCRIPTOR = _descriptor.FileDescriptor(
name='VehicleHalProto.proto',
package='emulator',
- serialized_pb='\n\x15VehicleHalProto.proto\x12\x08\x65mulator\"\xba\x01\n\x11VehicleAreaConfig\x12\x0f\n\x07\x61rea_id\x18\x01 \x02(\x05\x12\x17\n\x0fmin_int32_value\x18\x02 \x01(\x11\x12\x17\n\x0fmax_int32_value\x18\x03 \x01(\x11\x12\x17\n\x0fmin_int64_value\x18\x04 \x01(\x12\x12\x17\n\x0fmax_int64_value\x18\x05 \x01(\x12\x12\x17\n\x0fmin_float_value\x18\x06 \x01(\x02\x12\x17\n\x0fmax_float_value\x18\x07 \x01(\x02\"\x9b\x02\n\x11VehiclePropConfig\x12\x0c\n\x04prop\x18\x01 \x02(\x05\x12\x0e\n\x06\x61\x63\x63\x65ss\x18\x02 \x01(\x05\x12\x13\n\x0b\x63hange_mode\x18\x03 \x01(\x05\x12\x12\n\nvalue_type\x18\x04 \x01(\x05\x12\x17\n\x0fsupported_areas\x18\x05 \x01(\x05\x12\x31\n\x0c\x61rea_configs\x18\x06 \x03(\x0b\x32\x1b.emulator.VehicleAreaConfig\x12\x14\n\x0c\x63onfig_flags\x18\x07 \x01(\x05\x12\x14\n\x0c\x63onfig_array\x18\x08 \x03(\x05\x12\x15\n\rconfig_string\x18\t \x01(\t\x12\x17\n\x0fmin_sample_rate\x18\n \x01(\x02\x12\x17\n\x0fmax_sample_rate\x18\x0b \x01(\x02\"\xc5\x01\n\x10VehiclePropValue\x12\x0c\n\x04prop\x18\x01 \x02(\x05\x12\x12\n\nvalue_type\x18\x02 \x01(\x05\x12\x11\n\ttimestamp\x18\x03 \x01(\x03\x12\x0f\n\x07\x61rea_id\x18\x04 \x01(\x05\x12\x14\n\x0cint32_values\x18\x05 \x03(\x11\x12\x14\n\x0cint64_values\x18\x06 \x03(\x12\x12\x14\n\x0c\x66loat_values\x18\x07 \x03(\x02\x12\x14\n\x0cstring_value\x18\x08 \x01(\t\x12\x13\n\x0b\x62ytes_value\x18\t \x01(\x0c\"/\n\x0eVehiclePropGet\x12\x0c\n\x04prop\x18\x01 \x02(\x05\x12\x0f\n\x07\x61rea_id\x18\x02 \x01(\x05\"\xd8\x01\n\x0f\x45mulatorMessage\x12#\n\x08msg_type\x18\x01 \x02(\x0e\x32\x11.emulator.MsgType\x12 \n\x06status\x18\x02 \x01(\x0e\x32\x10.emulator.Status\x12&\n\x04prop\x18\x03 \x03(\x0b\x32\x18.emulator.VehiclePropGet\x12+\n\x06\x63onfig\x18\x04 \x03(\x0b\x32\x1b.emulator.VehiclePropConfig\x12)\n\x05value\x18\x05 \x03(\x0b\x32\x1a.emulator.VehiclePropValue*\x8a\x02\n\x07MsgType\x12\x12\n\x0eGET_CONFIG_CMD\x10\x00\x12\x13\n\x0fGET_CONFIG_RESP\x10\x01\x12\x16\n\x12GET_CONFIG_ALL_CMD\x10\x02\x12\x17\n\x13GET_CONFIG_ALL_RESP\x10\x03\x12\x14\n\x10GET_PROPERTY_CMD\x10\x04\x12\x15\n\x11GET_PROPERTY_RESP\x10\x05\x12\x18\n\x14GET_PROPERTY_ALL_CMD\x10\x06\x12\x19\n\x15GET_PROPERTY_ALL_RESP\x10\x07\x12\x14\n\x10SET_PROPERTY_CMD\x10\x08\x12\x15\n\x11SET_PROPERTY_RESP\x10\t\x12\x16\n\x12SET_PROPERTY_ASYNC\x10\n*\xfb\x01\n\x06Status\x12\r\n\tRESULT_OK\x10\x00\x12\x11\n\rERROR_UNKNOWN\x10\x01\x12\x1b\n\x17\x45RROR_UNIMPLEMENTED_CMD\x10\x02\x12\x1a\n\x16\x45RROR_INVALID_PROPERTY\x10\x03\x12\x19\n\x15\x45RROR_INVALID_AREA_ID\x10\x04\x12 \n\x1c\x45RROR_PROPERTY_UNINITIALIZED\x10\x05\x12\x1d\n\x19\x45RROR_WRITE_ONLY_PROPERTY\x10\x06\x12\x1d\n\x19\x45RROR_MEMORY_ALLOC_FAILED\x10\x07\x12\x1b\n\x17\x45RROR_INVALID_OPERATION\x10\x08\x42\x02H\x03')
+ serialized_pb='\n\x15VehicleHalProto.proto\x12\x08\x65mulator\"\xba\x01\n\x11VehicleAreaConfig\x12\x0f\n\x07\x61rea_id\x18\x01 \x02(\x05\x12\x17\n\x0fmin_int32_value\x18\x02 \x01(\x11\x12\x17\n\x0fmax_int32_value\x18\x03 \x01(\x11\x12\x17\n\x0fmin_int64_value\x18\x04 \x01(\x12\x12\x17\n\x0fmax_int64_value\x18\x05 \x01(\x12\x12\x17\n\x0fmin_float_value\x18\x06 \x01(\x02\x12\x17\n\x0fmax_float_value\x18\x07 \x01(\x02\"\x9b\x02\n\x11VehiclePropConfig\x12\x0c\n\x04prop\x18\x01 \x02(\x05\x12\x0e\n\x06\x61\x63\x63\x65ss\x18\x02 \x01(\x05\x12\x13\n\x0b\x63hange_mode\x18\x03 \x01(\x05\x12\x12\n\nvalue_type\x18\x04 \x01(\x05\x12\x17\n\x0fsupported_areas\x18\x05 \x01(\x05\x12\x31\n\x0c\x61rea_configs\x18\x06 \x03(\x0b\x32\x1b.emulator.VehicleAreaConfig\x12\x14\n\x0c\x63onfig_flags\x18\x07 \x01(\x05\x12\x14\n\x0c\x63onfig_array\x18\x08 \x03(\x05\x12\x15\n\rconfig_string\x18\t \x01(\t\x12\x17\n\x0fmin_sample_rate\x18\n \x01(\x02\x12\x17\n\x0fmax_sample_rate\x18\x0b \x01(\x02\"\xf2\x01\n\x10VehiclePropValue\x12\x0c\n\x04prop\x18\x01 \x02(\x05\x12\x12\n\nvalue_type\x18\x02 \x01(\x05\x12\x11\n\ttimestamp\x18\x03 \x01(\x03\x12+\n\x06status\x18\n \x01(\x0e\x32\x1b.emulator.VehiclePropStatus\x12\x0f\n\x07\x61rea_id\x18\x04 \x01(\x05\x12\x14\n\x0cint32_values\x18\x05 \x03(\x11\x12\x14\n\x0cint64_values\x18\x06 \x03(\x12\x12\x14\n\x0c\x66loat_values\x18\x07 \x03(\x02\x12\x14\n\x0cstring_value\x18\x08 \x01(\t\x12\x13\n\x0b\x62ytes_value\x18\t \x01(\x0c\"/\n\x0eVehiclePropGet\x12\x0c\n\x04prop\x18\x01 \x02(\x05\x12\x0f\n\x07\x61rea_id\x18\x02 \x01(\x05\"\xd8\x01\n\x0f\x45mulatorMessage\x12#\n\x08msg_type\x18\x01 \x02(\x0e\x32\x11.emulator.MsgType\x12 \n\x06status\x18\x02 \x01(\x0e\x32\x10.emulator.Status\x12&\n\x04prop\x18\x03 \x03(\x0b\x32\x18.emulator.VehiclePropGet\x12+\n\x06\x63onfig\x18\x04 \x03(\x0b\x32\x1b.emulator.VehiclePropConfig\x12)\n\x05value\x18\x05 \x03(\x0b\x32\x1a.emulator.VehiclePropValue*\x8a\x02\n\x07MsgType\x12\x12\n\x0eGET_CONFIG_CMD\x10\x00\x12\x13\n\x0fGET_CONFIG_RESP\x10\x01\x12\x16\n\x12GET_CONFIG_ALL_CMD\x10\x02\x12\x17\n\x13GET_CONFIG_ALL_RESP\x10\x03\x12\x14\n\x10GET_PROPERTY_CMD\x10\x04\x12\x15\n\x11GET_PROPERTY_RESP\x10\x05\x12\x18\n\x14GET_PROPERTY_ALL_CMD\x10\x06\x12\x19\n\x15GET_PROPERTY_ALL_RESP\x10\x07\x12\x14\n\x10SET_PROPERTY_CMD\x10\x08\x12\x15\n\x11SET_PROPERTY_RESP\x10\t\x12\x16\n\x12SET_PROPERTY_ASYNC\x10\n*\xfb\x01\n\x06Status\x12\r\n\tRESULT_OK\x10\x00\x12\x11\n\rERROR_UNKNOWN\x10\x01\x12\x1b\n\x17\x45RROR_UNIMPLEMENTED_CMD\x10\x02\x12\x1a\n\x16\x45RROR_INVALID_PROPERTY\x10\x03\x12\x19\n\x15\x45RROR_INVALID_AREA_ID\x10\x04\x12 \n\x1c\x45RROR_PROPERTY_UNINITIALIZED\x10\x05\x12\x1d\n\x19\x45RROR_WRITE_ONLY_PROPERTY\x10\x06\x12\x1d\n\x19\x45RROR_MEMORY_ALLOC_FAILED\x10\x07\x12\x1b\n\x17\x45RROR_INVALID_OPERATION\x10\x08*>\n\x11VehiclePropStatus\x12\r\n\tAVAILABLE\x10\x00\x12\x0f\n\x0bUNAVAILABLE\x10\x01\x12\t\n\x05\x45RROR\x10\x02\x42\x02H\x03')
_MSGTYPE = _descriptor.EnumDescriptor(
name='MsgType',
@@ -69,8 +69,8 @@
],
containing_type=None,
options=None,
- serialized_start=979,
- serialized_end=1245,
+ serialized_start=1024,
+ serialized_end=1290,
)
MsgType = enum_type_wrapper.EnumTypeWrapper(_MSGTYPE)
@@ -119,11 +119,37 @@
],
containing_type=None,
options=None,
- serialized_start=1248,
- serialized_end=1499,
+ serialized_start=1293,
+ serialized_end=1544,
)
Status = enum_type_wrapper.EnumTypeWrapper(_STATUS)
+_VEHICLEPROPSTATUS = _descriptor.EnumDescriptor(
+ name='VehiclePropStatus',
+ full_name='emulator.VehiclePropStatus',
+ filename=None,
+ file=DESCRIPTOR,
+ values=[
+ _descriptor.EnumValueDescriptor(
+ name='AVAILABLE', index=0, number=0,
+ options=None,
+ type=None),
+ _descriptor.EnumValueDescriptor(
+ name='UNAVAILABLE', index=1, number=1,
+ options=None,
+ type=None),
+ _descriptor.EnumValueDescriptor(
+ name='ERROR', index=2, number=2,
+ options=None,
+ type=None),
+ ],
+ containing_type=None,
+ options=None,
+ serialized_start=1546,
+ serialized_end=1608,
+)
+
+VehiclePropStatus = enum_type_wrapper.EnumTypeWrapper(_VEHICLEPROPSTATUS)
GET_CONFIG_CMD = 0
GET_CONFIG_RESP = 1
GET_CONFIG_ALL_CMD = 2
@@ -144,6 +170,9 @@
ERROR_WRITE_ONLY_PROPERTY = 6
ERROR_MEMORY_ALLOC_FAILED = 7
ERROR_INVALID_OPERATION = 8
+AVAILABLE = 0
+UNAVAILABLE = 1
+ERROR = 2
@@ -344,42 +373,49 @@
is_extension=False, extension_scope=None,
options=None),
_descriptor.FieldDescriptor(
- name='area_id', full_name='emulator.VehiclePropValue.area_id', index=3,
+ name='status', full_name='emulator.VehiclePropValue.status', index=3,
+ number=10, type=14, cpp_type=8, label=1,
+ has_default_value=False, default_value=0,
+ message_type=None, enum_type=None, containing_type=None,
+ is_extension=False, extension_scope=None,
+ options=None),
+ _descriptor.FieldDescriptor(
+ name='area_id', full_name='emulator.VehiclePropValue.area_id', index=4,
number=4, type=5, cpp_type=1, label=1,
has_default_value=False, default_value=0,
message_type=None, enum_type=None, containing_type=None,
is_extension=False, extension_scope=None,
options=None),
_descriptor.FieldDescriptor(
- name='int32_values', full_name='emulator.VehiclePropValue.int32_values', index=4,
+ name='int32_values', full_name='emulator.VehiclePropValue.int32_values', index=5,
number=5, type=17, cpp_type=1, label=3,
has_default_value=False, default_value=[],
message_type=None, enum_type=None, containing_type=None,
is_extension=False, extension_scope=None,
options=None),
_descriptor.FieldDescriptor(
- name='int64_values', full_name='emulator.VehiclePropValue.int64_values', index=5,
+ name='int64_values', full_name='emulator.VehiclePropValue.int64_values', index=6,
number=6, type=18, cpp_type=2, label=3,
has_default_value=False, default_value=[],
message_type=None, enum_type=None, containing_type=None,
is_extension=False, extension_scope=None,
options=None),
_descriptor.FieldDescriptor(
- name='float_values', full_name='emulator.VehiclePropValue.float_values', index=6,
+ name='float_values', full_name='emulator.VehiclePropValue.float_values', index=7,
number=7, type=2, cpp_type=6, label=3,
has_default_value=False, default_value=[],
message_type=None, enum_type=None, containing_type=None,
is_extension=False, extension_scope=None,
options=None),
_descriptor.FieldDescriptor(
- name='string_value', full_name='emulator.VehiclePropValue.string_value', index=7,
+ name='string_value', full_name='emulator.VehiclePropValue.string_value', index=8,
number=8, type=9, cpp_type=9, label=1,
has_default_value=False, default_value=unicode("", "utf-8"),
message_type=None, enum_type=None, containing_type=None,
is_extension=False, extension_scope=None,
options=None),
_descriptor.FieldDescriptor(
- name='bytes_value', full_name='emulator.VehiclePropValue.bytes_value', index=8,
+ name='bytes_value', full_name='emulator.VehiclePropValue.bytes_value', index=9,
number=9, type=12, cpp_type=9, label=1,
has_default_value=False, default_value="",
message_type=None, enum_type=None, containing_type=None,
@@ -395,7 +431,7 @@
is_extendable=False,
extension_ranges=[],
serialized_start=511,
- serialized_end=708,
+ serialized_end=753,
)
@@ -429,8 +465,8 @@
options=None,
is_extendable=False,
extension_ranges=[],
- serialized_start=710,
- serialized_end=757,
+ serialized_start=755,
+ serialized_end=802,
)
@@ -485,11 +521,12 @@
options=None,
is_extendable=False,
extension_ranges=[],
- serialized_start=760,
- serialized_end=976,
+ serialized_start=805,
+ serialized_end=1021,
)
_VEHICLEPROPCONFIG.fields_by_name['area_configs'].message_type = _VEHICLEAREACONFIG
+_VEHICLEPROPVALUE.fields_by_name['status'].enum_type = _VEHICLEPROPSTATUS
_EMULATORMESSAGE.fields_by_name['msg_type'].enum_type = _MSGTYPE
_EMULATORMESSAGE.fields_by_name['status'].enum_type = _STATUS
_EMULATORMESSAGE.fields_by_name['prop'].message_type = _VEHICLEPROPGET
diff --git a/tools/emulator/diagnostic_builder.py b/tools/emulator/diagnostic_builder.py
index b205a5b..9229169 100644
--- a/tools/emulator/diagnostic_builder.py
+++ b/tools/emulator/diagnostic_builder.py
@@ -15,12 +15,12 @@
# limitations under the License.
#
-# A helper class to generate COMPLEX property values that can be
+# A helper class to generate MIXED property values that can be
# set as the value for a diagnostic frame
# Spritually, the same as DiagnosticEventBuilder.java
-from diagnostic_sensors import OBD2_SENSOR_INTEGER_LAST_SYSTEM_INDEX
-from diagnostic_sensors import OBD2_SENSOR_FLOAT_LAST_SYSTEM_INDEX
+from diagnostic_sensors import DIAGNOSTIC_SENSOR_INTEGER_LAST_SYSTEM_INDEX
+from diagnostic_sensors import DIAGNOSTIC_SENSOR_FLOAT_LAST_SYSTEM_INDEX
class DiagnosticEventBuilder(object):
class ByteArray(object):
@@ -56,9 +56,9 @@
self.string_value = ""
self.bytes = ""
self.numIntSensors = propConfig.config[0].config_array[0] + \
- OBD2_SENSOR_INTEGER_LAST_SYSTEM_INDEX + 1
+ DIAGNOSTIC_SENSOR_INTEGER_LAST_SYSTEM_INDEX + 1
self.numFloatSensors = propConfig.config[0].config_array[1] + \
- OBD2_SENSOR_FLOAT_LAST_SYSTEM_INDEX + 1
+ DIAGNOSTIC_SENSOR_FLOAT_LAST_SYSTEM_INDEX + 1
self.bitmask = DiagnosticEventBuilder.ByteArray(
self.numIntSensors+self.numFloatSensors)
self.int32_values = [0] * self.numIntSensors
diff --git a/tools/emulator/diagnostic_injector.py b/tools/emulator/diagnostic_injector.py
index 7678576..310b595 100755
--- a/tools/emulator/diagnostic_injector.py
+++ b/tools/emulator/diagnostic_injector.py
@@ -25,7 +25,7 @@
import sys
import time
-import vhal_consts_2_1 as c
+import vhal_consts_2_0 as c
# vhal_emulator depends on a custom Python package that requires installation
# give user guidance should the import fail
@@ -95,7 +95,7 @@
builder.addFloatSensor(floatValue['id'], floatValue['value'])
builtEvent = builder.build()
print ("Sending %s %s..." % (eventType, builtEvent)),
- # and send it
+ # and send it
status = self.chat(
lambda hal:
hal.setProperty(eventTypeData['property'],
diff --git a/tools/emulator/driving_info_generator.py b/tools/emulator/driving_info_generator.py
new file mode 100644
index 0000000..975c832
--- /dev/null
+++ b/tools/emulator/driving_info_generator.py
@@ -0,0 +1,231 @@
+# 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.
+#
+
+import datetime
+import time
+
+from xml.dom import minidom
+
+import diagnostic_sensors as s
+import vhal_consts_2_0 as c
+
+from diagnostic_builder import DiagnosticEventBuilder
+
+# interval of generating driving information
+SAMPLE_INTERVAL_SECONDS = 0.5
+
+RPM_LOW = 1000
+RPM_HIGH = 3000
+
+REVERSE_DURATION_SECONDS = 10
+PARK_DURATION_SECONDS = 10
+
+# roughly 5 miles/hour
+REVERSE_SPEED_METERS_PER_SECOND = 2.3
+
+UTC_TIME_FORMAT = "%Y-%m-%dT%H:%M:%S"
+
+# Diagnostics property constants. The value is based on the record from a test drive
+FUEL_SYSTEM_STATUS_VALUE = 2
+AMBIENT_AIR_TEMPERATURE_VALUE = 21
+ENGINE_COOLANT_TEMPERATURE_VALUE = 75
+
+
+def speed2Gear(speed):
+ """
+ Get the current gear based on speed of vehicle. The conversion may not be strictly real but
+ are close enough to a normal vehicle. Assume the vehicle is moving forward.
+ """
+ if speed < 4.4:
+ # 0 - 10 mph
+ return c.VEHICLEGEAR_GEAR_1
+ elif speed < 11.2:
+ # 10 - 25 mph
+ return c.VEHICLEGEAR_GEAR_2
+ elif speed < 20.1:
+ # 25 - 45 mph
+ return c.VEHICLEGEAR_GEAR_3
+ elif speed < 26.8:
+ # 45 - 60 mph
+ return c.VEHICLEGEAR_GEAR_4
+ else:
+ # > 60 mph
+ return c.VEHICLEGEAR_GEAR_5
+
+class GpxFrame(object):
+ """
+ A class representing a track point from GPX file
+ """
+ def __init__(self, trkptDom):
+ timeElements = trkptDom.getElementsByTagName('time')
+ if timeElements:
+ # time value in GPX is in UTC format: YYYY-MM-DDTHH:MM:SS, need to parse it
+ self.datetime = datetime.datetime.strptime(timeElements[0].firstChild.nodeValue,
+ UTC_TIME_FORMAT)
+ speedElements = trkptDom.getElementsByTagName('speed')
+ if speedElements:
+ self.speedInMps = float(speedElements[0].firstChild.nodeValue)
+
+class DrivingInfoGenerator(object):
+ """
+ A class that generates driving information like speed, odometer, rpm, diagnostics etc. It
+ takes a GPX file which describes a real route that consists of a sequence of location data,
+ and then derive driving information from those data.
+
+ One assumption is that it is automatic transmission car, so that current gear does not
+ necessarily match selected gear.
+ """
+
+ def __init__(self, gpxFile, vhal):
+ self.gpxDom = minidom.parse(gpxFile)
+ # Speed of vehicle (meter / second)
+ self.speedInMps = 0
+ # Fixed RPM with average value during driving
+ self.rpm = RPM_LOW
+ # Odometer (kilometer)
+ self.odometerInKm = 0
+ # Gear selection
+ self.selectedGear = c.VEHICLEGEAR_GEAR_PARK
+ # Current gear
+ self.currentGear = c.VEHICLEGEAR_GEAR_PARK
+ # Timestamp while driving on route defined in GPX file
+ self.datetime = 0
+ # Get Diagnostics live frame property configure
+ vhal.getConfig(c.VEHICLEPROPERTY_OBD2_LIVE_FRAME)
+ self.liveFrameConfig = vhal.rxMsg()
+
+
+ def _generateFrame(self, listener):
+ """
+ Handle newly generated vehicle property with listener
+ """
+ listener.handle(c.VEHICLEPROPERTY_PERF_VEHICLE_SPEED, 0, self.speedInMps, "PERF_VEHICLE_SPEED")
+ listener.handle(c.VEHICLEPROPERTY_ENGINE_RPM, 0, self.rpm, "ENGINE_RPM")
+ listener.handle(c.VEHICLEPROPERTY_PERF_ODOMETER, 0, self.odometerInKm, "PERF_ODOMETER")
+ listener.handle(c.VEHICLEPROPERTY_CURRENT_GEAR, 0, self.currentGear, "CURRENT_GEAR")
+ listener.handle(c.VEHICLEPROPERTY_OBD2_LIVE_FRAME, 0,
+ self._buildDiagnosticLiveFrame(), "DIAGNOSTIC_LIVE_FRAME")
+
+ def _buildDiagnosticLiveFrame(self):
+ """
+ Build a diagnostic live frame with a few sensor fields set
+ """
+ builder = DiagnosticEventBuilder(self.liveFrameConfig)
+ builder.setStringValue('')
+ builder.addIntSensor(s.DIAGNOSTIC_SENSOR_INTEGER_FUEL_SYSTEM_STATUS,
+ FUEL_SYSTEM_STATUS_VALUE)
+ builder.addIntSensor(s.DIAGNOSTIC_SENSOR_INTEGER_AMBIENT_AIR_TEMPERATURE,
+ AMBIENT_AIR_TEMPERATURE_VALUE)
+ builder.addFloatSensor(s.DIAGNOSTIC_SENSOR_FLOAT_ENGINE_COOLANT_TEMPERATURE,
+ ENGINE_COOLANT_TEMPERATURE_VALUE)
+ builder.addFloatSensor(s.DIAGNOSTIC_SENSOR_FLOAT_ENGINE_RPM, self.rpm)
+ builder.addFloatSensor(s.DIAGNOSTIC_SENSOR_FLOAT_VEHICLE_SPEED, self.speedInMps)
+ return builder.build()
+
+ def _generateFromGpxFrame(self, gpxFrame, listener):
+ """
+ Generate a sequence of vehicle property frames from current track point to the next one.
+ The frequency of frames are pre-defined.
+
+ Some assumptions here:
+ - Two track points are very close to each other (e.g. 1 second driving distance)
+ - It is a straight line between two track point
+ - Speed is changing linearly between two track point
+
+ Given the info:
+ timestamp1 : speed1
+ timestamp2 : speed2
+
+ Vehicle properties in each frame are derived like this:
+ - Speed is calculated based on linear model
+ - Odometer is calculated based on speed and time
+ - RPM will be set to a low value if not accelerating, otherwise set to a high value
+ - Current gear will be set according to speed
+ """
+
+ duration = (gpxFrame.datetime - self.datetime).total_seconds()
+ speedIncrement = (gpxFrame.speedInMps - self.speedInMps) / duration * SAMPLE_INTERVAL_SECONDS
+ self.rpm = RPM_HIGH if speedIncrement > 0 else RPM_LOW
+
+ timeElapsed = 0
+ while timeElapsed < duration:
+ self._generateFrame(listener)
+ if timeElapsed + SAMPLE_INTERVAL_SECONDS < duration:
+ self.odometerInKm += (self.speedInMps + speedIncrement / 2.0) * SAMPLE_INTERVAL_SECONDS / 1000
+ self.speedInMps += speedIncrement
+ time.sleep(SAMPLE_INTERVAL_SECONDS)
+ else:
+ timeLeft = duration - timeElapsed
+ self.odometerInKm += (self.speedInMps + gpxFrame.speedInMps) / 2.0 * timeLeft / 1000
+ self.speedInMps = gpxFrame.speedInMps
+ time.sleep(timeLeft)
+
+ self.currentGear = speed2Gear(self.speedInMps)
+ timeElapsed += SAMPLE_INTERVAL_SECONDS
+
+ self.datetime = gpxFrame.datetime
+
+ def _generateInReverseMode(self, duration, listener):
+ print "Vehicle is reversing"
+ listener.handle(c.VEHICLEPROPERTY_GEAR_SELECTION, 0, c.VEHICLEGEAR_GEAR_REVERSE,
+ "GEAR_SELECTION")
+ listener.handle(c.VEHICLEPROPERTY_CURRENT_GEAR, 0, c.VEHICLEGEAR_GEAR_REVERSE,
+ "CURRENT_GEAR")
+ self.rpm = RPM_LOW
+ self.speedInMps = REVERSE_SPEED_METERS_PER_SECOND
+ curTime = 0
+ while curTime < duration:
+ self._generateFrame(listener)
+ self.odometerInKm += self.speedInMps * SAMPLE_INTERVAL_SECONDS / 1000
+ curTime += SAMPLE_INTERVAL_SECONDS
+ time.sleep(SAMPLE_INTERVAL_SECONDS)
+ # After reverse is done, set speed to 0
+ self.speedInMps = .0
+
+ def _generateInParkMode(self, duration, listener):
+ print "Vehicle is parked"
+ listener.handle(c.VEHICLEPROPERTY_GEAR_SELECTION, 0, c.VEHICLEGEAR_GEAR_PARK,
+ "GEAR_SELECTION")
+ listener.handle(c.VEHICLEPROPERTY_CURRENT_GEAR, 0, c.VEHICLEGEAR_GEAR_PARK,
+ "CURRENT_GEAR")
+ # Assume in park mode, engine is still on
+ self.rpm = RPM_LOW
+ self.speedInMps = .0
+ curTime = 0
+ while curTime < duration:
+ self._generateFrame(listener)
+ curTime += SAMPLE_INTERVAL_SECONDS
+ time.sleep(SAMPLE_INTERVAL_SECONDS)
+
+ def generate(self, listener):
+ # First, car is parked (probably in garage)
+ self._generateInParkMode(PARK_DURATION_SECONDS, listener)
+ # Second, car will reverse (out of garage)
+ self._generateInReverseMode(REVERSE_DURATION_SECONDS, listener)
+
+ trk = self.gpxDom.getElementsByTagName('trk')[0]
+ trkseg = trk.getElementsByTagName('trkseg')[0]
+ trkpts = trkseg.getElementsByTagName('trkpt')
+
+ print "Vehicle start moving forward"
+ listener.handle(c.VEHICLEPROPERTY_GEAR_SELECTION, 0, c.VEHICLEGEAR_GEAR_DRIVE,
+ "GEAR_SELECTION")
+
+ firstGpxFrame = GpxFrame(trkpts[0])
+ self.speedInMps = firstGpxFrame.speedInMps
+ self.datetime = firstGpxFrame.datetime
+
+ for i in xrange(1, len(trkpts)):
+ self._generateFromGpxFrame(GpxFrame(trkpts[i]), listener)
diff --git a/tools/emulator/gui.py b/tools/emulator/gui.py
index 594526a..3a0161d 100755
--- a/tools/emulator/gui.py
+++ b/tools/emulator/gui.py
@@ -24,7 +24,7 @@
import VehicleHalProto_pb2
from vhal_emulator import Vhal
-import vhal_consts_2_1 as c
+import vhal_consts_2_0 as c
# Define a simple thread that receives messages from a vhal object (v) and prints them
diff --git a/tools/emulator/user_action_generator.py b/tools/emulator/user_action_generator.py
new file mode 100644
index 0000000..50e969c
--- /dev/null
+++ b/tools/emulator/user_action_generator.py
@@ -0,0 +1,219 @@
+# 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.
+#
+
+import time
+
+import vhal_consts_2_0 as c
+
+# A list of user actions as a subset of VHAL properties to simulate
+userActions = [
+ c.VEHICLEPROPERTY_HVAC_POWER_ON,
+ c.VEHICLEPROPERTY_HVAC_TEMPERATURE_SET,
+ c.VEHICLEPROPERTY_HVAC_FAN_SPEED,
+ c.VEHICLEPROPERTY_HVAC_FAN_DIRECTION,
+ c.VEHICLEPROPERTY_HVAC_AUTO_ON,
+ c.VEHICLEPROPERTY_HVAC_RECIRC_ON,
+ c.VEHICLEPROPERTY_HVAC_AC_ON,
+ c.VEHICLEPROPERTY_HVAC_DEFROSTER
+]
+
+propDesc = {
+ c.VEHICLEPROPERTY_HVAC_POWER_ON: 'HVAC_POWER_ON',
+ c.VEHICLEPROPERTY_HVAC_TEMPERATURE_SET: 'HVAC_TEMPERATURE_SET',
+ c.VEHICLEPROPERTY_HVAC_FAN_SPEED: 'HVAC_FAN_SPEED',
+ c.VEHICLEPROPERTY_HVAC_FAN_DIRECTION: 'HVAC_FAN_DIRECTION',
+ c.VEHICLEPROPERTY_HVAC_AUTO_ON: 'HVAC_AUTO_ON',
+ c.VEHICLEPROPERTY_HVAC_RECIRC_ON: 'HVAC_AUTO_RECIRC_ON',
+ c.VEHICLEPROPERTY_HVAC_AC_ON: 'HVAC_AC_ON',
+ c.VEHICLEPROPERTY_HVAC_DEFROSTER: 'HVAC_DEFROSTER'
+}
+
+SHORT_SLEEP_TIME_SEC = 2
+LONG_SLEEP_TIME_SEC = 30
+
+MIN_TEMPERATURE_C = 22
+MAX_TEMPERATURE_C = 28
+
+MIN_FAN_SPEED = 1
+MAX_FAN_SPEED = 5
+
+class ActionPropConfig(object):
+ """
+ A configuration class that parse the vhal property config message and hold the
+ configuration values
+ """
+ def __init__(self, vhalConfig):
+ self.supportedAreas = self._getSupportedAreas(vhalConfig)
+ self.areaConfigs = self._getAreaConfigs(vhalConfig, self.supportedAreas,
+ vhalConfig.value_type)
+
+ def _getSupportedAreas(self, vhalConfig):
+ supportedAreas = []
+ for config in vhalConfig.area_configs:
+ supportedAreas.append(config.area_id)
+
+ return supportedAreas
+
+ def _getAreaConfigs(self, vhalConfig, supportedAreas, valueType):
+ areaConfigs = {}
+ configs = vhalConfig.area_configs
+ if not configs:
+ return None
+
+ if len(configs) == 1:
+ for area in supportedAreas:
+ areaConfigs[area] = AreaConfig(configs[0], valueType)
+ else:
+ for config in configs:
+ areaConfigs[config.area_id] = AreaConfig(config, valueType)
+
+ return areaConfigs
+
+class AreaConfig(object):
+ """
+ A configuration class is representing an area config of a vhal property.
+ """
+ def __init__(self, vhalAreaConfig, valueType):
+ """
+ The class is initialized by parsing the vhal area config object
+ """
+ if valueType == c.VEHICLEPROPERTYTYPE_INT32:
+ self.min = vhalAreaConfig.min_int32_value
+ self.max = vhalAreaConfig.max_int32_value
+ elif valueType == c.VEHICLEPROPERTYTYPE_INT64:
+ self.min = vhalAreaConfig.min_int64_value
+ self.max = vhalAreaConfig.max_int64_value
+ elif valueType == c.VEHICLEPROPERTYTYPE_FLOAT:
+ self.min = vhalAreaConfig.min_float_value
+ self.max = vhalAreaConfig.max_float_value
+ else:
+ self.min = None
+ self.max = None
+
+class UserActionGenerator(object):
+ """
+ A class generate user action related vhal properties in a deterministic algorithm based on
+ pre-fetched vhal configuration
+ """
+ def __init__(self, vhal):
+ self.configs = self._getConfig(vhal)
+
+
+ def _getConfig(self, vhal):
+ """
+ Get vhal configuration for properties that need to be simulated
+ """
+ vhalConfig = {}
+ for actionProp in userActions:
+ vhal.getConfig(actionProp)
+ vhalConfig[actionProp] = ActionPropConfig(vhal.rxMsg().config[0])
+ return vhalConfig
+
+ def _adjustContinuousProperty(self, prop, begin, end, listener):
+ """
+ The method generate continuous property value from "begin" value to "end" value
+ (exclusive).
+ """
+ config = self.configs[prop]
+ for area in config.supportedAreas:
+ areaConfig = config.areaConfigs[area]
+ if begin < end:
+ begin = areaConfig.min if begin < areaConfig.min else begin
+ end = areaConfig.max if end > areaConfig.max else end
+ else:
+ begin = areaConfig.max if begin > areaConfig.max else begin
+ end = areaConfig.min if end < areaConfig.min else end
+
+ for value in self._range(begin, end):
+ listener.handle(prop, area, value, propDesc[prop])
+ time.sleep(0.2)
+
+ def _setProperty(self, prop, value, listener):
+ """
+ This method generates single property value (e.g. boolean or integer value)
+ """
+ config = self.configs[prop]
+ for area in config.supportedAreas:
+ listener.handle(prop, area, value, propDesc[prop])
+ time.sleep(1)
+
+ def _range(self, begin, end):
+ if begin < end:
+ i = begin
+ while i < end:
+ yield i
+ i += 1
+ else:
+ i = begin
+ while i > end:
+ yield i
+ i += -1
+
+ def generate(self, listener):
+ """
+ Main method that simulate user in-car actions such as HVAC
+ """
+
+ # Turn on HVAC only for front seats
+ listener.handle(c.VEHICLEPROPERTY_HVAC_POWER_ON, c.VEHICLEAREASEAT_ROW_1_LEFT,
+ 1, 'HVAC_POWER_ON')
+ listener.handle(c.VEHICLEPROPERTY_HVAC_POWER_ON, c.VEHICLEAREASEAT_ROW_1_RIGHT,
+ 1, 'HVAC_POWER_ON')
+ time.sleep(SHORT_SLEEP_TIME_SEC)
+
+ while True:
+
+ self._setProperty(c.VEHICLEPROPERTY_HVAC_AC_ON, 1, listener)
+ time.sleep(SHORT_SLEEP_TIME_SEC)
+
+ self._setProperty(c.VEHICLEPROPERTY_HVAC_FAN_DIRECTION,
+ c.VEHICLEHVACFANDIRECTION_FACE, listener)
+ time.sleep(SHORT_SLEEP_TIME_SEC)
+
+ self._adjustContinuousProperty(c.VEHICLEPROPERTY_HVAC_TEMPERATURE_SET,
+ MAX_TEMPERATURE_C, MIN_TEMPERATURE_C, listener)
+ time.sleep(SHORT_SLEEP_TIME_SEC)
+
+ self._adjustContinuousProperty(c.VEHICLEPROPERTY_HVAC_FAN_SPEED,
+ MIN_FAN_SPEED, MAX_FAN_SPEED, listener)
+ time.sleep(LONG_SLEEP_TIME_SEC)
+
+ self._setProperty(c.VEHICLEPROPERTY_HVAC_AUTO_ON, 1, listener)
+ time.sleep(LONG_SLEEP_TIME_SEC)
+
+ self._setProperty(c.VEHICLEPROPERTY_HVAC_AUTO_ON, 0, listener)
+ time.sleep(SHORT_SLEEP_TIME_SEC)
+
+ self._setProperty(c.VEHICLEPROPERTY_HVAC_FAN_DIRECTION,
+ c.VEHICLEHVACFANDIRECTION_FACE, listener)
+ time.sleep(LONG_SLEEP_TIME_SEC)
+
+ self._setProperty(c.VEHICLEPROPERTY_HVAC_DEFROSTER, 1, listener)
+ time.sleep(SHORT_SLEEP_TIME_SEC)
+
+ self._setProperty(c.VEHICLEPROPERTY_HVAC_FAN_DIRECTION,
+ c.VEHICLEHVACFANDIRECTION_DEFROST, listener)
+ time.sleep(SHORT_SLEEP_TIME_SEC)
+
+ self._adjustContinuousProperty(c.VEHICLEPROPERTY_HVAC_TEMPERATURE_SET,
+ MIN_TEMPERATURE_C, MAX_TEMPERATURE_C, listener)
+ time.sleep(SHORT_SLEEP_TIME_SEC)
+
+ self._adjustContinuousProperty(c.VEHICLEPROPERTY_HVAC_FAN_SPEED,
+ MAX_FAN_SPEED, MIN_FAN_SPEED, listener)
+ time.sleep(LONG_SLEEP_TIME_SEC)
+
+ self._setProperty(c.VEHICLEPROPERTY_HVAC_AC_ON, 0, listener)
+ time.sleep(SHORT_SLEEP_TIME_SEC)
diff --git a/tools/emulator/vhal_const_generate.py b/tools/emulator/vhal_const_generate.py
index 55bcd1b..77bb74b 100755
--- a/tools/emulator/vhal_const_generate.py
+++ b/tools/emulator/vhal_const_generate.py
@@ -1,4 +1,4 @@
-#!/usr/bin/env python3.4
+#!/usr/bin/env python3
#
# Copyright (C) 2017 The Android Open Source Project
#
@@ -94,23 +94,15 @@
print("Vehicle HAL was not found at %s. lunch may provide a correct environment, or files moved" % vhal_location)
sys.exit(1)
-vhal_20_file = os.path.join(vhal_location, '2.0', 'types.hal')
-vhal_21_file = os.path.join(vhal_location, '2.1', 'types.hal')
-
-print("Generating content from Vehicle HAL 2.0 (%s) and 2.1 (%s)" % (vhal_20_file, vhal_21_file))
-
-vhal_20_doc = parser.parse(vhal_20_file)
-vhal_21_doc = parser.parse(vhal_21_file)
-
-# Work around the fact that the parser doesn't (yet?) deal with inheritance.
-# WARNING: This pattern is rather unsafe since we're not merging the lists as we should!
-# vhal_21_doc['enums']['VehiclePropertyGroup'] = vhal_20_doc['enums']['VehiclePropertyGroup']
-# vhal_21_doc['enums']['VehiclePropertyType'] = vhal_20_doc['enums']['VehiclePropertyType']
-# vhal_21_doc['enums']['VehicleArea'] = vhal_20_doc['enums']['VehicleArea']
-
def generateHal20():
- print("********************************")
- print("Generating VHal 2.0 constants...")
+ vhal_20_file = os.path.join(vhal_location, '2.0', 'types.hal')
+ if not(os.path.exists(vhal_20_file)):
+ print("Vehicle HAL was not found at %s. lunch may provide a correct environment, or files moved" % vhal_location)
+ sys.exit(1)
+
+ print("Generating constants from Vehicle HAL 2.0 (%s)" % (vhal_20_file))
+ vhal_20_doc = parser.parse(vhal_20_file)
+
vhal_20_file = open(os.path.join(script_directory, 'vhal_consts_2_0.py'), 'w')
printHeader(vhal_20_file)
@@ -129,19 +121,6 @@
print(" TYPE_FLOAT = [VEHICLEPROPERTYTYPE_FLOAT]", file=vhal_20_file)
print(" TYPE_INT32S = [VEHICLEPROPERTYTYPE_INT32_VEC]", file=vhal_20_file)
print(" TYPE_FLOATS = [VEHICLEPROPERTYTYPE_FLOAT_VEC]", file=vhal_20_file)
- print(" TYPE_COMPLEX = [VEHICLEPROPERTYTYPE_COMPLEX]", file=vhal_20_file)
-
-def generateHal21():
- print("********************************")
- print("Generating VHal 2.1 constants...")
- vhal_21_file = open(os.path.join(script_directory, 'vhal_consts_2_1.py'), 'w')
- printHeader(vhal_21_file)
- print('from vhal_consts_2_0 import *', file=vhal_21_file)
-
- for group in vhal_21_doc['enums']:
- print(group)
- printEnum(vhal_21_doc, group, vhal_21_file, lambda x : hex(x))
-
+ print(" TYPE_MIXED = [VEHICLEPROPERTYTYPE_MIXED]", file=vhal_20_file)
generateHal20()
-# generateHal21()
diff --git a/tools/emulator/vhal_consts_2_0.py b/tools/emulator/vhal_consts_2_0.py
index 59c430c..a9d9990 100644
--- a/tools/emulator/vhal_consts_2_0.py
+++ b/tools/emulator/vhal_consts_2_0.py
@@ -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,26 +15,48 @@
# DO NOT EDIT MANUALLY
# This file was autogenerated by vhal_const_generate.py
-# VehicleAudioContextFlag
-VEHICLEAUDIOCONTEXTFLAG_MUSIC_FLAG = 0x1
-VEHICLEAUDIOCONTEXTFLAG_NAVIGATION_FLAG = 0x2
-VEHICLEAUDIOCONTEXTFLAG_VOICE_COMMAND_FLAG = 0x4
-VEHICLEAUDIOCONTEXTFLAG_CALL_FLAG = 0x8
-VEHICLEAUDIOCONTEXTFLAG_ALARM_FLAG = 0x10
-VEHICLEAUDIOCONTEXTFLAG_NOTIFICATION_FLAG = 0x20
-VEHICLEAUDIOCONTEXTFLAG_UNKNOWN_FLAG = 0x40
-VEHICLEAUDIOCONTEXTFLAG_SAFETY_ALERT_FLAG = 0x80
-VEHICLEAUDIOCONTEXTFLAG_CD_ROM_FLAG = 0x100
-VEHICLEAUDIOCONTEXTFLAG_AUX_AUDIO_FLAG = 0x200
-VEHICLEAUDIOCONTEXTFLAG_SYSTEM_SOUND_FLAG = 0x400
-VEHICLEAUDIOCONTEXTFLAG_RADIO_FLAG = 0x800
-VEHICLEAUDIOCONTEXTFLAG_EXT_SOURCE_FLAG = 0x1000
+# VehicleUnit
+VEHICLEUNIT_SHOULD_NOT_USE = 0x0
+VEHICLEUNIT_METER_PER_SEC = 0x1
+VEHICLEUNIT_RPM = 0x2
+VEHICLEUNIT_HERTZ = 0x3
+VEHICLEUNIT_PERCENTILE = 0x10
+VEHICLEUNIT_MILLIMETER = 0x20
+VEHICLEUNIT_METER = 0x21
+VEHICLEUNIT_KILOMETER = 0x23
+VEHICLEUNIT_CELSIUS = 0x30
+VEHICLEUNIT_FAHRENHEIT = 0x31
+VEHICLEUNIT_KELVIN = 0x32
+VEHICLEUNIT_MILLILITER = 0x40
+VEHICLEUNIT_NANO_SECS = 0x50
+VEHICLEUNIT_SECS = 0x53
+VEHICLEUNIT_YEAR = 0x59
+VEHICLEUNIT_KILOPASCAL = 0x70
+VEHICLEUNIT_WATT_HOUR = 0x60
+VEHICLEUNIT_MILLIAMPERE = 0x61
+VEHICLEUNIT_MILLIVOLT = 0x62
+VEHICLEUNIT_MILLIWATTS = 0x63
-# VehicleAudioFocusIndex
-VEHICLEAUDIOFOCUSINDEX_FOCUS = 0x0
-VEHICLEAUDIOFOCUSINDEX_STREAMS = 0x1
-VEHICLEAUDIOFOCUSINDEX_EXTERNAL_FOCUS_STATE = 0x2
-VEHICLEAUDIOFOCUSINDEX_AUDIO_CONTEXTS = 0x3
+# VehicleLightSwitch
+VEHICLELIGHTSWITCH_OFF = 0x0
+VEHICLELIGHTSWITCH_ON = 0x1
+VEHICLELIGHTSWITCH_DAYTIME_RUNNING = 0x2
+VEHICLELIGHTSWITCH_AUTOMATIC = 0x100
+
+# VmsMessageWithLayerIntegerValuesIndex
+VMSMESSAGEWITHLAYERINTEGERVALUESINDEX_LAYER_TYPE = 0x1
+VMSMESSAGEWITHLAYERINTEGERVALUESINDEX_LAYER_SUBTYPE = 0x2
+VMSMESSAGEWITHLAYERINTEGERVALUESINDEX_LAYER_VERSION = 0x3
+
+# VehiclePropertyGroup
+VEHICLEPROPERTYGROUP_SYSTEM = 0x10000000
+VEHICLEPROPERTYGROUP_VENDOR = 0x20000000
+VEHICLEPROPERTYGROUP_MASK = 0xf0000000
+
+# VehicleApPowerStateShutdownParam
+VEHICLEAPPOWERSTATESHUTDOWNPARAM_SHUTDOWN_IMMEDIATELY = 0x1
+VEHICLEAPPOWERSTATESHUTDOWNPARAM_CAN_SLEEP = 0x2
+VEHICLEAPPOWERSTATESHUTDOWNPARAM_SHUTDOWN_ONLY = 0x3
# Obd2CommonIgnitionMonitors
OBD2COMMONIGNITIONMONITORS_COMPONENTS_AVAILABLE = 0x1
@@ -44,6 +66,441 @@
OBD2COMMONIGNITIONMONITORS_MISFIRE_AVAILABLE = 0x10
OBD2COMMONIGNITIONMONITORS_MISFIRE_INCOMPLETE = 0x20
+# PortLocationType
+PORTLOCATIONTYPE_UNKNOWN = 0x0
+PORTLOCATIONTYPE_FRONT_LEFT = 0x1
+PORTLOCATIONTYPE_FRONT_RIGHT = 0x2
+PORTLOCATIONTYPE_REAR_RIGHT = 0x3
+PORTLOCATIONTYPE_REAR_LEFT = 0x4
+PORTLOCATIONTYPE_FRONT = 0x5
+PORTLOCATIONTYPE_REAR = 0x6
+
+# Obd2SparkIgnitionMonitors
+OBD2SPARKIGNITIONMONITORS_EGR_AVAILABLE = 0x40
+OBD2SPARKIGNITIONMONITORS_EGR_INCOMPLETE = 0x80
+OBD2SPARKIGNITIONMONITORS_OXYGEN_SENSOR_HEATER_AVAILABLE = 0x100
+OBD2SPARKIGNITIONMONITORS_OXYGEN_SENSOR_HEATER_INCOMPLETE = 0x200
+OBD2SPARKIGNITIONMONITORS_OXYGEN_SENSOR_AVAILABLE = 0x400
+OBD2SPARKIGNITIONMONITORS_OXYGEN_SENSOR_INCOMPLETE = 0x800
+OBD2SPARKIGNITIONMONITORS_AC_REFRIGERANT_AVAILABLE = 0x1000
+OBD2SPARKIGNITIONMONITORS_AC_REFRIGERANT_INCOMPLETE = 0x2000
+OBD2SPARKIGNITIONMONITORS_SECONDARY_AIR_SYSTEM_AVAILABLE = 0x4000
+OBD2SPARKIGNITIONMONITORS_SECONDARY_AIR_SYSTEM_INCOMPLETE = 0x8000
+OBD2SPARKIGNITIONMONITORS_EVAPORATIVE_SYSTEM_AVAILABLE = 0x10000
+OBD2SPARKIGNITIONMONITORS_EVAPORATIVE_SYSTEM_INCOMPLETE = 0x20000
+OBD2SPARKIGNITIONMONITORS_HEATED_CATALYST_AVAILABLE = 0x40000
+OBD2SPARKIGNITIONMONITORS_HEATED_CATALYST_INCOMPLETE = 0x80000
+OBD2SPARKIGNITIONMONITORS_CATALYST_AVAILABLE = 0x100000
+OBD2SPARKIGNITIONMONITORS_CATALYST_INCOMPLETE = 0x200000
+
+# VmsSubscriptionsStateIntegerValuesIndex
+VMSSUBSCRIPTIONSSTATEINTEGERVALUESINDEX_SEQUENCE_NUMBER = 0x1
+VMSSUBSCRIPTIONSSTATEINTEGERVALUESINDEX_NUMBER_OF_LAYERS = 0x2
+VMSSUBSCRIPTIONSSTATEINTEGERVALUESINDEX_NUMBER_OF_ASSOCIATED_LAYERS = 0x3
+VMSSUBSCRIPTIONSSTATEINTEGERVALUESINDEX_SUBSCRIPTIONS_START = 0x4
+
+# VehicleApPowerStateReq
+VEHICLEAPPOWERSTATEREQ_OFF = 0x0
+VEHICLEAPPOWERSTATEREQ_DEEP_SLEEP = 0x1
+VEHICLEAPPOWERSTATEREQ_ON_DISP_OFF = 0x2
+VEHICLEAPPOWERSTATEREQ_ON_FULL = 0x3
+VEHICLEAPPOWERSTATEREQ_SHUTDOWN_PREPARE = 0x4
+
+# VehicleApPowerStateReqIndex
+VEHICLEAPPOWERSTATEREQINDEX_STATE = 0x0
+VEHICLEAPPOWERSTATEREQINDEX_ADDITIONAL = 0x1
+
+# Obd2IgnitionMonitorKind
+OBD2IGNITIONMONITORKIND_SPARK = 0x0
+OBD2IGNITIONMONITORKIND_COMPRESSION = 0x1
+
+# VehiclePropertyAccess
+VEHICLEPROPERTYACCESS_NONE = 0x0
+VEHICLEPROPERTYACCESS_READ = 0x1
+VEHICLEPROPERTYACCESS_WRITE = 0x2
+VEHICLEPROPERTYACCESS_READ_WRITE = 0x3
+
+# VehicleOilLevel
+VEHICLEOILLEVEL_CRITICALLY_LOW = 0x0
+VEHICLEOILLEVEL_LOW = 0x1
+VEHICLEOILLEVEL_NORMAL = 0x2
+VEHICLEOILLEVEL_HIGH = 0x3
+VEHICLEOILLEVEL_ERROR = 0x4
+
+# VmsBaseMessageIntegerValuesIndex
+VMSBASEMESSAGEINTEGERVALUESINDEX_MESSAGE_TYPE = 0x0
+
+# StatusCode
+STATUSCODE_OK = 0x0
+STATUSCODE_TRY_AGAIN = 0x1
+STATUSCODE_INVALID_ARG = 0x2
+STATUSCODE_NOT_AVAILABLE = 0x3
+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
+VEHICLELIGHTSTATE_DAYTIME_RUNNING = 0x2
+
+# VehicleApPowerBootupReason
+VEHICLEAPPOWERBOOTUPREASON_USER_POWER_ON = 0x0
+VEHICLEAPPOWERBOOTUPREASON_USER_UNLOCK = 0x1
+VEHICLEAPPOWERBOOTUPREASON_TIMER = 0x2
+
+# VehiclePropertyChangeMode
+VEHICLEPROPERTYCHANGEMODE_STATIC = 0x0
+VEHICLEPROPERTYCHANGEMODE_ON_CHANGE = 0x1
+VEHICLEPROPERTYCHANGEMODE_CONTINUOUS = 0x2
+
+# VmsMessageType
+VMSMESSAGETYPE_SUBSCRIBE = 0x1
+VMSMESSAGETYPE_SUBSCRIBE_TO_PUBLISHER = 0x2
+VMSMESSAGETYPE_UNSUBSCRIBE = 0x3
+VMSMESSAGETYPE_UNSUBSCRIBE_TO_PUBLISHER = 0x4
+VMSMESSAGETYPE_OFFERING = 0x5
+VMSMESSAGETYPE_AVAILABILITY_REQUEST = 0x6
+VMSMESSAGETYPE_SUBSCRIPTIONS_REQUEST = 0x7
+VMSMESSAGETYPE_AVAILABILITY_RESPONSE = 0x8
+VMSMESSAGETYPE_AVAILABILITY_CHANGE = 0x9
+VMSMESSAGETYPE_SUBSCRIPTIONS_RESPONSE = 0xa
+VMSMESSAGETYPE_SUBSCRIPTIONS_CHANGE = 0xb
+VMSMESSAGETYPE_DATA = 0xc
+VMSMESSAGETYPE_PUBLISHER_ID_REQUEST = 0xd
+VMSMESSAGETYPE_PUBLISHER_ID_RESPONSE = 0xe
+VMSMESSAGETYPE_PUBLISHER_INFORMATION_REQUEST = 0xf
+VMSMESSAGETYPE_PUBLISHER_INFORMATION_RESPONSE = 0x10
+VMSMESSAGETYPE_LAST_VMS_MESSAGE_TYPE = 0x10
+
+# DiagnosticIntegerSensorIndex
+DIAGNOSTICINTEGERSENSORINDEX_FUEL_SYSTEM_STATUS = 0x0
+DIAGNOSTICINTEGERSENSORINDEX_MALFUNCTION_INDICATOR_LIGHT_ON = 0x1
+DIAGNOSTICINTEGERSENSORINDEX_IGNITION_MONITORS_SUPPORTED = 0x2
+DIAGNOSTICINTEGERSENSORINDEX_IGNITION_SPECIFIC_MONITORS = 0x3
+DIAGNOSTICINTEGERSENSORINDEX_INTAKE_AIR_TEMPERATURE = 0x4
+DIAGNOSTICINTEGERSENSORINDEX_COMMANDED_SECONDARY_AIR_STATUS = 0x5
+DIAGNOSTICINTEGERSENSORINDEX_NUM_OXYGEN_SENSORS_PRESENT = 0x6
+DIAGNOSTICINTEGERSENSORINDEX_RUNTIME_SINCE_ENGINE_START = 0x7
+DIAGNOSTICINTEGERSENSORINDEX_DISTANCE_TRAVELED_WITH_MALFUNCTION_INDICATOR_LIGHT_ON = 0x8
+DIAGNOSTICINTEGERSENSORINDEX_WARMUPS_SINCE_CODES_CLEARED = 0x9
+DIAGNOSTICINTEGERSENSORINDEX_DISTANCE_TRAVELED_SINCE_CODES_CLEARED = 0xa
+DIAGNOSTICINTEGERSENSORINDEX_ABSOLUTE_BAROMETRIC_PRESSURE = 0xb
+DIAGNOSTICINTEGERSENSORINDEX_CONTROL_MODULE_VOLTAGE = 0xc
+DIAGNOSTICINTEGERSENSORINDEX_AMBIENT_AIR_TEMPERATURE = 0xd
+DIAGNOSTICINTEGERSENSORINDEX_TIME_WITH_MALFUNCTION_LIGHT_ON = 0xe
+DIAGNOSTICINTEGERSENSORINDEX_TIME_SINCE_TROUBLE_CODES_CLEARED = 0xf
+DIAGNOSTICINTEGERSENSORINDEX_MAX_FUEL_AIR_EQUIVALENCE_RATIO = 0x10
+DIAGNOSTICINTEGERSENSORINDEX_MAX_OXYGEN_SENSOR_VOLTAGE = 0x11
+DIAGNOSTICINTEGERSENSORINDEX_MAX_OXYGEN_SENSOR_CURRENT = 0x12
+DIAGNOSTICINTEGERSENSORINDEX_MAX_INTAKE_MANIFOLD_ABSOLUTE_PRESSURE = 0x13
+DIAGNOSTICINTEGERSENSORINDEX_MAX_AIR_FLOW_RATE_FROM_MASS_AIR_FLOW_SENSOR = 0x14
+DIAGNOSTICINTEGERSENSORINDEX_FUEL_TYPE = 0x15
+DIAGNOSTICINTEGERSENSORINDEX_FUEL_RAIL_ABSOLUTE_PRESSURE = 0x16
+DIAGNOSTICINTEGERSENSORINDEX_ENGINE_OIL_TEMPERATURE = 0x17
+DIAGNOSTICINTEGERSENSORINDEX_DRIVER_DEMAND_PERCENT_TORQUE = 0x18
+DIAGNOSTICINTEGERSENSORINDEX_ENGINE_ACTUAL_PERCENT_TORQUE = 0x19
+DIAGNOSTICINTEGERSENSORINDEX_ENGINE_REFERENCE_PERCENT_TORQUE = 0x1a
+DIAGNOSTICINTEGERSENSORINDEX_ENGINE_PERCENT_TORQUE_DATA_IDLE = 0x1b
+DIAGNOSTICINTEGERSENSORINDEX_ENGINE_PERCENT_TORQUE_DATA_POINT1 = 0x1c
+DIAGNOSTICINTEGERSENSORINDEX_ENGINE_PERCENT_TORQUE_DATA_POINT2 = 0x1d
+DIAGNOSTICINTEGERSENSORINDEX_ENGINE_PERCENT_TORQUE_DATA_POINT3 = 0x1e
+DIAGNOSTICINTEGERSENSORINDEX_ENGINE_PERCENT_TORQUE_DATA_POINT4 = 0x1f
+DIAGNOSTICINTEGERSENSORINDEX_LAST_SYSTEM_INDEX = 0x1f
+
+# VmsMessageWithLayerAndPublisherIdIntegerValuesIndex
+VMSMESSAGEWITHLAYERANDPUBLISHERIDINTEGERVALUESINDEX_PUBLISHER_ID = 0x4
+
+# VmsOfferingMessageIntegerValuesIndex
+VMSOFFERINGMESSAGEINTEGERVALUESINDEX_PUBLISHER_ID = 0x1
+VMSOFFERINGMESSAGEINTEGERVALUESINDEX_NUMBER_OF_OFFERS = 0x2
+VMSOFFERINGMESSAGEINTEGERVALUESINDEX_OFFERING_START = 0x3
+
+# VehicleApPowerStateConfigFlag
+VEHICLEAPPOWERSTATECONFIGFLAG_ENABLE_DEEP_SLEEP_FLAG = 0x1
+VEHICLEAPPOWERSTATECONFIGFLAG_CONFIG_SUPPORT_TIMER_POWER_ON_FLAG = 0x2
+
+# FuelType
+FUELTYPE_FUEL_TYPE_UNKNOWN = 0x0
+FUELTYPE_FUEL_TYPE_UNLEADED = 0x1
+FUELTYPE_FUEL_TYPE_LEADED = 0x2
+FUELTYPE_FUEL_TYPE_DIESEL_1 = 0x3
+FUELTYPE_FUEL_TYPE_DIESEL_2 = 0x4
+FUELTYPE_FUEL_TYPE_BIODIESEL = 0x5
+FUELTYPE_FUEL_TYPE_E85 = 0x6
+FUELTYPE_FUEL_TYPE_LPG = 0x7
+FUELTYPE_FUEL_TYPE_CNG = 0x8
+FUELTYPE_FUEL_TYPE_LNG = 0x9
+FUELTYPE_FUEL_TYPE_ELECTRIC = 0xa
+FUELTYPE_FUEL_TYPE_HYDROGEN = 0xb
+FUELTYPE_FUEL_TYPE_OTHER = 0xc
+
+# VehicleIgnitionState
+VEHICLEIGNITIONSTATE_UNDEFINED = 0x0
+VEHICLEIGNITIONSTATE_LOCK = 0x1
+VEHICLEIGNITIONSTATE_OFF = 0x2
+VEHICLEIGNITIONSTATE_ACC = 0x3
+VEHICLEIGNITIONSTATE_ON = 0x4
+VEHICLEIGNITIONSTATE_START = 0x5
+
+# VehicleAreaSeat
+VEHICLEAREASEAT_ROW_1_LEFT = 0x1
+VEHICLEAREASEAT_ROW_1_CENTER = 0x2
+VEHICLEAREASEAT_ROW_1_RIGHT = 0x4
+VEHICLEAREASEAT_ROW_2_LEFT = 0x10
+VEHICLEAREASEAT_ROW_2_CENTER = 0x20
+VEHICLEAREASEAT_ROW_2_RIGHT = 0x40
+VEHICLEAREASEAT_ROW_3_LEFT = 0x100
+VEHICLEAREASEAT_ROW_3_CENTER = 0x200
+VEHICLEAREASEAT_ROW_3_RIGHT = 0x400
+
+# VehicleTurnSignal
+VEHICLETURNSIGNAL_NONE = 0x0
+VEHICLETURNSIGNAL_RIGHT = 0x1
+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
+
+# VehiclePropertyType
+VEHICLEPROPERTYTYPE_STRING = 0x100000
+VEHICLEPROPERTYTYPE_BOOLEAN = 0x200000
+VEHICLEPROPERTYTYPE_INT32 = 0x400000
+VEHICLEPROPERTYTYPE_INT32_VEC = 0x410000
+VEHICLEPROPERTYTYPE_INT64 = 0x500000
+VEHICLEPROPERTYTYPE_INT64_VEC = 0x510000
+VEHICLEPROPERTYTYPE_FLOAT = 0x600000
+VEHICLEPROPERTYTYPE_FLOAT_VEC = 0x610000
+VEHICLEPROPERTYTYPE_BYTES = 0x700000
+VEHICLEPROPERTYTYPE_MIXED = 0xe00000
+VEHICLEPROPERTYTYPE_MASK = 0xff0000
+
+# VehicleAreaMirror
+VEHICLEAREAMIRROR_DRIVER_LEFT = 0x1
+VEHICLEAREAMIRROR_DRIVER_RIGHT = 0x2
+VEHICLEAREAMIRROR_DRIVER_CENTER = 0x4
+
+# Obd2FuelSystemStatus
+OBD2FUELSYSTEMSTATUS_OPEN_INSUFFICIENT_ENGINE_TEMPERATURE = 0x1
+OBD2FUELSYSTEMSTATUS_CLOSED_LOOP = 0x2
+OBD2FUELSYSTEMSTATUS_OPEN_ENGINE_LOAD_OR_DECELERATION = 0x4
+OBD2FUELSYSTEMSTATUS_OPEN_SYSTEM_FAILURE = 0x8
+OBD2FUELSYSTEMSTATUS_CLOSED_LOOP_BUT_FEEDBACK_FAULT = 0x10
+
+# Obd2SecondaryAirStatus
+OBD2SECONDARYAIRSTATUS_UPSTREAM = 0x1
+OBD2SECONDARYAIRSTATUS_DOWNSTREAM_OF_CATALYCIC_CONVERTER = 0x2
+OBD2SECONDARYAIRSTATUS_FROM_OUTSIDE_OR_OFF = 0x4
+OBD2SECONDARYAIRSTATUS_PUMP_ON_FOR_DIAGNOSTICS = 0x8
+
+# VehicleGear
+VEHICLEGEAR_GEAR_NEUTRAL = 0x1
+VEHICLEGEAR_GEAR_REVERSE = 0x2
+VEHICLEGEAR_GEAR_PARK = 0x4
+VEHICLEGEAR_GEAR_DRIVE = 0x8
+VEHICLEGEAR_GEAR_1 = 0x10
+VEHICLEGEAR_GEAR_2 = 0x20
+VEHICLEGEAR_GEAR_3 = 0x40
+VEHICLEGEAR_GEAR_4 = 0x80
+VEHICLEGEAR_GEAR_5 = 0x100
+VEHICLEGEAR_GEAR_6 = 0x200
+VEHICLEGEAR_GEAR_7 = 0x400
+VEHICLEGEAR_GEAR_8 = 0x800
+VEHICLEGEAR_GEAR_9 = 0x1000
+
+# VmsPublisherInformationIntegerValuesIndex
+VMSPUBLISHERINFORMATIONINTEGERVALUESINDEX_PUBLISHER_ID = 0x1
+
+# VmsAvailabilityStateIntegerValuesIndex
+VMSAVAILABILITYSTATEINTEGERVALUESINDEX_SEQUENCE_NUMBER = 0x1
+VMSAVAILABILITYSTATEINTEGERVALUESINDEX_NUMBER_OF_ASSOCIATED_LAYERS = 0x2
+VMSAVAILABILITYSTATEINTEGERVALUESINDEX_LAYERS_START = 0x3
+
+# VehicleHwKeyInputAction
+VEHICLEHWKEYINPUTACTION_ACTION_DOWN = 0x0
+VEHICLEHWKEYINPUTACTION_ACTION_UP = 0x1
+
+# VehicleApPowerStateReport
+VEHICLEAPPOWERSTATEREPORT_BOOT_COMPLETE = 0x1
+VEHICLEAPPOWERSTATEREPORT_DEEP_SLEEP_ENTRY = 0x2
+VEHICLEAPPOWERSTATEREPORT_DEEP_SLEEP_EXIT = 0x3
+VEHICLEAPPOWERSTATEREPORT_SHUTDOWN_POSTPONE = 0x4
+VEHICLEAPPOWERSTATEREPORT_SHUTDOWN_START = 0x5
+VEHICLEAPPOWERSTATEREPORT_DISPLAY_OFF = 0x6
+VEHICLEAPPOWERSTATEREPORT_DISPLAY_ON = 0x7
+
+# VehicleDisplay
+VEHICLEDISPLAY_MAIN = 0x0
+VEHICLEDISPLAY_INSTRUMENT_CLUSTER = 0x1
+
+# Obd2CompressionIgnitionMonitors
+OBD2COMPRESSIONIGNITIONMONITORS_EGR_OR_VVT_AVAILABLE = 0x40
+OBD2COMPRESSIONIGNITIONMONITORS_EGR_OR_VVT_INCOMPLETE = 0x80
+OBD2COMPRESSIONIGNITIONMONITORS_PM_FILTER_AVAILABLE = 0x100
+OBD2COMPRESSIONIGNITIONMONITORS_PM_FILTER_INCOMPLETE = 0x200
+OBD2COMPRESSIONIGNITIONMONITORS_EXHAUST_GAS_SENSOR_AVAILABLE = 0x400
+OBD2COMPRESSIONIGNITIONMONITORS_EXHAUST_GAS_SENSOR_INCOMPLETE = 0x800
+OBD2COMPRESSIONIGNITIONMONITORS_BOOST_PRESSURE_AVAILABLE = 0x1000
+OBD2COMPRESSIONIGNITIONMONITORS_BOOST_PRESSURE_INCOMPLETE = 0x2000
+OBD2COMPRESSIONIGNITIONMONITORS_NOx_SCR_AVAILABLE = 0x4000
+OBD2COMPRESSIONIGNITIONMONITORS_NOx_SCR_INCOMPLETE = 0x8000
+OBD2COMPRESSIONIGNITIONMONITORS_NMHC_CATALYST_AVAILABLE = 0x10000
+OBD2COMPRESSIONIGNITIONMONITORS_NMHC_CATALYST_INCOMPLETE = 0x20000
+
+# VehicleHvacFanDirection
+VEHICLEHVACFANDIRECTION_FACE = 0x1
+VEHICLEHVACFANDIRECTION_FLOOR = 0x2
+VEHICLEHVACFANDIRECTION_DEFROST = 0x4
+
+# VehicleAreaDoor
+VEHICLEAREADOOR_ROW_1_LEFT = 0x1
+VEHICLEAREADOOR_ROW_1_RIGHT = 0x4
+VEHICLEAREADOOR_ROW_2_LEFT = 0x10
+VEHICLEAREADOOR_ROW_2_RIGHT = 0x40
+VEHICLEAREADOOR_ROW_3_LEFT = 0x100
+VEHICLEAREADOOR_ROW_3_RIGHT = 0x400
+VEHICLEAREADOOR_HOOD = 0x10000000
+VEHICLEAREADOOR_REAR = 0x20000000
+
+# SubscribeFlags
+SUBSCRIBEFLAGS_UNDEFINED = 0x0
+SUBSCRIBEFLAGS_EVENTS_FROM_CAR = 0x1
+SUBSCRIBEFLAGS_EVENTS_FROM_ANDROID = 0x2
+
+# VehicleProperty
+VEHICLEPROPERTY_INVALID = 0x0
+VEHICLEPROPERTY_INFO_VIN = 0x11100100
+VEHICLEPROPERTY_INFO_MAKE = 0x11100101
+VEHICLEPROPERTY_INFO_MODEL = 0x11100102
+VEHICLEPROPERTY_INFO_MODEL_YEAR = 0x11400103
+VEHICLEPROPERTY_INFO_FUEL_CAPACITY = 0x11600104
+VEHICLEPROPERTY_INFO_FUEL_TYPE = 0x11410105
+VEHICLEPROPERTY_INFO_EV_BATTERY_CAPACITY = 0x11600106
+VEHICLEPROPERTY_INFO_EV_CONNECTOR_TYPE = 0x11410107
+VEHICLEPROPERTY_INFO_FUEL_DOOR_LOCATION = 0x11400108
+VEHICLEPROPERTY_INFO_EV_PORT_LOCATION = 0x11400109
+VEHICLEPROPERTY_INFO_DRIVER_SEAT = 0x1540010a
+VEHICLEPROPERTY_PERF_ODOMETER = 0x11600204
+VEHICLEPROPERTY_PERF_VEHICLE_SPEED = 0x11600207
+VEHICLEPROPERTY_ENGINE_COOLANT_TEMP = 0x11600301
+VEHICLEPROPERTY_ENGINE_OIL_LEVEL = 0x11400303
+VEHICLEPROPERTY_ENGINE_OIL_TEMP = 0x11600304
+VEHICLEPROPERTY_ENGINE_RPM = 0x11600305
+VEHICLEPROPERTY_WHEEL_TICK = 0x11510306
+VEHICLEPROPERTY_FUEL_LEVEL = 0x11600307
+VEHICLEPROPERTY_FUEL_DOOR_OPEN = 0x11200308
+VEHICLEPROPERTY_EV_BATTERY_LEVEL = 0x11600309
+VEHICLEPROPERTY_EV_CHARGE_PORT_OPEN = 0x1120030a
+VEHICLEPROPERTY_EV_CHARGE_PORT_CONNECTED = 0x1120030b
+VEHICLEPROPERTY_EV_BATTERY_INSTANTANEOUS_CHARGE_RATE = 0x1160030c
+VEHICLEPROPERTY_RANGE_REMAINING = 0x11600308
+VEHICLEPROPERTY_TIRE_PRESSURE = 0x17e00309
+VEHICLEPROPERTY_GEAR_SELECTION = 0x11400400
+VEHICLEPROPERTY_CURRENT_GEAR = 0x11400401
+VEHICLEPROPERTY_PARKING_BRAKE_ON = 0x11200402
+VEHICLEPROPERTY_PARKING_BRAKE_AUTO_APPLY = 0x11200403
+VEHICLEPROPERTY_FUEL_LEVEL_LOW = 0x11200405
+VEHICLEPROPERTY_NIGHT_MODE = 0x11200407
+VEHICLEPROPERTY_TURN_SIGNAL_STATE = 0x11400408
+VEHICLEPROPERTY_IGNITION_STATE = 0x11400409
+VEHICLEPROPERTY_ABS_ACTIVE = 0x1120040a
+VEHICLEPROPERTY_TRACTION_CONTROL_ACTIVE = 0x1120040b
+VEHICLEPROPERTY_HVAC_FAN_SPEED = 0x15400500
+VEHICLEPROPERTY_HVAC_FAN_DIRECTION = 0x15400501
+VEHICLEPROPERTY_HVAC_TEMPERATURE_CURRENT = 0x15600502
+VEHICLEPROPERTY_HVAC_TEMPERATURE_SET = 0x15600503
+VEHICLEPROPERTY_HVAC_DEFROSTER = 0x13200504
+VEHICLEPROPERTY_HVAC_AC_ON = 0x15200505
+VEHICLEPROPERTY_HVAC_MAX_AC_ON = 0x15200506
+VEHICLEPROPERTY_HVAC_MAX_DEFROST_ON = 0x15200507
+VEHICLEPROPERTY_HVAC_RECIRC_ON = 0x15200508
+VEHICLEPROPERTY_HVAC_DUAL_ON = 0x15200509
+VEHICLEPROPERTY_HVAC_AUTO_ON = 0x1520050a
+VEHICLEPROPERTY_HVAC_SEAT_TEMPERATURE = 0x1540050b
+VEHICLEPROPERTY_HVAC_SIDE_MIRROR_HEAT = 0x1440050c
+VEHICLEPROPERTY_HVAC_STEERING_WHEEL_HEAT = 0x1140050d
+VEHICLEPROPERTY_HVAC_TEMPERATURE_DISPLAY_UNITS = 0x1140050e
+VEHICLEPROPERTY_HVAC_ACTUAL_FAN_SPEED_RPM = 0x1540050f
+VEHICLEPROPERTY_HVAC_POWER_ON = 0x15200510
+VEHICLEPROPERTY_HVAC_FAN_DIRECTION_AVAILABLE = 0x15410511
+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
+VEHICLEPROPERTY_DISPLAY_BRIGHTNESS = 0x11400a03
+VEHICLEPROPERTY_HW_KEY_INPUT = 0x11410a10
+VEHICLEPROPERTY_DOOR_POS = 0x16400b00
+VEHICLEPROPERTY_DOOR_MOVE = 0x16400b01
+VEHICLEPROPERTY_DOOR_LOCK = 0x16200b02
+VEHICLEPROPERTY_MIRROR_Z_POS = 0x14400b40
+VEHICLEPROPERTY_MIRROR_Z_MOVE = 0x14400b41
+VEHICLEPROPERTY_MIRROR_Y_POS = 0x14400b42
+VEHICLEPROPERTY_MIRROR_Y_MOVE = 0x14400b43
+VEHICLEPROPERTY_MIRROR_LOCK = 0x11200b44
+VEHICLEPROPERTY_MIRROR_FOLD = 0x11200b45
+VEHICLEPROPERTY_SEAT_MEMORY_SELECT = 0x15400b80
+VEHICLEPROPERTY_SEAT_MEMORY_SET = 0x15400b81
+VEHICLEPROPERTY_SEAT_BELT_BUCKLED = 0x15200b82
+VEHICLEPROPERTY_SEAT_BELT_HEIGHT_POS = 0x15400b83
+VEHICLEPROPERTY_SEAT_BELT_HEIGHT_MOVE = 0x15400b84
+VEHICLEPROPERTY_SEAT_FORE_AFT_POS = 0x15400b85
+VEHICLEPROPERTY_SEAT_FORE_AFT_MOVE = 0x15400b86
+VEHICLEPROPERTY_SEAT_BACKREST_ANGLE_1_POS = 0x15400b87
+VEHICLEPROPERTY_SEAT_BACKREST_ANGLE_1_MOVE = 0x15400b88
+VEHICLEPROPERTY_SEAT_BACKREST_ANGLE_2_POS = 0x15400b89
+VEHICLEPROPERTY_SEAT_BACKREST_ANGLE_2_MOVE = 0x15400b8a
+VEHICLEPROPERTY_SEAT_HEIGHT_POS = 0x15400b8b
+VEHICLEPROPERTY_SEAT_HEIGHT_MOVE = 0x15400b8c
+VEHICLEPROPERTY_SEAT_DEPTH_POS = 0x15400b8d
+VEHICLEPROPERTY_SEAT_DEPTH_MOVE = 0x15400b8e
+VEHICLEPROPERTY_SEAT_TILT_POS = 0x15400b8f
+VEHICLEPROPERTY_SEAT_TILT_MOVE = 0x15400b90
+VEHICLEPROPERTY_SEAT_LUMBAR_FORE_AFT_POS = 0x15400b91
+VEHICLEPROPERTY_SEAT_LUMBAR_FORE_AFT_MOVE = 0x15400b92
+VEHICLEPROPERTY_SEAT_LUMBAR_SIDE_SUPPORT_POS = 0x15400b93
+VEHICLEPROPERTY_SEAT_LUMBAR_SIDE_SUPPORT_MOVE = 0x15400b94
+VEHICLEPROPERTY_SEAT_HEADREST_HEIGHT_POS = 0x11400b95
+VEHICLEPROPERTY_SEAT_HEADREST_HEIGHT_MOVE = 0x15400b96
+VEHICLEPROPERTY_SEAT_HEADREST_ANGLE_POS = 0x15400b97
+VEHICLEPROPERTY_SEAT_HEADREST_ANGLE_MOVE = 0x15400b98
+VEHICLEPROPERTY_SEAT_HEADREST_FORE_AFT_POS = 0x15400b99
+VEHICLEPROPERTY_SEAT_HEADREST_FORE_AFT_MOVE = 0x15400b9a
+VEHICLEPROPERTY_WINDOW_POS = 0x13400bc0
+VEHICLEPROPERTY_WINDOW_MOVE = 0x13400bc1
+VEHICLEPROPERTY_WINDOW_LOCK = 0x13200bc4
+VEHICLEPROPERTY_VEHICLE_MAP_SERVICE = 0x11e00c00
+VEHICLEPROPERTY_OBD2_LIVE_FRAME = 0x11e00d00
+VEHICLEPROPERTY_OBD2_FREEZE_FRAME = 0x11e00d01
+VEHICLEPROPERTY_OBD2_FREEZE_FRAME_INFO = 0x11e00d02
+VEHICLEPROPERTY_OBD2_FREEZE_FRAME_CLEAR = 0x11e00d03
+VEHICLEPROPERTY_HEADLIGHTS_STATE = 0x11400e00
+VEHICLEPROPERTY_HIGH_BEAM_LIGHTS_STATE = 0x11400e01
+VEHICLEPROPERTY_FOG_LIGHTS_STATE = 0x11400e02
+VEHICLEPROPERTY_HAZARD_LIGHTS_STATE = 0x11400e03
+VEHICLEPROPERTY_HEADLIGHTS_SWITCH = 0x11400e10
+VEHICLEPROPERTY_HIGH_BEAM_LIGHTS_SWITCH = 0x11400e11
+VEHICLEPROPERTY_FOG_LIGHTS_SWITCH = 0x11400e12
+VEHICLEPROPERTY_HAZARD_LIGHTS_SWITCH = 0x11400e13
+
# Obd2FuelType
OBD2FUELTYPE_NOT_AVAILABLE = 0x0
OBD2FUELTYPE_GASOLINE = 0x1
@@ -70,241 +527,17 @@
OBD2FUELTYPE_HYBRID_REGENERATIVE = 0x16
OBD2FUELTYPE_BIFUEL_RUNNING_DIESEL = 0x17
-# VehicleAudioVolumeState
-VEHICLEAUDIOVOLUMESTATE_STATE_OK = 0x0
-VEHICLEAUDIOVOLUMESTATE_LIMIT_REACHED = 0x1
-
-# VmsMessageWithLayerIntegerValuesIndex
-VMSMESSAGEWITHLAYERINTEGERVALUESINDEX_LAYER_TYPE = 0x1
-VMSMESSAGEWITHLAYERINTEGERVALUESINDEX_LAYER_SUBTYPE = 0x2
-VMSMESSAGEWITHLAYERINTEGERVALUESINDEX_LAYER_VERSION = 0x3
-
-# Obd2SparkIgnitionMonitors
-OBD2SPARKIGNITIONMONITORS_EGR_AVAILABLE = 0x40
-OBD2SPARKIGNITIONMONITORS_EGR_INCOMPLETE = 0x80
-OBD2SPARKIGNITIONMONITORS_OXYGEN_SENSOR_HEATER_AVAILABLE = 0x100
-OBD2SPARKIGNITIONMONITORS_OXYGEN_SENSOR_HEATER_INCOMPLETE = 0x200
-OBD2SPARKIGNITIONMONITORS_OXYGEN_SENSOR_AVAILABLE = 0x400
-OBD2SPARKIGNITIONMONITORS_OXYGEN_SENSOR_INCOMPLETE = 0x800
-OBD2SPARKIGNITIONMONITORS_AC_REFRIGERANT_AVAILABLE = 0x1000
-OBD2SPARKIGNITIONMONITORS_AC_REFRIGERANT_INCOMPLETE = 0x2000
-OBD2SPARKIGNITIONMONITORS_SECONDARY_AIR_SYSTEM_AVAILABLE = 0x4000
-OBD2SPARKIGNITIONMONITORS_SECONDARY_AIR_SYSTEM_INCOMPLETE = 0x8000
-OBD2SPARKIGNITIONMONITORS_EVAPORATIVE_SYSTEM_AVAILABLE = 0x10000
-OBD2SPARKIGNITIONMONITORS_EVAPORATIVE_SYSTEM_INCOMPLETE = 0x20000
-OBD2SPARKIGNITIONMONITORS_HEATED_CATALYST_AVAILABLE = 0x40000
-OBD2SPARKIGNITIONMONITORS_HEATED_CATALYST_INCOMPLETE = 0x80000
-OBD2SPARKIGNITIONMONITORS_CATALYST_AVAILABLE = 0x100000
-OBD2SPARKIGNITIONMONITORS_CATALYST_INCOMPLETE = 0x200000
-
-# VehicleArea
-VEHICLEAREA_GLOBAL = 0x1000000
-VEHICLEAREA_ZONE = 0x2000000
-VEHICLEAREA_WINDOW = 0x3000000
-VEHICLEAREA_MIRROR = 0x4000000
-VEHICLEAREA_SEAT = 0x5000000
-VEHICLEAREA_DOOR = 0x6000000
-VEHICLEAREA_MASK = 0xf000000
-
-# Obd2SecondaryAirStatus
-OBD2SECONDARYAIRSTATUS_UPSTREAM = 0x1
-OBD2SECONDARYAIRSTATUS_DOWNSTREAM_OF_CATALYCIC_CONVERTER = 0x2
-OBD2SECONDARYAIRSTATUS_FROM_OUTSIDE_OR_OFF = 0x4
-OBD2SECONDARYAIRSTATUS_PUMP_ON_FOR_DIAGNOSTICS = 0x8
-
-# VehicleAudioHwVariantConfigFlag
-VEHICLEAUDIOHWVARIANTCONFIGFLAG_INTERNAL_RADIO_FLAG = 0x1
-
-# VmsMessageWithLayerAndPublisherIdIntegerValuesIndex
-VMSMESSAGEWITHLAYERANDPUBLISHERIDINTEGERVALUESINDEX_PUBLISHER_ID = 0x4
-
-# Obd2CompressionIgnitionMonitors
-OBD2COMPRESSIONIGNITIONMONITORS_EGR_OR_VVT_AVAILABLE = 0x40
-OBD2COMPRESSIONIGNITIONMONITORS_EGR_OR_VVT_INCOMPLETE = 0x80
-OBD2COMPRESSIONIGNITIONMONITORS_PM_FILTER_AVAILABLE = 0x100
-OBD2COMPRESSIONIGNITIONMONITORS_PM_FILTER_INCOMPLETE = 0x200
-OBD2COMPRESSIONIGNITIONMONITORS_EXHAUST_GAS_SENSOR_AVAILABLE = 0x400
-OBD2COMPRESSIONIGNITIONMONITORS_EXHAUST_GAS_SENSOR_INCOMPLETE = 0x800
-OBD2COMPRESSIONIGNITIONMONITORS_BOOST_PRESSURE_AVAILABLE = 0x1000
-OBD2COMPRESSIONIGNITIONMONITORS_BOOST_PRESSURE_INCOMPLETE = 0x2000
-OBD2COMPRESSIONIGNITIONMONITORS_NOx_SCR_AVAILABLE = 0x4000
-OBD2COMPRESSIONIGNITIONMONITORS_NOx_SCR_INCOMPLETE = 0x8000
-OBD2COMPRESSIONIGNITIONMONITORS_NMHC_CATALYST_AVAILABLE = 0x10000
-OBD2COMPRESSIONIGNITIONMONITORS_NMHC_CATALYST_INCOMPLETE = 0x20000
-
-# VmsOfferingMessageIntegerValuesIndex
-VMSOFFERINGMESSAGEINTEGERVALUESINDEX_PUBLISHER_ID = 0x1
-VMSOFFERINGMESSAGEINTEGERVALUESINDEX_NUMBER_OF_OFFERS = 0x2
-VMSOFFERINGMESSAGEINTEGERVALUESINDEX_OFFERING_START = 0x3
-
-# VehicleAreaZone
-VEHICLEAREAZONE_ROW_1_LEFT = 0x1
-VEHICLEAREAZONE_ROW_1_CENTER = 0x2
-VEHICLEAREAZONE_ROW_1_RIGHT = 0x4
-VEHICLEAREAZONE_ROW_1 = 0x8
-VEHICLEAREAZONE_ROW_2_LEFT = 0x10
-VEHICLEAREAZONE_ROW_2_CENTER = 0x20
-VEHICLEAREAZONE_ROW_2_RIGHT = 0x40
-VEHICLEAREAZONE_ROW_2 = 0x80
-VEHICLEAREAZONE_ROW_3_LEFT = 0x100
-VEHICLEAREAZONE_ROW_3_CENTER = 0x200
-VEHICLEAREAZONE_ROW_3_RIGHT = 0x400
-VEHICLEAREAZONE_ROW_3 = 0x800
-VEHICLEAREAZONE_ROW_4_LEFT = 0x1000
-VEHICLEAREAZONE_ROW_4_CENTER = 0x2000
-VEHICLEAREAZONE_ROW_4_RIGHT = 0x4000
-VEHICLEAREAZONE_ROW_4 = 0x8000
-VEHICLEAREAZONE_WHOLE_CABIN = 0x80000000
-
-# Obd2IgnitionMonitorKind
-OBD2IGNITIONMONITORKIND_SPARK = 0x0
-OBD2IGNITIONMONITORKIND_COMPRESSION = 0x1
-
-# VmsAvailabilityStateIntegerValuesIndex
-VMSAVAILABILITYSTATEINTEGERVALUESINDEX_SEQUENCE_NUMBER = 0x1
-VMSAVAILABILITYSTATEINTEGERVALUESINDEX_NUMBER_OF_ASSOCIATED_LAYERS = 0x2
-VMSAVAILABILITYSTATEINTEGERVALUESINDEX_LAYERS_START = 0x3
-
-# VehicleApPowerStateConfigFlag
-VEHICLEAPPOWERSTATECONFIGFLAG_ENABLE_DEEP_SLEEP_FLAG = 0x1
-VEHICLEAPPOWERSTATECONFIGFLAG_CONFIG_SUPPORT_TIMER_POWER_ON_FLAG = 0x2
-
-# VehicleHvacFanDirection
-VEHICLEHVACFANDIRECTION_FACE = 0x1
-VEHICLEHVACFANDIRECTION_FLOOR = 0x2
-VEHICLEHVACFANDIRECTION_FACE_AND_FLOOR = 0x3
-VEHICLEHVACFANDIRECTION_DEFROST = 0x4
-VEHICLEHVACFANDIRECTION_DEFROST_AND_FLOOR = 0x5
-
-# VehicleHwKeyInputAction
-VEHICLEHWKEYINPUTACTION_ACTION_DOWN = 0x0
-VEHICLEHWKEYINPUTACTION_ACTION_UP = 0x1
-
-# Wheel
-WHEEL_UNKNOWN = 0x0
-WHEEL_LEFT_FRONT = 0x1
-WHEEL_RIGHT_FRONT = 0x2
-WHEEL_LEFT_REAR = 0x4
-WHEEL_RIGHT_REAR = 0x8
-
-# VehicleAudioVolumeCapabilityFlag
-VEHICLEAUDIOVOLUMECAPABILITYFLAG_PERSISTENT_STORAGE = 0x1
-VEHICLEAUDIOVOLUMECAPABILITYFLAG_MASTER_VOLUME_ONLY = 0x2
-
-# VehicleAudioVolumeIndex
-VEHICLEAUDIOVOLUMEINDEX_INDEX_STREAM = 0x0
-VEHICLEAUDIOVOLUMEINDEX_INDEX_VOLUME = 0x1
-VEHICLEAUDIOVOLUMEINDEX_INDEX_STATE = 0x2
-
-# VehicleRadioConstants
-VEHICLERADIOCONSTANTS_VEHICLE_RADIO_PRESET_MIN_VALUE = 0x1
-
-# VehicleGear
-VEHICLEGEAR_GEAR_NEUTRAL = 0x1
-VEHICLEGEAR_GEAR_REVERSE = 0x2
-VEHICLEGEAR_GEAR_PARK = 0x4
-VEHICLEGEAR_GEAR_DRIVE = 0x8
-VEHICLEGEAR_GEAR_LOW = 0x10
-VEHICLEGEAR_GEAR_1 = 0x10
-VEHICLEGEAR_GEAR_2 = 0x20
-VEHICLEGEAR_GEAR_3 = 0x40
-VEHICLEGEAR_GEAR_4 = 0x80
-VEHICLEGEAR_GEAR_5 = 0x100
-VEHICLEGEAR_GEAR_6 = 0x200
-VEHICLEGEAR_GEAR_7 = 0x400
-VEHICLEGEAR_GEAR_8 = 0x800
-VEHICLEGEAR_GEAR_9 = 0x1000
-
-# VehicleDrivingStatus
-VEHICLEDRIVINGSTATUS_UNRESTRICTED = 0x0
-VEHICLEDRIVINGSTATUS_NO_VIDEO = 0x1
-VEHICLEDRIVINGSTATUS_NO_KEYBOARD_INPUT = 0x2
-VEHICLEDRIVINGSTATUS_NO_VOICE_INPUT = 0x4
-VEHICLEDRIVINGSTATUS_NO_CONFIG = 0x8
-VEHICLEDRIVINGSTATUS_LIMIT_MESSAGE_LEN = 0x10
-
-# VehicleAudioRoutingPolicyIndex
-VEHICLEAUDIOROUTINGPOLICYINDEX_STREAM = 0x0
-VEHICLEAUDIOROUTINGPOLICYINDEX_CONTEXTS = 0x1
-
-# VmsSubscriptionsStateIntegerValuesIndex
-VMSSUBSCRIPTIONSSTATEINTEGERVALUESINDEX_SEQUENCE_NUMBER = 0x1
-VMSSUBSCRIPTIONSSTATEINTEGERVALUESINDEX_NUMBER_OF_LAYERS = 0x2
-VMSSUBSCRIPTIONSSTATEINTEGERVALUESINDEX_NUMBER_OF_ASSOCIATED_LAYERS = 0x3
-VMSSUBSCRIPTIONSSTATEINTEGERVALUESINDEX_SUBSCRIPTIONS_START = 0x4
-
-# SubscribeFlags
-SUBSCRIBEFLAGS_UNDEFINED = 0x0
-SUBSCRIBEFLAGS_HAL_EVENT = 0x1
-SUBSCRIBEFLAGS_SET_CALL = 0x2
-SUBSCRIBEFLAGS_DEFAULT = 0x1
-
-# VehicleAudioExtFocusFlag
-VEHICLEAUDIOEXTFOCUSFLAG_NONE_FLAG = 0x0
-VEHICLEAUDIOEXTFOCUSFLAG_PERMANENT_FLAG = 0x1
-VEHICLEAUDIOEXTFOCUSFLAG_TRANSIENT_FLAG = 0x2
-VEHICLEAUDIOEXTFOCUSFLAG_PLAY_ONLY_FLAG = 0x4
-VEHICLEAUDIOEXTFOCUSFLAG_MUTE_MEDIA_FLAG = 0x8
-
-# VehicleAudioFocusRequest
-VEHICLEAUDIOFOCUSREQUEST_REQUEST_GAIN = 0x1
-VEHICLEAUDIOFOCUSREQUEST_REQUEST_GAIN_TRANSIENT = 0x2
-VEHICLEAUDIOFOCUSREQUEST_REQUEST_GAIN_TRANSIENT_MAY_DUCK = 0x3
-VEHICLEAUDIOFOCUSREQUEST_REQUEST_GAIN_TRANSIENT_NO_DUCK = 0x4
-VEHICLEAUDIOFOCUSREQUEST_REQUEST_RELEASE = 0x5
-
-# VehiclePropertyType
-VEHICLEPROPERTYTYPE_STRING = 0x100000
-VEHICLEPROPERTYTYPE_BOOLEAN = 0x200000
-VEHICLEPROPERTYTYPE_INT32 = 0x400000
-VEHICLEPROPERTYTYPE_INT32_VEC = 0x410000
-VEHICLEPROPERTYTYPE_INT64 = 0x500000
-VEHICLEPROPERTYTYPE_FLOAT = 0x600000
-VEHICLEPROPERTYTYPE_FLOAT_VEC = 0x610000
-VEHICLEPROPERTYTYPE_BYTES = 0x700000
-VEHICLEPROPERTYTYPE_COMPLEX = 0xe00000
-VEHICLEPROPERTYTYPE_MASK = 0xff0000
-
-# VehiclePropertyAccess
-VEHICLEPROPERTYACCESS_NONE = 0x0
-VEHICLEPROPERTYACCESS_READ = 0x1
-VEHICLEPROPERTYACCESS_WRITE = 0x2
-VEHICLEPROPERTYACCESS_READ_WRITE = 0x3
-
-# Obd2FuelSystemStatus
-OBD2FUELSYSTEMSTATUS_OPEN_INSUFFICIENT_ENGINE_TEMPERATURE = 0x1
-OBD2FUELSYSTEMSTATUS_CLOSED_LOOP = 0x2
-OBD2FUELSYSTEMSTATUS_OPEN_ENGINE_LOAD_OR_DECELERATION = 0x4
-OBD2FUELSYSTEMSTATUS_OPEN_SYSTEM_FAILURE = 0x8
-OBD2FUELSYSTEMSTATUS_CLOSED_LOOP_BUT_FEEDBACK_FAULT = 0x10
-
-# VehicleTurnSignal
-VEHICLETURNSIGNAL_NONE = 0x0
-VEHICLETURNSIGNAL_RIGHT = 0x1
-VEHICLETURNSIGNAL_LEFT = 0x2
-VEHICLETURNSIGNAL_EMERGENCY = 0x4
-
-# VehicleAudioStreamFlag
-VEHICLEAUDIOSTREAMFLAG_STREAM0_FLAG = 0x1
-VEHICLEAUDIOSTREAMFLAG_STREAM1_FLAG = 0x2
-VEHICLEAUDIOSTREAMFLAG_STREAM2_FLAG = 0x4
-
-# VehicleApPowerBootupReason
-VEHICLEAPPOWERBOOTUPREASON_USER_POWER_ON = 0x0
-VEHICLEAPPOWERBOOTUPREASON_USER_UNLOCK = 0x1
-VEHICLEAPPOWERBOOTUPREASON_TIMER = 0x2
-
-# VehicleAudioFocusState
-VEHICLEAUDIOFOCUSSTATE_STATE_GAIN = 0x1
-VEHICLEAUDIOFOCUSSTATE_STATE_GAIN_TRANSIENT = 0x2
-VEHICLEAUDIOFOCUSSTATE_STATE_LOSS_TRANSIENT_CAN_DUCK = 0x3
-VEHICLEAUDIOFOCUSSTATE_STATE_LOSS_TRANSIENT = 0x4
-VEHICLEAUDIOFOCUSSTATE_STATE_LOSS = 0x5
-VEHICLEAUDIOFOCUSSTATE_STATE_LOSS_TRANSIENT_EXLCUSIVE = 0x6
-
-# VehicleAudioStream
-VEHICLEAUDIOSTREAM_STREAM0 = 0x0
-VEHICLEAUDIOSTREAM_STREAM1 = 0x1
+# VehicleAreaWindow
+VEHICLEAREAWINDOW_FRONT_WINDSHIELD = 0x1
+VEHICLEAREAWINDOW_REAR_WINDSHIELD = 0x2
+VEHICLEAREAWINDOW_ROW_1_LEFT = 0x10
+VEHICLEAREAWINDOW_ROW_1_RIGHT = 0x40
+VEHICLEAREAWINDOW_ROW_2_LEFT = 0x100
+VEHICLEAREAWINDOW_ROW_2_RIGHT = 0x400
+VEHICLEAREAWINDOW_ROW_3_LEFT = 0x1000
+VEHICLEAREAWINDOW_ROW_3_RIGHT = 0x4000
+VEHICLEAREAWINDOW_ROOF_TOP_1 = 0x10000
+VEHICLEAREAWINDOW_ROOF_TOP_2 = 0x20000
# DiagnosticFloatSensorIndex
DIAGNOSTICFLOATSENSORINDEX_CALCULATED_ENGINE_LOAD = 0x0
@@ -380,292 +613,19 @@
DIAGNOSTICFLOATSENSORINDEX_ENGINE_FUEL_RATE = 0x46
DIAGNOSTICFLOATSENSORINDEX_LAST_SYSTEM_INDEX = 0x46
-# VehicleAreaMirror
-VEHICLEAREAMIRROR_DRIVER_LEFT = 0x1
-VEHICLEAREAMIRROR_DRIVER_RIGHT = 0x2
-VEHICLEAREAMIRROR_DRIVER_CENTER = 0x4
+# VehicleArea
+VEHICLEAREA_GLOBAL = 0x1000000
+VEHICLEAREA_WINDOW = 0x3000000
+VEHICLEAREA_MIRROR = 0x4000000
+VEHICLEAREA_SEAT = 0x5000000
+VEHICLEAREA_DOOR = 0x6000000
+VEHICLEAREA_WHEEL = 0x7000000
+VEHICLEAREA_MASK = 0xf000000
-# VehicleAreaWindow
-VEHICLEAREAWINDOW_FRONT_WINDSHIELD = 0x1
-VEHICLEAREAWINDOW_REAR_WINDSHIELD = 0x2
-VEHICLEAREAWINDOW_ROOF_TOP = 0x4
-VEHICLEAREAWINDOW_ROW_1_LEFT = 0x10
-VEHICLEAREAWINDOW_ROW_1_RIGHT = 0x20
-VEHICLEAREAWINDOW_ROW_2_LEFT = 0x100
-VEHICLEAREAWINDOW_ROW_2_RIGHT = 0x200
-VEHICLEAREAWINDOW_ROW_3_LEFT = 0x1000
-VEHICLEAREAWINDOW_ROW_3_RIGHT = 0x2000
-
-# VehiclePropertyOperation
-VEHICLEPROPERTYOPERATION_GENERIC = 0x0
-VEHICLEPROPERTYOPERATION_SET = 0x1
-VEHICLEPROPERTYOPERATION_GET = 0x2
-VEHICLEPROPERTYOPERATION_SUBSCRIBE = 0x3
-
-# VehicleAreaDoor
-VEHICLEAREADOOR_ROW_1_LEFT = 0x1
-VEHICLEAREADOOR_ROW_1_RIGHT = 0x4
-VEHICLEAREADOOR_ROW_2_LEFT = 0x10
-VEHICLEAREADOOR_ROW_2_RIGHT = 0x40
-VEHICLEAREADOOR_ROW_3_LEFT = 0x100
-VEHICLEAREADOOR_ROW_3_RIGHT = 0x400
-VEHICLEAREADOOR_HOOD = 0x10000000
-VEHICLEAREADOOR_REAR = 0x20000000
-
-# StatusCode
-STATUSCODE_OK = 0x0
-STATUSCODE_TRY_AGAIN = 0x1
-STATUSCODE_INVALID_ARG = 0x2
-STATUSCODE_NOT_AVAILABLE = 0x3
-STATUSCODE_ACCESS_DENIED = 0x4
-STATUSCODE_INTERNAL_ERROR = 0x5
-
-# VehicleAreaSeat
-VEHICLEAREASEAT_ROW_1_LEFT = 0x1
-VEHICLEAREASEAT_ROW_1_CENTER = 0x2
-VEHICLEAREASEAT_ROW_1_RIGHT = 0x4
-VEHICLEAREASEAT_ROW_2_LEFT = 0x10
-VEHICLEAREASEAT_ROW_2_CENTER = 0x20
-VEHICLEAREASEAT_ROW_2_RIGHT = 0x40
-VEHICLEAREASEAT_ROW_3_LEFT = 0x100
-VEHICLEAREASEAT_ROW_3_CENTER = 0x200
-VEHICLEAREASEAT_ROW_3_RIGHT = 0x400
-
-# VmsMessageType
-VMSMESSAGETYPE_SUBSCRIBE = 0x1
-VMSMESSAGETYPE_SUBSCRIBE_TO_PUBLISHER = 0x2
-VMSMESSAGETYPE_UNSUBSCRIBE = 0x3
-VMSMESSAGETYPE_UNSUBSCRIBE_TO_PUBLISHER = 0x4
-VMSMESSAGETYPE_OFFERING = 0x5
-VMSMESSAGETYPE_AVAILABILITY_REQUEST = 0x6
-VMSMESSAGETYPE_SUBSCRIPTIONS_REQUEST = 0x7
-VMSMESSAGETYPE_AVAILABILITY_RESPONSE = 0x8
-VMSMESSAGETYPE_AVAILABILITY_CHANGE = 0x9
-VMSMESSAGETYPE_SUBSCRIPTIONS_RESPONSE = 0xa
-VMSMESSAGETYPE_SUBSCRIPTIONS_CHANGE = 0xb
-VMSMESSAGETYPE_DATA = 0xc
-
-# VehicleProperty
-VEHICLEPROPERTY_INVALID = 0x0
-VEHICLEPROPERTY_INFO_VIN = 0x11100100
-VEHICLEPROPERTY_INFO_MAKE = 0x11100101
-VEHICLEPROPERTY_INFO_MODEL = 0x11100102
-VEHICLEPROPERTY_INFO_MODEL_YEAR = 0x11400103
-VEHICLEPROPERTY_INFO_FUEL_CAPACITY = 0x11600104
-VEHICLEPROPERTY_PERF_ODOMETER = 0x11600204
-VEHICLEPROPERTY_PERF_VEHICLE_SPEED = 0x11600207
-VEHICLEPROPERTY_ENGINE_COOLANT_TEMP = 0x11600301
-VEHICLEPROPERTY_ENGINE_OIL_TEMP = 0x11600304
-VEHICLEPROPERTY_ENGINE_RPM = 0x11600305
-VEHICLEPROPERTY_GEAR_SELECTION = 0x11400400
-VEHICLEPROPERTY_CURRENT_GEAR = 0x11400401
-VEHICLEPROPERTY_PARKING_BRAKE_ON = 0x11200402
-VEHICLEPROPERTY_DRIVING_STATUS = 0x11400404
-VEHICLEPROPERTY_FUEL_LEVEL_LOW = 0x11200405
-VEHICLEPROPERTY_NIGHT_MODE = 0x11200407
-VEHICLEPROPERTY_TURN_SIGNAL_STATE = 0x11400408
-VEHICLEPROPERTY_IGNITION_STATE = 0x11400409
-VEHICLEPROPERTY_HVAC_FAN_SPEED = 0x12400500
-VEHICLEPROPERTY_HVAC_FAN_DIRECTION = 0x12400501
-VEHICLEPROPERTY_HVAC_TEMPERATURE_CURRENT = 0x12600502
-VEHICLEPROPERTY_HVAC_TEMPERATURE_SET = 0x12600503
-VEHICLEPROPERTY_HVAC_DEFROSTER = 0x13200504
-VEHICLEPROPERTY_HVAC_AC_ON = 0x12200505
-VEHICLEPROPERTY_HVAC_MAX_AC_ON = 0x12200506
-VEHICLEPROPERTY_HVAC_MAX_DEFROST_ON = 0x12200507
-VEHICLEPROPERTY_HVAC_RECIRC_ON = 0x12200508
-VEHICLEPROPERTY_HVAC_DUAL_ON = 0x12200509
-VEHICLEPROPERTY_HVAC_AUTO_ON = 0x1220050a
-VEHICLEPROPERTY_HVAC_SEAT_TEMPERATURE = 0x1540050b
-VEHICLEPROPERTY_HVAC_SIDE_MIRROR_HEAT = 0x1440050c
-VEHICLEPROPERTY_HVAC_STEERING_WHEEL_TEMP = 0x1140050d
-VEHICLEPROPERTY_HVAC_TEMPERATURE_UNITS = 0x1240050e
-VEHICLEPROPERTY_HVAC_ACTUAL_FAN_SPEED_RPM = 0x1240050f
-VEHICLEPROPERTY_HVAC_FAN_DIRECTION_AVAILABLE = 0x12400511
-VEHICLEPROPERTY_HVAC_POWER_ON = 0x12200510
-VEHICLEPROPERTY_ENV_OUTSIDE_TEMPERATURE = 0x11600703
-VEHICLEPROPERTY_ENV_CABIN_TEMPERATURE = 0x11600704
-VEHICLEPROPERTY_RADIO_PRESET = 0x11410801
-VEHICLEPROPERTY_AUDIO_FOCUS = 0x11410900
-VEHICLEPROPERTY_AUDIO_FOCUS_EXT_SYNC = 0x11410910
-VEHICLEPROPERTY_AUDIO_VOLUME = 0x11410901
-VEHICLEPROPERTY_AUDIO_VOLUME_EXT_SYNC = 0x11410911
-VEHICLEPROPERTY_AUDIO_VOLUME_LIMIT = 0x11410902
-VEHICLEPROPERTY_AUDIO_ROUTING_POLICY = 0x11410903
-VEHICLEPROPERTY_AUDIO_HW_VARIANT = 0x11400904
-VEHICLEPROPERTY_AUDIO_EXT_ROUTING_HINT = 0x11410905
-VEHICLEPROPERTY_AUDIO_STREAM_STATE = 0x11410906
-VEHICLEPROPERTY_AUDIO_PARAMETERS = 0x11100907
-VEHICLEPROPERTY_AP_POWER_STATE = 0x11410a00
-VEHICLEPROPERTY_DISPLAY_BRIGHTNESS = 0x11400a01
-VEHICLEPROPERTY_AP_POWER_BOOTUP_REASON = 0x11400a02
-VEHICLEPROPERTY_HW_KEY_INPUT = 0x11410a10
-VEHICLEPROPERTY_INSTRUMENT_CLUSTER_INFO = 0x11410a20
-VEHICLEPROPERTY_UNIX_TIME = 0x11500a30
-VEHICLEPROPERTY_CURRENT_TIME_IN_SECONDS = 0x11400a31
-VEHICLEPROPERTY_DOOR_POS = 0x16400b00
-VEHICLEPROPERTY_DOOR_MOVE = 0x16400b01
-VEHICLEPROPERTY_DOOR_LOCK = 0x16200b02
-VEHICLEPROPERTY_MIRROR_Z_POS = 0x14400b40
-VEHICLEPROPERTY_MIRROR_Z_MOVE = 0x14400b41
-VEHICLEPROPERTY_MIRROR_Y_POS = 0x14400b42
-VEHICLEPROPERTY_MIRROR_Y_MOVE = 0x14400b43
-VEHICLEPROPERTY_MIRROR_LOCK = 0x11200b44
-VEHICLEPROPERTY_MIRROR_FOLD = 0x11200b45
-VEHICLEPROPERTY_SEAT_MEMORY_SELECT = 0x15400b80
-VEHICLEPROPERTY_SEAT_MEMORY_SET = 0x15400b81
-VEHICLEPROPERTY_SEAT_BELT_BUCKLED = 0x15200b82
-VEHICLEPROPERTY_SEAT_BELT_HEIGHT_POS = 0x15400b83
-VEHICLEPROPERTY_SEAT_BELT_HEIGHT_MOVE = 0x15400b84
-VEHICLEPROPERTY_SEAT_FORE_AFT_POS = 0x15400b85
-VEHICLEPROPERTY_SEAT_FORE_AFT_MOVE = 0x15400b86
-VEHICLEPROPERTY_SEAT_BACKREST_ANGLE_1_POS = 0x15400b87
-VEHICLEPROPERTY_SEAT_BACKREST_ANGLE_1_MOVE = 0x15400b88
-VEHICLEPROPERTY_SEAT_BACKREST_ANGLE_2_POS = 0x15400b89
-VEHICLEPROPERTY_SEAT_BACKREST_ANGLE_2_MOVE = 0x15400b8a
-VEHICLEPROPERTY_SEAT_HEIGHT_POS = 0x15400b8b
-VEHICLEPROPERTY_SEAT_HEIGHT_MOVE = 0x15400b8c
-VEHICLEPROPERTY_SEAT_DEPTH_POS = 0x15400b8d
-VEHICLEPROPERTY_SEAT_DEPTH_MOVE = 0x15400b8e
-VEHICLEPROPERTY_SEAT_TILT_POS = 0x15400b8f
-VEHICLEPROPERTY_SEAT_TILT_MOVE = 0x15400b90
-VEHICLEPROPERTY_SEAT_LUMBAR_FORE_AFT_POS = 0x15400b91
-VEHICLEPROPERTY_SEAT_LUMBAR_FORE_AFT_MOVE = 0x15400b92
-VEHICLEPROPERTY_SEAT_LUMBAR_SIDE_SUPPORT_POS = 0x15400b93
-VEHICLEPROPERTY_SEAT_LUMBAR_SIDE_SUPPORT_MOVE = 0x15400b94
-VEHICLEPROPERTY_SEAT_HEADREST_HEIGHT_POS = 0x11400b95
-VEHICLEPROPERTY_SEAT_HEADREST_HEIGHT_MOVE = 0x15400b96
-VEHICLEPROPERTY_SEAT_HEADREST_ANGLE_POS = 0x15400b97
-VEHICLEPROPERTY_SEAT_HEADREST_ANGLE_MOVE = 0x15400b98
-VEHICLEPROPERTY_SEAT_HEADREST_FORE_AFT_POS = 0x15400b99
-VEHICLEPROPERTY_SEAT_HEADREST_FORE_AFT_MOVE = 0x15400b9a
-VEHICLEPROPERTY_WINDOW_POS = 0x11400bc0
-VEHICLEPROPERTY_WINDOW_MOVE = 0x11400bc1
-VEHICLEPROPERTY_WINDOW_VENT_POS = 0x11400bc2
-VEHICLEPROPERTY_WINDOW_VENT_MOVE = 0x11400bc3
-VEHICLEPROPERTY_WINDOW_LOCK = 0x11200bc4
-VEHICLEPROPERTY_WHEEL_TICK = 0x11e00306
-VEHICLEPROPERTY_ABS_ACTIVE = 0x1120040a
-VEHICLEPROPERTY_TRACTION_CONTROL_ACTIVE = 0x1120040b
-VEHICLEPROPERTY_HVAC_AUTO_RECIRC_ON = 0x12200512
-VEHICLEPROPERTY_VEHICLE_MAP_SERVICE = 0x11e00c00
-VEHICLEPROPERTY_OBD2_LIVE_FRAME = 0x11e00d00
-VEHICLEPROPERTY_OBD2_FREEZE_FRAME = 0x11e00d01
-VEHICLEPROPERTY_OBD2_FREEZE_FRAME_INFO = 0x11e00d02
-VEHICLEPROPERTY_OBD2_FREEZE_FRAME_CLEAR = 0x11e00d03
-
-# VehicleIgnitionState
-VEHICLEIGNITIONSTATE_UNDEFINED = 0x0
-VEHICLEIGNITIONSTATE_LOCK = 0x1
-VEHICLEIGNITIONSTATE_OFF = 0x2
-VEHICLEIGNITIONSTATE_ACC = 0x3
-VEHICLEIGNITIONSTATE_ON = 0x4
-VEHICLEIGNITIONSTATE_START = 0x5
-
-# VehiclePropertyGroup
-VEHICLEPROPERTYGROUP_SYSTEM = 0x10000000
-VEHICLEPROPERTYGROUP_VENDOR = 0x20000000
-VEHICLEPROPERTYGROUP_MASK = 0xf0000000
-
-# VehicleApPowerSetState
-VEHICLEAPPOWERSETSTATE_BOOT_COMPLETE = 0x1
-VEHICLEAPPOWERSETSTATE_DEEP_SLEEP_ENTRY = 0x2
-VEHICLEAPPOWERSETSTATE_DEEP_SLEEP_EXIT = 0x3
-VEHICLEAPPOWERSETSTATE_SHUTDOWN_POSTPONE = 0x4
-VEHICLEAPPOWERSETSTATE_SHUTDOWN_START = 0x5
-VEHICLEAPPOWERSETSTATE_DISPLAY_OFF = 0x6
-VEHICLEAPPOWERSETSTATE_DISPLAY_ON = 0x7
-
-# VmsBaseMessageIntegerValuesIndex
-VMSBASEMESSAGEINTEGERVALUESINDEX_MESSAGE_TYPE = 0x0
-
-# DiagnosticIntegerSensorIndex
-DIAGNOSTICINTEGERSENSORINDEX_FUEL_SYSTEM_STATUS = 0x0
-DIAGNOSTICINTEGERSENSORINDEX_MALFUNCTION_INDICATOR_LIGHT_ON = 0x1
-DIAGNOSTICINTEGERSENSORINDEX_IGNITION_MONITORS_SUPPORTED = 0x2
-DIAGNOSTICINTEGERSENSORINDEX_IGNITION_SPECIFIC_MONITORS = 0x3
-DIAGNOSTICINTEGERSENSORINDEX_INTAKE_AIR_TEMPERATURE = 0x4
-DIAGNOSTICINTEGERSENSORINDEX_COMMANDED_SECONDARY_AIR_STATUS = 0x5
-DIAGNOSTICINTEGERSENSORINDEX_NUM_OXYGEN_SENSORS_PRESENT = 0x6
-DIAGNOSTICINTEGERSENSORINDEX_RUNTIME_SINCE_ENGINE_START = 0x7
-DIAGNOSTICINTEGERSENSORINDEX_DISTANCE_TRAVELED_WITH_MALFUNCTION_INDICATOR_LIGHT_ON = 0x8
-DIAGNOSTICINTEGERSENSORINDEX_WARMUPS_SINCE_CODES_CLEARED = 0x9
-DIAGNOSTICINTEGERSENSORINDEX_DISTANCE_TRAVELED_SINCE_CODES_CLEARED = 0xa
-DIAGNOSTICINTEGERSENSORINDEX_ABSOLUTE_BAROMETRIC_PRESSURE = 0xb
-DIAGNOSTICINTEGERSENSORINDEX_CONTROL_MODULE_VOLTAGE = 0xc
-DIAGNOSTICINTEGERSENSORINDEX_AMBIENT_AIR_TEMPERATURE = 0xd
-DIAGNOSTICINTEGERSENSORINDEX_TIME_WITH_MALFUNCTION_LIGHT_ON = 0xe
-DIAGNOSTICINTEGERSENSORINDEX_TIME_SINCE_TROUBLE_CODES_CLEARED = 0xf
-DIAGNOSTICINTEGERSENSORINDEX_MAX_FUEL_AIR_EQUIVALENCE_RATIO = 0x10
-DIAGNOSTICINTEGERSENSORINDEX_MAX_OXYGEN_SENSOR_VOLTAGE = 0x11
-DIAGNOSTICINTEGERSENSORINDEX_MAX_OXYGEN_SENSOR_CURRENT = 0x12
-DIAGNOSTICINTEGERSENSORINDEX_MAX_INTAKE_MANIFOLD_ABSOLUTE_PRESSURE = 0x13
-DIAGNOSTICINTEGERSENSORINDEX_MAX_AIR_FLOW_RATE_FROM_MASS_AIR_FLOW_SENSOR = 0x14
-DIAGNOSTICINTEGERSENSORINDEX_FUEL_TYPE = 0x15
-DIAGNOSTICINTEGERSENSORINDEX_FUEL_RAIL_ABSOLUTE_PRESSURE = 0x16
-DIAGNOSTICINTEGERSENSORINDEX_ENGINE_OIL_TEMPERATURE = 0x17
-DIAGNOSTICINTEGERSENSORINDEX_DRIVER_DEMAND_PERCENT_TORQUE = 0x18
-DIAGNOSTICINTEGERSENSORINDEX_ENGINE_ACTUAL_PERCENT_TORQUE = 0x19
-DIAGNOSTICINTEGERSENSORINDEX_ENGINE_REFERENCE_PERCENT_TORQUE = 0x1a
-DIAGNOSTICINTEGERSENSORINDEX_ENGINE_PERCENT_TORQUE_DATA_IDLE = 0x1b
-DIAGNOSTICINTEGERSENSORINDEX_ENGINE_PERCENT_TORQUE_DATA_POINT1 = 0x1c
-DIAGNOSTICINTEGERSENSORINDEX_ENGINE_PERCENT_TORQUE_DATA_POINT2 = 0x1d
-DIAGNOSTICINTEGERSENSORINDEX_ENGINE_PERCENT_TORQUE_DATA_POINT3 = 0x1e
-DIAGNOSTICINTEGERSENSORINDEX_ENGINE_PERCENT_TORQUE_DATA_POINT4 = 0x1f
-DIAGNOSTICINTEGERSENSORINDEX_LAST_SYSTEM_INDEX = 0x1f
-
-# VehiclePropertyChangeMode
-VEHICLEPROPERTYCHANGEMODE_STATIC = 0x0
-VEHICLEPROPERTYCHANGEMODE_ON_CHANGE = 0x1
-VEHICLEPROPERTYCHANGEMODE_CONTINUOUS = 0x2
-VEHICLEPROPERTYCHANGEMODE_POLL = 0x3
-VEHICLEPROPERTYCHANGEMODE_ON_SET = 0x4
-
-# VehicleApPowerState
-VEHICLEAPPOWERSTATE_OFF = 0x0
-VEHICLEAPPOWERSTATE_DEEP_SLEEP = 0x1
-VEHICLEAPPOWERSTATE_ON_DISP_OFF = 0x2
-VEHICLEAPPOWERSTATE_ON_FULL = 0x3
-VEHICLEAPPOWERSTATE_SHUTDOWN_PREPARE = 0x4
-
-# VehicleInstrumentClusterType
-VEHICLEINSTRUMENTCLUSTERTYPE_NONE = 0x0
-VEHICLEINSTRUMENTCLUSTERTYPE_HAL_INTERFACE = 0x1
-VEHICLEINSTRUMENTCLUSTERTYPE_EXTERNAL_DISPLAY = 0x2
-
-# VehicleUnit
-VEHICLEUNIT_SHOULD_NOT_USE = 0x0
-VEHICLEUNIT_METER_PER_SEC = 0x1
-VEHICLEUNIT_RPM = 0x2
-VEHICLEUNIT_HERTZ = 0x3
-VEHICLEUNIT_PERCENTILE = 0x10
-VEHICLEUNIT_MILLIMETER = 0x20
-VEHICLEUNIT_METER = 0x21
-VEHICLEUNIT_KILOMETER = 0x23
-VEHICLEUNIT_CELSIUS = 0x30
-VEHICLEUNIT_FAHRENHEIT = 0x31
-VEHICLEUNIT_KELVIN = 0x32
-VEHICLEUNIT_MILLILITER = 0x40
-VEHICLEUNIT_NANO_SECS = 0x50
-VEHICLEUNIT_SECS = 0x53
-VEHICLEUNIT_YEAR = 0x59
-
-# VehicleAudioVolumeLimitIndex
-VEHICLEAUDIOVOLUMELIMITINDEX_STREAM = 0x0
-VEHICLEAUDIOVOLUMELIMITINDEX_MAX_VOLUME = 0x1
-
-# VehicleApPowerStateShutdownParam
-VEHICLEAPPOWERSTATESHUTDOWNPARAM_SHUTDOWN_IMMEDIATELY = 0x1
-VEHICLEAPPOWERSTATESHUTDOWNPARAM_CAN_SLEEP = 0x2
-VEHICLEAPPOWERSTATESHUTDOWNPARAM_SHUTDOWN_ONLY = 0x3
-
-# VehicleApPowerStateIndex
-VEHICLEAPPOWERSTATEINDEX_STATE = 0x0
-VEHICLEAPPOWERSTATEINDEX_ADDITIONAL = 0x1
-
-# VehicleDisplay
-VEHICLEDISPLAY_MAIN = 0x0
-VEHICLEDISPLAY_INSTRUMENT_CLUSTER = 0x1
+# VehiclePropertyStatus
+VEHICLEPROPERTYSTATUS_AVAILABLE = 0x0
+VEHICLEPROPERTYSTATUS_UNAVAILABLE = 0x1
+VEHICLEPROPERTYSTATUS_ERROR = 0x2
# Create a container of value_type constants to be used by vhal_emulator
class vhal_types_2_0:
@@ -677,4 +637,4 @@
TYPE_FLOAT = [VEHICLEPROPERTYTYPE_FLOAT]
TYPE_INT32S = [VEHICLEPROPERTYTYPE_INT32_VEC]
TYPE_FLOATS = [VEHICLEPROPERTYTYPE_FLOAT_VEC]
- TYPE_COMPLEX = [VEHICLEPROPERTYTYPE_COMPLEX]
+ TYPE_MIXED = [VEHICLEPROPERTYTYPE_MIXED]
diff --git a/tools/emulator/vhal_emulator.py b/tools/emulator/vhal_emulator.py
index 7cc6da7..f7351f1 100644
--- a/tools/emulator/vhal_emulator.py
+++ b/tools/emulator/vhal_emulator.py
@@ -204,9 +204,10 @@
cmd.msg_type = VehicleHalProto_pb2.GET_PROPERTY_ALL_CMD
self._txCmd(cmd)
- def setProperty(self, prop, area_id, value):
+ def setProperty(self, prop, area_id, value, status=VehicleHalProto_pb2.AVAILABLE):
"""
- Sends a setProperty command for the specified property ID, area ID, and value.
+ Sends a setProperty command for the specified property ID, area ID, value and status.
+ If Status is not specified, automatically send AVAILABLE as the default.
This function chooses the proper value field to populate based on the config for the
property. It is the caller's responsibility to ensure the value data is the proper
type.
@@ -217,6 +218,7 @@
propValue.prop = prop
# Insert value into the proper area
propValue.area_id = area_id
+ propValue.status = status;
# Determine the value_type and populate the correct value field in protoBuf
try:
valType = self._propToType[prop]
@@ -238,7 +240,7 @@
propValue.int32_values.extend(value)
elif valType in self._types.TYPE_FLOATS:
propValue.float_values.extend(value)
- elif valType in self._types.TYPE_COMPLEX:
+ elif valType in self._types.TYPE_MIXED:
propValue.string_value = \
getByAttributeOrKey(value, 'string_value', '')
propValue.bytes_value = \
diff --git a/tools/emulator/vhal_emulator_test.py b/tools/emulator/vhal_emulator_test.py
index ea4030d..6c56a1a 100755
--- a/tools/emulator/vhal_emulator_test.py
+++ b/tools/emulator/vhal_emulator_test.py
@@ -37,7 +37,7 @@
sys.dont_write_bytecode = True
import VehicleHalProto_pb2
-import vhal_consts_2_1
+import vhal_consts_2_0
import vhal_emulator
import logging
@@ -49,12 +49,12 @@
_vhal = 0 # Handle to VHAL object that communicates over socket to DUT
# TODO: b/38203109 - Fix OBD2 values, implement handling for complex properties
_skipProps = [
- vhal_consts_2_1.VEHICLEPROPERTY_OBD2_LIVE_FRAME,
- vhal_consts_2_1.VEHICLEPROPERTY_OBD2_FREEZE_FRAME,
- vhal_consts_2_1.VEHICLEPROPERTY_OBD2_FREEZE_FRAME_INFO,
- vhal_consts_2_1.VEHICLEPROPERTY_OBD2_FREEZE_FRAME_CLEAR,
- vhal_consts_2_1.VEHICLEPROPERTY_VEHICLE_MAP_SERVICE,
- vhal_consts_2_1.VEHICLEPROPERTY_WHEEL_TICK, # Need to support complex properties
+ vhal_consts_2_0.VEHICLEPROPERTY_OBD2_LIVE_FRAME,
+ vhal_consts_2_0.VEHICLEPROPERTY_OBD2_FREEZE_FRAME,
+ vhal_consts_2_0.VEHICLEPROPERTY_OBD2_FREEZE_FRAME_INFO,
+ vhal_consts_2_0.VEHICLEPROPERTY_OBD2_FREEZE_FRAME_CLEAR,
+ vhal_consts_2_0.VEHICLEPROPERTY_VEHICLE_MAP_SERVICE,
+ vhal_consts_2_0.VEHICLEPROPERTY_WHEEL_TICK, # Need to support complex properties
0x21E00666 # FakeDataControllingProperty - an internal test property
]
@@ -70,7 +70,7 @@
elif valType in self._types.TYPE_BYTES:
# Generate array of integers counting from 0
testValue = list(range(len(origValue)))
- elif valType == vhal_consts_2_1.VEHICLEPROPERTYTYPE_BOOLEAN:
+ elif valType == vhal_consts_2_0.VEHICLEPROPERTYTYPE_BOOLEAN:
testValue = origValue ^ 1
elif valType in self._types.TYPE_INT32:
try:
@@ -109,24 +109,43 @@
value = None
else:
valType = rxMsg.value[0].value_type
- if valType in self._types.TYPE_STRING:
- value = rxMsg.value[0].string_value
- elif valType in self._types.TYPE_BYTES:
- value = rxMsg.value[0].bytes_value
- elif valType == vhal_consts_2_1.VEHICLEPROPERTYTYPE_BOOLEAN:
- value = rxMsg.value[0].int32_values[0]
- elif valType in self._types.TYPE_INT32:
- value = rxMsg.value[0].int32_values[0]
- elif valType in self._types.TYPE_INT64:
- value = rxMsg.value[0].int64_values[0]
- elif valType in self._types.TYPE_FLOAT:
- value = rxMsg.value[0].float_values[0]
- # Truncate float to 5 decimal places
- value = "%.5f" % value
- value = float(value)
- else:
- self._log.error("getValueFromMsg: valType=0x%X is not handled", valType)
- value = None
+ try:
+ if valType in self._types.TYPE_STRING:
+ value = rxMsg.value[0].string_value
+ elif valType in self._types.TYPE_BYTES:
+ value = rxMsg.value[0].bytes_value
+ elif valType == vhal_consts_2_0.VEHICLEPROPERTYTYPE_BOOLEAN:
+ value = rxMsg.value[0].int32_values[0]
+ elif valType in self._types.TYPE_INT32:
+ value = rxMsg.value[0].int32_values[0]
+ elif valType in self._types.TYPE_INT64:
+ value = rxMsg.value[0].int64_values[0]
+ elif valType in self._types.TYPE_FLOAT:
+ value = rxMsg.value[0].float_values[0]
+ # Truncate float to 5 decimal places
+ value = "%.5f" % value
+ value = float(value)
+ else:
+ self._log.error("getValueFromMsg: valType=0x%X is not handled", valType)
+ value = None
+ except IndexError:
+ self._log.error("getValueFromMsg: Received malformed message: %s", str(rxMsg))
+ value = None
+ return value
+
+ def _validateVmsMessage(self, rxMsg):
+ return (len(rxMsg.value) == 1 and rxMsg.value[0].value_type in self._types.TYPE_MIXED and
+ len(rxMsg.value[0].int32_values) > 0 and
+ vhal_consts_2_0.VMSMESSAGETYPE_SUBSCRIBE <= rxMsg.value[0].int32_values[0]
+ <= vhal_consts_2_0.VMSMESSAGETYPE_LAST_VMS_MESSAGE_TYPE)
+
+ def _getVmsMessageTypeFromMsg(self, rxMsg):
+ if self._validateVmsMessage(rxMsg):
+ value = rxMsg.value[0].int32_values[
+ vhal_consts_2_0.VMSBASEMESSAGEINTEGERVALUESINDEX_MESSAGE_TYPE]
+ else:
+ self._log.error("getVmsMessageTypeFromMsg: Received invalid message")
+ value = None
return value
# Helper function to receive a message and validate the type and status
@@ -275,6 +294,48 @@
pass
self._log.info(" Finished testSetBadProperty()!")
+ def testGetVmsAvailability(self):
+ self._log.info("Starting testVms()...")
+
+ # Request the availability from the VmsCore.
+ value = {'int32_values' : [vhal_consts_2_0.VMSMESSAGETYPE_AVAILABILITY_REQUEST] }
+ self._vhal.setProperty(
+ vhal_consts_2_0.VEHICLEPROPERTY_VEHICLE_MAP_SERVICE, 0, value)
+
+ rxMsg, retVal = self._rxMsgAndValidate(VehicleHalProto_pb2.SET_PROPERTY_RESP,
+ VehicleHalProto_pb2.RESULT_OK)
+
+ # The Vms Core should immediately respond
+ rxMsg, retVal = self._rxMsgAndValidate(VehicleHalProto_pb2.SET_PROPERTY_ASYNC,
+ VehicleHalProto_pb2.RESULT_OK)
+
+ if self._getVmsMessageTypeFromMsg(rxMsg) != vhal_consts_2_0.VMSMESSAGETYPE_AVAILABILITY_RESPONSE:
+ self._log.error("testVms: VmsCore did not respond with AvailabilityResponse: %s", str(rxMsg))
+
+
+ # Test that we can get the property on command
+ self._vhal.getProperty(
+ vhal_consts_2_0.VEHICLEPROPERTY_VEHICLE_MAP_SERVICE, 0)
+ rxMsg, retVal = self._rxMsgAndValidate(VehicleHalProto_pb2.GET_PROPERTY_RESP,
+ VehicleHalProto_pb2.RESULT_OK)
+
+ if self._getVmsMessageTypeFromMsg(rxMsg) != vhal_consts_2_0.VMSMESSAGETYPE_AVAILABILITY_RESPONSE:
+ self._log.error("testVms: VmsCore did not respond with AvailabilityResponse: %s", str(rxMsg))
+ else:
+ # Parse Availability Response
+ layers = rxMsg.value[0].int32_values[
+ vhal_consts_2_0.VMSAVAILABILITYSTATEINTEGERVALUESINDEX_NUMBER_OF_ASSOCIATED_LAYERS]
+ index = vhal_consts_2_0.VMSAVAILABILITYSTATEINTEGERVALUESINDEX_LAYERS_START
+ numPublishersIndex = vhal_consts_2_0.VMSMESSAGEWITHLAYERINTEGERVALUESINDEX_LAYER_VERSION
+ self._log.info("testVms: %d available layers", layers)
+ for layer in xrange(layers):
+ self._log.info("testVms: Available layer: %s",
+ rxMsg.value[0].int32_values[index:index+numPublishersIndex])
+ index += numPublishersIndex + 1 + rxMsg.value[0].int32_values[index+numPublishersIndex]
+
+ if len(rxMsg.value[0].int32_values) != index:
+ self._log.error("testVms: Malformed AvailabilityResponse: index: %d %s", index, str(rxMsg))
+
def runTests(self):
self.testGetConfig()
self.testGetBadConfig()
@@ -282,6 +343,7 @@
self.testGetSet()
self.testGetBadProperty()
self.testSetBadProperty()
+ self.testGetVmsAvailability()
# Add new tests here to be run
@@ -305,5 +367,5 @@
self._configs = self._vhal.rxMsg().config
if __name__ == '__main__':
- v = VhalTest(vhal_consts_2_1.vhal_types_2_0)
+ v = VhalTest(vhal_consts_2_0.vhal_types_2_0)
v.runTests()
diff --git a/tools/emulator/vhal_prop_simulator.py b/tools/emulator/vhal_prop_simulator.py
new file mode 100755
index 0000000..9297a15
--- /dev/null
+++ b/tools/emulator/vhal_prop_simulator.py
@@ -0,0 +1,69 @@
+#!/usr/bin/env python
+#
+# 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.
+#
+
+import argparse
+import time
+
+from threading import Thread
+
+import driving_info_generator
+import user_action_generator
+import vhal_consts_2_0 as c
+
+from vhal_emulator import Vhal
+
+DEFAULT_TIMEOUT_SEC = 60 * 60 # 1 hour
+
+class VhalPropSimulator(object):
+ """
+ A class simulates vhal properties by calling each generator in a separate thread. It is
+ itself a listener passed to each generator to handle vhal event
+ """
+
+ def __init__(self, device, gpxFile,):
+ self.vhal = Vhal(c.vhal_types_2_0, device)
+ self.gpxFile = gpxFile
+
+ def handle(self, prop, area_id, value, desc=None):
+ """
+ handle generated VHAL property by injecting through vhal emulator.
+ """
+ print "Generated property %s with value: %s" % (desc, value)
+ self.vhal.setProperty(prop, area_id, value)
+
+ def _startGeneratorThread(self, generator):
+ thread = Thread(target=generator.generate, args=(self,))
+ thread.daemon = True
+ thread.start()
+
+ def run(self, timeout):
+ userActionGenerator = user_action_generator.UserActionGenerator(self.vhal)
+ drivingInfoGenerator = driving_info_generator.DrivingInfoGenerator(self.gpxFile, self.vhal)
+ self._startGeneratorThread(userActionGenerator)
+ self._startGeneratorThread(drivingInfoGenerator)
+ time.sleep(float(timeout))
+
+
+if __name__ == '__main__':
+ parser = argparse.ArgumentParser(description='Vhal Property Simulator')
+ parser.add_argument('-s', action='store', dest='deviceid', default=None)
+ parser.add_argument('--timeout', action='store', dest='timeout', default=DEFAULT_TIMEOUT_SEC)
+ parser.add_argument('--gpx', action='store', dest='gpxFile', default=None)
+ args = parser.parse_args()
+
+ simulator = VhalPropSimulator(device=args.deviceid, gpxFile=args.gpxFile)
+ simulator.run(args.timeout)
diff --git a/tools/io_analysis/check_file_read.py b/tools/io_analysis/check_file_read.py
deleted file mode 100644
index f785436..0000000
--- a/tools/io_analysis/check_file_read.py
+++ /dev/null
@@ -1,441 +0,0 @@
-#!/usr/bin/env python
-#
-# 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.
-#
-"""Analyze ext4 trace with custom open trace"""
-import collections
-import math
-import os
-import re
-import string
-import sys
-
-DBG = False
-DBG_ISSUE = False
-
-# hard coded maps to detect partition for given device or the other way around
-# this can be different per each device. This works for marlin.
-DEVICE_TO_PARTITION = { "253,0": "/system/", "253,1": "/vendor/", "259,19": "/data/" }
-PARTITION_TO_DEVICE = {}
-for key, value in DEVICE_TO_PARTITION.iteritems():
- PARTITION_TO_DEVICE[value] = key
-
-# init-1 [003] .... 2.703964: do_sys_open: init: open("/sys/fs/selinux/null", 131074, 0) fd = 0, inode = 22
-RE_DO_SYS_OPEN = r"""\s+\S+-([0-9]+).*\s+([0-9]+\.[0-9]+):\s+do_sys_open:\s+(\S+):\sopen..(\S+).,\s([0-9]+).\s+.+inode\s=\s([0-9]+)"""
-# init-1 [003] ...1 2.703991: ext4_ext_map_blocks_enter: dev 253,0 ino 2719 lblk 154 len 30 flags
-RE_EXT4_MA_BLOCKS_ENTER = r"""\s+(\S+)-([0-9]+).+\s+([0-9]+\.[0-9]+):\s+ext4_ext_map_blocks_enter:\s+dev\s+(\S+)\s+ino\s+([0-9]+)\s+lblk\s+([0-9]+)\s+len\s+([0-9]+)"""
-# init-1 [002] ...1 2.687205: ext4_ext_map_blocks_exit: dev 253,0 ino 8 flags lblk 0 pblk 196608 len 1 mflags M ret 1
-RE_EXT4_MA_BLOCKS_EXIT = r"""\s+(\S+)-([0-9]+).+\s+([0-9]+\.[0-9]+):\s+ext4_ext_map_blocks_exit:\s+dev\s+(\S+)\s+ino\s+([0-9]+)\sflags.*\slblk\s+([0-9]+)\spblk\s([0-9]+)\slen\s+([0-9]+).*mflags\s(\S*)\sret\s([0-9]+)"""
-# init-1 [002] ...1 2.887119: block_bio_remap: 8,0 R 10010384 + 8 <- (259,18) 3998944
-RE_BLOCK_BIO_REMAP = r""".+block_bio_remap:\s\d+,\d+\s\S+\s(\d+)\s\+\s\d+\s<-\s\([^\)]+\)\s(\d+)"""
-# kworker/u9:1-83 [003] d..2 2.682991: block_rq_issue: 8,0 RA 0 () 10140208 + 32 [kworker/u9:1]
-RE_BLOCK_RQ_ISSUE = r"""\s+\S+-([0-9]+).*\s+([0-9]+\.[0-9]+):\s+block_rq_issue:\s+([0-9]+)\,([0-9]+)\s+([RW]\S*)\s[0-9]+\s\([^\)]*\)\s([0-9]+)\s+\+\s+([0-9]+)\s+\[([^\]]+)\]"""
-
-EXT4_SIZE_TO_BLOCK_SIZE = 8 # ext4: 4KB, block device block size: 512B
-
-class FileAccess:
- def __init__(self, file):
- self.file = file
- self.accesses = []
- self.total_access = 0
- self.ext4_access_size_histogram = {} #key: read size, value: occurrence
- self.block_access_size_histogram = {}
- self.ext4_single_block_accesses = {} # process name, occurrence
- self.block_single_block_accesses = {} # process name, occurrence
- self.blocks_histogram = {} # K: offset, V: read counter
-
- def add_if_single_block(self, container, size, offset, process_name):
- if size != 1:
- return
- offsets = container.get(process_name)
- if not offsets:
- offsets = []
- container[process_name] = offsets
- offsets.append(offset)
-
- def add_access(self, time, offset, size, process_name, read_sizes):
- self.accesses.append((time, offset, size, process_name))
- self.total_access += size
- self.ext4_access_size_histogram[size] = self.ext4_access_size_histogram.get(size, 0) + 1
- read_offset = offset
- for s in read_sizes:
- self.block_access_size_histogram[s] = self.block_access_size_histogram.get(s, 0) + 1
- self.add_if_single_block(self.block_single_block_accesses, s, read_offset, process_name)
- read_offset += s
- for i in range(size):
- self.blocks_histogram[offset + i] = self.blocks_histogram.get(offset + i, 0) + 1
- self.add_if_single_block(self.ext4_single_block_accesses, size, offset, process_name)
-
- def add_merged_access(self, time, offsets, lens, process_names):
- total_read_offsets = set() # each read can overwrap. So count only once for block level counting
- for i in range(len(offsets)):
- self.accesses.append((time, offsets[i], lens[i], process_names[i]))
- self.ext4_access_size_histogram[lens[i]] = self.ext4_access_size_histogram.get(lens[i], 0) + 1
- self.add_if_single_block(self.ext4_single_block_accesses, lens[i], offsets[i], process_names[i])
- for j in range(len(lens)):
- total_read_offsets.add(offsets[i] + j)
- total_lens = len(total_read_offsets)
- start_offset = min(total_read_offsets)
- self.total_access += total_lens
- self.block_access_size_histogram[total_lens] = self.block_access_size_histogram.get(total_lens, 0) \
- + 1
- self.add_if_single_block(self.block_single_block_accesses, total_lens, start_offset, \
- process_names[0])
- for s in range(total_lens):
- self.blocks_histogram[start_offset + s] = self.blocks_histogram.get(start_offset + s, 0) + 1
-
-
- def dump(self):
- if len(self.ext4_access_size_histogram) > 1:
- print " Ext4 access size histograms:", collections.OrderedDict( \
- sorted(self.ext4_access_size_histogram.items(), key = lambda item: item[0]))
- if len(self.ext4_single_block_accesses) > 0 and self.total_access > 1:
- print " Ext4 single block accesses:", collections.OrderedDict( \
- sorted(self.ext4_single_block_accesses.items(), key = lambda item: item[1], reverse = True))
- if len(self.block_access_size_histogram) > 1:
- print " Block access size histograms:", collections.OrderedDict( \
- sorted(self.block_access_size_histogram.items(), key = lambda item: item[0]))
- if len(self.block_single_block_accesses) > 0 and self.total_access > 1:
- print " Block single block accesses:", collections.OrderedDict( \
- sorted(self.block_single_block_accesses.items(), key = lambda item: item[1], reverse = True))
- if self.total_access > 1:
- sorted_blocks_histogram = sorted(self.blocks_histogram.items(), key = lambda item: item[1], \
- reverse = True)
- prints = []
- repeating_reads_counter = 0
- for entry in sorted_blocks_histogram:
- offset = entry[0]
- counter = entry[1]
- if counter == 1:
- break
- prints.append(str(offset) + ":" + str(counter))
- repeating_reads_counter += (counter - 1)
- if len(prints) > 0:
- print " repeating accesses", repeating_reads_counter, " offset:count ->", ','.join(prints)
-
-class FileEvent:
- def __init__(self, open_time, file_name, process_name, inode, flags):
- self.file_name = file_name
- self.inode = inode
- self.total_open = 1
- self.processes = []
- self.processes.append((open_time, process_name, flags))
- self.read = FileAccess(self)
- self.write = FileAccess(self)
-
-
- def add_open(self, open_time, process_name, flags):
- self.processes.append((open_time, process_name, flags))
- self.total_open += 1
-
- def add_access(self, is_read, time, offset, size, process_name, read_sizes):
- if is_read:
- self.read.add_access(time, offset, size, process_name, read_sizes)
- else:
- self.write.add_access(time, offset, size, process_name, read_sizes)
-
- def add_merged_access(self, is_read, time, offsets, lens, process_names):
- if is_read:
- self.read.add_merged_access(time, offsets, lens, process_names)
- else:
- self.write.add_merged_access(time, offsets, lens, process_names)
-
- def dump(self, name_to_pid_map):
- print " ***filename %s, total reads %d, total writes %d, total open %d inode %s" \
- % (self.file_name, self.read.total_access, self.write.total_access, self.total_open,\
- self.inode)
- process_names = []
- for opener in self.processes:
- process_names.append(opener[1] + "-" + name_to_pid_map.get(opener[1], '?') + " t:" + \
- str(opener[0]) + " flags:" + opener[2])
- print " Processes opened this file:", ','.join(process_names)
- if self.read.total_access > 0:
- print " ****Reads:"
- self.read.dump()
- if self.write.total_access > 0:
- print " ****Writes:"
- self.write.dump()
-
- def dump_short(self):
- print " filename %s, total reads %d, total writes %d" % (self.file_name,
- self.read.total_access, self.write.total_access)
-
-class PendingAccess:
- def __init__(self, process_name, pid, time, dev, inode, lblk, pblk, len, fevent):
- self.process_name = process_name
- self.pid = pid
- self.time = time
- self.dev = dev
- self.inode = inode
- self.lblk = lblk
- self.pblk = pblk
- self.blk_len = len * EXT4_SIZE_TO_BLOCK_SIZE
- self.len = len
- self.fevent = fevent
- self.pending_accesses = set()
- for i in range(len):
- self.pending_accesses.add(i)
- self.access_sizes = [] # valid read for this file in block dev level.
- self.block_access_counter = 0
-
- def get_valid_access(self, block_offset, block_len):
- ext4_offset = block_offset / EXT4_SIZE_TO_BLOCK_SIZE
- if ext4_offset > self.len:
- return 0, 0
- ext4_len = block_len / EXT4_SIZE_TO_BLOCK_SIZE
- if (ext4_offset + ext4_len) > self.len:
- ext4_len = self.len - ext4_offset
- return ext4_offset, ext4_len
-
- def queue_block_access(self, ext4_offset, ext4_len):
- if ext4_len <= 0:
- return
- self.block_access_counter += 1
- ext4_blocks_accessed = 0
- for i in range(ext4_len):
- ext4_block_i = i + ext4_offset
- if ext4_block_i in self.pending_accesses:
- ext4_blocks_accessed += 1
- self.pending_accesses.remove(ext4_block_i)
- if ext4_blocks_accessed > 0:
- self.access_sizes.append(ext4_blocks_accessed)
-
- def handle_req_complete(self, time, is_read):
- self.fevent.add_access(is_read, self.time, self.lblk, self.len, self.process_name,\
- self.access_sizes)
-
- def handle_merged_req(self, time, offsets, lens, names, is_read):
- self.fevent.add_merged_access(is_read, time, offsets, lens, names)
-
- def is_req_complete(self):
- return len(self.pending_accesses) == 0
-
- def is_req_started(self):
- return self.len is not len(self.pending_accesses)
-
-class Trace:
- def __init__(self):
- self.files_per_device = {} # key: device, value: { key: inode, value; FileEvent }
- self.re_open = re.compile(RE_DO_SYS_OPEN)
- self.re_ext4_access = re.compile(RE_EXT4_MA_BLOCKS_EXIT)
- self.re_bio_remap = re.compile(RE_BLOCK_BIO_REMAP)
- self.re_block_issue = re.compile(RE_BLOCK_RQ_ISSUE)
- # req from ext4 that has not gone down to block level yet, K:block address,
- # V: list of PendingRead
- self.pending_accesses = {}
- self.remap = {}
- self.process_names = {} # K: PID, V : name
-
- def handle_line(self, line):
- match = self.re_open.match(line)
- if match:
- self.handle_open(match)
- return
- match = self.re_ext4_access.match(line)
- if match:
- self.handle_ext4_block_exit(match)
- return
- match = self.re_bio_remap.match(line)
- if match:
- self.handle_bio_remap(match)
- return
- match = self.re_block_issue.match(line)
- if match:
- self.handle_block_issue(match)
- return
-
- def handle_open(self, match):
- pid = int(match.group(1))
- time = match.group(2)
- process_name = match.group(3)
- file_name = match.group(4)
- flag = match.group(5)
- inode = int(match.group(6))
- dev_name = None
- self.process_names[pid] = process_name
- #print "open", pid, process_name, file_name, inode
- for p in PARTITION_TO_DEVICE:
- if file_name.startswith(p):
- dev_name = PARTITION_TO_DEVICE[p]
- if not dev_name:
- if DBG:
- print "Ignore open for file", file_name
- return
- files = self.files_per_device[dev_name]
- fevent = files.get(inode)
- if not fevent:
- fevent = FileEvent(time, file_name, process_name, inode, flag)
- files[inode] = fevent
- else:
- fevent.add_open(time, process_name, flag)
-
- def handle_ext4_block_exit(self, match):
- process_name = match.group(1)
- pid = int(match.group(2))
- time = float(match.group(3))
- dev = match.group(4)
- inode = int(match.group(5))
- lblk = int(match.group(6))
- pblk = int(match.group(7)) * EXT4_SIZE_TO_BLOCK_SIZE # address in ext4 blocks, ...
- l = int(match.group(8))
- mflags = match.group(9)
- ret = int(match.group(10))
- if ret <= 0: # no block access
- return
- process_name = self.process_names.get(pid, process_name)
- if process_name == '<...>':
- process_name = "pid-" + str(pid)
- if DBG_ISSUE:
- print "ext4", pblk, l, inode, process_name
- files = self.files_per_device.get(dev)
- if not files:
- if DEVICE_TO_PARTITION.get(dev):
- files = {}
- self.files_per_device[dev] = files
- else:
- if DBG:
- print "access ignored for device", dev
- return
- fevent = files.get(inode)
- if not fevent:
- if DBG:
- print 'no open for device %s with inode %s' % (dev, inode)
- fevent = FileEvent(time, "unknown", process_name, inode, "-")
- files[inode] = fevent
- pending_access = PendingAccess(process_name, pid, time, dev, inode, lblk, pblk, l,\
- fevent)
- access_list = self.pending_accesses.get(pblk, [])
- access_list.append(pending_access)
- self.pending_accesses[pblk] = access_list
-
- def handle_bio_remap(self, match):
- new_addr = int(match.group(1))
- old_addr = int(match.group(2))
- self.remap[new_addr] = old_addr
- if DBG_ISSUE:
- print "remap", new_addr, old_addr
-
- def handle_block_issue(self, match):
- pid = int(match.group(1))
- time = float(match.group(2))
- dev_major = match.group(3)
- dev_minor = match.group(4)
- access = match.group(5)
- new_address = int(match.group(6))
- l = int(match.group(7))
- name = match.group(8)
- name = self.process_names.get(pid, name)
- if name == '<...>':
- name = "pid-" + str(pid)
- is_read = not 'W' in access
- accesses_per_inodes = {} # K:inodes, V: list of two entries, 1st: offsets, 2nd: length
- addrs_to_remove = []
- completed_reqs = []
- address = self.remap.get(new_address, new_address)
- if DBG_ISSUE:
- print "issue", address, l, is_read, access
- for access_addr, access_list in self.pending_accesses.iteritems():
- if (address >= access_addr) and (address + l) > access_addr:
- reqs_to_remove = []
- for pending in access_list:
- offset, valid_access_size = pending.get_valid_access(address - access_addr, l)
- if valid_access_size > 0:
- if pending.is_req_started(): # spread across multiple reads. complete alone
- pending.queue_block_access(offset, valid_access_size)
- if pending.is_req_complete():
- pending.handle_req_complete(time, is_read)
- reqs_to_remove.append(pending)
- else: # possible multiple reads completed in this read. complete them together
- pending.queue_block_access(offset, valid_access_size)
- if pending.is_req_complete():
- reads = accesses_per_inodes.get(pending.inode, [[], [], []])
- reads[0].append(offset + pending.lblk)
- reads[1].append(valid_access_size)
- reads[2].append(pending.process_name)
- accesses_per_inodes[pending.inode] = reads
- completed_reqs.append(pending)
- reqs_to_remove.append(pending)
- for to_remove in reqs_to_remove:
- access_list.remove(to_remove)
- if len(access_list) == 0:
- addrs_to_remove.append(access_addr)
- for addr in addrs_to_remove:
- del self.pending_accesses[addr]
- for pending in completed_reqs: # these will be reported as batch
- accesses = accesses_per_inodes.get(pending.inode)
- if not accesses: # merged one already dispatched
- continue
- if len(accesses[0]) == 1:
- pending.handle_req_complete(time, is_read)
- else: #merged
- pending.handle_merged_req(time, accesses[0], accesses[1], accesses[2], is_read)
- del accesses_per_inodes[pending.inode]
-
- def dump_partition(self, partition_name, files):
- name_to_pid_map = {}
- for pid, name in self.process_names.iteritems():
- name_to_pid_map[name] = str(pid)
- print "**Dump partition:", partition_name, "total number of files:", len(files)
- total_reads = 0
- total_writes = 0
- files_sorted_by_read = files.values()
- files_sorted_by_read.sort(key=lambda f : f.read.total_access, reverse = True)
- files_sorted_by_write = files.values()
- files_sorted_by_write.sort(key=lambda f : f.write.total_access, reverse = True)
- print " Top 10 readers:"
- for i in range(min(10, len(files_sorted_by_read))):
- files_sorted_by_read[i].dump_short()
- print " Top 10 writers:"
- for i in range(min(10, len(files_sorted_by_write))):
- files_sorted_by_write[i].dump_short()
- for f in files_sorted_by_read:
- f.dump(name_to_pid_map)
- total_reads += f.read.total_access
- total_writes += f.write.total_access
- print " Total reads:", total_reads, " total writes:", total_writes
- return total_reads, total_writes, len(files)
-
-
- def dump(self):
- print "*Dump R/W per each partition"
- total_reads = 0
- total_writes = 0
- summaries = []
- for d in self.files_per_device:
- reads, writes, num_files = self.dump_partition(DEVICE_TO_PARTITION[d], \
- self.files_per_device[d])
- total_reads += reads
- total_writes += writes
- summaries.append((DEVICE_TO_PARTITION[d], reads, writes, num_files))
- print "*Summary*"
- print "Total blocks read", total_reads
- print "Total blocks wrote", total_writes
- print "Partition total_reads total_writes num_files"
- for s in summaries:
- print s[0], s[1], s[2], s[3]
-
-def main(argv):
- if (len(argv) < 2):
- print "check_fule_read.py filename"
- return
- filename = argv[1]
- trace = Trace()
- with open(filename) as f:
- for l in f:
- trace.handle_line(l)
- trace.dump()
-
-if __name__ == '__main__':
- main(sys.argv)
diff --git a/tools/io_analysis/check_io_trace.py b/tools/io_analysis/check_io_trace.py
deleted file mode 100644
index bc26c46..0000000
--- a/tools/io_analysis/check_io_trace.py
+++ /dev/null
@@ -1,193 +0,0 @@
-#!/usr/bin/env python
-#
-# 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.
-#
-"""Analyze block trace"""
-
-import collections
-import os
-import re
-import string
-import sys
-
-RE_BLOCK = r'.+\s+(block[a-z_]+):\s+'
-RE_BLOCK_BIO_QUEUE = r'.+\s+([0-9]+\.[0-9]+):\s+block_bio_queue:\s+([0-9]+)\,([0-9]+)\s+([RW]\S*)\s+([0-9]+)\s+\+\s+([0-9]+)\s+\[([^\]]+)'
-
-# dev_num = major * MULTIPLIER + minor
-DEV_MAJOR_MULTIPLIER = 1000
-
-# dm access is remapped to disk access. So account differently
-DM_MAJOR = 253
-
-class RwEvent:
- def __init__(self, block_num, start_time, size):
- self.block_num = block_num
- self.start_time = start_time
- self.size = size
- self.latency = 0
- def set_latency(self, latency):
- self.latency = latency
-
-def get_string_pos(strings, string_to_find):
- for i, s in enumerate(strings):
- if s == string_to_find:
- return i
- return -1
-
-
-class Trace:
- def __init__(self, process):
- self.process = process
- self.reads = [] #(start time, RwEvent)
- self.writes = [] #(start time, RwEvent)
- self.recent_reads = {} # K:
- self.total_latency = 0
- self.total_reads = 0
- self.total_writes = 0
- self.total_dm_reads = {} #K: devnum, V: blocks
- self.total_dm_writes = {}
- self.re_block_queue = re.compile(RE_BLOCK_BIO_QUEUE)
- self.processes = set()
- if process[-1] == '*':
- print "Process name starts with", process[:-1]
- self.process_name_is_prefix = True
- else:
- print "Process name", process
- self.process_name_is_prefix = False
-
- def parse_bio_queue(self, l):
- match = self.re_block_queue.match(l)
- if not match:
- return
- start_time = int(float(match.group(1))*1000000) #us
- major = int(match.group(2))
- minor = int(match.group(3))
- operation = match.group(4)
- block_num = int(match.group(5))
- size = int(match.group(6))
- process = match.group(7)
- if self.process_name_is_prefix:
- if not process.startswith(self.process[:-1]):
- return
- self.processes.add(process)
- else:
- if process != self.process:
- return
- if major == DM_MAJOR:
- devNum = major * DEV_MAJOR_MULTIPLIER + minor;
- if operation[0] == 'R':
- if devNum not in self.total_dm_reads:
- self.total_dm_reads[devNum] = 0
- self.total_dm_reads[devNum] += size
- elif operation[0] == 'W':
- if devNum not in self.total_dm_writes:
- self.total_dm_writes[devNum] = 0
- self.total_dm_writes[devNum] += size
- return
- event = RwEvent(block_num, start_time, size)
- if operation[0] == 'R':
- self.reads.append((start_time, event))
- self.recent_reads[block_num] = event
- self.total_reads += size
- elif operation[0] == 'W':
- self.writes.append((start_time, event))
- self.total_writes += size
-
- def parse_rq_complete(self, l):
- words = string.split(l)
- cmd_pos = get_string_pos(words, "block_rq_complete:")
- if cmd_pos == -1:
- cmd_pos = get_string_pos(words, "block_bio_complete:")
- block_num = int(words[-4])
- event = self.recent_reads.get(block_num)
- if not event:
- return
- operation = words[cmd_pos + 2]
- if not operation.startswith("R"):
- return
- end_time = int(float(words[cmd_pos - 1][:-1])*1000000) #us
- latency = end_time - event.start_time
- if latency > 20000:
- print "very bad latency:", latency, l
- print "start time,", event.start_time
- event.set_latency(latency)
- del self.recent_reads[block_num]
- self.total_latency += latency
-
- def parse_block_trace(self, l, match):
- try:
- cmd = match.group(1)
- if cmd == "block_bio_queue":
- self.parse_bio_queue(l)
- elif cmd == "block_rq_complete" or cmd == "block_bio_complete":
- self.parse_rq_complete(l)
- except ValueError:
- print "cannot parse:", l
- raise
-
- def dump(self):
- if self.process_name_is_prefix:
- print "Processes:", self.processes
- print "total read blocks,", self.total_reads
- print "total write blocks,", self.total_writes
- if len(self.reads) > 0:
- total_read_time = self.reads[-1][0] + self.reads[-1][1].latency - self.reads[0][0]
- else:
- total_read_time = 0
- print "Total DM R"
- for dev,size in self.total_dm_reads.items():
- print dev, size
- print "Total DM W"
- for dev,size in self.total_dm_writes.items():
- print dev, size
- print "total read time,",total_read_time
- read_size_histogram = {}
- latency_per_read_size = {}
- for (time, event) in self.reads:
- if not read_size_histogram.get(event.size):
- read_size_histogram[event.size] = 0
- if not latency_per_read_size.get(event.size):
- latency_per_read_size[event.size] = [ 0, 0] # num events, total latency
- read_size_histogram[event.size] = read_size_histogram[event.size] + 1
- latency_sum = latency_per_read_size[event.size]
- latency_sum[0] += 1
- latency_sum[1] += event.latency
- read_size_histogram = collections.OrderedDict(sorted(read_size_histogram.items()))
- print "read histogram"
- for k,v in read_size_histogram.iteritems():
- print k, ',', v
- print "latency per read size"
- latency_per_read_size = collections.OrderedDict(sorted(latency_per_read_size.items()))
- for k,v in latency_per_read_size.iteritems():
- if v[0] != 0:
- print k, ',', v[1] / v[0], v[0], v[1]
-
-def main(argv):
- if (len(argv) < 3):
- print "check_io_trace.py processname filename"
- return
- keyword = argv[1]
- filename = argv[2]
- trace = Trace(keyword)
- prog = re.compile(RE_BLOCK)
- with open(filename) as f:
- for l in f:
- result = prog.match(l)
- if result:
- trace.parse_block_trace(l, result)
- trace.dump()
-
-if __name__ == '__main__':
- main(sys.argv)
diff --git a/tools/io_analysis/check_io_trace_all.py b/tools/io_analysis/check_io_trace_all.py
deleted file mode 100644
index 8ea466d..0000000
--- a/tools/io_analysis/check_io_trace_all.py
+++ /dev/null
@@ -1,386 +0,0 @@
-#!/usr/bin/env python
-#
-# 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.
-#
-"""Analyze block trace"""
-
-import collections
-import os
-import re
-import string
-import sys
-
-# ex) <...>-52 [001] ...1 1.362574: block_bio_queue: 8,16 R 0 + 8 [kworker/u8:1]
-RE_BLOCK = r'.+-([0-9]+).*\s+([0-9]+\.[0-9]+):\s+block_bio_queue:\s+([0-9]+)\,([0-9]+)\s(\S+)\s+([0-9]+)\s+\+\s+([0-9]+)\s+\[([^\]]+)'
-# ex) <...>-453 [001] d..4 3.181854: sched_blocked_reason: pid=471 iowait=1 caller=__wait_on_buffer+0x24/0x2c
-RE_SCHED_BLOCKED_READSON = r'.+-([0-9]+)\s+\[([0-9]+)\]\s.*\s+([0-9]+\.[0-9]+):\s+sched_blocked_reason:\spid=([0-9]+)\siowait=([01])\scaller=(\S+)'
-# ex) <idle>-0 [000] d..3 3.181864: sched_switch: prev_comm=swapper/0 prev_pid=0 prev_prio=120 prev_state=R ==> next_comm=ueventd next_pid=471 next_prio=120
-RE_SCHED_SWITCH = r'.+-([0-9]+)\s+\[([0-9]+)\]\s.*\s+([0-9]+\.[0-9]+):\s+sched_switch:\sprev_comm=(.+)\sprev_pid=([0-9]+)\sprev_prio=([0-9]+)\sprev_state=(\S+).*next_comm=(.+)\snext_pid=([0-9]+)\snext_prio=([0-9]+)'
-
-# dev_num = major * MULTIPLIER + minor
-DEV_MAJOR_MULTIPLIER = 1000
-
-# dm access is remapped to disk access. So account differently
-DM_MAJOR = 253
-
-MAX_PROCESS_DUMP = 10
-
-class RwEvent:
- def __init__(self, block_num, start_time, size):
- self.block_num = block_num
- self.start_time = start_time
- self.size = size
-
-def get_string_pos(strings, string_to_find):
- for i, s in enumerate(strings):
- if s == string_to_find:
- return i
- return -1
-
-class ProcessData:
- def __init__(self, name):
- self.name = name
- self.reads = {} # k : dev_num, v : [] of reads
- self.per_device_total_reads = {}
- self.writes = {}
- self.per_device_total_writes = {}
- self.total_reads = 0
- self.total_writes = 0
- self.total_dm_reads = 0
- self.total_dm_writes = 0
-
-
- def add_read_event(self, major, minor, event):
- devNum = major * DEV_MAJOR_MULTIPLIER + minor;
- events = self.reads.get(devNum)
- if not events:
- events = []
- self.reads[devNum] = events
- self.per_device_total_reads[devNum] = 0
- events.append(event)
- self.total_reads += event.size
- self.per_device_total_reads[devNum] += event.size
-
- def add_write_event(self, major, minor, event):
- devNum = major * DEV_MAJOR_MULTIPLIER + minor;
- events = self.writes.get(devNum)
- if not events:
- events = []
- self.writes[devNum] = events
- self.per_device_total_writes[devNum] = 0
- events.append(event)
- self.total_writes += event.size
- self.per_device_total_writes[devNum] += event.size
-
- def add_dm_read(self, size):
- self.total_dm_reads += size
-
- def add_dm_write(self, size):
- self.total_dm_writes += size
-
- def dump(self):
- print "Process,", self.name
- print " total reads,", self.total_reads
- print " total writes,", self.total_writes
- print " total dm reads,", self.total_dm_reads
- print " total dm writes,", self.total_dm_writes
- print " R per device"
- sorted_r = collections.OrderedDict(sorted(self.per_device_total_reads.items(), \
- key = lambda item: item[1], reverse = True))
- for i in range(len(sorted_r)):
- dev = sorted_r.popitem(last=False)
- print " ", dev[0],dev[1]
-
- print " W per device"
- sorted_w = collections.OrderedDict(sorted(self.per_device_total_writes.items(), \
- key = lambda item: item[1], reverse = True))
- for i in range(len(sorted_w)):
- dev = sorted_w.popitem(last=False)
- print " ", dev[0],dev[1]
-
-class IoTrace:
-
- def __init__(self):
- self.ios = {} #K: process name, v:ProcessData
- self.total_reads = 0
- self.total_writes = 0
- self.total_reads_per_device = {} #K: block num, V: total blocks
- self.total_writes_per_device = {}
- self.total_dm_reads = {} #K: devnum, V: blocks
- self.total_dm_writes = {}
- self.re_block = re.compile(RE_BLOCK)
-
- def parse(self, l):
- match = self.re_block.match(l)
- if not match:
- return False
- try:
- self.do_parse_bio_queue(l, match)
- except ValueError:
- print "cannot parse:", l
- raise
- return True
-
- def do_parse_bio_queue(self, l, match):
- pid = match.group(1)
- start_time = float(match.group(2))*1000 #ms
- major = int(match.group(3))
- minor = int(match.group(4))
- devNum = major * DEV_MAJOR_MULTIPLIER + minor;
- operation = match.group(5)
- block_num = int(match.group(6))
- size = int(match.group(7))
- process = match.group(8) + "-" + pid
- event = RwEvent(block_num, start_time, size)
- io = self.ios.get(process)
- if not io:
- io = ProcessData(process)
- self.ios[process] = io
- if major == DM_MAJOR:
- devNum = major * DEV_MAJOR_MULTIPLIER + minor;
- if 'R' in operation[0]:
- if devNum not in self.total_dm_reads:
- self.total_dm_reads[devNum] = 0
- self.total_dm_reads[devNum] += size
- io.add_dm_read(size)
- elif 'W' in operation[0]:
- if devNum not in self.total_dm_writes:
- self.total_dm_writes[devNum] = 0
- self.total_dm_writes[devNum] += size
- io.add_dm_write(size)
- return
- if 'R' in operation[0]:
- io.add_read_event(major, minor, event)
- self.total_reads += size
- per_device = self.total_reads_per_device.get(devNum)
- if not per_device:
- self.total_reads_per_device[devNum] = 0
- self.total_reads_per_device[devNum] += size
- elif 'W' in operation[0]:
- io.add_write_event(major, minor, event)
- self.total_writes += size
- per_device = self.total_writes_per_device.get(devNum)
- if not per_device:
- self.total_writes_per_device[devNum] = 0
- self.total_writes_per_device[devNum] += size
-
- def dump(self):
- print "total read blocks,", self.total_reads
- print "total write blocks,", self.total_writes
- print "Total DM R"
- for dev,size in self.total_dm_reads.items():
- print dev, size
- print "Total DM W"
- for dev,size in self.total_dm_writes.items():
- print dev, size
- print "**Process total R/W"
- sorted_by_total_rw = collections.OrderedDict(sorted(self.ios.items(), \
- key = lambda item: item[1].total_reads + item[1].total_writes, reverse = True))
- for i in range(MAX_PROCESS_DUMP):
- process = sorted_by_total_rw.popitem(last=False)
- if not process:
- break
- process[1].dump()
-
- print "**Process total W"
- sorted_by_total_w = collections.OrderedDict(sorted(self.ios.items(), \
- key = lambda item: item[1].total_writes, reverse = True))
- for i in range(5):
- process = sorted_by_total_w.popitem(last=False)
- if not process:
- break
- process[1].dump()
-
- print "**Device total R"
- sorted_by_total_r = collections.OrderedDict(sorted(self.total_reads_per_device.items(), \
- key = lambda item: item[1], reverse = True))
- for i in range(len(sorted_by_total_r)):
- dev = sorted_by_total_r.popitem(last=False)
- print dev[0],dev[1]
-
- print "**Device total W"
- sorted_by_total_w = collections.OrderedDict(sorted(self.total_writes_per_device.items(), \
- key = lambda item: item[1], reverse = True))
- for i in range(len(sorted_by_total_w)):
- dev = sorted_by_total_w.popitem(last=False)
- print dev[0],dev[1]
-
-class SchedProcess:
- def __init__(self, pid):
- self.pid = pid
- self.name = "unknown"
- self.total_execution_time = 0.0
- self.total_io_wait_time = 0.0
- self.total_other_wait_time = 0.0
- self.waiting_calls = {} # k: waiting_call, v : waiting counter
- self.io_waiting_call_times = {} # k: waiting_call, v: total wait time
- self.in_iowait = False
- self.last_waiting_call = None
- self.last_switch_out_time = 0.0
- self.last_switch_in_time = 0.0
- self.last_core = -1
- self.execution_time_per_core = {} # k: core, v : time
- self.io_latency_histograms = {} # k : delay in ms, v : count
-
- def handle_reason(self, current_time, iowait, waiting_call):
- #if self.pid == 1232:
- # print current_time, iowait, waiting_call
- if iowait == 1:
- self.in_iowait = True
- self.last_waiting_call = waiting_call
- call_counter = self.waiting_calls.get(waiting_call, 0)
- call_counter += 1
- self.waiting_calls[waiting_call] = call_counter
-
- def handle_switch_out(self, current_time, out_state, priority, name, core):
- #if self.pid == 1232:
- # print "out", current_time, out_state
- if self.name != name:
- self.name = name
- self.last_switch_out_time = current_time
- if self.last_switch_in_time == 0.0: # switch in not recorded. ignore this one
- return
- execution_time = current_time - self.last_switch_in_time
- self.total_execution_time += execution_time
- core_execution_time = self.execution_time_per_core.get(core, 0.0)
- core_execution_time += execution_time
- self.execution_time_per_core[core] = core_execution_time
-
- def handle_switch_in(self, current_time, priority, name, core):
- #if self.pid == 1232:
- # print "in", current_time, self.in_iowait
- if self.name != name:
- self.name = name
- self.last_switch_in_time = current_time
- if self.last_switch_out_time == 0.0: # in without out, probably 1st
- self.in_iowait = False
- return
- wait_time = current_time - self.last_switch_out_time
- if self.in_iowait:
- self.total_io_wait_time += wait_time
- total_waiting_call_time = self.io_waiting_call_times.get(self.last_waiting_call, 0.0)
- total_waiting_call_time += wait_time
- self.io_waiting_call_times[self.last_waiting_call] = total_waiting_call_time
- wait_time_ms = int(wait_time*10) / 10.0 # resolution up to 0.1 ms
- histogram_count = self.io_latency_histograms.get(wait_time_ms, 0)
- histogram_count += 1
- self.io_latency_histograms[wait_time_ms] = histogram_count
- else:
- self.total_other_wait_time += wait_time
- self.in_iowait = False
-
-
- def dump(self):
- print "PID:", self.pid, " name:", self.name
- print " total execution time:", self.total_execution_time,\
- " io wait:", self.total_io_wait_time, " other wait:", self.total_other_wait_time
- sorted_data = collections.OrderedDict(sorted(self.execution_time_per_core.items(), \
- key = lambda item: item[0], reverse = False))
- print " Core execution:", sorted_data
- sorted_data = collections.OrderedDict(sorted(self.waiting_calls.items(), \
- key = lambda item: item[1], reverse = True))
- print " Wait calls:", sorted_data
- sorted_data = collections.OrderedDict(sorted(self.io_waiting_call_times.items(), \
- key = lambda item: item[1], reverse = True))
- print " IO Wait time per wait calls:", sorted_data
- sorted_data = collections.OrderedDict(sorted(self.io_latency_histograms.items(), \
- key = lambda item: item[0], reverse = False))
- print " Wait time histogram:", sorted_data
-
-class SchedTrace:
- def __init__(self):
- self.re_switch = re.compile(RE_SCHED_SWITCH)
- self.re_reason = re.compile(RE_SCHED_BLOCKED_READSON)
- self.processes = {} # key: pid, v : SchedProcess
-
- def parse(self, l):
- checked_reason = False
- match = self.re_switch.match(l)
- if not match:
- match = self.re_reason.match(l)
- checked_reason = True
- if not match:
- return False
- try:
- if checked_reason:
- self.do_handle_reason(l, match)
- else:
- self.do_handle_switch(l, match)
- except ValueError:
- print "cannot parse:", l
- raise
- return True
-
- def do_handle_switch(self, l, match):
- current_pid = int(match.group(1))
- cpu_core = int(match.group(2))
- current_time = float(match.group(3))*1000 #ms
- out_name = match.group(4)
- out_pid = int(match.group(5))
- out_prio = int(match.group(6))
- out_state = match.group(7)
- in_name = match.group(8)
- in_pid = int(match.group(9))
- in_prio = int(match.group(10))
- out_process = self.processes.get(out_pid)
- if not out_process:
- out_process = SchedProcess(out_pid)
- self.processes[out_pid] = out_process
- in_process = self.processes.get(in_pid)
- if not in_process:
- in_process = SchedProcess(in_pid)
- self.processes[in_pid] = in_process
- out_process.handle_switch_out(current_time, out_state, out_prio, out_name, cpu_core)
- in_process.handle_switch_in(current_time, in_prio, in_name, cpu_core)
-
- def do_handle_reason(self, l, match):
- current_pid = int(match.group(1))
- cpu_core = int(match.group(2))
- current_time = float(match.group(3))*1000 #ms
- pid = int(match.group(4))
- iowait = int(match.group(5))
- waiting_call = match.group(6)
- process = self.processes.get(pid)
- if not process:
- process = SchedProcess(pid)
- self.processes[pid] = process
- process.handle_reason(current_time, iowait, waiting_call)
-
- def dump(self):
- sorted_by_total_execution = collections.OrderedDict(sorted(self.processes.items(), \
- key = lambda item: item[1].total_io_wait_time, reverse = True))
- for k, v in sorted_by_total_execution.iteritems():
- if v.total_execution_time > 10.0 or v.total_io_wait_time != 0.0:
- v.dump()
-
-def main(argv):
- if (len(argv) < 2):
- print "check_io_trace_all.py filename"
- return
- filename = argv[1]
-
- io_trace = IoTrace()
- sched_trace = SchedTrace()
- with open(filename) as f:
- for l in f:
- if io_trace.parse(l):
- continue
- sched_trace.parse(l)
- io_trace.dump()
- print "\n\n\n"
- sched_trace.dump()
-
-if __name__ == '__main__':
- main(sys.argv)
diff --git a/tools/io_analysis/check_verity.py b/tools/io_analysis/check_verity.py
deleted file mode 100644
index a69818f..0000000
--- a/tools/io_analysis/check_verity.py
+++ /dev/null
@@ -1,139 +0,0 @@
-#!/usr/bin/env python
-#
-# 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.
-#
-"""Analyze dm_verity trace"""
-import collections
-import math
-import os
-import re
-import string
-import sys
-
-RE_VERITY = r'.+\s+([0-9]+\.[0-9]+):\s+block_verity_msg:\s+(\S+)\s+([0-9]+)\,([0-9]+)\s+([0-9]+)\s+([0-9]+)'
-
-def get_average_and_std_dev(l):
- sum_io = 0.0
- sum_verity = 0.0
- sum_total = 0.0
- N = len(l)
- sum_blocks = 0.0
- for e in l:
- sum_io += e.io_latency
- sum_verity += e.verity_latency
- sum_total += e.total_latency
- sum_blocks += e.size
- average_io = sum_io / N
- average_verity = sum_verity / N
- average_total = sum_total / N
- var_io = 0.0
- var_verity = 0.0
- var_total = 0.0
- for e in l:
- var_io += (e.io_latency - average_io)**2
- var_verity += (e.verity_latency - average_verity)**2
- var_total += (e.total_latency - average_total)**2
- sigma_io = math.sqrt(var_io / N)
- sigma_verity = math.sqrt(var_verity / N)
- sigma_total = math.sqrt(var_total / N)
- return (average_io, sigma_io, sum_io), (average_verity, sigma_verity, sum_verity), \
- (average_total, sigma_total, sum_total), sum_blocks
-
-
-class Event:
- def __init__(self, start_time, block_num, size):
- self.block_num = block_num
- self.start_time = start_time
- self.io_end_time = 0
- self.finish_time = 0
- self.size = size
- self.total_latency = 0
- self.io_latency = 0
- self.verity_latency = 0
-
- def set_io_end_time(self, io_end_time):
- self.io_end_time = io_end_time
- self.io_latency = io_end_time - self.start_time
-
- def set_finish_time(self, finish_time):
- self.finish_time = finish_time
- self.verity_latency = finish_time - self.io_end_time
- self.total_latency = finish_time - self.start_time
-
-class VerityTrace:
- def __init__(self):
- self.reads = [] # all events in start time
- self.block_size_vs_reads_histogram = {} # key: size, value: list of events
- self.recents = {} # not finished, key: block_nr, value: event
- self.re = re.compile(RE_VERITY)
-
- def handle_line(self, line):
- match = self.re.match(line)
- if not match:
- return
- time = int(float(match.group(1))*1000000) #us
- step = match.group(2)
- block_nr = int(match.group(5))
- size = int(match.group(6))
- recent_key = block_nr * 1000 + size
- if step == "map":
- event = Event(time, block_nr, size)
- self.recents[recent_key] = event
- self.reads.append(event)
- per_size_list = self.block_size_vs_reads_histogram.get(size)
- if not per_size_list:
- per_size_list = []
- self.block_size_vs_reads_histogram[size] = per_size_list
- per_size_list.append(event)
- elif step == "end_io":
- event = self.recents[recent_key]
- event.set_io_end_time(time)
- elif step == "finish_io":
- event = self.recents[recent_key]
- event.set_finish_time(time)
- del self.recents[recent_key]
-
- def dump_list(self, msg, l):
- io, verity, total, blocks = get_average_and_std_dev(l)
- print msg, "counts:", len(l), "io latency:", io[0], io[1], io[2], "verity latency:", \
- verity[0], verity[1], verity[2], "total:", total[0], total[1], total[2]
- return io, verity, total, blocks
-
- def dump(self):
- print "Numbers: average (us), stddev (us), total (us)"
- io, verity, total, blocks = self.dump_list ("total,", self.reads)
- io_latency_per_1024KB = io[2] / blocks * (1024 / 4)
- verity_latency_per_1024KB = verity[2] / blocks * (1024 / 4)
- total_latency_per_1024KB = io_latency_per_1024KB + verity_latency_per_1024KB
- print "Average latency for 1024KB (us), IO:", io_latency_per_1024KB, \
- "Verity:", verity_latency_per_1024KB, "Total:", total_latency_per_1024KB
- sizes = sorted(self.block_size_vs_reads_histogram.keys())
- print "Latency per read size"
- for s in sizes:
- self.dump_list ("size " + str(s), self.block_size_vs_reads_histogram[s])
-
-def main(argv):
- if (len(argv) < 2):
- print "check_io_trace.py filename"
- return
- filename = argv[1]
- trace = VerityTrace()
- with open(filename) as f:
- for l in f:
- trace.handle_line(l)
- trace.dump()
-
-if __name__ == '__main__':
- main(sys.argv)
diff --git a/tools/ioanalyze/analyzer.py b/tools/ioanalyze/analyzer.py
new file mode 100755
index 0000000..7ab77b6
--- /dev/null
+++ b/tools/ioanalyze/analyzer.py
@@ -0,0 +1,266 @@
+#!/usr/bin/env python3
+
+import argparse
+import datetime
+import json
+import matplotlib.pyplot as plt
+import sys
+
+class UidSnapshot(object):
+ def __init__(self, activity):
+ self.uid = activity['uid']
+ self.foregroundWrittenBytes = activity['foregroundWrittenBytes']
+ self.foregroundFsyncCalls = activity['foregroundFsyncCalls']
+ self.backgroundFsyncCalls = activity['backgroundFsyncCalls']
+ self.backgroundWrittenBytes = activity['backgroundWrittenBytes']
+ self.appPackages = activity['appPackages']
+ self.runtimeMs = activity['runtimeMs']
+ self.totalWrittenBytes = self.foregroundWrittenBytes + self.backgroundWrittenBytes
+ self.totalFsyncCalls = self.backgroundFsyncCalls + self.foregroundFsyncCalls
+ if self.appPackages is None: self.appPackages = []
+
+class Snapshot(object):
+ def __init__(self, activity, uptime):
+ self.uptime = uptime
+ self.uids = {}
+ self.foregroundWrittenBytes = 0
+ self.foregroundFsyncCalls = 0
+ self.backgroundFsyncCalls = 0
+ self.backgroundWrittenBytes = 0
+ self.totalWrittenBytes = 0
+ self.totalFsyncCalls = 0
+ for entry in activity:
+ uid = entry['uid']
+ snapshot = UidSnapshot(entry)
+ self.foregroundWrittenBytes += snapshot.foregroundWrittenBytes
+ self.foregroundFsyncCalls += snapshot.foregroundFsyncCalls
+ self.backgroundFsyncCalls += snapshot.backgroundFsyncCalls
+ self.backgroundWrittenBytes += snapshot.backgroundWrittenBytes
+ self.totalWrittenBytes += snapshot.totalWrittenBytes
+ self.totalFsyncCalls += snapshot.totalFsyncCalls
+ self.uids[uid] = snapshot
+
+class Document(object):
+ def __init__(self, f):
+ self.snapshots = []
+ uptimes = [0, 0]
+ for line in f:
+ line = json.loads(line)
+ if line['type'] != 'snapshot': continue
+ activity = line['activity']
+ uptime = line['uptime']
+ if uptime < uptimes[0]: uptimes[0] = uptime
+ if uptime > uptimes[1]: uptimes[1] = uptime
+ self.snapshots.append(Snapshot(activity, uptime))
+ self.runtime = datetime.timedelta(milliseconds=uptimes[1]-uptimes[0])
+
+def merge(l1, l2):
+ s1 = set(l1)
+ s2 = set(l2)
+ return list(s1 | s2)
+
+
+thresholds = [
+ (1024 * 1024 * 1024 * 1024, "TB"),
+ (1024 * 1024 * 1024, "GB"),
+ (1024 * 1024, "MB"),
+ (1024, "KB"),
+ (1, "bytes")
+]
+def prettyPrintBytes(n):
+ for t in thresholds:
+ if n >= t[0]:
+ return "%.1f %s" % (n / (t[0] + 0.0), t[1])
+ return "0 bytes"
+
+# knowledge extracted from android_filesystem_config.h
+wellKnownUids = {
+ 0 : ["linux kernel"],
+ 1010 : ["wifi"],
+ 1013 : ["mediaserver"],
+ 1017 : ["keystore"],
+ 1019 : ["DRM server"],
+ 1021 : ["GPS"],
+ 1023 : ["media storage write access"],
+ 1036 : ["logd"],
+ 1040 : ["mediaextractor"],
+ 1041 : ["audioserver"],
+ 1046 : ["mediacodec"],
+ 1047 : ["cameraserver"],
+ 1053 : ["webview zygote"],
+ 1054 : ["vehicle hal"],
+ 1058 : ["tombstoned"],
+ 1066 : ["statsd"],
+ 1067 : ["incidentd"],
+ 9999 : ["nobody"],
+}
+
+class UserActivity(object):
+ def __init__(self, uid):
+ self.uid = uid
+ self.snapshots = []
+ self.appPackages = wellKnownUids.get(uid, [])
+ self.foregroundWrittenBytes = 0
+ self.foregroundFsyncCalls = 0
+ self.backgroundFsyncCalls = 0
+ self.backgroundWrittenBytes = 0
+ self.totalWrittenBytes = 0
+ self.totalFsyncCalls = 0
+
+ def addSnapshot(self, snapshot):
+ assert snapshot.uid == self.uid
+ self.snapshots.append(snapshot)
+ self.foregroundWrittenBytes += snapshot.foregroundWrittenBytes
+ self.foregroundFsyncCalls += snapshot.foregroundFsyncCalls
+ self.backgroundFsyncCalls += snapshot.backgroundFsyncCalls
+ self.backgroundWrittenBytes += snapshot.backgroundWrittenBytes
+ self.totalWrittenBytes += snapshot.totalWrittenBytes
+ self.totalFsyncCalls += snapshot.totalFsyncCalls
+ self.appPackages = merge(self.appPackages, snapshot.appPackages)
+
+ def plot(self, foreground=True, background=True, total=True):
+ plt.figure()
+ plt.title("I/O activity for UID %s" % (self.uid))
+ X = range(0,len(self.snapshots))
+ minY = 0
+ maxY = 0
+ if foreground:
+ Y = [s.foregroundWrittenBytes for s in self.snapshots]
+ if any([y > 0 for y in Y]):
+ plt.plot(X, Y, 'b-')
+ minY = min(minY, min(Y))
+ maxY = max(maxY, max(Y))
+ if background:
+ Y = [s.backgroundWrittenBytes for s in self.snapshots]
+ if any([y > 0 for y in Y]):
+ plt.plot(X, Y, 'g-')
+ minY = min(minY, min(Y))
+ maxY = max(maxY, max(Y))
+ if total:
+ Y = [s.totalWrittenBytes for s in self.snapshots]
+ if any([y > 0 for y in Y]):
+ plt.plot(X, Y, 'r-')
+ minY = min(minY, min(Y))
+ maxY = max(maxY, max(Y))
+
+ i = int((maxY - minY) / 5)
+ Yt = list(range(minY, maxY, i))
+ Yl = [prettyPrintBytes(y) for y in Yt]
+ plt.yticks(Yt, Yl)
+ Xt = list(range(0, len(X)))
+ plt.xticks(Xt)
+
+class SystemActivity(object):
+ def __init__(self):
+ self.uids = {}
+ self.snapshots = []
+ self.foregroundWrittenBytes = 0
+ self.foregroundFsyncCalls = 0
+ self.backgroundFsyncCalls = 0
+ self.backgroundWrittenBytes = 0
+ self.totalWrittenBytes = 0
+ self.totalFsyncCalls = 0
+
+ def addSnapshot(self, snapshot):
+ self.snapshots.append(snapshot)
+ self.foregroundWrittenBytes += snapshot.foregroundWrittenBytes
+ self.foregroundFsyncCalls += snapshot.foregroundFsyncCalls
+ self.backgroundFsyncCalls += snapshot.backgroundFsyncCalls
+ self.backgroundWrittenBytes += snapshot.backgroundWrittenBytes
+ self.totalWrittenBytes += snapshot.totalWrittenBytes
+ self.totalFsyncCalls += snapshot.totalFsyncCalls
+ for uid in snapshot.uids:
+ if uid not in self.uids: self.uids[uid] = UserActivity(uid)
+ self.uids[uid].addSnapshot(snapshot.uids[uid])
+
+ def loadDocument(self, doc):
+ for snapshot in doc.snapshots:
+ self.addSnapshot(snapshot)
+
+ def sorted(self, f):
+ return sorted(self.uids.values(), key=f, reverse=True)
+
+ def pie(self):
+ plt.figure()
+ plt.title("Total disk writes per UID")
+ A = [(K, self.uids[K].totalWrittenBytes) for K in self.uids]
+ A = filter(lambda i: i[1] > 0, A)
+ A = list(sorted(A, key=lambda i: i[1], reverse=True))
+ X = [i[1] for i in A]
+ L = [i[0] for i in A]
+ plt.pie(X, labels=L, counterclock=False, startangle=90)
+
+parser = argparse.ArgumentParser("Process FlashApp logs into reports")
+parser.add_argument("filename")
+parser.add_argument("--reportuid", action="append", default=[])
+parser.add_argument("--plotuid", action="append", default=[])
+parser.add_argument("--totalpie", action="store_true", default=False)
+
+args = parser.parse_args()
+
+class UidFilter(object):
+ def __call__(self, uid):
+ return False
+
+class UidFilterAcceptAll(UidFilter):
+ def __call__(self, uid):
+ return True
+
+class UidFilterAcceptSome(UidFilter):
+ def __init__(self, uids):
+ self.uids = uids
+
+ def __call__(self, uid):
+ return uid in self.uids
+
+uidset = set()
+plotfilter = None
+for uid in args.plotuid:
+ if uid == "all":
+ plotfilter = UidFilterAcceptAll()
+ break
+ else:
+ uidset.add(int(uid))
+if plotfilter is None: plotfilter = UidFilterAcceptSome(uidset)
+
+uidset = set()
+reportfilter = None
+for uid in args.reportuid:
+ if uid == "all":
+ reportfilter = UidFilterAcceptAll()
+ break
+ else:
+ uidset.add(int(uid))
+if reportfilter is None:
+ if len(uidset) == 0:
+ reportfilter = UidFilterAcceptAll()
+ else:
+ reportfilter = UidFilterAcceptSome(uidset)
+
+document = Document(open(args.filename))
+print("System runtime: %s\n" % (document.runtime))
+system = SystemActivity()
+system.loadDocument(document)
+
+print("Total bytes written: %s (of which %s in foreground and %s in background)\n" % (
+ prettyPrintBytes(system.totalWrittenBytes),
+ prettyPrintBytes(system.foregroundWrittenBytes),
+ prettyPrintBytes(system.backgroundWrittenBytes)))
+
+writemost = filter(lambda ua: ua.totalWrittenBytes > 0, system.sorted(lambda ua: ua.totalWrittenBytes))
+for entry in writemost:
+ if reportfilter(entry.uid):
+ print("user id %d (%s) wrote %s (of which %s in foreground and %s in background)" % (
+ entry.uid,
+ ','.join(entry.appPackages),
+ prettyPrintBytes(entry.totalWrittenBytes),
+ prettyPrintBytes(entry.foregroundWrittenBytes),
+ prettyPrintBytes(entry.backgroundWrittenBytes)))
+ if plotfilter(entry.uid):
+ entry.plot()
+ plt.show()
+
+if args.totalpie:
+ system.pie()
+ plt.show()
+
diff --git a/tools/bootanalyze/Android.mk b/tools/keventreader/Android.mk
similarity index 92%
copy from tools/bootanalyze/Android.mk
copy to tools/keventreader/Android.mk
index 5df0dd8..1220a1a 100644
--- a/tools/bootanalyze/Android.mk
+++ b/tools/keventreader/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.
diff --git a/libvehiclemonitor/java/Android.mk b/tools/keventreader/client/Android.mk
similarity index 64%
copy from libvehiclemonitor/java/Android.mk
copy to tools/keventreader/client/Android.mk
index 1ced365..529feea 100644
--- a/libvehiclemonitor/java/Android.mk
+++ b/tools/keventreader/client/Android.mk
@@ -1,4 +1,4 @@
-# Copyright (C) 2016 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.
@@ -18,9 +18,14 @@
include $(CLEAR_VARS)
-LOCAL_MODULE := libvehiclemonitor-java
+LOCAL_MODULE := com.android.car.keventreader-client
LOCAL_MODULE_TAGS := optional
-LOCAL_SRC_FILES := $(call all-java-files-under, src) $(call all-Iaidl-files-under, src)
+LOCAL_SRC_FILES := $(call all-java-files-under, src)
+
+LOCAL_SRC_FILES += ../common/com/android/car/keventreader/IEventCallback.aidl
+LOCAL_SRC_FILES += ../common/com/android/car/keventreader/IEventProvider.aidl
+
+LOCAL_AIDL_INCLUDES += $(LOCAL_PATH)/../common
include $(BUILD_STATIC_JAVA_LIBRARY)
diff --git a/tools/keventreader/client/src/com/android/car/keventreader/EventReaderService.java b/tools/keventreader/client/src/com/android/car/keventreader/EventReaderService.java
new file mode 100644
index 0000000..b50bbb1
--- /dev/null
+++ b/tools/keventreader/client/src/com/android/car/keventreader/EventReaderService.java
@@ -0,0 +1,64 @@
+/*
+ * 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.keventreader;
+
+import android.annotation.Nullable;
+import android.os.RemoteException;
+import android.os.ServiceManager;
+import android.util.Log;
+import java.util.Objects;
+
+public final class EventReaderService {
+ private static final String TAG = "car.keventreader";
+ private static final String SERVICE_NAME = "com.android.car.keventreader";
+ private final IEventProvider mService;
+
+ private EventReaderService(IEventProvider service) {
+ mService = Objects.requireNonNull(service);
+ }
+
+ @Nullable
+ private static IEventProvider getService() {
+ return IEventProvider.Stub.asInterface(ServiceManager.getService(SERVICE_NAME));
+ }
+
+ @Nullable
+ public static EventReaderService tryGet() {
+ IEventProvider provider = getService();
+ if (provider == null) return null;
+ return new EventReaderService(provider);
+ }
+
+ public boolean registerCallback(IEventCallback callback) {
+ try {
+ mService.registerCallback(callback);
+ return true;
+ } catch (RemoteException e) {
+ Log.e(TAG, "unable to register new callback", e);
+ return false;
+ }
+ }
+
+ public boolean unregisterCallback(IEventCallback callback) {
+ try {
+ mService.unregisterCallback(callback);
+ return true;
+ } catch (RemoteException e) {
+ Log.e(TAG, "unable to remove callback registration", e);
+ return false;
+ }
+ }
+}
diff --git a/tools/keventreader/client/src/com/android/car/keventreader/KeypressEvent.java b/tools/keventreader/client/src/com/android/car/keventreader/KeypressEvent.java
new file mode 100644
index 0000000..34aa992
--- /dev/null
+++ b/tools/keventreader/client/src/com/android/car/keventreader/KeypressEvent.java
@@ -0,0 +1,633 @@
+/*
+ * 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.keventreader;
+
+import android.os.Parcel;
+import android.os.Parcelable;
+import java.util.HashMap;
+import java.util.Map;
+
+public final class KeypressEvent implements Parcelable {
+ private static final Map<Integer, String> KEYCODE_NAME_MAP = new HashMap<Integer, String>() {{
+ put(0,"RESERVED");
+ put(1,"ESC");
+ put(2,"1");
+ put(3,"2");
+ put(4,"3");
+ put(5,"4");
+ put(6,"5");
+ put(7,"6");
+ put(8,"7");
+ put(9,"8");
+ put(10,"9");
+ put(11,"0");
+ put(12,"MINUS");
+ put(13,"EQUAL");
+ put(14,"BACKSPACE");
+ put(15,"TAB");
+ put(16,"Q");
+ put(17,"W");
+ put(18,"E");
+ put(19,"R");
+ put(20,"T");
+ put(21,"Y");
+ put(22,"U");
+ put(23,"I");
+ put(24,"O");
+ put(25,"P");
+ put(26,"LEFTBRACE");
+ put(27,"RIGHTBRACE");
+ put(28,"ENTER");
+ put(29,"LEFTCTRL");
+ put(30,"A");
+ put(31,"S");
+ put(32,"D");
+ put(33,"F");
+ put(34,"G");
+ put(35,"H");
+ put(36,"J");
+ put(37,"K");
+ put(38,"L");
+ put(39,"SEMICOLON");
+ put(40,"APOSTROPHE");
+ put(41,"GRAVE");
+ put(42,"LEFTSHIFT");
+ put(43,"BACKSLASH");
+ put(44,"Z");
+ put(45,"X");
+ put(46,"C");
+ put(47,"V");
+ put(48,"B");
+ put(49,"N");
+ put(50,"M");
+ put(51,"COMMA");
+ put(52,"DOT");
+ put(53,"SLASH");
+ put(54,"RIGHTSHIFT");
+ put(55,"KPASTERISK");
+ put(56,"LEFTALT");
+ put(57,"SPACE");
+ put(58,"CAPSLOCK");
+ put(59,"F1");
+ put(60,"F2");
+ put(61,"F3");
+ put(62,"F4");
+ put(63,"F5");
+ put(64,"F6");
+ put(65,"F7");
+ put(66,"F8");
+ put(67,"F9");
+ put(68,"F10");
+ put(69,"NUMLOCK");
+ put(70,"SCROLLLOCK");
+ put(71,"KP7");
+ put(72,"KP8");
+ put(73,"KP9");
+ put(74,"KPMINUS");
+ put(75,"KP4");
+ put(76,"KP5");
+ put(77,"KP6");
+ put(78,"KPPLUS");
+ put(79,"KP1");
+ put(80,"KP2");
+ put(81,"KP3");
+ put(82,"KP0");
+ put(83,"KPDOT");
+ put(85,"ZENKAKUHANKAKU");
+ put(86,"102ND");
+ put(87,"F11");
+ put(88,"F12");
+ put(89,"RO");
+ put(90,"KATAKANA");
+ put(91,"HIRAGANA");
+ put(92,"HENKAN");
+ put(93,"KATAKANAHIRAGANA");
+ put(94,"MUHENKAN");
+ put(95,"KPJPCOMMA");
+ put(96,"KPENTER");
+ put(97,"RIGHTCTRL");
+ put(98,"KPSLASH");
+ put(99,"SYSRQ");
+ put(100,"RIGHTALT");
+ put(101,"LINEFEED");
+ put(102,"HOME");
+ put(103,"UP");
+ put(104,"PAGEUP");
+ put(105,"LEFT");
+ put(106,"RIGHT");
+ put(107,"END");
+ put(108,"DOWN");
+ put(109,"PAGEDOWN");
+ put(110,"INSERT");
+ put(111,"DELETE");
+ put(112,"MACRO");
+ put(113,"MUTE");
+ put(114,"VOLUMEDOWN");
+ put(115,"VOLUMEUP");
+ put(116,"POWER");
+ put(117,"KPEQUAL");
+ put(118,"KPPLUSMINUS");
+ put(119,"PAUSE");
+ put(120,"SCALE");
+ put(121,"KPCOMMA");
+ put(122,"HANGEUL");
+ put(123,"HANJA");
+ put(124,"YEN");
+ put(125,"LEFTMETA");
+ put(126,"RIGHTMETA");
+ put(127,"COMPOSE");
+ put(128,"STOP");
+ put(129,"AGAIN");
+ put(130,"PROPS");
+ put(131,"UNDO");
+ put(132,"FRONT");
+ put(133,"COPY");
+ put(134,"OPEN");
+ put(135,"PASTE");
+ put(136,"FIND");
+ put(137,"CUT");
+ put(138,"HELP");
+ put(139,"MENU");
+ put(140,"CALC");
+ put(141,"SETUP");
+ put(142,"SLEEP");
+ put(143,"WAKEUP");
+ put(144,"FILE");
+ put(145,"SENDFILE");
+ put(146,"DELETEFILE");
+ put(147,"XFER");
+ put(148,"PROG1");
+ put(149,"PROG2");
+ put(150,"WWW");
+ put(151,"MSDOS");
+ put(152,"SCREENLOCK");
+ put(153,"ROTATE_DISPLAY");
+ put(154,"CYCLEWINDOWS");
+ put(155,"MAIL");
+ put(156,"BOOKMARKS");
+ put(157,"COMPUTER");
+ put(158,"BACK");
+ put(159,"FORWARD");
+ put(160,"CLOSECD");
+ put(161,"EJECTCD");
+ put(162,"EJECTCLOSECD");
+ put(163,"NEXTSONG");
+ put(164,"PLAYPAUSE");
+ put(165,"PREVIOUSSONG");
+ put(166,"STOPCD");
+ put(167,"RECORD");
+ put(168,"REWIND");
+ put(169,"PHONE");
+ put(170,"ISO");
+ put(171,"CONFIG");
+ put(172,"HOMEPAGE");
+ put(173,"REFRESH");
+ put(174,"EXIT");
+ put(175,"MOVE");
+ put(176,"EDIT");
+ put(177,"SCROLLUP");
+ put(178,"SCROLLDOWN");
+ put(179,"KPLEFTPAREN");
+ put(180,"KPRIGHTPAREN");
+ put(181,"NEW");
+ put(182,"REDO");
+ put(183,"F13");
+ put(184,"F14");
+ put(185,"F15");
+ put(186,"F16");
+ put(187,"F17");
+ put(188,"F18");
+ put(189,"F19");
+ put(190,"F20");
+ put(191,"F21");
+ put(192,"F22");
+ put(193,"F23");
+ put(194,"F24");
+ put(200,"PLAYCD");
+ put(201,"PAUSECD");
+ put(202,"PROG3");
+ put(203,"PROG4");
+ put(204,"DASHBOARD");
+ put(205,"SUSPEND");
+ put(206,"CLOSE");
+ put(207,"PLAY");
+ put(208,"FASTFORWARD");
+ put(209,"BASSBOOST");
+ put(210,"PRINT");
+ put(211,"HP");
+ put(212,"CAMERA");
+ put(213,"SOUND");
+ put(214,"QUESTION");
+ put(215,"EMAIL");
+ put(216,"CHAT");
+ put(217,"SEARCH");
+ put(218,"CONNECT");
+ put(219,"FINANCE");
+ put(220,"SPORT");
+ put(221,"SHOP");
+ put(222,"ALTERASE");
+ put(223,"CANCEL");
+ put(224,"BRIGHTNESSDOWN");
+ put(225,"BRIGHTNESSUP");
+ put(226,"MEDIA");
+ put(227,"SWITCHVIDEOMODE");
+ put(228,"KBDILLUMTOGGLE");
+ put(229,"KBDILLUMDOWN");
+ put(230,"KBDILLUMUP");
+ put(231,"SEND");
+ put(232,"REPLY");
+ put(233,"FORWARDMAIL");
+ put(234,"SAVE");
+ put(235,"DOCUMENTS");
+ put(236,"BATTERY");
+ put(237,"BLUETOOTH");
+ put(238,"WLAN");
+ put(239,"UWB");
+ put(240,"UNKNOWN");
+ put(241,"VIDEO_NEXT");
+ put(242,"VIDEO_PREV");
+ put(243,"BRIGHTNESS_CYCLE");
+ put(244,"BRIGHTNESS_AUTO");
+ put(245,"DISPLAY_OFF");
+ put(246,"WWAN");
+ put(247,"RFKILL");
+ put(248,"MICMUTE");
+ put(0x160,"OK");
+ put(0x161,"SELECT");
+ put(0x162,"GOTO");
+ put(0x163,"CLEAR");
+ put(0x164,"POWER2");
+ put(0x165,"OPTION");
+ put(0x166,"INFO");
+ put(0x167,"TIME");
+ put(0x168,"VENDOR");
+ put(0x169,"ARCHIVE");
+ put(0x16a,"PROGRAM");
+ put(0x16b,"CHANNEL");
+ put(0x16c,"FAVORITES");
+ put(0x16d,"EPG");
+ put(0x16e,"PVR");
+ put(0x16f,"MHP");
+ put(0x170,"LANGUAGE");
+ put(0x171,"TITLE");
+ put(0x172,"SUBTITLE");
+ put(0x173,"ANGLE");
+ put(0x174,"ZOOM");
+ put(0x175,"MODE");
+ put(0x176,"KEYBOARD");
+ put(0x177,"SCREEN");
+ put(0x178,"PC");
+ put(0x179,"TV");
+ put(0x17a,"TV2");
+ put(0x17b,"VCR");
+ put(0x17c,"VCR2");
+ put(0x17d,"SAT");
+ put(0x17e,"SAT2");
+ put(0x17f,"CD");
+ put(0x180,"TAPE");
+ put(0x181,"RADIO");
+ put(0x182,"TUNER");
+ put(0x183,"PLAYER");
+ put(0x184,"TEXT");
+ put(0x185,"DVD");
+ put(0x186,"AUX");
+ put(0x187,"MP3");
+ put(0x188,"AUDIO");
+ put(0x189,"VIDEO");
+ put(0x18a,"DIRECTORY");
+ put(0x18b,"LIST");
+ put(0x18c,"MEMO");
+ put(0x18d,"CALENDAR");
+ put(0x18e,"RED");
+ put(0x18f,"GREEN");
+ put(0x190,"YELLOW");
+ put(0x191,"BLUE");
+ put(0x192,"CHANNELUP");
+ put(0x193,"CHANNELDOWN");
+ put(0x194,"FIRST");
+ put(0x195,"LAST");
+ put(0x196,"AB");
+ put(0x197,"NEXT");
+ put(0x198,"RESTART");
+ put(0x199,"SLOW");
+ put(0x19a,"SHUFFLE");
+ put(0x19b,"BREAK");
+ put(0x19c,"PREVIOUS");
+ put(0x19d,"DIGITS");
+ put(0x19e,"TEEN");
+ put(0x19f,"TWEN");
+ put(0x1a0,"VIDEOPHONE");
+ put(0x1a1,"GAMES");
+ put(0x1a2,"ZOOMIN");
+ put(0x1a3,"ZOOMOUT");
+ put(0x1a4,"ZOOMRESET");
+ put(0x1a5,"WORDPROCESSOR");
+ put(0x1a6,"EDITOR");
+ put(0x1a7,"SPREADSHEET");
+ put(0x1a8,"GRAPHICSEDITOR");
+ put(0x1a9,"PRESENTATION");
+ put(0x1aa,"DATABASE");
+ put(0x1ab,"NEWS");
+ put(0x1ac,"VOICEMAIL");
+ put(0x1ad,"ADDRESSBOOK");
+ put(0x1ae,"MESSENGER");
+ put(0x1af,"DISPLAYTOGGLE");
+ put(0x1b0,"SPELLCHECK");
+ put(0x1b1,"LOGOFF");
+ put(0x1b2,"DOLLAR");
+ put(0x1b3,"EURO");
+ put(0x1b4,"FRAMEBACK");
+ put(0x1b5,"FRAMEFORWARD");
+ put(0x1b6,"CONTEXT_MENU");
+ put(0x1b7,"MEDIA_REPEAT");
+ put(0x1b8,"10CHANNELSUP");
+ put(0x1b9,"10CHANNELSDOWN");
+ put(0x1ba,"IMAGES");
+ put(0x1c0,"DEL_EOL");
+ put(0x1c1,"DEL_EOS");
+ put(0x1c2,"INS_LINE");
+ put(0x1c3,"DEL_LINE");
+ put(0x1d0,"FN");
+ put(0x1d1,"FN_ESC");
+ put(0x1d2,"FN_F1");
+ put(0x1d3,"FN_F2");
+ put(0x1d4,"FN_F3");
+ put(0x1d5,"FN_F4");
+ put(0x1d6,"FN_F5");
+ put(0x1d7,"FN_F6");
+ put(0x1d8,"FN_F7");
+ put(0x1d9,"FN_F8");
+ put(0x1da,"FN_F9");
+ put(0x1db,"FN_F10");
+ put(0x1dc,"FN_F11");
+ put(0x1dd,"FN_F12");
+ put(0x1de,"FN_1");
+ put(0x1df,"FN_2");
+ put(0x1e0,"FN_D");
+ put(0x1e1,"FN_E");
+ put(0x1e2,"FN_F");
+ put(0x1e3,"FN_S");
+ put(0x1e4,"FN_B");
+ put(0x1f1,"BRL_DOT1");
+ put(0x1f2,"BRL_DOT2");
+ put(0x1f3,"BRL_DOT3");
+ put(0x1f4,"BRL_DOT4");
+ put(0x1f5,"BRL_DOT5");
+ put(0x1f6,"BRL_DOT6");
+ put(0x1f7,"BRL_DOT7");
+ put(0x1f8,"BRL_DOT8");
+ put(0x1f9,"BRL_DOT9");
+ put(0x1fa,"BRL_DOT10");
+ put(0x200,"NUMERIC_0");
+ put(0x201,"NUMERIC_1");
+ put(0x202,"NUMERIC_2");
+ put(0x203,"NUMERIC_3");
+ put(0x204,"NUMERIC_4");
+ put(0x205,"NUMERIC_5");
+ put(0x206,"NUMERIC_6");
+ put(0x207,"NUMERIC_7");
+ put(0x208,"NUMERIC_8");
+ put(0x209,"NUMERIC_9");
+ put(0x20a,"NUMERIC_STAR");
+ put(0x20b,"NUMERIC_POUND");
+ put(0x20c,"NUMERIC_A");
+ put(0x20d,"NUMERIC_B");
+ put(0x20e,"NUMERIC_C");
+ put(0x20f,"NUMERIC_D");
+ put(0x210,"CAMERA_FOCUS");
+ put(0x211,"WPS_BUTTON");
+ put(0x212,"TOUCHPAD_TOGGLE");
+ put(0x213,"TOUCHPAD_ON");
+ put(0x214,"TOUCHPAD_OFF");
+ put(0x215,"CAMERA_ZOOMIN");
+ put(0x216,"CAMERA_ZOOMOUT");
+ put(0x217,"CAMERA_UP");
+ put(0x218,"CAMERA_DOWN");
+ put(0x219,"CAMERA_LEFT");
+ put(0x21a,"CAMERA_RIGHT");
+ put(0x21b,"ATTENDANT_ON");
+ put(0x21c,"ATTENDANT_OFF");
+ put(0x21d,"ATTENDANT_TOGGLE");
+ put(0x21e,"LIGHTS_TOGGLE");
+ put(0x230,"ALS_TOGGLE");
+ put(0x240,"BUTTONCONFIG");
+ put(0x241,"TASKMANAGER");
+ put(0x242,"JOURNAL");
+ put(0x243,"CONTROLPANEL");
+ put(0x244,"APPSELECT");
+ put(0x245,"SCREENSAVER");
+ put(0x246,"VOICECOMMAND");
+ put(0x247,"ASSISTANT");
+ put(0x250,"BRIGHTNESS_MIN");
+ put(0x251,"BRIGHTNESS_MAX");
+ put(0x260,"KBDINPUTASSIST_PREV");
+ put(0x261,"KBDINPUTASSIST_NEXT");
+ put(0x262,"KBDINPUTASSIST_PREVGROUP");
+ put(0x263,"KBDINPUTASSIST_NEXTGROUP");
+ put(0x264,"KBDINPUTASSIST_ACCEPT");
+ put(0x265,"KBDINPUTASSIST_CANCEL");
+ put(0x266,"RIGHT_UP");
+ put(0x267,"RIGHT_DOWN");
+ put(0x268,"LEFT_UP");
+ put(0x269,"LEFT_DOWN");
+ put(0x26a,"ROOT_MENU");
+ put(0x26b,"MEDIA_TOP_MENU");
+ put(0x26c,"NUMERIC_11");
+ put(0x26d,"NUMERIC_12");
+ put(0x26e,"AUDIO_DESC");
+ put(0x26f,"3D_MODE");
+ put(0x270,"NEXT_FAVORITE");
+ put(0x271,"STOP_RECORD");
+ put(0x272,"PAUSE_RECORD");
+ put(0x273,"VOD");
+ put(0x274,"UNMUTE");
+ put(0x275,"FASTREVERSE");
+ put(0x276,"SLOWREVERSE");
+ put(0x277,"DATA");
+ put(0x278,"ONSCREEN_KEYBOARD");
+ put(113,"MIN_INTERESTING");
+ put(0x2ff,"MAX");
+ put(0x100,"MISC");
+ put(0x100,"0");
+ put(0x101,"1");
+ put(0x102,"2");
+ put(0x103,"3");
+ put(0x104,"4");
+ put(0x105,"5");
+ put(0x106,"6");
+ put(0x107,"7");
+ put(0x108,"8");
+ put(0x109,"9");
+ put(0x110,"MOUSE");
+ put(0x110,"LEFT");
+ put(0x111,"RIGHT");
+ put(0x112,"MIDDLE");
+ put(0x113,"SIDE");
+ put(0x114,"EXTRA");
+ put(0x115,"FORWARD");
+ put(0x116,"BACK");
+ put(0x117,"TASK");
+ put(0x120,"JOYSTICK");
+ put(0x120,"TRIGGER");
+ put(0x121,"THUMB");
+ put(0x122,"THUMB2");
+ put(0x123,"TOP");
+ put(0x124,"TOP2");
+ put(0x125,"PINKIE");
+ put(0x126,"BASE");
+ put(0x127,"BASE2");
+ put(0x128,"BASE3");
+ put(0x129,"BASE4");
+ put(0x12a,"BASE5");
+ put(0x12b,"BASE6");
+ put(0x12f,"DEAD");
+ put(0x130,"GAMEPAD");
+ put(0x130,"SOUTH");
+ put(0x131,"EAST");
+ put(0x132,"C");
+ put(0x133,"NORTH");
+ put(0x134,"WEST");
+ put(0x135,"Z");
+ put(0x136,"TL");
+ put(0x137,"TR");
+ put(0x138,"TL2");
+ put(0x139,"TR2");
+ put(0x13a,"SELECT");
+ put(0x13b,"START");
+ put(0x13c,"MODE");
+ put(0x13d,"THUMBL");
+ put(0x13e,"THUMBR");
+ put(0x140,"DIGI");
+ put(0x140,"TOOL_PEN");
+ put(0x141,"TOOL_RUBBER");
+ put(0x142,"TOOL_BRUSH");
+ put(0x143,"TOOL_PENCIL");
+ put(0x144,"TOOL_AIRBRUSH");
+ put(0x145,"TOOL_FINGER");
+ put(0x146,"TOOL_MOUSE");
+ put(0x147,"TOOL_LENS");
+ put(0x148,"TOOL_QUINTTAP");
+ put(0x149,"STYLUS3");
+ put(0x14a,"TOUCH");
+ put(0x14b,"STYLUS");
+ put(0x14c,"STYLUS2");
+ put(0x14d,"TOOL_DOUBLETAP");
+ put(0x14e,"TOOL_TRIPLETAP");
+ put(0x14f,"TOOL_QUADTAP");
+ put(0x150,"WHEEL");
+ put(0x150,"GEAR_DOWN");
+ put(0x151,"GEAR_UP");
+ put(0x220,"DPAD_UP");
+ put(0x221,"DPAD_DOWN");
+ put(0x222,"DPAD_LEFT");
+ put(0x223,"DPAD_RIGHT");
+ put(0x2c0,"TRIGGER_HAPPY");
+ put(0x2c0,"TRIGGER_HAPPY1");
+ put(0x2c1,"TRIGGER_HAPPY2");
+ put(0x2c2,"TRIGGER_HAPPY3");
+ put(0x2c3,"TRIGGER_HAPPY4");
+ put(0x2c4,"TRIGGER_HAPPY5");
+ put(0x2c5,"TRIGGER_HAPPY6");
+ put(0x2c6,"TRIGGER_HAPPY7");
+ put(0x2c7,"TRIGGER_HAPPY8");
+ put(0x2c8,"TRIGGER_HAPPY9");
+ put(0x2c9,"TRIGGER_HAPPY10");
+ put(0x2ca,"TRIGGER_HAPPY11");
+ put(0x2cb,"TRIGGER_HAPPY12");
+ put(0x2cc,"TRIGGER_HAPPY13");
+ put(0x2cd,"TRIGGER_HAPPY14");
+ put(0x2ce,"TRIGGER_HAPPY15");
+ put(0x2cf,"TRIGGER_HAPPY16");
+ put(0x2d0,"TRIGGER_HAPPY17");
+ put(0x2d1,"TRIGGER_HAPPY18");
+ put(0x2d2,"TRIGGER_HAPPY19");
+ put(0x2d3,"TRIGGER_HAPPY20");
+ put(0x2d4,"TRIGGER_HAPPY21");
+ put(0x2d5,"TRIGGER_HAPPY22");
+ put(0x2d6,"TRIGGER_HAPPY23");
+ put(0x2d7,"TRIGGER_HAPPY24");
+ put(0x2d8,"TRIGGER_HAPPY25");
+ put(0x2d9,"TRIGGER_HAPPY26");
+ put(0x2da,"TRIGGER_HAPPY27");
+ put(0x2db,"TRIGGER_HAPPY28");
+ put(0x2dc,"TRIGGER_HAPPY29");
+ put(0x2dd,"TRIGGER_HAPPY30");
+ put(0x2de,"TRIGGER_HAPPY31");
+ put(0x2df,"TRIGGER_HAPPY32");
+ put(0x2e0,"TRIGGER_HAPPY33");
+ put(0x2e1,"TRIGGER_HAPPY34");
+ put(0x2e2,"TRIGGER_HAPPY35");
+ put(0x2e3,"TRIGGER_HAPPY36");
+ put(0x2e4,"TRIGGER_HAPPY37");
+ put(0x2e5,"TRIGGER_HAPPY38");
+ put(0x2e6,"TRIGGER_HAPPY39");
+ put(0x2e7,"TRIGGER_HAPPY40");
+ }};
+
+ public final String source;
+ public final int keycode;
+ public final boolean isKeydown;
+
+ public static final Parcelable.Creator<KeypressEvent> CREATOR =
+ new Parcelable.Creator<KeypressEvent>() {
+ public KeypressEvent createFromParcel(Parcel in) {
+ return new KeypressEvent(in);
+ }
+
+ public KeypressEvent[] newArray(int size) {
+ return new KeypressEvent[size];
+ }
+ };
+
+ public KeypressEvent(Parcel in) {
+ source = in.readString();
+ keycode = in.readInt();
+ isKeydown = (in.readInt() != 0);
+ }
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ @Override
+ public void writeToParcel(Parcel dest, int flags) {
+ dest.writeString(source);
+ dest.writeInt(keycode);
+ dest.writeInt(isKeydown ? 1 : 0);
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (o instanceof KeypressEvent) {
+ KeypressEvent other = (KeypressEvent)o;
+ return other.source.equals(source) &&
+ other.keycode == keycode &&
+ other.isKeydown == isKeydown;
+ }
+ return false;
+ }
+
+ @Override
+ public String toString() {
+ return"Event{source = " + source + ", keycode = " + keycode +
+ ", isKeydown = " + isKeydown + "}";
+ }
+
+ public String keycodeToString() {
+ return KEYCODE_NAME_MAP.getOrDefault(keycode, Integer.toHexString(keycode));
+ }
+}
diff --git a/car-lib/src/android/car/hardware/radio/CarRadioEvent.aidl b/tools/keventreader/common/com/android/car/keventreader/IEventCallback.aidl
similarity index 71%
copy from car-lib/src/android/car/hardware/radio/CarRadioEvent.aidl
copy to tools/keventreader/common/com/android/car/keventreader/IEventCallback.aidl
index 0865646..5df8354 100644
--- a/car-lib/src/android/car/hardware/radio/CarRadioEvent.aidl
+++ b/tools/keventreader/common/com/android/car/keventreader/IEventCallback.aidl
@@ -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.
@@ -14,6 +14,10 @@
* limitations under the License.
*/
-package android.car.hardware.radio;
+package com.android.car.keventreader;
-parcelable CarRadioEvent;
+import com.android.car.keventreader.KeypressEvent;
+
+oneway interface IEventCallback {
+ void onEvent(in KeypressEvent event);
+}
diff --git a/car-lib/src/android/car/media/ICarAudioCallback.aidl b/tools/keventreader/common/com/android/car/keventreader/IEventProvider.aidl
similarity index 66%
copy from car-lib/src/android/car/media/ICarAudioCallback.aidl
copy to tools/keventreader/common/com/android/car/keventreader/IEventProvider.aidl
index 7e01c71..744d0b2 100644
--- a/car-lib/src/android/car/media/ICarAudioCallback.aidl
+++ b/tools/keventreader/common/com/android/car/keventreader/IEventProvider.aidl
@@ -1,5 +1,5 @@
/*
- * 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,11 @@
* limitations under the License.
*/
-package android.car.media;
+package com.android.car.keventreader;
-/** @hide */
-oneway interface ICarAudioCallback {
- void onParameterChange(in String params) = 0;
+import com.android.car.keventreader.IEventCallback;
+
+interface IEventProvider {
+ void registerCallback(in IEventCallback callback);
+ void unregisterCallback(in IEventCallback callback);
}
diff --git a/car-lib/src/android/car/hardware/radio/CarRadioEvent.aidl b/tools/keventreader/common/com/android/car/keventreader/KeypressEvent.aidl
similarity index 79%
copy from car-lib/src/android/car/hardware/radio/CarRadioEvent.aidl
copy to tools/keventreader/common/com/android/car/keventreader/KeypressEvent.aidl
index 0865646..197be3a 100644
--- a/car-lib/src/android/car/hardware/radio/CarRadioEvent.aidl
+++ b/tools/keventreader/common/com/android/car/keventreader/KeypressEvent.aidl
@@ -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.
@@ -14,6 +14,6 @@
* limitations under the License.
*/
-package android.car.hardware.radio;
+package com.android.car.keventreader;
-parcelable CarRadioEvent;
+parcelable KeypressEvent cpp_header "event.h";
diff --git a/tools/keventreader/server/Android.mk b/tools/keventreader/server/Android.mk
new file mode 100644
index 0000000..726e2fc
--- /dev/null
+++ b/tools/keventreader/server/Android.mk
@@ -0,0 +1,47 @@
+# 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.
+#
+#
+
+LOCAL_PATH:= $(call my-dir)
+
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES := \
+ main.cpp \
+ eventgatherer.cpp \
+ inputsource.cpp \
+ keymap.cpp \
+ event.cpp \
+ eventprovider.cpp \
+ ../common/com/android/car/keventreader/IEventCallback.aidl \
+ ../common/com/android/car/keventreader/IEventProvider.aidl \
+
+LOCAL_C_INCLUDES += \
+ frameworks/base/include
+
+LOCAL_SHARED_LIBRARIES := \
+ libbinder \
+ liblog \
+ libutils
+
+LOCAL_AIDL_INCLUDES = $(LOCAL_PATH)/../common
+
+LOCAL_MODULE := com.android.car.keventreader
+LOCAL_MODULE_TAGS := optional
+
+LOCAL_CFLAGS += -Wall -Werror
+LOCAL_CPPFLAGS += -std=c++17
+
+include $(BUILD_EXECUTABLE)
diff --git a/car-lib/src/android/car/hardware/radio/CarRadioEvent.aidl b/tools/keventreader/server/defines.h
similarity index 77%
copy from car-lib/src/android/car/hardware/radio/CarRadioEvent.aidl
copy to tools/keventreader/server/defines.h
index 0865646..59ff2c7 100644
--- a/car-lib/src/android/car/hardware/radio/CarRadioEvent.aidl
+++ b/tools/keventreader/server/defines.h
@@ -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,7 +13,5 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-
-package android.car.hardware.radio;
-
-parcelable CarRadioEvent;
+#define LOG_TAG "com.android.car.keventreader"
+#define SERVICE_NAME "com.android.car.keventreader"
diff --git a/tools/keventreader/server/event.cpp b/tools/keventreader/server/event.cpp
new file mode 100644
index 0000000..68ef512
--- /dev/null
+++ b/tools/keventreader/server/event.cpp
@@ -0,0 +1,46 @@
+/*
+ * 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.
+ */
+#include "event.h"
+
+#include <binder/Parcel.h>
+#include <utils/String8.h>
+#include <utils/String16.h>
+
+using namespace com::android::car::keventreader;
+
+KeypressEvent::KeypressEvent(const std::string source, uint32_t keycode, bool keydown) {
+ this->source = source;
+ this->keycode = keycode;
+ this->keydown = keydown;
+}
+
+status_t KeypressEvent::writeToParcel(Parcel* parcel) const {
+ String16 s16 = String16(source.c_str());
+ parcel->writeString16(s16);
+ parcel->writeUint32(keycode);
+ parcel->writeBool(keydown);
+
+ return OK;
+}
+
+status_t KeypressEvent::readFromParcel(const Parcel* parcel) {
+ String16 s16 = parcel->readString16();
+ source = std::string(String8(s16).c_str());
+ keycode = parcel->readUint32();
+ keydown = parcel->readBool();
+
+ return OK;
+}
diff --git a/tools/keventreader/server/event.h b/tools/keventreader/server/event.h
new file mode 100644
index 0000000..d4941f1
--- /dev/null
+++ b/tools/keventreader/server/event.h
@@ -0,0 +1,39 @@
+/*
+ * 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.
+ */
+#ifndef CAR_KEVENTREADER_EVENT
+#define CAR_KEVENTREADER_EVENT
+
+#include <binder/Parcelable.h>
+#include <string>
+#include <string_view>
+
+using namespace android;
+
+namespace com::android::car::keventreader {
+ struct KeypressEvent : public Parcelable {
+ // required to be callable as KeypressEvent() because Parcelable
+ KeypressEvent(const std::string source = "", uint32_t keycode = 0, bool keydown = false);
+
+ std::string source;
+ uint32_t keycode;
+ bool keydown;
+
+ virtual status_t writeToParcel(Parcel* parcel) const override;
+ virtual status_t readFromParcel(const Parcel* parcel) override;
+ };
+}
+
+#endif //CAR_KEVENTREADER_EVENT
diff --git a/tools/keventreader/server/eventgatherer.cpp b/tools/keventreader/server/eventgatherer.cpp
new file mode 100644
index 0000000..a157d0d
--- /dev/null
+++ b/tools/keventreader/server/eventgatherer.cpp
@@ -0,0 +1,65 @@
+/*
+ * 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.
+ */
+#include "eventgatherer.h"
+#include "defines.h"
+#include <utils/Log.h>
+
+using namespace com::android::car::keventreader;
+
+EventGatherer::EventGatherer(int argc, const char** argv) {
+ for (auto i = 1; i < argc; ++i) {
+ auto dev = std::make_unique<InputSource>(argv[i]);
+ if (dev && *dev) {
+ ALOGD("opened input source file %s", argv[i]);
+ mFds.push_back({dev->descriptor(), POLLIN, 0});
+ mDevices.emplace(dev->descriptor(), std::move(dev));
+ } else {
+ ALOGW("failed to open input source file %s", argv[i]);
+ }
+ }
+}
+
+size_t EventGatherer::size() const {
+ return mDevices.size();
+}
+
+std::vector<com::android::car::keventreader::KeypressEvent> EventGatherer::read() {
+ constexpr int FOREVER = -1;
+ std::vector<com::android::car::keventreader::KeypressEvent> result;
+
+ int count = poll(&mFds[0], mFds.size(), FOREVER);
+ if (count < 0) {
+ ALOGE("poll failed: errno = %d", errno);
+ return result;
+ }
+
+ for (auto& fd : mFds) {
+ if (fd.revents != 0) {
+ if (fd.revents == POLLIN) {
+ if (auto dev = mDevices[fd.fd].get()) {
+ while(auto evt = dev->read()) {
+ result.push_back(*evt);
+ }
+ --count; // found one source of events we care abour
+ }
+ }
+ fd.revents = 0;
+ if (count == 0) break; // if we read all events, no point in continuing the scan
+ }
+ }
+
+ return result;
+}
diff --git a/tools/keventreader/server/eventgatherer.h b/tools/keventreader/server/eventgatherer.h
new file mode 100644
index 0000000..71b5f9a
--- /dev/null
+++ b/tools/keventreader/server/eventgatherer.h
@@ -0,0 +1,41 @@
+/*
+ * 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.
+ */
+#ifndef CAR_KEVENTREADER_EVENTGATHERER
+#define CAR_KEVENTREADER_EVENTGATHERER
+
+#include "inputsource.h"
+#include "event.h"
+
+#include <map>
+#include <memory>
+#include <poll.h>
+#include <vector>
+
+namespace com::android::car::keventreader {
+ class EventGatherer {
+ public:
+ EventGatherer(int argc, const char** argv);
+
+ size_t size() const;
+
+ std::vector<com::android::car::keventreader::KeypressEvent> read();
+ private:
+ std::map<int, std::unique_ptr<InputSource>> mDevices;
+ std::vector<pollfd> mFds;
+ };
+}
+
+#endif //CAR_KEVENTREADER_EVENTGATHERER
diff --git a/tools/keventreader/server/eventprovider.cpp b/tools/keventreader/server/eventprovider.cpp
new file mode 100644
index 0000000..44ea266
--- /dev/null
+++ b/tools/keventreader/server/eventprovider.cpp
@@ -0,0 +1,52 @@
+/*
+ * 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.
+ */
+#include "defines.h"
+#include "eventprovider.h"
+#include <algorithm>
+#include <utils/Log.h>
+
+using namespace com::android::car::keventreader;
+
+EventProviderImpl::EventProviderImpl(EventGatherer&& g) : mGatherer(std::move(g)) {}
+
+std::thread EventProviderImpl::startLoop() {
+ auto t = std::thread( [this] () -> void {
+ while(true) {
+ auto events = mGatherer.read();
+ {
+ std::scoped_lock lock(mMutex);
+ for (auto&& cb : mCallbacks) {
+ for (const auto& event : events) {
+ cb->onEvent(event);
+ }
+ }
+ }
+ }
+ });
+ return t;
+}
+
+Status EventProviderImpl::registerCallback(const sp<IEventCallback>& cb) {
+ std::scoped_lock lock(mMutex);
+ mCallbacks.push_back(cb);
+ return Status::ok();
+}
+
+Status EventProviderImpl::unregisterCallback(const sp<IEventCallback>& cb) {
+ std::scoped_lock lock(mMutex);
+ std::remove(mCallbacks.begin(), mCallbacks.end(), cb);
+ return Status::ok();
+}
diff --git a/tools/keventreader/server/eventprovider.h b/tools/keventreader/server/eventprovider.h
new file mode 100644
index 0000000..17a98b6
--- /dev/null
+++ b/tools/keventreader/server/eventprovider.h
@@ -0,0 +1,45 @@
+/*
+ * 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.
+ */
+#ifndef CAR_KEVENTREADER_EVENTPROVIDER
+#define CAR_KEVENTREADER_EVENTPROVIDER
+
+#include "com/android/car/keventreader/IEventCallback.h"
+#include "com/android/car/keventreader/BnEventProvider.h"
+#include <binder/Binder.h>
+#include "eventgatherer.h"
+#include <mutex>
+#include <thread>
+#include <vector>
+
+using namespace android;
+using namespace android::binder;
+
+namespace com::android::car::keventreader {
+ class EventProviderImpl : public BnEventProvider {
+ public:
+ EventProviderImpl(EventGatherer&&);
+ std::thread startLoop();
+
+ virtual Status registerCallback(const sp<IEventCallback>& callback) override;
+ virtual Status unregisterCallback(const sp<IEventCallback>& callback) override;
+ private:
+ EventGatherer mGatherer;
+ std::mutex mMutex;
+ std::vector<sp<IEventCallback>> mCallbacks;
+ };
+}
+
+#endif
diff --git a/tools/keventreader/server/inputsource.cpp b/tools/keventreader/server/inputsource.cpp
new file mode 100644
index 0000000..07b3c90
--- /dev/null
+++ b/tools/keventreader/server/inputsource.cpp
@@ -0,0 +1,73 @@
+/*
+ * 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.
+ */
+#include "inputsource.h"
+#include "defines.h"
+#include <utils/Log.h>
+
+#include <fcntl.h>
+#include <sstream>
+#include <string.h>
+#include <unistd.h>
+
+using namespace com::android::car::keventreader;
+
+InputSource::kevent::kevent() {
+ bzero(this, sizeof(*this));
+}
+
+bool InputSource::kevent::isKeypress() const {
+ return type == EV_KEY;
+}
+
+bool InputSource::kevent::isKeydown() const {
+ return isKeypress() && (value == 1);
+}
+
+bool InputSource::kevent::isKeyup() const {
+ return isKeypress() && (value == 0);
+}
+
+InputSource::InputSource(const char* file) : mFilePath(file), mDescriptor(open(file, O_RDONLY)) {}
+
+InputSource::operator bool() const {
+ return descriptor() >= 0;
+}
+
+int InputSource::descriptor() const {
+ return mDescriptor;
+}
+
+std::optional<com::android::car::keventreader::KeypressEvent> InputSource::read() const {
+ kevent evt;
+
+ auto cnt = ::read(mDescriptor, &evt, sizeof(evt));
+
+ // the kernel guarantees that we will always be able to read a whole number of events
+ if (cnt < static_cast<decltype(cnt)>(sizeof(evt))) {
+ return std::nullopt;
+ }
+ if (!evt.isKeypress()) {
+ return std::nullopt;
+ }
+
+ ALOGD("input source %s generated code %u (down = %s)",
+ mFilePath.c_str(), evt.code, evt.isKeydown() ? "true" : "false");
+ return com::android::car::keventreader::KeypressEvent(mFilePath, evt.code, evt.isKeydown());
+}
+
+InputSource::~InputSource() {
+ if (mDescriptor) ::close(mDescriptor);
+}
diff --git a/tools/keventreader/server/inputsource.h b/tools/keventreader/server/inputsource.h
new file mode 100644
index 0000000..282628e
--- /dev/null
+++ b/tools/keventreader/server/inputsource.h
@@ -0,0 +1,50 @@
+/*
+ * 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.
+ */
+#ifndef CAR_KEVENTREADER_INPUTSOURCE
+#define CAR_KEVENTREADER_INPUTSOURCE
+
+#include <linux/input.h>
+#include <optional>
+#include <string>
+#include "event.h"
+
+namespace com::android::car::keventreader {
+ class InputSource {
+ public:
+ explicit InputSource(const char* file);
+
+ explicit operator bool() const;
+
+ int descriptor() const;
+
+ std::optional<com::android::car::keventreader::KeypressEvent> read() const;
+
+ virtual ~InputSource();
+ private:
+ struct kevent : public ::input_event {
+ kevent();
+ bool isKeypress() const;
+ bool isKeydown() const;
+ bool isKeyup() const;
+ };
+ static_assert(sizeof(kevent) == sizeof(::input_event), "do not add data to input_event");
+
+ std::string mFilePath;
+ int mDescriptor;
+ };
+}
+
+#endif //CAR_KEVENTREADER_INPUTSOURCE
diff --git a/tools/keventreader/server/keymap.cpp b/tools/keventreader/server/keymap.cpp
new file mode 100644
index 0000000..2e7c06d
--- /dev/null
+++ b/tools/keventreader/server/keymap.cpp
@@ -0,0 +1,595 @@
+/*
+ * 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.
+ */
+#include "keymap.h"
+#include <sstream>
+
+using namespace com::android::car::keventreader;
+
+Keymap& Keymap::get() {
+ static Keymap gKeymap;
+
+ return gKeymap;
+}
+
+Keymap::Keymap() {
+ fillMap();
+}
+
+std::string_view Keymap::getDisplayName(int keycode) {
+ auto iter = mKeyMap.find(keycode), end = mKeyMap.end();
+ if (iter == end) {
+ std::stringstream ss;
+ ss << "unknown " << keycode;
+ return ss.str();
+ }
+ return iter->second;
+}
+
+void Keymap::fillMap() {
+ mKeyMap.emplace(0,"RESERVED");
+ mKeyMap.emplace(1,"ESC");
+ mKeyMap.emplace(2,"1");
+ mKeyMap.emplace(3,"2");
+ mKeyMap.emplace(4,"3");
+ mKeyMap.emplace(5,"4");
+ mKeyMap.emplace(6,"5");
+ mKeyMap.emplace(7,"6");
+ mKeyMap.emplace(8,"7");
+ mKeyMap.emplace(9,"8");
+ mKeyMap.emplace(10,"9");
+ mKeyMap.emplace(11,"0");
+ mKeyMap.emplace(12,"MINUS");
+ mKeyMap.emplace(13,"EQUAL");
+ mKeyMap.emplace(14,"BACKSPACE");
+ mKeyMap.emplace(15,"TAB");
+ mKeyMap.emplace(16,"Q");
+ mKeyMap.emplace(17,"W");
+ mKeyMap.emplace(18,"E");
+ mKeyMap.emplace(19,"R");
+ mKeyMap.emplace(20,"T");
+ mKeyMap.emplace(21,"Y");
+ mKeyMap.emplace(22,"U");
+ mKeyMap.emplace(23,"I");
+ mKeyMap.emplace(24,"O");
+ mKeyMap.emplace(25,"P");
+ mKeyMap.emplace(26,"LEFTBRACE");
+ mKeyMap.emplace(27,"RIGHTBRACE");
+ mKeyMap.emplace(28,"ENTER");
+ mKeyMap.emplace(29,"LEFTCTRL");
+ mKeyMap.emplace(30,"A");
+ mKeyMap.emplace(31,"S");
+ mKeyMap.emplace(32,"D");
+ mKeyMap.emplace(33,"F");
+ mKeyMap.emplace(34,"G");
+ mKeyMap.emplace(35,"H");
+ mKeyMap.emplace(36,"J");
+ mKeyMap.emplace(37,"K");
+ mKeyMap.emplace(38,"L");
+ mKeyMap.emplace(39,"SEMICOLON");
+ mKeyMap.emplace(40,"APOSTROPHE");
+ mKeyMap.emplace(41,"GRAVE");
+ mKeyMap.emplace(42,"LEFTSHIFT");
+ mKeyMap.emplace(43,"BACKSLASH");
+ mKeyMap.emplace(44,"Z");
+ mKeyMap.emplace(45,"X");
+ mKeyMap.emplace(46,"C");
+ mKeyMap.emplace(47,"V");
+ mKeyMap.emplace(48,"B");
+ mKeyMap.emplace(49,"N");
+ mKeyMap.emplace(50,"M");
+ mKeyMap.emplace(51,"COMMA");
+ mKeyMap.emplace(52,"DOT");
+ mKeyMap.emplace(53,"SLASH");
+ mKeyMap.emplace(54,"RIGHTSHIFT");
+ mKeyMap.emplace(55,"KPASTERISK");
+ mKeyMap.emplace(56,"LEFTALT");
+ mKeyMap.emplace(57,"SPACE");
+ mKeyMap.emplace(58,"CAPSLOCK");
+ mKeyMap.emplace(59,"F1");
+ mKeyMap.emplace(60,"F2");
+ mKeyMap.emplace(61,"F3");
+ mKeyMap.emplace(62,"F4");
+ mKeyMap.emplace(63,"F5");
+ mKeyMap.emplace(64,"F6");
+ mKeyMap.emplace(65,"F7");
+ mKeyMap.emplace(66,"F8");
+ mKeyMap.emplace(67,"F9");
+ mKeyMap.emplace(68,"F10");
+ mKeyMap.emplace(69,"NUMLOCK");
+ mKeyMap.emplace(70,"SCROLLLOCK");
+ mKeyMap.emplace(71,"KP7");
+ mKeyMap.emplace(72,"KP8");
+ mKeyMap.emplace(73,"KP9");
+ mKeyMap.emplace(74,"KPMINUS");
+ mKeyMap.emplace(75,"KP4");
+ mKeyMap.emplace(76,"KP5");
+ mKeyMap.emplace(77,"KP6");
+ mKeyMap.emplace(78,"KPPLUS");
+ mKeyMap.emplace(79,"KP1");
+ mKeyMap.emplace(80,"KP2");
+ mKeyMap.emplace(81,"KP3");
+ mKeyMap.emplace(82,"KP0");
+ mKeyMap.emplace(83,"KPDOT");
+ mKeyMap.emplace(85,"ZENKAKUHANKAKU");
+ mKeyMap.emplace(86,"102ND");
+ mKeyMap.emplace(87,"F11");
+ mKeyMap.emplace(88,"F12");
+ mKeyMap.emplace(89,"RO");
+ mKeyMap.emplace(90,"KATAKANA");
+ mKeyMap.emplace(91,"HIRAGANA");
+ mKeyMap.emplace(92,"HENKAN");
+ mKeyMap.emplace(93,"KATAKANAHIRAGANA");
+ mKeyMap.emplace(94,"MUHENKAN");
+ mKeyMap.emplace(95,"KPJPCOMMA");
+ mKeyMap.emplace(96,"KPENTER");
+ mKeyMap.emplace(97,"RIGHTCTRL");
+ mKeyMap.emplace(98,"KPSLASH");
+ mKeyMap.emplace(99,"SYSRQ");
+ mKeyMap.emplace(100,"RIGHTALT");
+ mKeyMap.emplace(101,"LINEFEED");
+ mKeyMap.emplace(102,"HOME");
+ mKeyMap.emplace(103,"UP");
+ mKeyMap.emplace(104,"PAGEUP");
+ mKeyMap.emplace(105,"LEFT");
+ mKeyMap.emplace(106,"RIGHT");
+ mKeyMap.emplace(107,"END");
+ mKeyMap.emplace(108,"DOWN");
+ mKeyMap.emplace(109,"PAGEDOWN");
+ mKeyMap.emplace(110,"INSERT");
+ mKeyMap.emplace(111,"DELETE");
+ mKeyMap.emplace(112,"MACRO");
+ mKeyMap.emplace(113,"MUTE");
+ mKeyMap.emplace(114,"VOLUMEDOWN");
+ mKeyMap.emplace(115,"VOLUMEUP");
+ mKeyMap.emplace(116,"POWER");
+ mKeyMap.emplace(117,"KPEQUAL");
+ mKeyMap.emplace(118,"KPPLUSMINUS");
+ mKeyMap.emplace(119,"PAUSE");
+ mKeyMap.emplace(120,"SCALE");
+ mKeyMap.emplace(121,"KPCOMMA");
+ mKeyMap.emplace(122,"HANGEUL");
+ mKeyMap.emplace(123,"HANJA");
+ mKeyMap.emplace(124,"YEN");
+ mKeyMap.emplace(125,"LEFTMETA");
+ mKeyMap.emplace(126,"RIGHTMETA");
+ mKeyMap.emplace(127,"COMPOSE");
+ mKeyMap.emplace(128,"STOP");
+ mKeyMap.emplace(129,"AGAIN");
+ mKeyMap.emplace(130,"PROPS");
+ mKeyMap.emplace(131,"UNDO");
+ mKeyMap.emplace(132,"FRONT");
+ mKeyMap.emplace(133,"COPY");
+ mKeyMap.emplace(134,"OPEN");
+ mKeyMap.emplace(135,"PASTE");
+ mKeyMap.emplace(136,"FIND");
+ mKeyMap.emplace(137,"CUT");
+ mKeyMap.emplace(138,"HELP");
+ mKeyMap.emplace(139,"MENU");
+ mKeyMap.emplace(140,"CALC");
+ mKeyMap.emplace(141,"SETUP");
+ mKeyMap.emplace(142,"SLEEP");
+ mKeyMap.emplace(143,"WAKEUP");
+ mKeyMap.emplace(144,"FILE");
+ mKeyMap.emplace(145,"SENDFILE");
+ mKeyMap.emplace(146,"DELETEFILE");
+ mKeyMap.emplace(147,"XFER");
+ mKeyMap.emplace(148,"PROG1");
+ mKeyMap.emplace(149,"PROG2");
+ mKeyMap.emplace(150,"WWW");
+ mKeyMap.emplace(151,"MSDOS");
+ mKeyMap.emplace(152,"SCREENLOCK");
+ mKeyMap.emplace(153,"ROTATE_DISPLAY");
+ mKeyMap.emplace(154,"CYCLEWINDOWS");
+ mKeyMap.emplace(155,"MAIL");
+ mKeyMap.emplace(156,"BOOKMARKS");
+ mKeyMap.emplace(157,"COMPUTER");
+ mKeyMap.emplace(158,"BACK");
+ mKeyMap.emplace(159,"FORWARD");
+ mKeyMap.emplace(160,"CLOSECD");
+ mKeyMap.emplace(161,"EJECTCD");
+ mKeyMap.emplace(162,"EJECTCLOSECD");
+ mKeyMap.emplace(163,"NEXTSONG");
+ mKeyMap.emplace(164,"PLAYPAUSE");
+ mKeyMap.emplace(165,"PREVIOUSSONG");
+ mKeyMap.emplace(166,"STOPCD");
+ mKeyMap.emplace(167,"RECORD");
+ mKeyMap.emplace(168,"REWIND");
+ mKeyMap.emplace(169,"PHONE");
+ mKeyMap.emplace(170,"ISO");
+ mKeyMap.emplace(171,"CONFIG");
+ mKeyMap.emplace(172,"HOMEPAGE");
+ mKeyMap.emplace(173,"REFRESH");
+ mKeyMap.emplace(174,"EXIT");
+ mKeyMap.emplace(175,"MOVE");
+ mKeyMap.emplace(176,"EDIT");
+ mKeyMap.emplace(177,"SCROLLUP");
+ mKeyMap.emplace(178,"SCROLLDOWN");
+ mKeyMap.emplace(179,"KPLEFTPAREN");
+ mKeyMap.emplace(180,"KPRIGHTPAREN");
+ mKeyMap.emplace(181,"NEW");
+ mKeyMap.emplace(182,"REDO");
+ mKeyMap.emplace(183,"F13");
+ mKeyMap.emplace(184,"F14");
+ mKeyMap.emplace(185,"F15");
+ mKeyMap.emplace(186,"F16");
+ mKeyMap.emplace(187,"F17");
+ mKeyMap.emplace(188,"F18");
+ mKeyMap.emplace(189,"F19");
+ mKeyMap.emplace(190,"F20");
+ mKeyMap.emplace(191,"F21");
+ mKeyMap.emplace(192,"F22");
+ mKeyMap.emplace(193,"F23");
+ mKeyMap.emplace(194,"F24");
+ mKeyMap.emplace(200,"PLAYCD");
+ mKeyMap.emplace(201,"PAUSECD");
+ mKeyMap.emplace(202,"PROG3");
+ mKeyMap.emplace(203,"PROG4");
+ mKeyMap.emplace(204,"DASHBOARD");
+ mKeyMap.emplace(205,"SUSPEND");
+ mKeyMap.emplace(206,"CLOSE");
+ mKeyMap.emplace(207,"PLAY");
+ mKeyMap.emplace(208,"FASTFORWARD");
+ mKeyMap.emplace(209,"BASSBOOST");
+ mKeyMap.emplace(210,"PRINT");
+ mKeyMap.emplace(211,"HP");
+ mKeyMap.emplace(212,"CAMERA");
+ mKeyMap.emplace(213,"SOUND");
+ mKeyMap.emplace(214,"QUESTION");
+ mKeyMap.emplace(215,"EMAIL");
+ mKeyMap.emplace(216,"CHAT");
+ mKeyMap.emplace(217,"SEARCH");
+ mKeyMap.emplace(218,"CONNECT");
+ mKeyMap.emplace(219,"FINANCE");
+ mKeyMap.emplace(220,"SPORT");
+ mKeyMap.emplace(221,"SHOP");
+ mKeyMap.emplace(222,"ALTERASE");
+ mKeyMap.emplace(223,"CANCEL");
+ mKeyMap.emplace(224,"BRIGHTNESSDOWN");
+ mKeyMap.emplace(225,"BRIGHTNESSUP");
+ mKeyMap.emplace(226,"MEDIA");
+ mKeyMap.emplace(227,"SWITCHVIDEOMODE");
+ mKeyMap.emplace(228,"KBDILLUMTOGGLE");
+ mKeyMap.emplace(229,"KBDILLUMDOWN");
+ mKeyMap.emplace(230,"KBDILLUMUP");
+ mKeyMap.emplace(231,"SEND");
+ mKeyMap.emplace(232,"REPLY");
+ mKeyMap.emplace(233,"FORWARDMAIL");
+ mKeyMap.emplace(234,"SAVE");
+ mKeyMap.emplace(235,"DOCUMENTS");
+ mKeyMap.emplace(236,"BATTERY");
+ mKeyMap.emplace(237,"BLUETOOTH");
+ mKeyMap.emplace(238,"WLAN");
+ mKeyMap.emplace(239,"UWB");
+ mKeyMap.emplace(240,"UNKNOWN");
+ mKeyMap.emplace(241,"VIDEO_NEXT");
+ mKeyMap.emplace(242,"VIDEO_PREV");
+ mKeyMap.emplace(243,"BRIGHTNESS_CYCLE");
+ mKeyMap.emplace(244,"BRIGHTNESS_AUTO");
+ mKeyMap.emplace(245,"DISPLAY_OFF");
+ mKeyMap.emplace(246,"WWAN");
+ mKeyMap.emplace(247,"RFKILL");
+ mKeyMap.emplace(248,"MICMUTE");
+ mKeyMap.emplace(0x160,"OK");
+ mKeyMap.emplace(0x161,"SELECT");
+ mKeyMap.emplace(0x162,"GOTO");
+ mKeyMap.emplace(0x163,"CLEAR");
+ mKeyMap.emplace(0x164,"POWER2");
+ mKeyMap.emplace(0x165,"OPTION");
+ mKeyMap.emplace(0x166,"INFO");
+ mKeyMap.emplace(0x167,"TIME");
+ mKeyMap.emplace(0x168,"VENDOR");
+ mKeyMap.emplace(0x169,"ARCHIVE");
+ mKeyMap.emplace(0x16a,"PROGRAM");
+ mKeyMap.emplace(0x16b,"CHANNEL");
+ mKeyMap.emplace(0x16c,"FAVORITES");
+ mKeyMap.emplace(0x16d,"EPG");
+ mKeyMap.emplace(0x16e,"PVR");
+ mKeyMap.emplace(0x16f,"MHP");
+ mKeyMap.emplace(0x170,"LANGUAGE");
+ mKeyMap.emplace(0x171,"TITLE");
+ mKeyMap.emplace(0x172,"SUBTITLE");
+ mKeyMap.emplace(0x173,"ANGLE");
+ mKeyMap.emplace(0x174,"ZOOM");
+ mKeyMap.emplace(0x175,"MODE");
+ mKeyMap.emplace(0x176,"KEYBOARD");
+ mKeyMap.emplace(0x177,"SCREEN");
+ mKeyMap.emplace(0x178,"PC");
+ mKeyMap.emplace(0x179,"TV");
+ mKeyMap.emplace(0x17a,"TV2");
+ mKeyMap.emplace(0x17b,"VCR");
+ mKeyMap.emplace(0x17c,"VCR2");
+ mKeyMap.emplace(0x17d,"SAT");
+ mKeyMap.emplace(0x17e,"SAT2");
+ mKeyMap.emplace(0x17f,"CD");
+ mKeyMap.emplace(0x180,"TAPE");
+ mKeyMap.emplace(0x181,"RADIO");
+ mKeyMap.emplace(0x182,"TUNER");
+ mKeyMap.emplace(0x183,"PLAYER");
+ mKeyMap.emplace(0x184,"TEXT");
+ mKeyMap.emplace(0x185,"DVD");
+ mKeyMap.emplace(0x186,"AUX");
+ mKeyMap.emplace(0x187,"MP3");
+ mKeyMap.emplace(0x188,"AUDIO");
+ mKeyMap.emplace(0x189,"VIDEO");
+ mKeyMap.emplace(0x18a,"DIRECTORY");
+ mKeyMap.emplace(0x18b,"LIST");
+ mKeyMap.emplace(0x18c,"MEMO");
+ mKeyMap.emplace(0x18d,"CALENDAR");
+ mKeyMap.emplace(0x18e,"RED");
+ mKeyMap.emplace(0x18f,"GREEN");
+ mKeyMap.emplace(0x190,"YELLOW");
+ mKeyMap.emplace(0x191,"BLUE");
+ mKeyMap.emplace(0x192,"CHANNELUP");
+ mKeyMap.emplace(0x193,"CHANNELDOWN");
+ mKeyMap.emplace(0x194,"FIRST");
+ mKeyMap.emplace(0x195,"LAST");
+ mKeyMap.emplace(0x196,"AB");
+ mKeyMap.emplace(0x197,"NEXT");
+ mKeyMap.emplace(0x198,"RESTART");
+ mKeyMap.emplace(0x199,"SLOW");
+ mKeyMap.emplace(0x19a,"SHUFFLE");
+ mKeyMap.emplace(0x19b,"BREAK");
+ mKeyMap.emplace(0x19c,"PREVIOUS");
+ mKeyMap.emplace(0x19d,"DIGITS");
+ mKeyMap.emplace(0x19e,"TEEN");
+ mKeyMap.emplace(0x19f,"TWEN");
+ mKeyMap.emplace(0x1a0,"VIDEOPHONE");
+ mKeyMap.emplace(0x1a1,"GAMES");
+ mKeyMap.emplace(0x1a2,"ZOOMIN");
+ mKeyMap.emplace(0x1a3,"ZOOMOUT");
+ mKeyMap.emplace(0x1a4,"ZOOMRESET");
+ mKeyMap.emplace(0x1a5,"WORDPROCESSOR");
+ mKeyMap.emplace(0x1a6,"EDITOR");
+ mKeyMap.emplace(0x1a7,"SPREADSHEET");
+ mKeyMap.emplace(0x1a8,"GRAPHICSEDITOR");
+ mKeyMap.emplace(0x1a9,"PRESENTATION");
+ mKeyMap.emplace(0x1aa,"DATABASE");
+ mKeyMap.emplace(0x1ab,"NEWS");
+ mKeyMap.emplace(0x1ac,"VOICEMAIL");
+ mKeyMap.emplace(0x1ad,"ADDRESSBOOK");
+ mKeyMap.emplace(0x1ae,"MESSENGER");
+ mKeyMap.emplace(0x1af,"DISPLAYTOGGLE");
+ mKeyMap.emplace(0x1b0,"SPELLCHECK");
+ mKeyMap.emplace(0x1b1,"LOGOFF");
+ mKeyMap.emplace(0x1b2,"DOLLAR");
+ mKeyMap.emplace(0x1b3,"EURO");
+ mKeyMap.emplace(0x1b4,"FRAMEBACK");
+ mKeyMap.emplace(0x1b5,"FRAMEFORWARD");
+ mKeyMap.emplace(0x1b6,"CONTEXT_MENU");
+ mKeyMap.emplace(0x1b7,"MEDIA_REPEAT");
+ mKeyMap.emplace(0x1b8,"10CHANNELSUP");
+ mKeyMap.emplace(0x1b9,"10CHANNELSDOWN");
+ mKeyMap.emplace(0x1ba,"IMAGES");
+ mKeyMap.emplace(0x1c0,"DEL_EOL");
+ mKeyMap.emplace(0x1c1,"DEL_EOS");
+ mKeyMap.emplace(0x1c2,"INS_LINE");
+ mKeyMap.emplace(0x1c3,"DEL_LINE");
+ mKeyMap.emplace(0x1d0,"FN");
+ mKeyMap.emplace(0x1d1,"FN_ESC");
+ mKeyMap.emplace(0x1d2,"FN_F1");
+ mKeyMap.emplace(0x1d3,"FN_F2");
+ mKeyMap.emplace(0x1d4,"FN_F3");
+ mKeyMap.emplace(0x1d5,"FN_F4");
+ mKeyMap.emplace(0x1d6,"FN_F5");
+ mKeyMap.emplace(0x1d7,"FN_F6");
+ mKeyMap.emplace(0x1d8,"FN_F7");
+ mKeyMap.emplace(0x1d9,"FN_F8");
+ mKeyMap.emplace(0x1da,"FN_F9");
+ mKeyMap.emplace(0x1db,"FN_F10");
+ mKeyMap.emplace(0x1dc,"FN_F11");
+ mKeyMap.emplace(0x1dd,"FN_F12");
+ mKeyMap.emplace(0x1de,"FN_1");
+ mKeyMap.emplace(0x1df,"FN_2");
+ mKeyMap.emplace(0x1e0,"FN_D");
+ mKeyMap.emplace(0x1e1,"FN_E");
+ mKeyMap.emplace(0x1e2,"FN_F");
+ mKeyMap.emplace(0x1e3,"FN_S");
+ mKeyMap.emplace(0x1e4,"FN_B");
+ mKeyMap.emplace(0x1f1,"BRL_DOT1");
+ mKeyMap.emplace(0x1f2,"BRL_DOT2");
+ mKeyMap.emplace(0x1f3,"BRL_DOT3");
+ mKeyMap.emplace(0x1f4,"BRL_DOT4");
+ mKeyMap.emplace(0x1f5,"BRL_DOT5");
+ mKeyMap.emplace(0x1f6,"BRL_DOT6");
+ mKeyMap.emplace(0x1f7,"BRL_DOT7");
+ mKeyMap.emplace(0x1f8,"BRL_DOT8");
+ mKeyMap.emplace(0x1f9,"BRL_DOT9");
+ mKeyMap.emplace(0x1fa,"BRL_DOT10");
+ mKeyMap.emplace(0x200,"NUMERIC_0");
+ mKeyMap.emplace(0x201,"NUMERIC_1");
+ mKeyMap.emplace(0x202,"NUMERIC_2");
+ mKeyMap.emplace(0x203,"NUMERIC_3");
+ mKeyMap.emplace(0x204,"NUMERIC_4");
+ mKeyMap.emplace(0x205,"NUMERIC_5");
+ mKeyMap.emplace(0x206,"NUMERIC_6");
+ mKeyMap.emplace(0x207,"NUMERIC_7");
+ mKeyMap.emplace(0x208,"NUMERIC_8");
+ mKeyMap.emplace(0x209,"NUMERIC_9");
+ mKeyMap.emplace(0x20a,"NUMERIC_STAR");
+ mKeyMap.emplace(0x20b,"NUMERIC_POUND");
+ mKeyMap.emplace(0x20c,"NUMERIC_A");
+ mKeyMap.emplace(0x20d,"NUMERIC_B");
+ mKeyMap.emplace(0x20e,"NUMERIC_C");
+ mKeyMap.emplace(0x20f,"NUMERIC_D");
+ mKeyMap.emplace(0x210,"CAMERA_FOCUS");
+ mKeyMap.emplace(0x211,"WPS_BUTTON");
+ mKeyMap.emplace(0x212,"TOUCHPAD_TOGGLE");
+ mKeyMap.emplace(0x213,"TOUCHPAD_ON");
+ mKeyMap.emplace(0x214,"TOUCHPAD_OFF");
+ mKeyMap.emplace(0x215,"CAMERA_ZOOMIN");
+ mKeyMap.emplace(0x216,"CAMERA_ZOOMOUT");
+ mKeyMap.emplace(0x217,"CAMERA_UP");
+ mKeyMap.emplace(0x218,"CAMERA_DOWN");
+ mKeyMap.emplace(0x219,"CAMERA_LEFT");
+ mKeyMap.emplace(0x21a,"CAMERA_RIGHT");
+ mKeyMap.emplace(0x21b,"ATTENDANT_ON");
+ mKeyMap.emplace(0x21c,"ATTENDANT_OFF");
+ mKeyMap.emplace(0x21d,"ATTENDANT_TOGGLE");
+ mKeyMap.emplace(0x21e,"LIGHTS_TOGGLE");
+ mKeyMap.emplace(0x230,"ALS_TOGGLE");
+ mKeyMap.emplace(0x240,"BUTTONCONFIG");
+ mKeyMap.emplace(0x241,"TASKMANAGER");
+ mKeyMap.emplace(0x242,"JOURNAL");
+ mKeyMap.emplace(0x243,"CONTROLPANEL");
+ mKeyMap.emplace(0x244,"APPSELECT");
+ mKeyMap.emplace(0x245,"SCREENSAVER");
+ mKeyMap.emplace(0x246,"VOICECOMMAND");
+ mKeyMap.emplace(0x247,"ASSISTANT");
+ mKeyMap.emplace(0x250,"BRIGHTNESS_MIN");
+ mKeyMap.emplace(0x251,"BRIGHTNESS_MAX");
+ mKeyMap.emplace(0x260,"KBDINPUTASSIST_PREV");
+ mKeyMap.emplace(0x261,"KBDINPUTASSIST_NEXT");
+ mKeyMap.emplace(0x262,"KBDINPUTASSIST_PREVGROUP");
+ mKeyMap.emplace(0x263,"KBDINPUTASSIST_NEXTGROUP");
+ mKeyMap.emplace(0x264,"KBDINPUTASSIST_ACCEPT");
+ mKeyMap.emplace(0x265,"KBDINPUTASSIST_CANCEL");
+ mKeyMap.emplace(0x266,"RIGHT_UP");
+ mKeyMap.emplace(0x267,"RIGHT_DOWN");
+ mKeyMap.emplace(0x268,"LEFT_UP");
+ mKeyMap.emplace(0x269,"LEFT_DOWN");
+ mKeyMap.emplace(0x26a,"ROOT_MENU");
+ mKeyMap.emplace(0x26b,"MEDIA_TOP_MENU");
+ mKeyMap.emplace(0x26c,"NUMERIC_11");
+ mKeyMap.emplace(0x26d,"NUMERIC_12");
+ mKeyMap.emplace(0x26e,"AUDIO_DESC");
+ mKeyMap.emplace(0x26f,"3D_MODE");
+ mKeyMap.emplace(0x270,"NEXT_FAVORITE");
+ mKeyMap.emplace(0x271,"STOP_RECORD");
+ mKeyMap.emplace(0x272,"PAUSE_RECORD");
+ mKeyMap.emplace(0x273,"VOD");
+ mKeyMap.emplace(0x274,"UNMUTE");
+ mKeyMap.emplace(0x275,"FASTREVERSE");
+ mKeyMap.emplace(0x276,"SLOWREVERSE");
+ mKeyMap.emplace(0x277,"DATA");
+ mKeyMap.emplace(0x278,"ONSCREEN_KEYBOARD");
+ mKeyMap.emplace(113,"MIN_INTERESTING");
+ mKeyMap.emplace(0x2ff,"MAX");
+ mKeyMap.emplace(0x100,"MISC");
+ mKeyMap.emplace(0x100,"0");
+ mKeyMap.emplace(0x101,"1");
+ mKeyMap.emplace(0x102,"2");
+ mKeyMap.emplace(0x103,"3");
+ mKeyMap.emplace(0x104,"4");
+ mKeyMap.emplace(0x105,"5");
+ mKeyMap.emplace(0x106,"6");
+ mKeyMap.emplace(0x107,"7");
+ mKeyMap.emplace(0x108,"8");
+ mKeyMap.emplace(0x109,"9");
+ mKeyMap.emplace(0x110,"MOUSE");
+ mKeyMap.emplace(0x110,"LEFT");
+ mKeyMap.emplace(0x111,"RIGHT");
+ mKeyMap.emplace(0x112,"MIDDLE");
+ mKeyMap.emplace(0x113,"SIDE");
+ mKeyMap.emplace(0x114,"EXTRA");
+ mKeyMap.emplace(0x115,"FORWARD");
+ mKeyMap.emplace(0x116,"BACK");
+ mKeyMap.emplace(0x117,"TASK");
+ mKeyMap.emplace(0x120,"JOYSTICK");
+ mKeyMap.emplace(0x120,"TRIGGER");
+ mKeyMap.emplace(0x121,"THUMB");
+ mKeyMap.emplace(0x122,"THUMB2");
+ mKeyMap.emplace(0x123,"TOP");
+ mKeyMap.emplace(0x124,"TOP2");
+ mKeyMap.emplace(0x125,"PINKIE");
+ mKeyMap.emplace(0x126,"BASE");
+ mKeyMap.emplace(0x127,"BASE2");
+ mKeyMap.emplace(0x128,"BASE3");
+ mKeyMap.emplace(0x129,"BASE4");
+ mKeyMap.emplace(0x12a,"BASE5");
+ mKeyMap.emplace(0x12b,"BASE6");
+ mKeyMap.emplace(0x12f,"DEAD");
+ mKeyMap.emplace(0x130,"GAMEPAD");
+ mKeyMap.emplace(0x130,"SOUTH");
+ mKeyMap.emplace(0x131,"EAST");
+ mKeyMap.emplace(0x132,"C");
+ mKeyMap.emplace(0x133,"NORTH");
+ mKeyMap.emplace(0x134,"WEST");
+ mKeyMap.emplace(0x135,"Z");
+ mKeyMap.emplace(0x136,"TL");
+ mKeyMap.emplace(0x137,"TR");
+ mKeyMap.emplace(0x138,"TL2");
+ mKeyMap.emplace(0x139,"TR2");
+ mKeyMap.emplace(0x13a,"SELECT");
+ mKeyMap.emplace(0x13b,"START");
+ mKeyMap.emplace(0x13c,"MODE");
+ mKeyMap.emplace(0x13d,"THUMBL");
+ mKeyMap.emplace(0x13e,"THUMBR");
+ mKeyMap.emplace(0x140,"DIGI");
+ mKeyMap.emplace(0x140,"TOOL_PEN");
+ mKeyMap.emplace(0x141,"TOOL_RUBBER");
+ mKeyMap.emplace(0x142,"TOOL_BRUSH");
+ mKeyMap.emplace(0x143,"TOOL_PENCIL");
+ mKeyMap.emplace(0x144,"TOOL_AIRBRUSH");
+ mKeyMap.emplace(0x145,"TOOL_FINGER");
+ mKeyMap.emplace(0x146,"TOOL_MOUSE");
+ mKeyMap.emplace(0x147,"TOOL_LENS");
+ mKeyMap.emplace(0x148,"TOOL_QUINTTAP");
+ mKeyMap.emplace(0x149,"STYLUS3");
+ mKeyMap.emplace(0x14a,"TOUCH");
+ mKeyMap.emplace(0x14b,"STYLUS");
+ mKeyMap.emplace(0x14c,"STYLUS2");
+ mKeyMap.emplace(0x14d,"TOOL_DOUBLETAP");
+ mKeyMap.emplace(0x14e,"TOOL_TRIPLETAP");
+ mKeyMap.emplace(0x14f,"TOOL_QUADTAP");
+ mKeyMap.emplace(0x150,"WHEEL");
+ mKeyMap.emplace(0x150,"GEAR_DOWN");
+ mKeyMap.emplace(0x151,"GEAR_UP");
+ mKeyMap.emplace(0x220,"DPAD_UP");
+ mKeyMap.emplace(0x221,"DPAD_DOWN");
+ mKeyMap.emplace(0x222,"DPAD_LEFT");
+ mKeyMap.emplace(0x223,"DPAD_RIGHT");
+ mKeyMap.emplace(0x2c0,"TRIGGER_HAPPY");
+ mKeyMap.emplace(0x2c0,"TRIGGER_HAPPY1");
+ mKeyMap.emplace(0x2c1,"TRIGGER_HAPPY2");
+ mKeyMap.emplace(0x2c2,"TRIGGER_HAPPY3");
+ mKeyMap.emplace(0x2c3,"TRIGGER_HAPPY4");
+ mKeyMap.emplace(0x2c4,"TRIGGER_HAPPY5");
+ mKeyMap.emplace(0x2c5,"TRIGGER_HAPPY6");
+ mKeyMap.emplace(0x2c6,"TRIGGER_HAPPY7");
+ mKeyMap.emplace(0x2c7,"TRIGGER_HAPPY8");
+ mKeyMap.emplace(0x2c8,"TRIGGER_HAPPY9");
+ mKeyMap.emplace(0x2c9,"TRIGGER_HAPPY10");
+ mKeyMap.emplace(0x2ca,"TRIGGER_HAPPY11");
+ mKeyMap.emplace(0x2cb,"TRIGGER_HAPPY12");
+ mKeyMap.emplace(0x2cc,"TRIGGER_HAPPY13");
+ mKeyMap.emplace(0x2cd,"TRIGGER_HAPPY14");
+ mKeyMap.emplace(0x2ce,"TRIGGER_HAPPY15");
+ mKeyMap.emplace(0x2cf,"TRIGGER_HAPPY16");
+ mKeyMap.emplace(0x2d0,"TRIGGER_HAPPY17");
+ mKeyMap.emplace(0x2d1,"TRIGGER_HAPPY18");
+ mKeyMap.emplace(0x2d2,"TRIGGER_HAPPY19");
+ mKeyMap.emplace(0x2d3,"TRIGGER_HAPPY20");
+ mKeyMap.emplace(0x2d4,"TRIGGER_HAPPY21");
+ mKeyMap.emplace(0x2d5,"TRIGGER_HAPPY22");
+ mKeyMap.emplace(0x2d6,"TRIGGER_HAPPY23");
+ mKeyMap.emplace(0x2d7,"TRIGGER_HAPPY24");
+ mKeyMap.emplace(0x2d8,"TRIGGER_HAPPY25");
+ mKeyMap.emplace(0x2d9,"TRIGGER_HAPPY26");
+ mKeyMap.emplace(0x2da,"TRIGGER_HAPPY27");
+ mKeyMap.emplace(0x2db,"TRIGGER_HAPPY28");
+ mKeyMap.emplace(0x2dc,"TRIGGER_HAPPY29");
+ mKeyMap.emplace(0x2dd,"TRIGGER_HAPPY30");
+ mKeyMap.emplace(0x2de,"TRIGGER_HAPPY31");
+ mKeyMap.emplace(0x2df,"TRIGGER_HAPPY32");
+ mKeyMap.emplace(0x2e0,"TRIGGER_HAPPY33");
+ mKeyMap.emplace(0x2e1,"TRIGGER_HAPPY34");
+ mKeyMap.emplace(0x2e2,"TRIGGER_HAPPY35");
+ mKeyMap.emplace(0x2e3,"TRIGGER_HAPPY36");
+ mKeyMap.emplace(0x2e4,"TRIGGER_HAPPY37");
+ mKeyMap.emplace(0x2e5,"TRIGGER_HAPPY38");
+ mKeyMap.emplace(0x2e6,"TRIGGER_HAPPY39");
+ mKeyMap.emplace(0x2e7,"TRIGGER_HAPPY40");
+}
diff --git a/tools/keventreader/server/keymap.h b/tools/keventreader/server/keymap.h
new file mode 100644
index 0000000..28f68d6
--- /dev/null
+++ b/tools/keventreader/server/keymap.h
@@ -0,0 +1,37 @@
+/*
+ * 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.
+ */
+#ifndef CAR_KEVENTREADER_KEYMAP
+#define CAR_KEVENTREADER_KEYMAP
+
+#include <string>
+#include <map>
+
+namespace com::android::car::keventreader {
+ // this class provides output that is based on the Linux keycodes table
+ class Keymap {
+ public:
+ static Keymap& get();
+
+ std::string_view getDisplayName(int keycode);
+
+ private:
+ std::map<int, const char*> mKeyMap;
+ void fillMap();
+ Keymap();
+ };
+}
+
+#endif //CAR_KEVENTREADER_KEYMAP
diff --git a/tools/keventreader/server/main.cpp b/tools/keventreader/server/main.cpp
new file mode 100644
index 0000000..fdf9a1c
--- /dev/null
+++ b/tools/keventreader/server/main.cpp
@@ -0,0 +1,74 @@
+/*
+ * 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.
+ */
+#include "defines.h"
+
+#include <binder/IPCThreadState.h>
+#include <binder/IServiceManager.h>
+#include <binder/ProcessState.h>
+#include <iostream>
+#include <signal.h>
+#include <utils/Log.h>
+#include "eventgatherer.h"
+#include "keymap.h"
+#include "eventprovider.h"
+
+
+using namespace android;
+using namespace com::android::car::keventreader;
+
+/**
+ * This tool expects to be able to read input events in the Linux kernel input_event format
+ * (see linux/input.h); that format is available by means of /dev/input/event* files (which are
+ * mapped 1-to-1 to input sources that provide keypresses as input (e.g. keyboards)
+ * The tool will hook up to each such file passed as input
+ */
+static const char* SYNTAX_INSTRUCTIONS =
+ "invalid command line arguments - provide one or more /dev/input/event files";
+
+static void error(int code) {
+ ALOGE("%s", SYNTAX_INSTRUCTIONS);
+ std::cerr << SYNTAX_INSTRUCTIONS << '\n';
+ exit(code);
+}
+
+int main(int argc, const char** argv) {
+ if (argc < 2 || argv[1] == nullptr || argv[1][0] == 0) {
+ error(1);
+ }
+
+ EventGatherer gatherer(argc, argv);
+ if (0 == gatherer.size()) {
+ error(2);
+ }
+
+ ALOGI("starting " LOG_TAG);
+ signal(SIGPIPE, SIG_IGN);
+
+ sp<ProcessState> processSelf(ProcessState::self());
+ sp<IServiceManager> serviceManager = defaultServiceManager();
+ auto service = std::make_unique<EventProviderImpl>(std::move(gatherer));
+ serviceManager->addService(String16(SERVICE_NAME), service.get());
+
+ processSelf->startThreadPool();
+
+ ALOGI(LOG_TAG " started");
+
+ auto svcthread = service->startLoop();
+ IPCThreadState::self()->joinThreadPool();
+
+ ALOGW(LOG_TAG " joined and going down");
+ exit(0);
+}
diff --git a/vehicle-hal-support-lib/Android.mk b/vehicle-hal-support-lib/Android.mk
index cd24b59..22e094c 100644
--- a/vehicle-hal-support-lib/Android.mk
+++ b/vehicle-hal-support-lib/Android.mk
@@ -26,7 +26,6 @@
LOCAL_STATIC_JAVA_LIBRARIES := \
android.hidl.base-V1.0-java \
android.hardware.automotive.vehicle-V2.0-java \
- junit \
- legacy-android-test
+ junit
include $(BUILD_STATIC_JAVA_LIBRARY)
diff --git a/vehicle-hal-support-lib/src/com/android/car/vehiclehal/test/MockedVehicleHal.java b/vehicle-hal-support-lib/src/com/android/car/vehiclehal/test/MockedVehicleHal.java
index 0da3565..477c2c5 100644
--- a/vehicle-hal-support-lib/src/com/android/car/vehiclehal/test/MockedVehicleHal.java
+++ b/vehicle-hal-support-lib/src/com/android/car/vehiclehal/test/MockedVehicleHal.java
@@ -16,11 +16,12 @@
package com.android.car.vehiclehal.test;
-import static java.lang.Integer.toHexString;
import static junit.framework.Assert.assertEquals;
import static junit.framework.Assert.assertNotNull;
import static junit.framework.Assert.fail;
+import static java.lang.Integer.toHexString;
+
import android.hardware.automotive.vehicle.V2_0.IVehicle;
import android.hardware.automotive.vehicle.V2_0.IVehicleCallback;
import android.hardware.automotive.vehicle.V2_0.StatusCode;
@@ -48,7 +49,7 @@
public interface VehicleHalPropertyHandler {
default void onPropertySet(VehiclePropValue value) {}
default VehiclePropValue onPropertyGet(VehiclePropValue value) { return null; }
- default void onPropertySubscribe(int property, int zones, float sampleRate) {}
+ default void onPropertySubscribe(int property, float sampleRate) {}
default void onPropertyUnsubscribe(int property) {}
VehicleHalPropertyHandler NOP = new VehicleHalPropertyHandler() {};
@@ -92,11 +93,20 @@
}
}
- public synchronized void injectEvent(VehiclePropValue value) {
+ public synchronized void injectEvent(VehiclePropValue value, boolean setProperty) {
List<IVehicleCallback> callbacks = mSubscribers.get(value.prop);
assertNotNull("Injecting event failed for property: " + value.prop
+ ". No listeners found", callbacks);
- for (IVehicleCallback callback : callbacks) {
+
+ if (setProperty) {
+ // Update property if requested
+ VehicleHalPropertyHandler handler = mPropertyHandlerMap.get(value.prop);
+ if (handler != null) {
+ handler.onPropertySet(value);
+ }
+ }
+
+ for (IVehicleCallback callback: callbacks) {
try {
callback.onPropertyEvent(Lists.newArrayList(value));
} catch (RemoteException e) {
@@ -106,6 +116,10 @@
}
}
+ public synchronized void injectEvent(VehiclePropValue value) {
+ injectEvent(value, false);
+ }
+
public synchronized void injectError(int errorCode, int propertyId, int areaId) {
List<IVehicleCallback> callbacks = mSubscribers.get(propertyId);
assertNotNull("Injecting error failed for property: " + propertyId
@@ -169,12 +183,20 @@
return StatusCode.INVALID_ARG;
}
- handler.onPropertySubscribe(opt.propId, opt.vehicleAreas, opt.sampleRate);
+ handler.onPropertySubscribe(opt.propId, opt.sampleRate);
List<IVehicleCallback> subscribers = mSubscribers.get(opt.propId);
if (subscribers == null) {
subscribers = new ArrayList<>();
mSubscribers.put(opt.propId, subscribers);
notifyAll();
+ } else {
+ for (IVehicleCallback s : subscribers) {
+ if (callback.asBinder() == s.asBinder()) {
+ // Remove callback that was registered previously for this property
+ subscribers.remove(callback);
+ break;
+ }
+ }
}
subscribers.add(callback);
}
@@ -217,7 +239,7 @@
}
@Override
- public void onPropertySubscribe(int property, int zones, float sampleRate) {
+ public void onPropertySubscribe(int property, float sampleRate) {
fail("Unexpected onPropertySubscribe call");
}
@@ -265,7 +287,7 @@
}
@Override
- public synchronized void onPropertySubscribe(int property, int zones, float sampleRate) {
+ public synchronized void onPropertySubscribe(int property, float sampleRate) {
assertEquals(mConfig.prop, property);
mSubscribed = true;
}
diff --git a/vehicle-hal-support-lib/src/com/android/car/vehiclehal/test/VehiclePropConfigBuilder.java b/vehicle-hal-support-lib/src/com/android/car/vehiclehal/test/VehiclePropConfigBuilder.java
index 402d121..59868d5 100644
--- a/vehicle-hal-support-lib/src/com/android/car/vehiclehal/test/VehiclePropConfigBuilder.java
+++ b/vehicle-hal-support-lib/src/com/android/car/vehiclehal/test/VehiclePropConfigBuilder.java
@@ -49,8 +49,6 @@
newConfig.prop = propConfig.prop;
newConfig.access = propConfig.access;
newConfig.changeMode = propConfig.changeMode;
- newConfig.supportedAreas = propConfig.supportedAreas;
- newConfig.configFlags = propConfig.configFlags;
newConfig.configString = propConfig.configString;
newConfig.minSampleRate = propConfig.minSampleRate;
newConfig.maxSampleRate = propConfig.maxSampleRate;
@@ -83,18 +81,6 @@
}
@CheckResult
- public VehiclePropConfigBuilder setSupportedAreas(int supportedAreas) {
- mConfig.supportedAreas = supportedAreas;
- return this;
- }
-
- @CheckResult
- public VehiclePropConfigBuilder setConfigFlags(int configFlags) {
- mConfig.configFlags = configFlags;
- return this;
- }
-
- @CheckResult
public VehiclePropConfigBuilder setConfigString(String configString) {
mConfig.configString = configString;
return this;
diff --git a/vehicle_monitor_service/Android.mk b/vehicle_monitor_service/Android.mk
deleted file mode 100644
index bd9f2ac..0000000
--- a/vehicle_monitor_service/Android.mk
+++ /dev/null
@@ -1,65 +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.
-#
-#
-LOCAL_PATH:= $(call my-dir)
-##################################
-include $(CLEAR_VARS)
-
-LOCAL_SRC_FILES := $(patsubst ./%,%, $(shell cd $(LOCAL_PATH); \
- find . -name "*.cpp" -and -not -name ".*"))
-
-LOCAL_SRC_FILES := $(filter-out main_vehiclemonitor.cpp, $(LOCAL_SRC_FILES))
-
-LOCAL_C_INCLUDES += \
- frameworks/base/include \
- packages/services/Car/libvehiclemonitor/include
-
-LOCAL_SHARED_LIBRARIES := \
- libbinder
-
-LOCAL_MODULE := libvehiclemonitorservice
-LOCAL_MODULE_TAGS := optional
-
-LOCAL_CFLAGS += -Werror
-
-include $(BUILD_STATIC_LIBRARY)
-
-##################################
-include $(CLEAR_VARS)
-
-LOCAL_SRC_FILES := \
- main_vehiclemonitor.cpp
-
-LOCAL_C_INCLUDES += \
- frameworks/base/include \
- packages/services/Car/libvehiclemonitor/include
-
-LOCAL_SHARED_LIBRARIES := \
- libbinder \
- liblog \
- libutils \
- libvehiclemonitor-native
-
-LOCAL_WHOLE_STATIC_LIBRARIES := \
- libvehiclemonitorservice
-
-LOCAL_STRIP_MODULE := keep_symbols
-
-LOCAL_MODULE := vehicle_monitor_service
-LOCAL_MODULE_TAGS := optional
-
-LOCAL_CFLAGS += -Werror
-
-include $(BUILD_EXECUTABLE)
diff --git a/vehicle_monitor_service/ProcessMonitor.cpp b/vehicle_monitor_service/ProcessMonitor.cpp
deleted file mode 100644
index 521473f..0000000
--- a/vehicle_monitor_service/ProcessMonitor.cpp
+++ /dev/null
@@ -1,290 +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.
- */
-#define LOG_TAG "ProcessMonitor"
-
-#include <mutex>
-#include <sys/param.h>
-#include <dirent.h>
-
-#include "ProcessMonitor.h"
-
-#define DBG_VERBOSE
-#ifdef DBG_VERBOSE
-#define LOG_VERBOSE(x...) ALOGD(x)
-#else
-#define LOG_VERBOSE(x...)
-#endif
-
-#define MAX_LINE 256
-#define SELF_IO "/proc/self/io"
-#define NUM_PROC_DUMP 10
-
-namespace android {
-
-static bool procDeltaCpuCmp(const std::pair<pid_t, const std::shared_ptr<ProcInfo>> a,
- const std::pair<pid_t, const std::shared_ptr<ProcInfo>> b) {
- return a.second->delta_time > b.second->delta_time;
-}
-
-static bool procDeltaMemCmp(const std::pair<pid_t, const std::shared_ptr<ProcInfo>> a,
- const std::pair<pid_t, const std::shared_ptr<ProcInfo>> b) {
- return a.second->delta_rss > b.second->delta_rss;
-}
-
-static bool procDeltaWbytesCmp(const std::pair<pid_t, const std::shared_ptr<ProcInfo>> a,
- const std::pair<pid_t, const std::shared_ptr<ProcInfo>> b) {
- return a.second->delta_wbytes > b.second->delta_wbytes;
-}
-
-static bool procCpuCmp(const std::pair<pid_t, const std::shared_ptr<ProcInfo>> a,
- const std::pair<pid_t, const std::shared_ptr<ProcInfo>> b) {
- return (a.second->utime + a.second->utime) > (b.second->stime + b.second->stime);
-}
-
-static bool procMemCmp(const std::pair<pid_t, const std::shared_ptr<ProcInfo>> a,
- const std::pair<pid_t, const std::shared_ptr<ProcInfo>> b) {
- return a.second->rss > b.second->rss;
-}
-
-static bool procWbytesCmp(const std::pair<pid_t, const std::shared_ptr<ProcInfo>> a,
- const std::pair<pid_t, const std::shared_ptr<ProcInfo>> b) {
- return a.second->wbytes > b.second->wbytes;
-}
-
-ProcessMonitor::ProcessMonitor() {
- //TODO: read config from policy files.
- if (access(SELF_IO, F_OK) == -1) {
- mIoSupported = false;
- ALOGE("**** DISK I/O PROFILING DISABLED!!!!****\n"
- "Kernel doesn't support I/O profiling.");
- } else {
- mIoSupported = true;
- }
-}
-
-ProcessMonitor::~ProcessMonitor() {
-}
-
-void ProcessMonitor::dump(String8& msg) {
- std::shared_lock<std::shared_timed_mutex> lock(mMutex);
- msg.append("ProcessMonitor\n");
- msg.appendFormat("Processes count: %d\n", (int) mProcInfoMap.size());
- msg.append("Top CPU usage\n");
- dumpTopProcesses(msg, procCpuCmp);
- msg.append("Top CPU usage increase\n");
- dumpTopProcesses(msg, procDeltaCpuCmp);
- msg.append("Top memory usage\n");
- dumpTopProcesses(msg, procMemCmp);
- msg.append("Top memory usage increase\n");
- dumpTopProcesses(msg, procDeltaMemCmp);
- if (mIoSupported) {
- msg.append("Top disk IO \n");
- dumpTopProcesses(msg, procWbytesCmp);
- msg.append("Top disk IO increase \n");
- dumpTopProcesses(msg, procDeltaWbytesCmp);
- } else {
- msg.append("Disk IO monitoring not supported.\n");
- }
-}
-
-void ProcessMonitor::dumpTopProcesses(
- String8& msg,
- bool (*procCmpFn) (
- const std::pair<pid_t, const std::shared_ptr<ProcInfo>>,
- const std::pair<pid_t, const std::shared_ptr<ProcInfo>>)) {
-
- std::vector<std::pair<pid_t, std::shared_ptr<ProcInfo>>> topPids(NUM_PROC_DUMP);
- std::partial_sort_copy(mProcInfoMap.begin(),
- mProcInfoMap.end(),
- topPids.begin(),
- topPids.end(),
- *procCmpFn);
- for (auto it = topPids.begin(); it != topPids.end(); ++it) {
- msg.appendFormat("(%s) PID: %d: delta_time: %" PRIu64 ", delta_rss: %" PRIu64 ", "
- "delta_wbytes: %" PRIu64 ", utime: %" PRIu64" , stime: %" PRIu64 ", "
- "rss: %" PRIu64 ", wbytes: %" PRIu64 "\n",
- it->second->name.c_str(),
- it->first,
- it->second->delta_time,
- it->second->delta_rss,
- it->second->delta_wbytes,
- it->second->utime,
- it->second->stime,
- it->second->rss,
- it->second->wbytes);
- }
-
-}
-
-status_t ProcessMonitor::setAppPriority(uint32_t , uint32_t, uint32_t) {
- std::unique_lock<std::shared_timed_mutex> lock(mMutex);
- // TODO implement.
- return NO_ERROR;
-}
-
-status_t ProcessMonitor::process() {
- status_t status = updateProcessInfo();
- if (status != NO_ERROR) {
- return status;
- }
- return improveSystemHealth();
-}
-
-status_t ProcessMonitor::improveSystemHealth() {
- // TODO: implement policy enforcer. kill apps that abuse system.
- return NO_ERROR;
-}
-
-status_t ProcessMonitor::updateProcessInfo() {
- std::unique_lock<std::shared_timed_mutex> lock(mMutex);
- std::set<pid_t> oldPids;
- populateExistingPids(oldPids);
- DIR *procDir;
- procDir = opendir("/proc");
- if (!procDir) {
- ALOGE("Failed to open /proc dir");
- return PERMISSION_DENIED;
- }
- struct dirent *pidDir;
- pid_t pid;
- while ((pidDir = readdir(procDir))) {
- if (!isdigit(pidDir->d_name[0])) {
- continue;
- }
- pid = atoi(pidDir->d_name);
- updateOrAddProcess(pid);
- oldPids.erase(pid);
- }
- deleteOutdatedPids(oldPids);
- return NO_ERROR;
-}
-
-void ProcessMonitor::deleteOutdatedPids(std::set<pid_t>& pidSet) {
- for(auto it = pidSet.begin(); it != pidSet.end(); ++it) {
- LOG_VERBOSE("Process %d ended. Removing from process map", *it);
- mProcInfoMap.erase(*it);
- }
-}
-
-void ProcessMonitor::populateExistingPids(std::set<pid_t>& pidSet) {
- for(auto it = mProcInfoMap.begin(); it != mProcInfoMap.end(); ++it) {
- pidSet.insert(it->first);
- }
-}
-
-void ProcessMonitor::updateOrAddProcess(pid_t pid) {
- auto pidDataIt = mProcInfoMap.find(pid);
- std::shared_ptr<ProcInfo> pidData;
- if (pidDataIt == mProcInfoMap.end()) {
- pidData = std::make_shared<ProcInfo>();
- mProcInfoMap.insert(std::pair<pid_t, std::shared_ptr<ProcInfo>>(pid, pidData));
- } else {
- pidData = pidDataIt->second;
- }
- auto originalPidData = std::make_shared<ProcInfo>(*pidData);
- readStat(pidData, pid);
- if (mIoSupported) {
- readIo(pidData, pid);
- }
- readCmdline(pidData, pid);
- readStatus(pidData, pid);
- updateDiffs(pidData, originalPidData);
-}
-
-void ProcessMonitor::readStat(std::shared_ptr<ProcInfo> pidData, pid_t pid) {
- char filename[64];
- sprintf(filename, "/proc/%d/stat", pid);
- FILE *file;
- file = fopen(filename, "r");
- if (!file) {
- ALOGD("Failed to open file %s for reading", filename);
- return;
- }
- fscanf(file,
- "%*d %*s %*c %*d %*d %*d %*d %*d %*d %*d %*d %*d %*d "
- "%" SCNu64
- "%" SCNu64 "%*d %*d %*d %*d %*d %*d %*d "
- "%*" SCNu64
- "%" SCNu64 "%*d %*d %*d %*d %*d %*d %*d %*d %*d %*d %*d %*d %*d %*d "
- "%*d",
- &pidData->utime,
- &pidData->stime,
- &pidData->rss);
- fclose(file);
-}
-
-void ProcessMonitor::readIo(std::shared_ptr<ProcInfo> pidData, pid_t pid) {
- char filename[64];
- sprintf(filename, "/proc/%d/io", pid);
- FILE *file;
- file = fopen(filename, "r");
- if (!file) {
- ALOGD("Failed to open file %s for reading", filename);
- return;
- }
- char buf[MAX_LINE];
- while (fgets(buf, MAX_LINE, file)) {
- sscanf(buf, "write_bytes: %" PRIu64, &pidData->wbytes);
- }
- fclose(file);
-}
-
-void ProcessMonitor::readCmdline(std::shared_ptr<ProcInfo> pidData, pid_t pid) {
- char filename[64];
- sprintf(filename, "/proc/%d/cmdline", pid);
- FILE *file;
- file = fopen(filename, "r");
- if (!file) {
- ALOGD("Failed to open file %s for reading", filename);
- return;
- }
- char buf[MAXPATHLEN];
- fgets(buf, MAXPATHLEN, file);
- fclose(file);
- if (strlen(buf) > 0) {
- pidData->name.assign(buf);
- }
-}
-
-void ProcessMonitor::readStatus(std::shared_ptr<ProcInfo> pidData, pid_t pid) {
- char filename[64];
- sprintf(filename, "/proc/%d/status", pid);
- FILE *file;
- file = fopen(filename, "r");
- if (!file) {
- ALOGD("Failed to open file %s for reading", filename);
- return;
- }
- char line[MAX_LINE];
- unsigned int uid;
- while (fgets(line, MAX_LINE, file)) {
- sscanf(line, "Uid: %u", &uid);
- }
- fclose(file);
- pidData->uid = uid;
-
-}
-
-void ProcessMonitor::updateDiffs(std::shared_ptr<ProcInfo> pidData,
- std::shared_ptr<ProcInfo> oldPidData) {
- pidData->delta_utime = pidData->utime - oldPidData->utime;
- pidData->delta_stime = pidData->stime - oldPidData->stime;
- pidData->delta_time = pidData->delta_utime + pidData->delta_stime;
- pidData->delta_rss = pidData->rss - oldPidData->rss;
- pidData->delta_wbytes = pidData->wbytes - oldPidData->wbytes;
-}
-
-}; // namespace android
diff --git a/vehicle_monitor_service/ProcessMonitor.h b/vehicle_monitor_service/ProcessMonitor.h
deleted file mode 100644
index d9f4d25..0000000
--- a/vehicle_monitor_service/ProcessMonitor.h
+++ /dev/null
@@ -1,94 +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.
- */
-#ifndef CAR_PROCESS_MONITOR_H_
-#define CAR_PROCESS_MONITOR_H_
-
-#include <map>
-#include <memory>
-#include <set>
-#include <string>
-#include <shared_mutex>
-
-#include <inttypes.h>
-#include <cutils/compiler.h>
-
-#include <binder/BinderService.h>
-#include <binder/IBinder.h>
-#include <utils/String8.h>
-
-#include <IVehicleMonitor.h>
-#include <HandlerThread.h>
-
-namespace android {
-
-// ----------------------------------------------------------------------------
-struct ProcInfo {
- pid_t pid;
- uid_t uid;
- std::string name;
- uint64_t utime;
- uint64_t stime;
- uint64_t rss;
- uint64_t wbytes;
- int64_t delta_utime;
- int64_t delta_stime;
- int64_t delta_time;
- int64_t delta_rss;
- int64_t delta_wbytes;
-};
-
-// ----------------------------------------------------------------------------
-
-// This class is used to collect information about running processes.
-// It also enforces certain policies to running apps - ex. kills non-system,
-// non-foreground applications that use too much memory, CPU, or write too much
-// data to disk.
-class ProcessMonitor {
-public:
- ProcessMonitor();
- ~ProcessMonitor();
-
- void dump(String8& msg);
- status_t setAppPriority(uint32_t pid, uint32_t uid, uint32_t priority);
- status_t process();
-
-private:
- status_t updateProcessInfo();
- void populateExistingPids(std::set<pid_t>& pidSet);
- void deleteOutdatedPids(std::set<pid_t>& pidSet);
- void updateOrAddProcess(pid_t pid);
- void readStat(std::shared_ptr<ProcInfo> pidData, pid_t pid);
- void readIo(std::shared_ptr<ProcInfo> pidData, pid_t pid);
- void readCmdline(std::shared_ptr<ProcInfo> pidData, pid_t pid);
- void readStatus(std::shared_ptr<ProcInfo> pidData, pid_t pid);
- void updateDiffs(std::shared_ptr<ProcInfo> pidData,
- std::shared_ptr<ProcInfo> oldPidData);
- status_t improveSystemHealth();
- void dumpTopProcesses(String8& msg,
- bool (*procCmpFn) (
- const std::pair<pid_t, const std::shared_ptr<ProcInfo>>,
- const std::pair<pid_t, const std::shared_ptr<ProcInfo>>));
-
-
-private:
- std::map<pid_t, std::shared_ptr<ProcInfo>> mProcInfoMap;
- bool mIoSupported;
- mutable std::shared_timed_mutex mMutex;
-};
-
-}
-
-#endif /* CAR_PROCESS_MONITOR_H_ */
diff --git a/vehicle_monitor_service/VehicleMonitorService.cpp b/vehicle_monitor_service/VehicleMonitorService.cpp
deleted file mode 100644
index 7368064..0000000
--- a/vehicle_monitor_service/VehicleMonitorService.cpp
+++ /dev/null
@@ -1,142 +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.
- */
-#define LOG_TAG "VehicleMonitor"
-
-#include <assert.h>
-
-#include <binder/PermissionCache.h>
-#include <utils/Errors.h>
-#include <utils/SystemClock.h>
-
-#include "VehicleMonitorService.h"
-
-//#define DBG_VERBOSE
-#ifdef DBG_VERBOSE
-#define LOG_VERBOSE(x...) ALOGD(x)
-#else
-#define LOG_VERBOSE(x...)
-#endif
-
-namespace android {
-
-const nsecs_t monitorInterval = 15000000000; // 15s
-
-VehicleMonitorMessageHandler::VehicleMonitorMessageHandler(const sp<Looper>& looper,
- VehicleMonitorService& service)
- : mLooper(looper),
- mService(service),
- mLastDispatchTime(0) {
- mLooper->sendMessageDelayed(monitorInterval, this, Message(COLLECT_DATA));
-}
-
-VehicleMonitorMessageHandler::~VehicleMonitorMessageHandler() {
-}
-
-void VehicleMonitorMessageHandler::dump(String8& msg) {
- msg.appendFormat("mLastDispatchTime:%" PRId64 "\n", mLastDispatchTime);
- mProcessMonitor.dump(msg);
-}
-
-void VehicleMonitorMessageHandler::doHandleCollectData() {
- {
- std::lock_guard<std::mutex> autoLock(mLock);
- mLastDispatchTime = elapsedRealtime();
- mProcessMonitor.process();
- }
-
- // TODO: do better timing for sendMessage
- mLooper->sendMessageDelayed(monitorInterval, this, Message(COLLECT_DATA));
-}
-
-void VehicleMonitorMessageHandler::handleMessage(const Message& message) {
- switch (message.what) {
- case COLLECT_DATA:
- doHandleCollectData();
- break;
- default:
- // TODO?
- break;
- }
-}
-
-// ----------------------------------------------------
-VehicleMonitorService* VehicleMonitorService::sInstance = NULL;
-
-status_t VehicleMonitorService::dump(int fd, const Vector<String16>& /*args*/) {
- static const String16 sDump("android.permission.DUMP");
- String8 msg;
- if (!PermissionCache::checkCallingPermission(sDump)) {
- msg.appendFormat("Permission Denial: "
- "can't dump VMS from pid=%d, uid=%d\n",
- IPCThreadState::self()->getCallingPid(),
- IPCThreadState::self()->getCallingUid());
- write(fd, msg.string(), msg.size());
- return NO_ERROR;
- }
- msg.appendFormat("*Handler, now in ms:%" PRId64 "\n", elapsedRealtime());
- mHandler->dump(msg);
- write(fd, msg.string(), msg.size());
- return NO_ERROR;
-}
-
-VehicleMonitorService::VehicleMonitorService() {
- sInstance = this;
-}
-
-VehicleMonitorService::~VehicleMonitorService() {
- sInstance = NULL;
-}
-
-void VehicleMonitorService::binderDied(const wp<IBinder>& who) {
- std::lock_guard<std::mutex> autoLock(mLock);
- sp<IBinder> ibinder = who.promote();
- ibinder->unlinkToDeath(this);
- // TODO: reset all priorities set by CarService.
-}
-
-void VehicleMonitorService::release() {
- std::lock_guard<std::mutex> autoLock(mLock);
- mHandlerThread->quit();
-}
-
-void VehicleMonitorService::onFirstRef() {
- std::lock_guard<std::mutex> autoLock(mLock);
- mHandlerThread = new HandlerThread();
- status_t r = mHandlerThread->start("VMS.NATIVE_LOOP");
- if (r != NO_ERROR) {
- ALOGE("cannot start handler thread, error:%d", r);
- return;
- }
- sp<VehicleMonitorMessageHandler> handler(
- new VehicleMonitorMessageHandler(mHandlerThread->getLooper(), *this));
- assert(handler.get() != NULL);
- mHandler = handler;
-}
-
-status_t VehicleMonitorService::setAppPriority(uint32_t, uint32_t, vehicle_app_priority) {
- //TODO
- return NO_ERROR;
-}
-
-status_t VehicleMonitorService::setMonitorListener(
- const sp<IVehicleMonitorListener> &listener) {
- sp<IBinder> ibinder = IInterface::asBinder(listener);
- LOG_VERBOSE("setMonitorListener, binder 0x%x", ibinder.get());
- //TODO
- return NO_ERROR;
-}
-
-}; // namespace android
diff --git a/vehicle_monitor_service/VehicleMonitorService.h b/vehicle_monitor_service/VehicleMonitorService.h
deleted file mode 100644
index 57ade9d..0000000
--- a/vehicle_monitor_service/VehicleMonitorService.h
+++ /dev/null
@@ -1,99 +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.
- */
-#ifndef CAR_VEHICLE_MONITOR_SERVICE_H_
-#define CAR_VEHICLE_MONITOR_SERVICE_H_
-
-#include <mutex>
-#include <inttypes.h>
-#include <cutils/compiler.h>
-
-#include <binder/BinderService.h>
-#include <binder/IBinder.h>
-#include <utils/String8.h>
-
-#include <ProcessMonitor.h>
-#include <IVehicleMonitor.h>
-#include <IVehicleMonitorListener.h>
-#include <HandlerThread.h>
-
-namespace android {
-// ----------------------------------------------------------------------------
-
-class VehicleMonitorService;
-
-/**
- * MessageHandler to handle periodic data processing.
- * Init / release is handled in the handler thread to allow upper layer to
- * allocate resource for the thread.
- */
-class VehicleMonitorMessageHandler : public MessageHandler {
- enum {
- COLLECT_DATA = 0,
- };
-
-public:
- // not passing VMS as sp as this is held by VMS always.
- VehicleMonitorMessageHandler(
- const sp<Looper>& mLooper, VehicleMonitorService& service);
- virtual ~VehicleMonitorMessageHandler();
-
- void dump(String8& msg);
-
-private:
- void handleMessage(const Message& message);
- void doHandleCollectData();
-
-private:
- mutable std::mutex mLock;
- const sp<Looper> mLooper;
- ProcessMonitor mProcessMonitor;
- VehicleMonitorService& mService;
- int64_t mLastDispatchTime;
-};
-
-// ----------------------------------------------------------------------------
-class VehicleMonitorService :
- public BinderService<VehicleMonitorService>,
- public BnVehicleMonitor,
- public IBinder::DeathRecipient {
-public:
- static const char* getServiceName() ANDROID_API {
- return IVehicleMonitor::SERVICE_NAME;
- };
-
- VehicleMonitorService();
- ~VehicleMonitorService();
- virtual status_t dump(int fd, const Vector<String16>& args);
- void release();
- virtual void binderDied(const wp<IBinder>& who);
- virtual status_t setAppPriority(
- uint32_t pid, uint32_t uid, vehicle_app_priority priority);
- virtual status_t setMonitorListener(
- const sp<IVehicleMonitorListener> &listener);
-
-private:
- // RefBase
- virtual void onFirstRef();
-private:
- static VehicleMonitorService* sInstance;
- sp<HandlerThread> mHandlerThread;
- sp<VehicleMonitorMessageHandler> mHandler;
- mutable std::mutex mLock;
-};
-
-}
-
-#endif /* CAR_VEHICLE_MONITOR_SERVICE_H_ */
diff --git a/vehicle_monitor_service/main_vehiclemonitor.cpp b/vehicle_monitor_service/main_vehiclemonitor.cpp
deleted file mode 100644
index 2994a07..0000000
--- a/vehicle_monitor_service/main_vehiclemonitor.cpp
+++ /dev/null
@@ -1,37 +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.
- */
-
-#define LOG_TAG "VMS"
-
-#include <signal.h>
-
-#include <binder/IServiceManager.h>
-#include <utils/Log.h>
-
-#include "VehicleMonitorService.h"
-
-using namespace android;
-
-int main(int /*argc*/, char** /*argv*/)
-{
- ALOGI("vehicle_monitor_service: starting");
- signal(SIGPIPE, SIG_IGN);
- // this will wait for service manager if not available yet.
- sp<IServiceManager> sm = defaultServiceManager();
- VehicleMonitorService::instantiate();
- ProcessState::self()->startThreadPool();
- IPCThreadState::self()->joinThreadPool();
-}