Merge changes If500c1cc,I248385ea,I05e27dba into qt-qpr1-dev
* changes:
Fix crash in CarPowerManagementService
Clean up synchronization of CarPowerManagementService
Disable user switching while resuming from Suspend to RAM
diff --git a/car_product/init/init.bootstat.rc b/car_product/init/init.bootstat.rc
index 5c5e796..4122ea4 100644
--- a/car_product/init/init.bootstat.rc
+++ b/car_product/init/init.bootstat.rc
@@ -4,4 +4,4 @@
# This is a common source of Android security bugs.
#
on property:boot.car_service_created=1
- exec - root root -- /system/bin/bootstat -r car_service_created
+ exec - system log -- /system/bin/bootstat -r car_service_created
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 6b5ddac..1d5fd14 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
@@ -93,4 +93,8 @@
<string name="config_dataUsageSummaryComponent">com.android.car.settings/com.android.car.settings.datausage.DataWarningAndLimitActivity</string>
<bool name="config_automotiveHideNavBarForKeyboard">true</bool>
+
+ <!-- Turn off Wallpaper service -->
+ <bool name="config_enableWallpaperService">false</bool>
+
</resources>
diff --git a/service/src/com/android/car/BinderInterfaceContainer.java b/service/src/com/android/car/BinderInterfaceContainer.java
index a03b633..5d57b16 100644
--- a/service/src/com/android/car/BinderInterfaceContainer.java
+++ b/service/src/com/android/car/BinderInterfaceContainer.java
@@ -122,8 +122,10 @@
public synchronized void clear() {
Collection<BinderInterface<T>> interfaces = getInterfaces();
for (BinderInterface<T> bInterface : interfaces) {
- removeBinder(bInterface.binderInterface);
+ IBinder binder = bInterface.binderInterface.asBinder();
+ binder.unlinkToDeath(bInterface, 0);
}
+ mBinders.clear();
}
private void handleBinderDeath(BinderInterface<T> bInterface) {
diff --git a/service/src/com/android/car/BluetoothDeviceConnectionPolicy.java b/service/src/com/android/car/BluetoothDeviceConnectionPolicy.java
index 4bb2790..c0f393a 100644
--- a/service/src/com/android/car/BluetoothDeviceConnectionPolicy.java
+++ b/service/src/com/android/car/BluetoothDeviceConnectionPolicy.java
@@ -117,7 +117,7 @@
}
}
}
- private BluetoothBroadcastReceiver mBluetoothBroadcastReceiver;
+ private final BluetoothBroadcastReceiver mBluetoothBroadcastReceiver;
/**
* Create a new BluetoothDeviceConnectionPolicy object, responsible for encapsulating the
@@ -153,6 +153,7 @@
mUserId = userId;
mContext = Objects.requireNonNull(context);
mCarBluetoothService = bluetoothService;
+ mBluetoothBroadcastReceiver = new BluetoothBroadcastReceiver();
mBluetoothAdapter = Objects.requireNonNull(BluetoothAdapter.getDefaultAdapter());
}
@@ -160,9 +161,8 @@
* Setup the Bluetooth profile service connections and Vehicle Event listeners.
* and start the state machine -{@link BluetoothAutoConnectStateMachine}
*/
- public synchronized void init() {
+ public void init() {
logd("init()");
- mBluetoothBroadcastReceiver = new BluetoothBroadcastReceiver();
IntentFilter profileFilter = new IntentFilter();
profileFilter.addAction(BluetoothAdapter.ACTION_STATE_CHANGED);
mContext.registerReceiverAsUser(mBluetoothBroadcastReceiver, UserHandle.CURRENT,
@@ -190,7 +190,7 @@
* Clean up slate. Close the Bluetooth profile service connections and quit the state machine -
* {@link BluetoothAutoConnectStateMachine}
*/
- public synchronized void release() {
+ public void release() {
logd("release()");
if (mCarPowerManager != null) {
mCarPowerManager.clearListener();
@@ -198,7 +198,6 @@
}
if (mBluetoothBroadcastReceiver != null) {
mContext.unregisterReceiver(mBluetoothBroadcastReceiver);
- mBluetoothBroadcastReceiver = null;
}
}
@@ -250,7 +249,7 @@
/**
* Print the verbose status of the object
*/
- public synchronized void dump(PrintWriter writer, String indent) {
+ public void dump(PrintWriter writer, String indent) {
writer.println(indent + TAG + ":");
writer.println(indent + "\tUserId: " + mUserId);
}
diff --git a/service/src/com/android/car/BluetoothProfileDeviceManager.java b/service/src/com/android/car/BluetoothProfileDeviceManager.java
index 505a05b..e73d9ea 100644
--- a/service/src/com/android/car/BluetoothProfileDeviceManager.java
+++ b/service/src/com/android/car/BluetoothProfileDeviceManager.java
@@ -46,6 +46,8 @@
import android.util.Log;
import android.util.SparseArray;
+import com.android.internal.annotations.GuardedBy;
+
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.Arrays;
@@ -114,23 +116,30 @@
}, new int[] {}));
}
+ // Fixed per-profile information for the profile this object manages
private final int mProfileId;
private final String mSettingsKey;
private final String mProfileConnectionAction;
private final ParcelUuid[] mProfileUuids;
private final int[] mProfileTriggers;
+
+ // Central priority list of devices
+ private final Object mPrioritizedDevicesLock = new Object();
+ @GuardedBy("mPrioritizedDevicesLock")
private ArrayList<BluetoothDevice> mPrioritizedDevices;
- private BluetoothAdapter mBluetoothAdapter;
- private BluetoothBroadcastReceiver mBluetoothBroadcastReceiver;
-
- private ICarBluetoothUserService mBluetoothUserProxies;
-
+ // Auto connection process state
private final Object mAutoConnectLock = new Object();
+ @GuardedBy("mAutoConnectLock")
private boolean mConnecting = false;
+ @GuardedBy("mAutoConnectLock")
private int mAutoConnectPriority;
+ @GuardedBy("mAutoConnectLock")
private ArrayList<BluetoothDevice> mAutoConnectingDevices;
+ private final BluetoothAdapter mBluetoothAdapter;
+ private final BluetoothBroadcastReceiver mBluetoothBroadcastReceiver;
+ private final ICarBluetoothUserService mBluetoothUserProxies;
private final Handler mHandler = new Handler(Looper.getMainLooper());
/**
@@ -313,6 +322,7 @@
mProfileUuids = bpi.mUuids;
mProfileTriggers = bpi.mProfileTriggers;
+ mBluetoothBroadcastReceiver = new BluetoothBroadcastReceiver();
mBluetoothAdapter = Objects.requireNonNull(BluetoothAdapter.getDefaultAdapter());
}
@@ -327,7 +337,7 @@
mAutoConnectPriority = -1;
mAutoConnectingDevices = null;
}
- mBluetoothBroadcastReceiver = new BluetoothBroadcastReceiver();
+
IntentFilter profileFilter = new IntentFilter();
profileFilter.addAction(mProfileConnectionAction);
profileFilter.addAction(BluetoothAdapter.ACTION_STATE_CHANGED);
@@ -347,7 +357,6 @@
if (mContext != null) {
mContext.unregisterReceiver(mBluetoothBroadcastReceiver);
}
- mBluetoothBroadcastReceiver = null;
}
cancelAutoConnecting();
commit();
@@ -392,7 +401,7 @@
}
}
- synchronized (this) {
+ synchronized (mPrioritizedDevicesLock) {
mPrioritizedDevices = devices;
}
@@ -408,7 +417,7 @@
private boolean commit() {
StringBuilder sb = new StringBuilder();
String delimiter = "";
- synchronized (this) {
+ synchronized (mPrioritizedDevicesLock) {
for (BluetoothDevice device : mPrioritizedDevices) {
sb.append(delimiter);
sb.append(device.getAddress());
@@ -434,7 +443,7 @@
addDevice(device); // No-op if device is already in the priority list
}
- synchronized (this) {
+ synchronized (mPrioritizedDevicesLock) {
ArrayList<BluetoothDevice> devices = getDeviceListSnapshot();
for (BluetoothDevice device : devices) {
if (!bondedDevices.contains(device)) {
@@ -451,7 +460,7 @@
*/
public ArrayList<BluetoothDevice> getDeviceListSnapshot() {
ArrayList<BluetoothDevice> devices = new ArrayList<>();
- synchronized (this) {
+ synchronized (mPrioritizedDevicesLock) {
devices = (ArrayList) mPrioritizedDevices.clone();
}
return devices;
@@ -462,12 +471,14 @@
*
* @param device - The device you wish to add
*/
- public synchronized void addDevice(BluetoothDevice device) {
+ public void addDevice(BluetoothDevice device) {
if (device == null) return;
- if (mPrioritizedDevices.contains(device)) return;
- logd("Add device " + device);
- mPrioritizedDevices.add(device);
- commit();
+ synchronized (mPrioritizedDevicesLock) {
+ if (mPrioritizedDevices.contains(device)) return;
+ logd("Add device " + device);
+ mPrioritizedDevices.add(device);
+ commit();
+ }
}
/**
@@ -475,12 +486,14 @@
*
* @param device - The device you wish to remove
*/
- public synchronized void removeDevice(BluetoothDevice device) {
+ public void removeDevice(BluetoothDevice device) {
if (device == null) return;
- if (!mPrioritizedDevices.contains(device)) return;
- logd("Remove device " + device);
- mPrioritizedDevices.remove(device);
- commit();
+ synchronized (mPrioritizedDevicesLock) {
+ if (!mPrioritizedDevices.contains(device)) return;
+ logd("Remove device " + device);
+ mPrioritizedDevices.remove(device);
+ commit();
+ }
}
/**
@@ -489,10 +502,12 @@
* @param device - The device you want the priority of
* @return The priority of the device, or -1 if the device is not in the list
*/
- public synchronized int getDeviceConnectionPriority(BluetoothDevice device) {
+ public int getDeviceConnectionPriority(BluetoothDevice device) {
if (device == null) return -1;
logd("Get connection priority of " + device);
- return mPrioritizedDevices.indexOf(device);
+ synchronized (mPrioritizedDevicesLock) {
+ return mPrioritizedDevices.indexOf(device);
+ }
}
/**
@@ -505,16 +520,18 @@
* @param device - The device you want to set the priority of
* @param priority - The priority you want to the device to have
*/
- public synchronized void setDeviceConnectionPriority(BluetoothDevice device, int priority) {
- if (device == null || priority < 0 || priority > mPrioritizedDevices.size()
- || getDeviceConnectionPriority(device) == priority) return;
- if (mPrioritizedDevices.contains(device)) {
- mPrioritizedDevices.remove(device);
- if (priority > mPrioritizedDevices.size()) priority = mPrioritizedDevices.size();
+ public void setDeviceConnectionPriority(BluetoothDevice device, int priority) {
+ synchronized (mPrioritizedDevicesLock) {
+ if (device == null || priority < 0 || priority > mPrioritizedDevices.size()
+ || getDeviceConnectionPriority(device) == priority) return;
+ if (mPrioritizedDevices.contains(device)) {
+ mPrioritizedDevices.remove(device);
+ if (priority > mPrioritizedDevices.size()) priority = mPrioritizedDevices.size();
+ }
+ logd("Set connection priority of " + device + " to " + priority);
+ mPrioritizedDevices.add(priority, device);
+ commit();
}
- logd("Set connection priority of " + device + " to " + priority);
- mPrioritizedDevices.add(priority, device);
- commit();
}
/**
diff --git a/service/src/com/android/car/BluetoothProfileInhibitManager.java b/service/src/com/android/car/BluetoothProfileInhibitManager.java
index 4dcc6b7..691592f 100644
--- a/service/src/com/android/car/BluetoothProfileInhibitManager.java
+++ b/service/src/com/android/car/BluetoothProfileInhibitManager.java
@@ -56,14 +56,16 @@
private final int mUserId;
private final ICarBluetoothUserService mBluetoothUserProxies;
- @GuardedBy("this")
+ private final Object mProfileInhibitsLock = new Object();
+
+ @GuardedBy("mProfileInhibitsLock")
private final SetMultimap<BluetoothConnection, InhibitRecord> mProfileInhibits =
new SetMultimap<>();
- @GuardedBy("this")
+ @GuardedBy("mProfileInhibitsLock")
private final HashSet<InhibitRecord> mRestoredInhibits = new HashSet<>();
- @GuardedBy("this")
+ @GuardedBy("mProfileInhibitsLock")
private final HashSet<BluetoothConnection> mAlreadyDisabledProfiles = new HashSet<>();
private final Handler mHandler = new Handler(Looper.getMainLooper());
@@ -190,7 +192,7 @@
}
public boolean removeSelf() {
- synchronized (BluetoothProfileInhibitManager.this) {
+ synchronized (mProfileInhibitsLock) {
if (mRemoved) {
return true;
}
@@ -328,9 +330,7 @@
BluetoothConnection params = new BluetoothConnection(profile, device);
InhibitRecord record;
- synchronized (this) {
- record = findInhibitRecord(params, token);
- }
+ record = findInhibitRecord(params, token);
if (record == null) {
Log.e(TAG, "Record not found");
@@ -343,64 +343,66 @@
/**
* Add a profile inhibit record, disabling the profile if necessary.
*/
- private synchronized boolean addInhibitRecord(InhibitRecord record) {
- BluetoothConnection params = record.getParams();
- if (!isProxyAvailable(params.getProfile())) {
- return false;
- }
-
- Set<InhibitRecord> previousRecords = mProfileInhibits.get(params);
- if (findInhibitRecord(params, record.getToken()) != null) {
- Log.e(TAG, "Inhibit request already registered - skipping duplicate");
- return false;
- }
-
- try {
- record.getToken().linkToDeath(record, 0);
- } catch (RemoteException e) {
- Log.e(TAG, "Could not link to death on inhibit token (already dead?)", e);
- return false;
- }
-
- boolean isNewlyAdded = previousRecords.isEmpty();
- mProfileInhibits.put(params, record);
-
- if (isNewlyAdded) {
- try {
- int priority =
- mBluetoothUserProxies.getProfilePriority(
- params.getProfile(),
- params.getDevice());
- if (priority == BluetoothProfile.PRIORITY_OFF) {
- // This profile was already disabled (and not as the result of an inhibit).
- // Add it to the already-disabled list, and do nothing else.
- mAlreadyDisabledProfiles.add(params);
-
- logd("Profile " + Utils.getProfileName(params.getProfile())
- + " already disabled for device " + params.getDevice()
- + " - suppressing re-enable");
- } else {
- mBluetoothUserProxies.setProfilePriority(
- params.getProfile(),
- params.getDevice(),
- BluetoothProfile.PRIORITY_OFF);
- mBluetoothUserProxies.bluetoothDisconnectFromProfile(
- params.getProfile(),
- params.getDevice());
- logd("Disabled profile "
- + Utils.getProfileName(params.getProfile())
- + " for device " + params.getDevice());
- }
- } catch (RemoteException e) {
- Log.e(TAG, "Could not disable profile", e);
- record.getToken().unlinkToDeath(record, 0);
- mProfileInhibits.remove(params, record);
+ private boolean addInhibitRecord(InhibitRecord record) {
+ synchronized (mProfileInhibitsLock) {
+ BluetoothConnection params = record.getParams();
+ if (!isProxyAvailable(params.getProfile())) {
return false;
}
- }
- commit();
- return true;
+ Set<InhibitRecord> previousRecords = mProfileInhibits.get(params);
+ if (findInhibitRecord(params, record.getToken()) != null) {
+ Log.e(TAG, "Inhibit request already registered - skipping duplicate");
+ return false;
+ }
+
+ try {
+ record.getToken().linkToDeath(record, 0);
+ } catch (RemoteException e) {
+ Log.e(TAG, "Could not link to death on inhibit token (already dead?)", e);
+ return false;
+ }
+
+ boolean isNewlyAdded = previousRecords.isEmpty();
+ mProfileInhibits.put(params, record);
+
+ if (isNewlyAdded) {
+ try {
+ int priority =
+ mBluetoothUserProxies.getProfilePriority(
+ params.getProfile(),
+ params.getDevice());
+ if (priority == BluetoothProfile.PRIORITY_OFF) {
+ // This profile was already disabled (and not as the result of an inhibit).
+ // Add it to the already-disabled list, and do nothing else.
+ mAlreadyDisabledProfiles.add(params);
+
+ logd("Profile " + Utils.getProfileName(params.getProfile())
+ + " already disabled for device " + params.getDevice()
+ + " - suppressing re-enable");
+ } else {
+ mBluetoothUserProxies.setProfilePriority(
+ params.getProfile(),
+ params.getDevice(),
+ BluetoothProfile.PRIORITY_OFF);
+ mBluetoothUserProxies.bluetoothDisconnectFromProfile(
+ params.getProfile(),
+ params.getDevice());
+ logd("Disabled profile "
+ + Utils.getProfileName(params.getProfile())
+ + " for device " + params.getDevice());
+ }
+ } catch (RemoteException e) {
+ Log.e(TAG, "Could not disable profile", e);
+ record.getToken().unlinkToDeath(record, 0);
+ mProfileInhibits.remove(params, record);
+ return false;
+ }
+ }
+
+ commit();
+ return true;
+ }
}
/**
@@ -411,41 +413,45 @@
* @return InhibitRecord for the connection parameters and token if exists, null otherwise.
*/
private InhibitRecord findInhibitRecord(BluetoothConnection params, IBinder token) {
- return mProfileInhibits.get(params)
- .stream()
- .filter(r -> r.getToken() == token)
- .findAny()
- .orElse(null);
+ synchronized (mProfileInhibitsLock) {
+ return mProfileInhibits.get(params)
+ .stream()
+ .filter(r -> r.getToken() == token)
+ .findAny()
+ .orElse(null);
+ }
}
/**
* Remove a given profile inhibit record, reconnecting if necessary.
*/
- private synchronized boolean removeInhibitRecord(InhibitRecord record) {
- BluetoothConnection params = record.getParams();
- if (!isProxyAvailable(params.getProfile())) {
- return false;
- }
- if (!mProfileInhibits.containsEntry(params, record)) {
- Log.e(TAG, "Record already removed");
- // Removing something a second time vacuously succeeds.
- return true;
- }
-
- // Re-enable profile before unlinking and removing the record, in case of error.
- // The profile should be re-enabled if this record is the only one left for that
- // device and profile combination.
- if (mProfileInhibits.get(params).size() == 1) {
- if (!restoreProfilePriority(params)) {
+ private boolean removeInhibitRecord(InhibitRecord record) {
+ synchronized (mProfileInhibitsLock) {
+ BluetoothConnection params = record.getParams();
+ if (!isProxyAvailable(params.getProfile())) {
return false;
}
+ if (!mProfileInhibits.containsEntry(params, record)) {
+ Log.e(TAG, "Record already removed");
+ // Removing something a second time vacuously succeeds.
+ return true;
+ }
+
+ // Re-enable profile before unlinking and removing the record, in case of error.
+ // The profile should be re-enabled if this record is the only one left for that
+ // device and profile combination.
+ if (mProfileInhibits.get(params).size() == 1) {
+ if (!restoreProfilePriority(params)) {
+ return false;
+ }
+ }
+
+ record.getToken().unlinkToDeath(record, 0);
+ mProfileInhibits.remove(params, record);
+
+ commit();
+ return true;
}
-
- record.getToken().unlinkToDeath(record, 0);
- mProfileInhibits.remove(params, record);
-
- commit();
- return true;
}
/**
@@ -504,46 +510,51 @@
* Keep trying to remove all profile inhibits that were restored from settings
* until all such inhibits have been removed.
*/
- private synchronized void removeRestoredProfileInhibits() {
- tryRemoveRestoredProfileInhibits();
+ private void removeRestoredProfileInhibits() {
+ synchronized (mProfileInhibitsLock) {
+ tryRemoveRestoredProfileInhibits();
- if (!mRestoredInhibits.isEmpty()) {
- logd("Could not remove all restored profile inhibits - "
- + "trying again in " + RESTORE_BACKOFF_MILLIS + "ms");
- mHandler.postDelayed(
- this::removeRestoredProfileInhibits,
- RESTORED_PROFILE_INHIBIT_TOKEN,
- RESTORE_BACKOFF_MILLIS);
+ if (!mRestoredInhibits.isEmpty()) {
+ logd("Could not remove all restored profile inhibits - "
+ + "trying again in " + RESTORE_BACKOFF_MILLIS + "ms");
+ mHandler.postDelayed(
+ this::removeRestoredProfileInhibits,
+ RESTORED_PROFILE_INHIBIT_TOKEN,
+ RESTORE_BACKOFF_MILLIS);
+ }
}
}
/**
* Release all active inhibit records prior to user switch or shutdown
*/
- private synchronized void releaseAllInhibitsBeforeUnbind() {
+ private void releaseAllInhibitsBeforeUnbind() {
logd("Unbinding CarBluetoothUserService - releasing all profile inhibits");
- for (BluetoothConnection params : mProfileInhibits.keySet()) {
- for (InhibitRecord record : mProfileInhibits.get(params)) {
- record.removeSelf();
+
+ synchronized (mProfileInhibitsLock) {
+ for (BluetoothConnection params : mProfileInhibits.keySet()) {
+ for (InhibitRecord record : mProfileInhibits.get(params)) {
+ record.removeSelf();
+ }
}
+
+ // Some inhibits might be hanging around because they couldn't be cleaned up.
+ // Make sure they get persisted...
+ commit();
+
+ // ...then clear them from the map.
+ mProfileInhibits.clear();
+
+ // We don't need to maintain previously-disabled profiles any more - they were already
+ // skipped in saveProfileInhibitsToSettings() above, and they don't need any
+ // further handling when the user resumes.
+ mAlreadyDisabledProfiles.clear();
+
+ // Clean up bookkeeping for restored inhibits. (If any are still around, they'll be
+ // restored again when this user restarts.)
+ mHandler.removeCallbacksAndMessages(RESTORED_PROFILE_INHIBIT_TOKEN);
+ mRestoredInhibits.clear();
}
-
- // Some inhibits might be hanging around because they couldn't be cleaned up.
- // Make sure they get persisted...
- commit();
-
- // ...then clear them from the map.
- mProfileInhibits.clear();
-
- // We don't need to maintain previously-disabled profiles any more - they were already
- // skipped in saveProfileInhibitsToSettings() above, and they don't need any
- // further handling when the user resumes.
- mAlreadyDisabledProfiles.clear();
-
- // Clean up bookkeeping for restored inhibits. (If any are still around, they'll be
- // restored again when this user restarts.)
- mHandler.removeCallbacksAndMessages(RESTORED_PROFILE_INHIBIT_TOKEN);
- mRestoredInhibits.clear();
}
/**
@@ -564,7 +575,7 @@
/**
* Print the verbose status of the object
*/
- public synchronized void dump(PrintWriter writer, String indent) {
+ public void dump(PrintWriter writer, String indent) {
writer.println(indent + TAG + ":");
// User metadata
@@ -572,7 +583,7 @@
// Current inhibits
String inhibits;
- synchronized (this) {
+ synchronized (mProfileInhibitsLock) {
inhibits = mProfileInhibits.keySet().toString();
}
writer.println(indent + "\tInhibited profiles: " + inhibits);
diff --git a/service/src/com/android/car/CarBluetoothService.java b/service/src/com/android/car/CarBluetoothService.java
index 0c992e1..54d15a1 100644
--- a/service/src/com/android/car/CarBluetoothService.java
+++ b/service/src/com/android/car/CarBluetoothService.java
@@ -28,6 +28,8 @@
import android.util.Log;
import android.util.SparseArray;
+import com.android.internal.annotations.GuardedBy;
+
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.Arrays;
@@ -63,20 +65,31 @@
BluetoothProfile.PAN
);
+ // Each time PerUserCarService connects we need to get new Bluetooth profile proxies and refresh
+ // all our internal objects to use them. When it disconnects we're to assume our proxies are
+ // invalid. This lock protects all our internal objects.
+ private final Object mPerUserLock = new Object();
+
// Set of Bluetooth Profile Device Managers, own the priority connection lists, updated on user
// switch
- private SparseArray<BluetoothProfileDeviceManager> mProfileDeviceManagers = new SparseArray<>();
+ private final SparseArray<BluetoothProfileDeviceManager> mProfileDeviceManagers =
+ new SparseArray<>();
// Profile-Inhibit Manager that will temporarily inhibit connections on profiles, per user
+ @GuardedBy("mPerUserLock")
private BluetoothProfileInhibitManager mInhibitManager = null;
// Default Bluetooth device connection policy, per user, enabled with an overlay
private final boolean mUseDefaultPolicy;
+ @GuardedBy("mPerUserLock")
private BluetoothDeviceConnectionPolicy mBluetoothDeviceConnectionPolicy = null;
// Listen for user switch events from the PerUserCarService
+ @GuardedBy("mPerUserLock")
private int mUserId;
+ @GuardedBy("mPerUserLock")
private ICarUserService mCarUserService;
+ @GuardedBy("mPerUserLock")
private ICarBluetoothUserService mCarBluetoothUserService;
private final PerUserCarServiceHelper mUserServiceHelper;
private final PerUserCarServiceHelper.ServiceCallback mUserServiceCallback =
@@ -84,8 +97,14 @@
@Override
public void onServiceConnected(ICarUserService carUserService) {
logd("Connected to PerUserCarService");
- synchronized (this) {
+ synchronized (mPerUserLock) {
+ // Explicitly clear out existing per-user objects since we can't rely on the
+ // onServiceDisconnected and onPreUnbind calls to always be called before this
+ destroyUser();
+
mCarUserService = carUserService;
+
+ // Create new objects with our new set of profile proxies
initializeUser();
}
}
@@ -99,9 +118,7 @@
@Override
public void onServiceDisconnected() {
logd("Disconnected from PerUserCarService");
- synchronized (this) {
- mCarUserService = null;
- }
+ destroyUser();
}
};
@@ -126,7 +143,7 @@
* Wait for the user service helper to report a user before initializing a user.
*/
@Override
- public synchronized void init() {
+ public void init() {
logd("init()");
mUserServiceHelper.registerServiceCallback(mUserServiceCallback);
}
@@ -137,11 +154,10 @@
* Clean up the user context once we've detached from the user service helper, if any.
*/
@Override
- public synchronized void release() {
+ public void release() {
logd("release()");
mUserServiceHelper.unregisterServiceCallback(mUserServiceCallback);
destroyUser();
- mCarUserService = null;
}
/**
@@ -158,32 +174,37 @@
*
* Only call this following a known user switch once we've connected to the user service helper.
*/
- private synchronized void initializeUser() {
+ private void initializeUser() {
logd("Initializing new user");
- mUserId = ActivityManager.getCurrentUser();
- createBluetoothUserService();
- createBluetoothProfileDeviceManagers();
- createBluetoothProfileInhibitManager();
+ synchronized (mPerUserLock) {
+ mUserId = ActivityManager.getCurrentUser();
+ createBluetoothUserService();
+ createBluetoothProfileDeviceManagers();
+ createBluetoothProfileInhibitManager();
- // Determine if we need to begin the default policy
- mBluetoothDeviceConnectionPolicy = null;
- if (mUseDefaultPolicy) {
- createBluetoothDeviceConnectionPolicy();
+ // Determine if we need to begin the default policy
+ mBluetoothDeviceConnectionPolicy = null;
+ if (mUseDefaultPolicy) {
+ createBluetoothDeviceConnectionPolicy();
+ }
+ logd("Switched to user " + mUserId);
}
- logd("Switched to user " + mUserId);
}
/**
* Destroy the current user context, defined by the set of profile proxies, profile device
* managers, inhibit manager and the policy.
*/
- private synchronized void destroyUser() {
+ private void destroyUser() {
logd("Destroying user " + mUserId);
- destroyBluetoothDeviceConnectionPolicy();
- destroyBluetoothProfileInhibitManager();
- destroyBluetoothProfileDeviceManagers();
- destroyBluetoothUserService();
- mUserId = -1;
+ synchronized (mPerUserLock) {
+ destroyBluetoothDeviceConnectionPolicy();
+ destroyBluetoothProfileInhibitManager();
+ destroyBluetoothProfileDeviceManagers();
+ destroyBluetoothUserService();
+ mCarUserService = null;
+ mUserId = -1;
+ }
}
/**
@@ -192,17 +213,17 @@
* Also sets up the connection proxy objects required to communicate with the Bluetooth
* Profile Services.
*/
- private synchronized void createBluetoothUserService() {
- if (mCarUserService != null) {
- try {
- mCarBluetoothUserService = mCarUserService.getBluetoothUserService();
- mCarBluetoothUserService.setupBluetoothConnectionProxies();
- } catch (RemoteException e) {
- Log.e(TAG, "Remote Service Exception on ServiceConnection Callback: "
- + e.getMessage());
+ private void createBluetoothUserService() {
+ synchronized (mPerUserLock) {
+ if (mCarUserService != null) {
+ try {
+ mCarBluetoothUserService = mCarUserService.getBluetoothUserService();
+ mCarBluetoothUserService.setupBluetoothConnectionProxies();
+ } catch (RemoteException e) {
+ Log.e(TAG, "Remote Service Exception on ServiceConnection Callback: "
+ + e.getMessage());
+ }
}
- } else {
- logd("PerUserCarService not connected. Cannot get bluetooth user proxy objects");
}
}
@@ -210,109 +231,130 @@
* Close out the Per User Car Bluetooth profile proxy connections and destroys the Car Bluetooth
* User Service object.
*/
- private synchronized void destroyBluetoothUserService() {
- if (mCarBluetoothUserService == null) return;
- try {
- mCarBluetoothUserService.closeBluetoothConnectionProxies();
- } catch (RemoteException e) {
- Log.e(TAG, "Remote Service Exception on ServiceConnection Callback: "
- + e.getMessage());
+ private void destroyBluetoothUserService() {
+ synchronized (mPerUserLock) {
+ if (mCarBluetoothUserService == null) return;
+ try {
+ mCarBluetoothUserService.closeBluetoothConnectionProxies();
+ } catch (RemoteException e) {
+ Log.e(TAG, "Remote Service Exception on ServiceConnection Callback: "
+ + e.getMessage());
+ }
+ mCarBluetoothUserService = null;
}
- mCarBluetoothUserService = null;
}
/**
* Clears out Profile Device Managers and re-creates them for the current user.
*/
- private synchronized void createBluetoothProfileDeviceManagers() {
- mProfileDeviceManagers.clear();
- if (mUserId == -1) {
- logd("No foreground user, cannot create profile device managers");
- return;
- }
- for (int profileId : sManagedProfiles) {
- BluetoothProfileDeviceManager deviceManager = BluetoothProfileDeviceManager.create(
- mContext, mUserId, mCarBluetoothUserService, profileId);
- if (deviceManager == null) {
- logd("Failed to create profile device manager for "
- + Utils.getProfileName(profileId));
- continue;
+ private void createBluetoothProfileDeviceManagers() {
+ synchronized (mPerUserLock) {
+ if (mUserId == -1) {
+ logd("No foreground user, cannot create profile device managers");
+ return;
}
- mProfileDeviceManagers.put(profileId, deviceManager);
- logd("Created profile device manager for " + Utils.getProfileName(profileId));
- }
+ for (int profileId : sManagedProfiles) {
+ BluetoothProfileDeviceManager deviceManager = mProfileDeviceManagers.get(profileId);
+ if (deviceManager != null) {
+ deviceManager.stop();
+ mProfileDeviceManagers.remove(profileId);
+ logd("Existing device manager removed for profile "
+ + Utils.getProfileName(profileId));
+ }
- for (int i = 0; i < mProfileDeviceManagers.size(); i++) {
- int key = mProfileDeviceManagers.keyAt(i);
- BluetoothProfileDeviceManager deviceManager =
- (BluetoothProfileDeviceManager) mProfileDeviceManagers.get(key);
- deviceManager.start();
+ deviceManager = BluetoothProfileDeviceManager.create(mContext, mUserId,
+ mCarBluetoothUserService, profileId);
+ if (deviceManager == null) {
+ logd("Failed to create profile device manager for "
+ + Utils.getProfileName(profileId));
+ continue;
+ }
+ mProfileDeviceManagers.put(profileId, deviceManager);
+ logd("Created profile device manager for " + Utils.getProfileName(profileId));
+ }
+
+ for (int i = 0; i < mProfileDeviceManagers.size(); i++) {
+ int key = mProfileDeviceManagers.keyAt(i);
+ BluetoothProfileDeviceManager deviceManager =
+ (BluetoothProfileDeviceManager) mProfileDeviceManagers.get(key);
+ deviceManager.start();
+ }
}
}
/**
* Stops and clears the entire set of Profile Device Managers.
*/
- private synchronized void destroyBluetoothProfileDeviceManagers() {
- for (int i = 0; i < mProfileDeviceManagers.size(); i++) {
- int key = mProfileDeviceManagers.keyAt(i);
- BluetoothProfileDeviceManager deviceManager =
- (BluetoothProfileDeviceManager) mProfileDeviceManagers.get(key);
- deviceManager.stop();
+ private void destroyBluetoothProfileDeviceManagers() {
+ synchronized (mPerUserLock) {
+ for (int i = 0; i < mProfileDeviceManagers.size(); i++) {
+ int key = mProfileDeviceManagers.keyAt(i);
+ BluetoothProfileDeviceManager deviceManager =
+ (BluetoothProfileDeviceManager) mProfileDeviceManagers.get(key);
+ deviceManager.stop();
+ }
+ mProfileDeviceManagers.clear();
}
- mProfileDeviceManagers.clear();
}
/**
* Creates an instance of a BluetoothProfileInhibitManager under the current user
*/
- private synchronized void createBluetoothProfileInhibitManager() {
+ private void createBluetoothProfileInhibitManager() {
logd("Creating inhibit manager");
- if (mUserId == -1) {
- logd("No foreground user, cannot create profile inhibit manager");
- return;
+ synchronized (mPerUserLock) {
+ if (mUserId == -1) {
+ logd("No foreground user, cannot create profile inhibit manager");
+ return;
+ }
+ mInhibitManager = new BluetoothProfileInhibitManager(mContext, mUserId,
+ mCarBluetoothUserService);
+ mInhibitManager.start();
}
- mInhibitManager = new BluetoothProfileInhibitManager(mContext, mUserId,
- mCarBluetoothUserService);
- mInhibitManager.start();
}
/**
* Destroys the current instance of a BluetoothProfileInhibitManager, if one exists
*/
- private synchronized void destroyBluetoothProfileInhibitManager() {
+ private void destroyBluetoothProfileInhibitManager() {
logd("Destroying inhibit manager");
- if (mInhibitManager == null) return;
- mInhibitManager.stop();
- mInhibitManager = null;
+ synchronized (mPerUserLock) {
+ if (mInhibitManager == null) return;
+ mInhibitManager.stop();
+ mInhibitManager = null;
+ }
}
/**
* Creates an instance of a BluetoothDeviceConnectionPolicy under the current user
*/
- private synchronized void createBluetoothDeviceConnectionPolicy() {
+ private void createBluetoothDeviceConnectionPolicy() {
logd("Creating device connection policy");
- if (mUserId == -1) {
- logd("No foreground user, cannot create device connection policy");
- return;
+ synchronized (mPerUserLock) {
+ if (mUserId == -1) {
+ logd("No foreground user, cannot create device connection policy");
+ return;
+ }
+ mBluetoothDeviceConnectionPolicy = BluetoothDeviceConnectionPolicy.create(mContext,
+ mUserId, this);
+ if (mBluetoothDeviceConnectionPolicy == null) {
+ logd("Failed to create default Bluetooth device connection policy.");
+ return;
+ }
+ mBluetoothDeviceConnectionPolicy.init();
}
- mBluetoothDeviceConnectionPolicy = BluetoothDeviceConnectionPolicy.create(mContext, mUserId,
- this);
- if (mBluetoothDeviceConnectionPolicy == null) {
- logd("Failed to create default Bluetooth device connection policy.");
- return;
- }
- mBluetoothDeviceConnectionPolicy.init();
}
/**
* Destroys the current instance of a BluetoothDeviceConnectionPolicy, if one exists
*/
- private synchronized void destroyBluetoothDeviceConnectionPolicy() {
+ private void destroyBluetoothDeviceConnectionPolicy() {
logd("Destroying device connection policy");
- if (mBluetoothDeviceConnectionPolicy != null) {
- mBluetoothDeviceConnectionPolicy.release();
- mBluetoothDeviceConnectionPolicy = null;
+ synchronized (mPerUserLock) {
+ if (mBluetoothDeviceConnectionPolicy != null) {
+ mBluetoothDeviceConnectionPolicy.release();
+ mBluetoothDeviceConnectionPolicy = null;
+ }
}
}
@@ -322,7 +364,9 @@
* @return true if the default policy is active, false otherwise
*/
public boolean isUsingDefaultConnectionPolicy() {
- return mBluetoothDeviceConnectionPolicy != null;
+ synchronized (mPerUserLock) {
+ return mBluetoothDeviceConnectionPolicy != null;
+ }
}
/**
@@ -332,7 +376,7 @@
public void connectDevices() {
enforceBluetoothAdminPermission();
logd("Connect devices for each profile");
- synchronized (this) {
+ synchronized (mPerUserLock) {
for (int i = 0; i < mProfileDeviceManagers.size(); i++) {
int key = mProfileDeviceManagers.keyAt(i);
BluetoothProfileDeviceManager deviceManager =
@@ -350,7 +394,7 @@
*/
public List<BluetoothDevice> getProfileDevicePriorityList(int profile) {
enforceBluetoothAdminPermission();
- synchronized (this) {
+ synchronized (mPerUserLock) {
BluetoothProfileDeviceManager deviceManager =
(BluetoothProfileDeviceManager) mProfileDeviceManagers.get(profile);
if (deviceManager != null) {
@@ -369,7 +413,7 @@
*/
public int getDeviceConnectionPriority(int profile, BluetoothDevice device) {
enforceBluetoothAdminPermission();
- synchronized (this) {
+ synchronized (mPerUserLock) {
BluetoothProfileDeviceManager deviceManager =
(BluetoothProfileDeviceManager) mProfileDeviceManagers.get(profile);
if (deviceManager != null) {
@@ -388,7 +432,7 @@
*/
public void setDeviceConnectionPriority(int profile, BluetoothDevice device, int priority) {
enforceBluetoothAdminPermission();
- synchronized (this) {
+ synchronized (mPerUserLock) {
BluetoothProfileDeviceManager deviceManager =
(BluetoothProfileDeviceManager) mProfileDeviceManagers.get(profile);
if (deviceManager != null) {
@@ -408,11 +452,13 @@
* owning the token dies, the request will automatically be released
* @return True if the profile was successfully inhibited, false if an error occurred.
*/
- synchronized boolean requestProfileInhibit(BluetoothDevice device, int profile, IBinder token) {
+ boolean requestProfileInhibit(BluetoothDevice device, int profile, IBinder token) {
logd("Request profile inhibit: profile " + Utils.getProfileName(profile)
+ ", device " + device.getAddress());
- if (mInhibitManager == null) return false;
- return mInhibitManager.requestProfileInhibit(device, profile, token);
+ synchronized (mPerUserLock) {
+ if (mInhibitManager == null) return false;
+ return mInhibitManager.requestProfileInhibit(device, profile, token);
+ }
}
/**
@@ -425,11 +471,13 @@
* {@link #requestBluetoothProfileInhibit}.
* @return True if the request was released, false if an error occurred.
*/
- synchronized boolean releaseProfileInhibit(BluetoothDevice device, int profile, IBinder token) {
+ boolean releaseProfileInhibit(BluetoothDevice device, int profile, IBinder token) {
logd("Release profile inhibit: profile " + Utils.getProfileName(profile)
+ ", device " + device.getAddress());
- if (mInhibitManager == null) return false;
- return mInhibitManager.releaseProfileInhibit(device, profile, token);
+ synchronized (mPerUserLock) {
+ if (mInhibitManager == null) return false;
+ return mInhibitManager.releaseProfileInhibit(device, profile, token);
+ }
}
/**
@@ -452,29 +500,31 @@
* Print out the verbose debug status of this object
*/
@Override
- public synchronized void dump(PrintWriter writer) {
+ public void dump(PrintWriter writer) {
writer.println("*" + TAG + "*");
- writer.println("\tUser ID: " + mUserId);
- writer.println("\tUser Proxies: " + (mCarBluetoothUserService != null ? "Yes" : "No"));
+ synchronized (mPerUserLock) {
+ writer.println("\tUser ID: " + mUserId);
+ writer.println("\tUser Proxies: " + (mCarBluetoothUserService != null ? "Yes" : "No"));
- // Profile Device Manager statuses
- for (int i = 0; i < mProfileDeviceManagers.size(); i++) {
- int key = mProfileDeviceManagers.keyAt(i);
- BluetoothProfileDeviceManager deviceManager =
- (BluetoothProfileDeviceManager) mProfileDeviceManagers.get(key);
- deviceManager.dump(writer, "\t");
- }
+ // Profile Device Manager statuses
+ for (int i = 0; i < mProfileDeviceManagers.size(); i++) {
+ int key = mProfileDeviceManagers.keyAt(i);
+ BluetoothProfileDeviceManager deviceManager =
+ (BluetoothProfileDeviceManager) mProfileDeviceManagers.get(key);
+ deviceManager.dump(writer, "\t");
+ }
- // Profile Inhibits
- if (mInhibitManager != null) mInhibitManager.dump(writer, "\t");
- else writer.println("\tBluetoothProfileInhibitManager: null");
+ // Profile Inhibits
+ if (mInhibitManager != null) mInhibitManager.dump(writer, "\t");
+ else writer.println("\tBluetoothProfileInhibitManager: null");
- // Device Connection Policy
- writer.println("\tUsing default policy? " + (mUseDefaultPolicy ? "Yes" : "No"));
- if (mBluetoothDeviceConnectionPolicy == null) {
- writer.println("\tBluetoothDeviceConnectionPolicy: null");
- } else {
- mBluetoothDeviceConnectionPolicy.dump(writer, "\t");
+ // Device Connection Policy
+ writer.println("\tUsing default policy? " + (mUseDefaultPolicy ? "Yes" : "No"));
+ if (mBluetoothDeviceConnectionPolicy == null) {
+ writer.println("\tBluetoothDeviceConnectionPolicy: null");
+ } else {
+ mBluetoothDeviceConnectionPolicy.dump(writer, "\t");
+ }
}
}
diff --git a/service/src/com/android/car/CarTestService.java b/service/src/com/android/car/CarTestService.java
index 776fd53..d72d87d 100644
--- a/service/src/com/android/car/CarTestService.java
+++ b/service/src/com/android/car/CarTestService.java
@@ -123,4 +123,4 @@
releaseToken(mToken);
}
}
-}
\ No newline at end of file
+}
diff --git a/service/src/com/android/car/ICarImpl.java b/service/src/com/android/car/ICarImpl.java
index c61610e..d98b780 100644
--- a/service/src/com/android/car/ICarImpl.java
+++ b/service/src/com/android/car/ICarImpl.java
@@ -68,6 +68,7 @@
public static final String INTERNAL_INPUT_SERVICE = "internal_input";
public static final String INTERNAL_SYSTEM_ACTIVITY_MONITORING_SERVICE =
"system_activity_monitoring";
+ public static final String INTERNAL_VMS_MANAGER = "vms_manager";
private final Context mContext;
private final VehicleHal mHal;
@@ -165,8 +166,8 @@
mVmsBrokerService = new VmsBrokerService();
mVmsClientManager = new VmsClientManager(
// CarStatsService needs to be passed to the constructor due to HAL init order
- serviceContext, mCarStatsService, mCarUserService, mUserManagerHelper,
- mVmsBrokerService, mHal.getVmsHal());
+ serviceContext, mCarStatsService, mCarUserService, mVmsBrokerService,
+ mHal.getVmsHal());
mVmsSubscriberService = new VmsSubscriberService(
serviceContext, mVmsBrokerService, mVmsClientManager, mHal.getVmsHal());
mVmsPublisherService = new VmsPublisherService(
@@ -243,7 +244,6 @@
mAllServices[i].release();
}
mHal.release();
- CarLocalServices.removeAllServices();
}
void vehicleHalReconnected(IVehicle vehicle) {
@@ -377,6 +377,8 @@
return mCarInputService;
case INTERNAL_SYSTEM_ACTIVITY_MONITORING_SERVICE:
return mSystemActivityMonitoringService;
+ case INTERNAL_VMS_MANAGER:
+ return mVmsClientManager;
default:
Log.w(CarLog.TAG_SERVICE, "getCarInternalService for unknown service:" +
serviceName);
diff --git a/service/src/com/android/car/systeminterface/TimeInterface.java b/service/src/com/android/car/systeminterface/TimeInterface.java
index dea1153..fd350a5 100644
--- a/service/src/com/android/car/systeminterface/TimeInterface.java
+++ b/service/src/com/android/car/systeminterface/TimeInterface.java
@@ -19,6 +19,9 @@
import static java.util.concurrent.Executors.newSingleThreadScheduledExecutor;
import android.os.SystemClock;
+
+import com.android.internal.annotations.GuardedBy;
+
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
@@ -42,16 +45,34 @@
void cancelAllActions();
class DefaultImpl implements TimeInterface {
- private final ScheduledExecutorService mExecutor = newSingleThreadScheduledExecutor();
+ private final Object mLock = new Object();
+
+ @GuardedBy("mLock")
+ private ScheduledExecutorService mExecutor;
@Override
public void scheduleAction(Runnable r, long delayMs) {
- mExecutor.scheduleAtFixedRate(r, delayMs, delayMs, TimeUnit.MILLISECONDS);
+ ScheduledExecutorService executor;
+ synchronized (mLock) {
+ executor = mExecutor;
+ if (executor == null) {
+ executor = newSingleThreadScheduledExecutor();
+ mExecutor = executor;
+ }
+ }
+ executor.scheduleAtFixedRate(r, delayMs, delayMs, TimeUnit.MILLISECONDS);
}
@Override
public void cancelAllActions() {
- mExecutor.shutdownNow();
+ ScheduledExecutorService executor;
+ synchronized (mLock) {
+ executor = mExecutor;
+ mExecutor = null;
+ }
+ if (executor != null) {
+ executor.shutdownNow();
+ }
}
}
}
diff --git a/service/src/com/android/car/vms/VmsClientManager.java b/service/src/com/android/car/vms/VmsClientManager.java
index 0db0457..346c730 100644
--- a/service/src/com/android/car/vms/VmsClientManager.java
+++ b/service/src/com/android/car/vms/VmsClientManager.java
@@ -17,14 +17,11 @@
package com.android.car.vms;
import android.car.Car;
-import android.car.userlib.CarUserManagerHelper;
import android.car.vms.IVmsPublisherClient;
import android.car.vms.IVmsSubscriberClient;
-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.PackageManager;
import android.content.pm.ServiceInfo;
@@ -52,7 +49,6 @@
import java.io.PrintWriter;
import java.util.Collection;
-import java.util.HashMap;
import java.util.Map;
import java.util.NoSuchElementException;
import java.util.function.IntSupplier;
@@ -75,7 +71,6 @@
private final PackageManager mPackageManager;
private final UserManager mUserManager;
private final CarUserService mUserService;
- private final CarUserManagerHelper mUserManagerHelper;
private final CarStatsService mStatsService;
private final Handler mHandler;
private final IntSupplier mGetCallingUid;
@@ -101,7 +96,7 @@
private int mCurrentUser;
@GuardedBy("mLock")
- private final Map<IBinder, SubscriberConnection> mSubscribers = new HashMap<>();
+ private final Map<IBinder, SubscriberConnection> mSubscribers = new ArrayMap<>();
@VisibleForTesting
final Runnable mSystemUserUnlockedListener = () -> {
@@ -112,22 +107,25 @@
};
@VisibleForTesting
- final BroadcastReceiver mUserSwitchReceiver = new BroadcastReceiver() {
+ public final CarUserService.UserCallback mUserCallback = new CarUserService.UserCallback() {
@Override
- public void onReceive(Context context, Intent intent) {
- if (DBG) Log.d(TAG, "Received " + intent);
+ public void onSwitchUser(int userId) {
synchronized (mLock) {
- int currentUserId = mUserManagerHelper.getCurrentForegroundUserId();
- if (mCurrentUser != currentUserId) {
+ if (mCurrentUser != userId) {
+ mCurrentUser = userId;
terminate(mCurrentUserClients);
terminate(mSubscribers.values().stream()
- .filter(subscriber -> subscriber.mUserId != currentUserId)
+ .filter(subscriber -> subscriber.mUserId != mCurrentUser)
.filter(subscriber -> subscriber.mUserId != UserHandle.USER_SYSTEM));
}
- mCurrentUser = currentUserId;
+ }
+ bindToUserClients();
+ }
- if (mUserManager.isUserUnlocked(mCurrentUser)) {
- bindToSystemClients();
+ @Override
+ public void onUserLockChanged(int userId, boolean unlocked) {
+ synchronized (mLock) {
+ if (mCurrentUser == userId && unlocked) {
bindToUserClients();
}
}
@@ -140,29 +138,26 @@
* @param context Context to use for registering receivers and binding services.
* @param statsService Service for logging client metrics.
* @param userService User service for registering system unlock listener.
- * @param userManagerHelper User manager for querying current user state.
* @param brokerService Service managing the VMS publisher/subscriber state.
* @param halService Service providing the HAL client interface
*/
public VmsClientManager(Context context, CarStatsService statsService,
- CarUserService userService, CarUserManagerHelper userManagerHelper,
- VmsBrokerService brokerService, VmsHalService halService) {
- this(context, statsService, userService, userManagerHelper, brokerService, halService,
+ CarUserService userService, VmsBrokerService brokerService,
+ VmsHalService halService) {
+ this(context, statsService, userService, brokerService, halService,
new Handler(Looper.getMainLooper()), Binder::getCallingUid);
}
@VisibleForTesting
VmsClientManager(Context context, CarStatsService statsService,
- CarUserService userService, CarUserManagerHelper userManagerHelper,
- VmsBrokerService brokerService, VmsHalService halService,
- Handler handler, IntSupplier getCallingUid) {
+ CarUserService userService, VmsBrokerService brokerService,
+ VmsHalService halService, Handler handler, IntSupplier getCallingUid) {
mContext = context;
mPackageManager = context.getPackageManager();
mUserManager = (UserManager) context.getSystemService(Context.USER_SERVICE);
mStatsService = statsService;
mUserService = userService;
- mUserManagerHelper = userManagerHelper;
- mCurrentUser = mUserManagerHelper.getCurrentForegroundUserId();
+ mCurrentUser = UserHandle.USER_NULL;
mBrokerService = brokerService;
mHandler = handler;
mGetCallingUid = getCallingUid;
@@ -186,17 +181,12 @@
@Override
public void init() {
mUserService.runOnUser0Unlock(mSystemUserUnlockedListener);
-
- IntentFilter userSwitchFilter = new IntentFilter();
- userSwitchFilter.addAction(Intent.ACTION_USER_SWITCHED);
- userSwitchFilter.addAction(Intent.ACTION_USER_UNLOCKED);
- mContext.registerReceiverAsUser(mUserSwitchReceiver, UserHandle.ALL, userSwitchFilter, null,
- null);
+ mUserService.addUserCallback(mUserCallback);
}
@Override
public void release() {
- mContext.unregisterReceiver(mUserSwitchReceiver);
+ mUserService.removeUserCallback(mUserCallback);
synchronized (mLock) {
if (mHalClient != null) {
mPublisherService.onClientDisconnected(HAL_CLIENT_NAME);
@@ -365,15 +355,24 @@
}
private void bindToUserClients() {
+ bindToSystemClients(); // Bind system clients on user switch, if they are not already bound.
synchronized (mLock) {
+ if (mCurrentUser == UserHandle.USER_NULL) {
+ Log.e(TAG, "Unknown user in foreground.");
+ return;
+ }
// To avoid the risk of double-binding, clients running as the system user must only
// ever be bound in bindToSystemClients().
- // In a headless multi-user system, the system user will never be in the foreground.
if (mCurrentUser == UserHandle.USER_SYSTEM) {
Log.e(TAG, "System user in foreground. Userspace clients will not be bound.");
return;
}
+ if (!mUserManager.isUserUnlocked(mCurrentUser)) {
+ Log.i(TAG, "Waiting for foreground user to be unlocked.");
+ return;
+ }
+
String[] clientNames = mContext.getResources().getStringArray(
R.array.vmsPublisherUserClients);
Log.i(TAG, "Attempting to bind " + clientNames.length + " user client(s)");
diff --git a/tests/BugReportApp/res/values-fr-rCA/strings.xml b/tests/BugReportApp/res/values-fr-rCA/strings.xml
new file mode 100644
index 0000000..904bd00
--- /dev/null
+++ b/tests/BugReportApp/res/values-fr-rCA/strings.xml
@@ -0,0 +1,47 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ Copyright (C) 2019 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="app_name" msgid="2596316479611335185">"Rapport de bogue"</string>
+ <string name="bugreport_info_quit" msgid="5590138890181142473">"Fermer"</string>
+ <string name="bugreport_info_start" msgid="667324824650830832">"Lancer le rapport de bogue"</string>
+ <string name="bugreport_info_status" msgid="7211044508792815451">"État :"</string>
+ <string name="bugreport_dialog_submit" msgid="2789636252713280633">"Envoyer"</string>
+ <string name="bugreport_dialog_cancel" msgid="4741928791364757040">"Annuler"</string>
+ <string name="bugreport_dialog_show_bugreports" msgid="6964385141627170297">"Afficher les rapports de bogue"</string>
+ <string name="bugreport_dialog_close" msgid="289925437277364266">"Fermer"</string>
+ <string name="bugreport_dialog_title" msgid="3315160684205929910">"Parler et décrire le problème"</string>
+ <string name="bugreport_dialog_recording_finished" msgid="3982335902169398758">"Enregistrement terminé"</string>
+ <string name="bugreport_dialog_in_progress_title" msgid="3782308141532622394">"Un rapport de bogue est déjà en cours de récupération"</string>
+ <string name="bugreport_dialog_in_progress_title_finished" msgid="1610236990020413471">"Un rapport de bogue a été récupéré"</string>
+ <string name="bugreport_move_button_text" msgid="1245698439228323880">"Déplacer vers USB"</string>
+ <string name="bugreport_upload_button_text" msgid="2322576150507025845">"Téléverser sur Google"</string>
+ <string name="toast_permissions_denied" msgid="7054832711916992770">"Veuillez accorder les autorisations"</string>
+ <string name="toast_bug_report_in_progress" msgid="8319601113129121579">"Rapport de bogue déjà en cours de récupération"</string>
+ <string name="toast_timed_out" msgid="4410178570031498895">"Délai dépassé, annulation de l\'opération en cours…"</string>
+ <string name="toast_status_failed" msgid="6365384202315043395">"Échec du rapport de bogue"</string>
+ <string name="toast_status_finished" msgid="7473653838545631945">"Rapport de bogue terminé"</string>
+ <string name="toast_status_pending_upload" msgid="7893505453527958690">"Le rapport de bogue est prêt à être téléversé"</string>
+ <string name="toast_status_screencap_failed" msgid="2187083897594745149">"Échec de la capture d\'écran"</string>
+ <string name="toast_status_dump_state_failed" msgid="8072469535227541761">"Échec de l\'état de la capture"</string>
+ <string name="notification_bugreport_in_progress" msgid="8486454116357963238">"Le rapport de bogue est en cours de création"</string>
+ <string name="notification_bugreport_finished_title" msgid="3970195939909624320">"Récupération du rapport de bogue en cours…"</string>
+ <string name="notification_bugreport_manual_upload_finished_text" msgid="7091975159082077240">"Veuillez le téléverser lorsque le véhicule sera stationné"</string>
+ <string name="notification_bugreport_auto_upload_finished_text" msgid="2598986330417740616">"Le rapport sera automatiquement téléversé"</string>
+ <string name="notification_bugreport_channel_name" msgid="776902295433824255">"Chaîne d\'état du rapport de bogue"</string>
+</resources>
diff --git a/tests/CarDeveloperOptions/res/values-bs/strings.xml b/tests/CarDeveloperOptions/res/values-bs/strings.xml
index d8d8503..083faf0 100644
--- a/tests/CarDeveloperOptions/res/values-bs/strings.xml
+++ b/tests/CarDeveloperOptions/res/values-bs/strings.xml
@@ -2991,7 +2991,7 @@
<string name="enhanced_4g_lte_mode_title" msgid="1624079276378568594">"VoLTE"</string>
<string name="enhanced_4g_lte_mode_title_advanced_calling" msgid="5155507161065290507">"Napredno pozivanje"</string>
<string name="enhanced_4g_lte_mode_title_4g_calling" msgid="1262729135500839141">"Pozivanje putem 4G mreže"</string>
- <string name="enhanced_4g_lte_mode_summary" msgid="4515503153340557170">"Koristi LTE usluge za poboljšanje glasovne i drugih komunikacija (preporučeno)"</string>
+ <string name="enhanced_4g_lte_mode_summary" msgid="4515503153340557170">"Koristite LTE usluge za poboljšanje glasovne i drugih komunikacija (preporučeno)"</string>
<string name="enhanced_4g_lte_mode_summary_4g_calling" msgid="1006226172299077404">"Koristi usluge 4G mreže za poboljšanje glasovne i drugih komunikacija (preporučeno)"</string>
<string name="preferred_network_type_title" msgid="1980819233332592332">"Tip preferirane mreže"</string>
<string name="preferred_network_type_summary" msgid="8828375904939960006">"LTE (preporučeno)"</string>
@@ -4494,14 +4494,14 @@
<string name="mobile_network_erase_sim_error_dialog_title" msgid="9026625253242102706">"Nije moguće izbrisati SIM"</string>
<string name="mobile_network_erase_sim_error_dialog_body" msgid="5955463559366034787">"Nije moguće izbrisati ovaj SIM zbog greške.\n\nPonovo pokrenite uređaj i pokušajte ponovo."</string>
<string name="preferred_network_mode_title" msgid="8324526359482124770">"Vrsta preferirane mreže"</string>
- <string name="preferred_network_mode_summary" msgid="388957154320426335">"Promijeni način rada mreže"</string>
+ <string name="preferred_network_mode_summary" msgid="388957154320426335">"Promijenite način rada mreže"</string>
<string name="preferred_network_mode_dialogtitle" msgid="5448698073828567428">"Vrsta preferirane mreže"</string>
<string name="carrier_settings_euicc" msgid="7723199738771996732">"Operater"</string>
<string name="carrier_settings_version" msgid="2657511289029828425">"Verzija postavki"</string>
<string name="call_category" msgid="3418535202893644015">"Pozivanje"</string>
<string name="video_calling_settings_title" msgid="8011841542502156112">"Operater video pozivanja"</string>
<string name="cdma_system_select_title" msgid="5620679296177526467">"Odabir sistema"</string>
- <string name="cdma_system_select_summary" msgid="6749131988334321244">"Promijeni način rada CDMA rominga"</string>
+ <string name="cdma_system_select_summary" msgid="6749131988334321244">"Promijenite način rada CDMA rominga"</string>
<string name="cdma_system_select_dialogtitle" msgid="7489000866289285390">"Odabir sistema"</string>
<string name="network_operator_category" msgid="9136988058829550510">"Mreža"</string>
<string name="network_select_title" msgid="9176906726897071251">"Mreža"</string>
diff --git a/tests/CarDeveloperOptions/res/values-es/strings.xml b/tests/CarDeveloperOptions/res/values-es/strings.xml
index e71fba8..e4d8025 100644
--- a/tests/CarDeveloperOptions/res/values-es/strings.xml
+++ b/tests/CarDeveloperOptions/res/values-es/strings.xml
@@ -2590,7 +2590,7 @@
<string name="sync_failed" msgid="3142663443336915051">"Error de sincronización"</string>
<string name="sync_active" msgid="1112604707180806364">"Sincronización activa"</string>
<string name="account_sync_settings_title" msgid="3344538161552327748">"Sincronización"</string>
- <string name="sync_is_failing" msgid="8284618104132302644">"En este momento hay incidencias con la sincronización. Se restablecerá en breve."</string>
+ <string name="sync_is_failing" msgid="8284618104132302644">"En este momento hay problemas con la sincronización. Se restablecerá en breve."</string>
<string name="add_account_label" msgid="4461298847239641874">"Añadir cuenta"</string>
<string name="managed_profile_not_available_label" msgid="8784246681719821917">"El perfil de trabajo aún no está disponible"</string>
<string name="work_mode_label" msgid="6845849194740195757">"Perfil de trabajo"</string>
@@ -4047,7 +4047,7 @@
<string name="display_cutout_emulation_keywords" msgid="6795671536772871439">"recorte de la pantalla, corte"</string>
<string name="overlay_option_device_default" msgid="165508753381657697">"Opción predeterminada del dispositivo"</string>
<string name="overlay_toast_failed_to_apply" msgid="5692251825129250040">"No se ha podido crear la superposición"</string>
- <string name="special_access" msgid="1453926335914696206">"Acceso especial de apps"</string>
+ <string name="special_access" msgid="1453926335914696206">"Acceso especial de aplicaciones"</string>
<plurals name="special_access_summary" formatted="false" msgid="5182092345063909346">
<item quantity="other"><xliff:g id="COUNT">%d</xliff:g> aplicaciones pueden utilizar datos sin restricción</item>
<item quantity="one">1 aplicación puede utilizar datos sin restricción</item>
diff --git a/tests/CarDeveloperOptions/res/values-fi/strings.xml b/tests/CarDeveloperOptions/res/values-fi/strings.xml
index fc6363f..eadaca7 100644
--- a/tests/CarDeveloperOptions/res/values-fi/strings.xml
+++ b/tests/CarDeveloperOptions/res/values-fi/strings.xml
@@ -942,7 +942,7 @@
<string name="wifi_dpp_scan_open_network_qr_code_with_another_device" msgid="572011882416511818">"Yhdistä <xliff:g id="SSID">%1$s</xliff:g> skannaamalla tämä QR-koodi"</string>
<string name="wifi_dpp_could_not_detect_valid_qr_code" msgid="27667719861826438">"QR-koodin luku epäonnistui. Keskitä koodi ja yritä uudelleen."</string>
<string name="wifi_dpp_failure_authentication_or_configuration" msgid="9142051662156233679">"Yritä uudelleen. Jos ongelma ei ratkea, ota yhteyttä laitteen valmistajaan"</string>
- <string name="wifi_dpp_failure_not_compatible" msgid="4320027179973678283">"Jokin meni pieleen"</string>
+ <string name="wifi_dpp_failure_not_compatible" msgid="4320027179973678283">"Jotain meni pieleen"</string>
<string name="wifi_dpp_failure_timeout" msgid="5060065168142109420">"Varmista, että laite on liitetty virtalähteeseen, ladattu ja päällä"</string>
<string name="wifi_dpp_failure_generic" msgid="7840142544736640189">"Varmista, että laite on liitetty virtalähteeseen, ladattu ja päällä. Jos ongelma ei ratkea, ota yhteyttä laitteen valmistajaan"</string>
<string name="wifi_dpp_failure_not_supported" msgid="111779621766171626">"Tämä laite ei tue <xliff:g id="SSID">%1$s</xliff:g>:n lisäämistä"</string>
diff --git a/tests/CarDeveloperOptions/res/values-fr/strings.xml b/tests/CarDeveloperOptions/res/values-fr/strings.xml
index fe052fd..2d5a459 100644
--- a/tests/CarDeveloperOptions/res/values-fr/strings.xml
+++ b/tests/CarDeveloperOptions/res/values-fr/strings.xml
@@ -3781,7 +3781,7 @@
<string name="running_frequency" msgid="7545170806968474449">"Fréquence"</string>
<string name="memory_maximum_usage" msgid="4734981118293469479">"Utilisation maximale"</string>
<string name="no_data_usage" msgid="903383745620135746">"Aucune donnée utilisée"</string>
- <string name="zen_access_warning_dialog_title" msgid="7704910289810337055">"Autoriser l\'accès au mode Ne pas déranger pour <xliff:g id="APP">%1$s</xliff:g> ?"</string>
+ <string name="zen_access_warning_dialog_title" msgid="7704910289810337055">"Autoriser \"<xliff:g id="APP">%1$s</xliff:g>\" à accéder au mode Ne pas déranger ?"</string>
<string name="zen_access_warning_dialog_summary" msgid="2717755746850874577">"L\'application disposera d\'une autorisation d\'activation ou de désactivation du mode Ne pas déranger et de modification des paramètres associés."</string>
<string name="zen_access_disabled_package_warning" msgid="7086237569177576966">"Doit rester activé, car l\'accès aux notifications est activé"</string>
<string name="zen_access_revoke_warning_dialog_title" msgid="6850994585577513299">"Révoquer l\'accès au mode Ne pas déranger pour <xliff:g id="APP">%1$s</xliff:g> ?"</string>
diff --git a/tests/CarDeveloperOptions/res/values-it/strings.xml b/tests/CarDeveloperOptions/res/values-it/strings.xml
index 22a0378..a43f6ad 100644
--- a/tests/CarDeveloperOptions/res/values-it/strings.xml
+++ b/tests/CarDeveloperOptions/res/values-it/strings.xml
@@ -3820,7 +3820,7 @@
<string name="write_settings_description" msgid="2536706293042882500">"Questa autorizzazione consente a un\'app di modificare le impostazioni di sistema."</string>
<string name="write_settings_on" msgid="7328986337962635118">"Sì"</string>
<string name="write_settings_off" msgid="5708257434958406202">"No"</string>
- <string name="external_source_switch_title" msgid="5947220058496373178">"Consenti da questa fonte"</string>
+ <string name="external_source_switch_title" msgid="5947220058496373178">"Consenti da questa origine"</string>
<string name="camera_gesture_title" msgid="899403310746415135">"Doppia rotazione per fotocamera"</string>
<string name="camera_gesture_desc" msgid="7751841175916789527">"Apri l\'app Fotocamera ruotando due volte il polso"</string>
<string name="camera_double_tap_power_gesture_title" msgid="8874747801078147525">"Premi due volte tasto di acc. per fotoc."</string>
diff --git a/tests/CarDeveloperOptions/res/values-nl/strings.xml b/tests/CarDeveloperOptions/res/values-nl/strings.xml
index e009d08..f1c2d86 100644
--- a/tests/CarDeveloperOptions/res/values-nl/strings.xml
+++ b/tests/CarDeveloperOptions/res/values-nl/strings.xml
@@ -2658,8 +2658,8 @@
<string name="data_usage_menu_split_4g" msgid="2264683155484246409">"4G-gebruik apart weergeven"</string>
<string name="data_usage_menu_show_wifi" msgid="8444311679299008486">"Wifi weergeven"</string>
<string name="data_usage_menu_hide_wifi" msgid="1808008314306824090">"Wifi verbergen"</string>
- <string name="data_usage_menu_show_ethernet" msgid="2130574690318410238">"Ethernet-gebruik weergeven"</string>
- <string name="data_usage_menu_hide_ethernet" msgid="1191233197312414533">"Ethernet-gebruik verbergen"</string>
+ <string name="data_usage_menu_show_ethernet" msgid="2130574690318410238">"Ethernetgebruik weergeven"</string>
+ <string name="data_usage_menu_hide_ethernet" msgid="1191233197312414533">"Ethernetgebruik verbergen"</string>
<string name="data_usage_menu_metered" msgid="3087525150259956831">"Netwerkbeperkingen"</string>
<string name="data_usage_menu_auto_sync" msgid="3350154877737572146">"Gegevens automatisch synchroniseren"</string>
<string name="data_usage_menu_sim_cards" msgid="8508154611676507088">"Simkaarten"</string>
@@ -3931,12 +3931,12 @@
<string name="cellular_data_usage" msgid="1236562234207782386">"Gebruik van mobiele data"</string>
<string name="app_cellular_data_usage" msgid="8499761516172121957">"Datagebruik van app"</string>
<string name="wifi_data_usage" msgid="275569900562265895">"Wifi-datagebruik"</string>
- <string name="ethernet_data_usage" msgid="747614925362556718">"Ethernet-datagebruik"</string>
+ <string name="ethernet_data_usage" msgid="747614925362556718">"Ethernetdatagebruik"</string>
<string name="wifi" msgid="1586738489862966138">"Wifi"</string>
<string name="ethernet" msgid="2365753635113154667">"Ethernet"</string>
<string name="cell_data_template" msgid="5473177306229738078">"<xliff:g id="AMOUNT">^1</xliff:g> mobiele data"</string>
<string name="wifi_data_template" msgid="3146090439147042068">"<xliff:g id="AMOUNT">^1</xliff:g> wifi-data"</string>
- <string name="ethernet_data_template" msgid="6414118030827090119">"<xliff:g id="AMOUNT">^1</xliff:g> Ethernet-data"</string>
+ <string name="ethernet_data_template" msgid="6414118030827090119">"<xliff:g id="AMOUNT">^1</xliff:g> ethernetdata"</string>
<string name="billing_cycle" msgid="5740717948341713190">"Datawaarschuwing en -limiet"</string>
<string name="app_usage_cycle" msgid="213483325132959663">"Gebruikscyclus app-data"</string>
<string name="cell_data_warning" msgid="8902740337286652689">"<xliff:g id="ID_1">^1</xliff:g> datawaarschuwing"</string>
diff --git a/tests/carservice_test/src/com/android/car/MockedCarTestBase.java b/tests/carservice_test/src/com/android/car/MockedCarTestBase.java
index 5989000..69eba19 100644
--- a/tests/carservice_test/src/com/android/car/MockedCarTestBase.java
+++ b/tests/carservice_test/src/com/android/car/MockedCarTestBase.java
@@ -56,6 +56,7 @@
import com.android.car.vehiclehal.test.MockedVehicleHal.StaticPropertyHandler;
import com.android.car.vehiclehal.test.MockedVehicleHal.VehicleHalPropertyHandler;
import com.android.car.vehiclehal.test.VehiclePropConfigBuilder;
+import com.android.car.vms.VmsClientManager;
import org.junit.After;
import org.junit.Before;
@@ -185,6 +186,10 @@
return (CarPackageManagerService) mCarImpl.getCarService(Car.PACKAGE_SERVICE);
}
+ public VmsClientManager getVmsClientManager() {
+ return (VmsClientManager) mCarImpl.getCarInternalService(ICarImpl.INTERNAL_VMS_MANAGER);
+ }
+
protected Context getCarServiceContext() {
return getContext();
}
diff --git a/tests/carservice_test/src/com/android/car/MockedVmsTestBase.java b/tests/carservice_test/src/com/android/car/MockedVmsTestBase.java
index 450b9e9..ccc2e6c 100644
--- a/tests/carservice_test/src/com/android/car/MockedVmsTestBase.java
+++ b/tests/carservice_test/src/com/android/car/MockedVmsTestBase.java
@@ -18,6 +18,7 @@
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
+import android.app.ActivityManager;
import android.car.Car;
import android.car.VehicleAreaType;
import android.car.vms.VmsAvailableLayers;
@@ -25,7 +26,6 @@
import android.car.vms.VmsPublisherClientService;
import android.car.vms.VmsSubscriberManager;
import android.car.vms.VmsSubscriptionState;
-import android.content.Intent;
import android.hardware.automotive.vehicle.V2_0.VehiclePropValue;
import android.hardware.automotive.vehicle.V2_0.VehicleProperty;
import android.hardware.automotive.vehicle.V2_0.VehiclePropertyAccess;
@@ -34,7 +34,6 @@
import android.hardware.automotive.vehicle.V2_0.VmsBaseMessageIntegerValuesIndex;
import android.hardware.automotive.vehicle.V2_0.VmsMessageType;
import android.hardware.automotive.vehicle.V2_0.VmsStartSessionMessageIntegerValuesIndex;
-import android.os.UserHandle;
import android.util.Log;
import android.util.Pair;
@@ -83,8 +82,7 @@
@Before
public void setUpVms() throws Exception {
// Trigger VmsClientManager to bind to the MockPublisherClient
- getContext().sendBroadcastAsUser(new Intent(Intent.ACTION_USER_UNLOCKED), UserHandle.ALL);
-
+ getVmsClientManager().mUserCallback.onSwitchUser(ActivityManager.getCurrentUser());
mVmsSubscriberManager = (VmsSubscriberManager) getCar().getCarManager(
Car.VMS_SUBSCRIBER_SERVICE);
mSubscriberClient = new MockSubscriberClient();
diff --git a/tests/carservice_test/src/com/android/car/VmsPublisherClientPermissionTest.java b/tests/carservice_test/src/com/android/car/VmsPublisherClientPermissionTest.java
index 0e3adde..0bb9d4f 100644
--- a/tests/carservice_test/src/com/android/car/VmsPublisherClientPermissionTest.java
+++ b/tests/carservice_test/src/com/android/car/VmsPublisherClientPermissionTest.java
@@ -21,10 +21,9 @@
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
+import android.app.ActivityManager;
import android.car.vms.VmsPublisherClientService;
import android.car.vms.VmsSubscriptionState;
-import android.content.Intent;
-import android.os.UserHandle;
import org.junit.Before;
import org.junit.Test;
@@ -98,7 +97,7 @@
@Before
public void triggerClientBinding() {
- getContext().sendBroadcastAsUser(new Intent(Intent.ACTION_USER_UNLOCKED), UserHandle.ALL);
+ getVmsClientManager().mUserCallback.onSwitchUser(ActivityManager.getCurrentUser());
}
@Test
diff --git a/tests/carservice_unit_test/src/com/android/car/vms/VmsClientManagerTest.java b/tests/carservice_unit_test/src/com/android/car/vms/VmsClientManagerTest.java
index 68769c8..c7d6489 100644
--- a/tests/carservice_unit_test/src/com/android/car/vms/VmsClientManagerTest.java
+++ b/tests/carservice_unit_test/src/com/android/car/vms/VmsClientManagerTest.java
@@ -25,7 +25,6 @@
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.argThat;
import static org.mockito.ArgumentMatchers.eq;
-import static org.mockito.ArgumentMatchers.isNull;
import static org.mockito.ArgumentMatchers.same;
import static org.mockito.Mockito.atLeast;
import static org.mockito.Mockito.atMost;
@@ -38,7 +37,6 @@
import static org.mockito.Mockito.when;
import android.car.Car;
-import android.car.userlib.CarUserManagerHelper;
import android.car.vms.IVmsPublisherClient;
import android.car.vms.IVmsPublisherService;
import android.car.vms.IVmsSubscriberClient;
@@ -48,7 +46,6 @@
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
-import android.content.IntentFilter;
import android.content.ServiceConnection;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
@@ -95,8 +92,6 @@
private static final String USER_CLIENT_NAME =
"com.google.android.apps.vms.test/com.google.android.apps.vms.test.VmsUserClient U=10";
private static final int USER_ID_U11 = 11;
- private static final String USER_CLIENT_NAME_U11 =
- "com.google.android.apps.vms.test/com.google.android.apps.vms.test.VmsUserClient U=11";
private static final String TEST_PACKAGE = "test.package1";
private static final String HAL_CLIENT_NAME = "HalClient";
@@ -123,8 +118,6 @@
private UserManager mUserManager;
@Mock
private CarUserService mUserService;
- @Mock
- private CarUserManagerHelper mUserManagerHelper;
@Mock
private VmsBrokerService mBrokerService;
@@ -207,17 +200,15 @@
new String[]{ USER_CLIENT });
when(mContext.getSystemService(eq(Context.USER_SERVICE))).thenReturn(mUserManager);
- when(mUserManagerHelper.getCurrentForegroundUserId())
- .thenAnswer(invocation -> mForegroundUserId);
-
- mForegroundUserId = USER_ID;
- mCallingAppUid = UserHandle.getUid(USER_ID, 0);
mClientManager = new VmsClientManager(mContext, mStatsService, mUserService,
- mUserManagerHelper, mBrokerService, mHal, mHandler, () -> mCallingAppUid);
+ mBrokerService, mHal, mHandler, () -> mCallingAppUid);
verify(mHal).setClientManager(mClientManager);
mClientManager.setPublisherService(mPublisherService);
+ notifyUserSwitched(USER_ID, false);
+ mCallingAppUid = UserHandle.getUid(USER_ID, 0);
+
when(mSubscriberClient1.asBinder()).thenReturn(mSubscriberBinder1);
when(mSubscriberClient2.asBinder()).thenReturn(mSubscriberBinder2);
@@ -225,7 +216,7 @@
}
@After
- public void tearDown() throws Exception {
+ public void tearDown() {
verify(mContext, atLeast(0)).getSystemService(eq(Context.USER_SERVICE));
verify(mContext, atLeast(0)).getResources();
verify(mContext, atLeast(0)).getPackageManager();
@@ -239,15 +230,8 @@
// Verify registration of system user unlock listener
verify(mUserService).runOnUser0Unlock(mClientManager.mSystemUserUnlockedListener);
-
- // Verify registration of user switch receiver
- ArgumentCaptor<IntentFilter> userFilterCaptor = ArgumentCaptor.forClass(IntentFilter.class);
- verify(mContext).registerReceiverAsUser(eq(mClientManager.mUserSwitchReceiver),
- eq(UserHandle.ALL), userFilterCaptor.capture(), isNull(), isNull());
- IntentFilter userEventFilter = userFilterCaptor.getValue();
- assertEquals(2, userEventFilter.countActions());
- assertTrue(userEventFilter.hasAction(Intent.ACTION_USER_SWITCHED));
- assertTrue(userEventFilter.hasAction(Intent.ACTION_USER_UNLOCKED));
+ // Verify user callback is added
+ verify(mUserService).addUserCallback(eq(mClientManager.mUserCallback));
}
@Test
@@ -255,7 +239,7 @@
mClientManager.release();
// Verify user switch receiver is unregistered
- verify(mContext).unregisterReceiver(mClientManager.mUserSwitchReceiver);
+ verify(mUserService).removeUserCallback(mClientManager.mUserCallback);
}
@Test
@@ -328,6 +312,14 @@
}
@Test
+ public void testUserUnlocked_OtherUserUnlocked() {
+ notifyUserUnlocked(USER_ID_U11, true);
+
+ // Process will not be bound
+ verifyUserBind(0);
+ }
+
+ @Test
public void testUserUnlocked_ClientNotFound() throws Exception {
when(mPackageManager.getServiceInfo(eq(USER_CLIENT_COMPONENT), anyInt()))
.thenThrow(new PackageManager.NameNotFoundException());
@@ -761,6 +753,7 @@
resetContext();
reset(mPublisherService);
+ notifyUserSwitched(USER_ID_U11, false);
notifyUserUnlocked(USER_ID_U11, true);
verify(mContext).unbindService(connection);
@@ -780,6 +773,7 @@
resetContext();
reset(mPublisherService);
+ notifyUserSwitched(USER_ID_U11, false);
notifyUserUnlocked(UserHandle.USER_SYSTEM, true);
verify(mContext).unbindService(connection);
@@ -796,6 +790,7 @@
ServiceConnection connection = mConnectionCaptor.getValue();
resetContext();
+ notifyUserSwitched(USER_ID_U11, false);
notifyUserUnlocked(USER_ID_U11, true);
verify(mContext).unbindService(connection);
@@ -924,9 +919,7 @@
public void testOnUserSwitch_RemoveSubscriber() {
mClientManager.addSubscriber(mSubscriberClient1);
- mForegroundUserId = USER_ID_U11;
- mClientManager.mUserSwitchReceiver.onReceive(mContext, new Intent());
-
+ notifyUserSwitched(USER_ID_U11, false);
verify(mBrokerService).removeDeadSubscriber(mSubscriberClient1);
assertEquals(UNKNOWN_PACKAGE, mClientManager.getPackageName(mSubscriberClient1));
assertEquals(-1, mClientManager.getSubscriberUid(mSubscriberClient1));
@@ -937,8 +930,7 @@
public void testOnUserSwitch_RemoveSubscriber_AddNewSubscriber() {
mClientManager.addSubscriber(mSubscriberClient1);
- mForegroundUserId = USER_ID_U11;
- mClientManager.mUserSwitchReceiver.onReceive(mContext, new Intent());
+ notifyUserSwitched(USER_ID_U11, false);
verify(mBrokerService).removeDeadSubscriber(mSubscriberClient1);
mCallingAppUid = UserHandle.getUid(USER_ID_U11, 0);
@@ -962,8 +954,7 @@
mClientManager.addSubscriber(mSubscriberClient2);
- mForegroundUserId = USER_ID_U11;
- mClientManager.mUserSwitchReceiver.onReceive(mContext, new Intent());
+ notifyUserSwitched(USER_ID_U11, false);
verify(mBrokerService).removeDeadSubscriber(mSubscriberClient1);
verify(mBrokerService, never()).removeDeadSubscriber(mSubscriberClient2);
@@ -979,8 +970,7 @@
verify(mHalClientLog).logConnectionState(ConnectionState.CONNECTED);
reset(mPublisherService);
- mForegroundUserId = USER_ID_U11;
- mClientManager.mUserSwitchReceiver.onReceive(mContext, new Intent());
+ notifyUserSwitched(USER_ID_U11, false);
verify(mBrokerService, never()).removeDeadSubscriber(subscriberClient);
assertEquals(HAL_CLIENT_NAME, mClientManager.getPackageName(subscriberClient));
@@ -1045,23 +1035,14 @@
}
private void notifyUserSwitched(int foregroundUserId, boolean isForegroundUserUnlocked) {
- notifyUserAction(foregroundUserId, isForegroundUserUnlocked, Intent.ACTION_USER_SWITCHED);
+ when(mUserManager.isUserUnlocked(foregroundUserId)).thenReturn(isForegroundUserUnlocked);
+ mForegroundUserId = foregroundUserId; // Member variable used by verifyUserBind()
+ mClientManager.mUserCallback.onSwitchUser(foregroundUserId);
}
private void notifyUserUnlocked(int foregroundUserId, boolean isForegroundUserUnlocked) {
- notifyUserAction(foregroundUserId, isForegroundUserUnlocked, Intent.ACTION_USER_UNLOCKED);
- }
-
- // Sets the current foreground user + unlock state and dispatches the specified intent action
- private void notifyUserAction(int foregroundUserId, boolean isForegroundUserUnlocked,
- String action) {
- mForegroundUserId = foregroundUserId; // Member variable used by verifyUserBind()
- when(mUserManagerHelper.getCurrentForegroundUserId()).thenReturn(foregroundUserId);
-
- reset(mUserManager);
when(mUserManager.isUserUnlocked(foregroundUserId)).thenReturn(isForegroundUserUnlocked);
-
- mClientManager.mUserSwitchReceiver.onReceive(mContext, new Intent(action));
+ mClientManager.mUserCallback.onUserLockChanged(foregroundUserId, isForegroundUserUnlocked);
}
private void verifySystemBind(int times) {