Sync tieProfileLockIfNecessary() with internal main am: ada6ce9436
Original change: https://android-review.googlesource.com/c/platform/frameworks/base/+/2871508
Change-Id: I09431365f49d72fad8d0b755de3026de5f6380df
Signed-off-by: Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
diff --git a/core/java/android/os/HidlSupport.java b/core/java/android/os/HidlSupport.java
index 7716055..91b796a 100644
--- a/core/java/android/os/HidlSupport.java
+++ b/core/java/android/os/HidlSupport.java
@@ -218,13 +218,6 @@
@SystemApi
public static native int getPidIfSharable();
- /**
- * Return true if HIDL is supported on this device and false if not.
- *
- * @hide
- */
- public static native boolean isHidlSupported();
-
/** @hide */
public HidlSupport() {}
}
diff --git a/core/java/android/os/HwBinder.java b/core/java/android/os/HwBinder.java
index bc19655..feed208 100644
--- a/core/java/android/os/HwBinder.java
+++ b/core/java/android/os/HwBinder.java
@@ -18,7 +18,6 @@
import android.annotation.SystemApi;
import android.compat.annotation.UnsupportedAppUsage;
-import android.util.Log;
import libcore.util.NativeAllocationRegistry;
@@ -79,17 +78,6 @@
String iface,
String serviceName)
throws RemoteException, NoSuchElementException {
- if (!HidlSupport.isHidlSupported()
- && (iface.equals("android.hidl.manager@1.0::IServiceManager")
- || iface.equals("android.hidl.manager@1.1::IServiceManager")
- || iface.equals("android.hidl.manager@1.2::IServiceManager"))) {
- Log.i(
- TAG,
- "Replacing Java hwservicemanager with a fake HwNoService"
- + " because HIDL is not supported on this device.");
- return new HwNoService();
- }
-
return getService(iface, serviceName, false /* retry */);
}
/**
diff --git a/core/java/android/os/HwNoService.java b/core/java/android/os/HwNoService.java
deleted file mode 100644
index 117c3ad..0000000
--- a/core/java/android/os/HwNoService.java
+++ /dev/null
@@ -1,52 +0,0 @@
-/*
- * Copyright (C) 2023 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT 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.os;
-
-/**
- * A fake hwservicemanager that is used locally when HIDL isn't supported on the device.
- *
- * @hide
- */
-final class HwNoService implements IHwBinder, IHwInterface {
- /** @hide */
- @Override
- public void transact(int code, HwParcel request, HwParcel reply, int flags) {}
-
- /** @hide */
- @Override
- public IHwInterface queryLocalInterface(String descriptor) {
- return new HwNoService();
- }
-
- /** @hide */
- @Override
- public boolean linkToDeath(DeathRecipient recipient, long cookie) {
- return true;
- }
-
- /** @hide */
- @Override
- public boolean unlinkToDeath(DeathRecipient recipient) {
- return true;
- }
-
- /** @hide */
- @Override
- public IHwBinder asBinder() {
- return this;
- }
-}
diff --git a/core/java/android/service/persistentdata/OWNERS b/core/java/android/service/persistentdata/OWNERS
new file mode 100644
index 0000000..6dfb888
--- /dev/null
+++ b/core/java/android/service/persistentdata/OWNERS
@@ -0,0 +1 @@
+include /services/core/java/com/android/server/pdb/OWNERS
diff --git a/core/jni/android_os_HidlSupport.cpp b/core/jni/android_os_HidlSupport.cpp
index 3e51e93..e3602d8 100644
--- a/core/jni/android_os_HidlSupport.cpp
+++ b/core/jni/android_os_HidlSupport.cpp
@@ -15,7 +15,6 @@
*/
#include <hidl/HidlTransportSupport.h>
-#include <hidl/ServiceManagement.h>
#include <nativehelper/JNIHelp.h>
#include "core_jni_helpers.h"
@@ -25,13 +24,8 @@
return android::hardware::details::getPidIfSharable();
}
-static jboolean android_os_HidlSupport_isHidlSupported(JNIEnv*, jclass) {
- return android::hardware::isHidlSupported();
-}
-
static const JNINativeMethod gHidlSupportMethods[] = {
- {"getPidIfSharable", "()I", (void*)android_os_HidlSupport_getPidIfSharable},
- {"isHidlSupported", "()Z", (void*)android_os_HidlSupport_isHidlSupported},
+ {"getPidIfSharable", "()I", (void*)android_os_HidlSupport_getPidIfSharable},
};
const char* const kHidlSupportPathName = "android/os/HidlSupport";
diff --git a/core/jni/com_android_internal_os_ZygoteCommandBuffer.cpp b/core/jni/com_android_internal_os_ZygoteCommandBuffer.cpp
index 2b5b8f7..3377362 100644
--- a/core/jni/com_android_internal_os_ZygoteCommandBuffer.cpp
+++ b/core/jni/com_android_internal_os_ZygoteCommandBuffer.cpp
@@ -63,6 +63,7 @@
std::optional<std::pair<char*, char*>> readLine(FailFn fail_fn) {
char* result = mBuffer + mNext;
while (true) {
+ // We have scanned up to, but not including mNext for this line's newline.
if (mNext == mEnd) {
if (mEnd == MAX_COMMAND_BYTES) {
return {};
@@ -89,7 +90,7 @@
} else {
mNext = nl - mBuffer + 1;
if (--mLinesLeft < 0) {
- fail_fn("ZygoteCommandBuffer.readLine attempted to read past mEnd of command");
+ fail_fn("ZygoteCommandBuffer.readLine attempted to read past end of command");
}
return std::make_pair(result, nl);
}
@@ -125,8 +126,8 @@
mEnd += lineLen + 1;
}
- // Clear mBuffer, start reading new command, return the number of arguments, leaving mBuffer
- // positioned at the beginning of first argument. Return 0 on EOF.
+ // Start reading new command, return the number of arguments, leaving mBuffer positioned at the
+ // beginning of first argument. Return 0 on EOF.
template<class FailFn>
int getCount(FailFn fail_fn) {
mLinesLeft = 1;
@@ -451,11 +452,14 @@
(CREATE_ERROR("Write unexpectedly returned short: %d < 5", res));
}
}
- // Clear buffer and get count from next command.
- n_buffer->clear();
for (;;) {
+ // Clear buffer and get count from next command.
+ n_buffer->clear();
// Poll isn't strictly necessary for now. But without it, disconnect is hard to detect.
int poll_res = TEMP_FAILURE_RETRY(poll(fd_structs, 2, -1 /* infinite timeout */));
+ if (poll_res < 0) {
+ fail_fn_z(CREATE_ERROR("Poll failed: %d: %s", errno, strerror(errno)));
+ }
if ((fd_structs[SESSION_IDX].revents & POLLIN) != 0) {
if (n_buffer->getCount(fail_fn_z) != 0) {
break;
diff --git a/media/OWNERS b/media/OWNERS
index 4a6648e..994a7b8 100644
--- a/media/OWNERS
+++ b/media/OWNERS
@@ -21,7 +21,6 @@
include platform/frameworks/av:/media/janitors/media_solutions_OWNERS
# SEO
-sungsoo@google.com
# SEA/KIR/BVE
jtinker@google.com
diff --git a/media/java/android/media/OWNERS b/media/java/android/media/OWNERS
index bbe5e06..058c5be 100644
--- a/media/java/android/media/OWNERS
+++ b/media/java/android/media/OWNERS
@@ -2,7 +2,6 @@
fgoldfain@google.com
elaurent@google.com
lajos@google.com
-sungsoo@google.com
jmtrivi@google.com
# go/android-fwk-media-solutions for info on areas of ownership.
diff --git a/services/core/java/com/android/server/audio/AudioService.java b/services/core/java/com/android/server/audio/AudioService.java
index bedfd1c..b555a52 100644
--- a/services/core/java/com/android/server/audio/AudioService.java
+++ b/services/core/java/com/android/server/audio/AudioService.java
@@ -37,7 +37,6 @@
import static android.provider.Settings.Secure.VOLUME_HUSH_MUTE;
import static android.provider.Settings.Secure.VOLUME_HUSH_OFF;
import static android.provider.Settings.Secure.VOLUME_HUSH_VIBRATE;
-
import static com.android.server.audio.SoundDoseHelper.ACTION_CHECK_MUSIC_ACTIVE;
import static com.android.server.utils.EventLogger.Event.ALOGE;
import static com.android.server.utils.EventLogger.Event.ALOGI;
@@ -73,7 +72,6 @@
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
-import android.content.pm.ResolveInfo;
import android.content.pm.UserInfo;
import android.content.res.Configuration;
import android.content.res.Resources;
@@ -263,6 +261,8 @@
private final SettingsAdapter mSettings;
private final AudioPolicyFacade mAudioPolicy;
+ private final MusicFxHelper mMusicFxHelper;
+
/** Debug audio mode */
protected static final boolean DEBUG_MODE = false;
@@ -403,9 +403,15 @@
private static final int MSG_CONFIGURATION_CHANGED = 54;
private static final int MSG_BROADCAST_MASTER_MUTE = 55;
- /** Messages handled by the {@link SoundDoseHelper}. */
+ /**
+ * Messages handled by the {@link SoundDoseHelper}, do not exceed
+ * {@link MUSICFX_HELPER_MSG_START}.
+ */
/*package*/ static final int SAFE_MEDIA_VOLUME_MSG_START = 1000;
+ /** Messages handled by the {@link MusicFxHelper}. */
+ /*package*/ static final int MUSICFX_HELPER_MSG_START = 1100;
+
// start of messages handled under wakelock
// these messages can only be queued, i.e. sent with queueMsgUnderWakeLock(),
// and not with sendMsg(..., ..., SENDMSG_QUEUE, ...)
@@ -1268,6 +1274,8 @@
0 /* arg1 */, 0 /* arg2 */, null /* obj */, 0 /* delay */);
queueMsgUnderWakeLock(mAudioHandler, MSG_INIT_SPATIALIZER,
0 /* arg1 */, 0 /* arg2 */, null /* obj */, 0 /* delay */);
+
+ mMusicFxHelper = new MusicFxHelper(mContext, mAudioHandler);
}
private void initVolumeStreamStates() {
@@ -4946,7 +4954,7 @@
private void setMasterMuteInternalNoCallerCheck(
boolean mute, int flags, int userId, String eventSource) {
if (DEBUG_VOL) {
- Log.d(TAG, TextUtils.formatSimple("Master mute %s, %d, user=%d from %s",
+ Log.d(TAG, TextUtils.formatSimple("Master mute %s, flags 0x%x, userId=%d from %s",
mute, flags, userId, eventSource));
}
@@ -9409,11 +9417,21 @@
onConfigurationChanged();
break;
+ case MusicFxHelper.MSG_EFFECT_CLIENT_GONE:
+ mMusicFxHelper.handleMessage(msg);
+ break;
+
+ case SoundDoseHelper.MSG_CONFIGURE_SAFE_MEDIA:
+ case SoundDoseHelper.MSG_CONFIGURE_SAFE_MEDIA_FORCED:
+ case SoundDoseHelper.MSG_PERSIST_SAFE_VOLUME_STATE:
+ case SoundDoseHelper.MSG_PERSIST_MUSIC_ACTIVE_MS:
+ case SoundDoseHelper.MSG_PERSIST_CSD_VALUES:
+ case SoundDoseHelper.MSG_CSD_UPDATE_ATTENUATION:
+ mSoundDoseHelper.handleMessage(msg);
+ break;
+
default:
- if (msg.what >= SAFE_MEDIA_VOLUME_MSG_START) {
- // msg could be for the SoundDoseHelper
- mSoundDoseHelper.handleMessage(msg);
- }
+ Log.e(TAG, "Unsupported msgId " + msg.what);
}
}
}
@@ -9648,7 +9666,7 @@
}
} else if (action.equals(AudioEffect.ACTION_OPEN_AUDIO_EFFECT_CONTROL_SESSION) ||
action.equals(AudioEffect.ACTION_CLOSE_AUDIO_EFFECT_CONTROL_SESSION)) {
- handleAudioEffectBroadcast(context, intent);
+ mMusicFxHelper.handleAudioEffectBroadcast(context, intent);
} else if (action.equals(Intent.ACTION_PACKAGES_SUSPENDED)) {
final int[] suspendedUids = intent.getIntArrayExtra(Intent.EXTRA_CHANGED_UID_LIST);
final String[] suspendedPackages =
@@ -9703,27 +9721,6 @@
}
} // end class AudioServiceUserRestrictionsListener
- private void handleAudioEffectBroadcast(Context context, Intent intent) {
- String target = intent.getPackage();
- if (target != null) {
- Log.w(TAG, "effect broadcast already targeted to " + target);
- return;
- }
- intent.addFlags(Intent.FLAG_INCLUDE_STOPPED_PACKAGES);
- // TODO this should target a user-selected panel
- List<ResolveInfo> ril = context.getPackageManager().queryBroadcastReceivers(
- intent, 0 /* flags */);
- if (ril != null && ril.size() != 0) {
- ResolveInfo ri = ril.get(0);
- if (ri != null && ri.activityInfo != null && ri.activityInfo.packageName != null) {
- intent.setPackage(ri.activityInfo.packageName);
- context.sendBroadcastAsUser(intent, UserHandle.ALL);
- return;
- }
- }
- Log.w(TAG, "couldn't find receiver package for effect intent");
- }
-
private void killBackgroundUserProcessesWithRecordAudioPermission(UserInfo oldUser) {
PackageManager pm = mContext.getPackageManager();
// Find the home activity of the user. It should not be killed to avoid expensive restart,
@@ -13178,6 +13175,11 @@
return mDeviceBroker.getDeviceSensorUuid(device);
}
+ @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
+ MusicFxHelper getMusicFxHelper() {
+ return mMusicFxHelper;
+ }
+
//======================
// misc
//======================
diff --git a/services/core/java/com/android/server/audio/MusicFxHelper.java b/services/core/java/com/android/server/audio/MusicFxHelper.java
new file mode 100644
index 0000000..85b3b49
--- /dev/null
+++ b/services/core/java/com/android/server/audio/MusicFxHelper.java
@@ -0,0 +1,410 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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.server.audio;
+
+import static android.content.pm.PackageManager.MATCH_ANY_USER;
+
+import static com.android.server.audio.AudioService.MUSICFX_HELPER_MSG_START;
+
+import android.annotation.NonNull;
+import android.annotation.RequiresPermission;
+import android.app.ActivityManager;
+import android.app.IUidObserver;
+import android.app.UidObserver;
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.Intent;
+import android.content.ServiceConnection;
+import android.content.pm.PackageManager;
+import android.content.pm.ResolveInfo;
+import android.content.pm.UserInfo;
+import android.media.AudioManager;
+import android.media.audiofx.AudioEffect;
+import android.os.Binder;
+import android.os.IBinder;
+import android.os.Message;
+import android.os.RemoteException;
+import android.os.UserHandle;
+import android.util.Log;
+import android.util.SparseArray;
+
+import com.android.internal.annotations.GuardedBy;
+import com.android.server.audio.AudioService.AudioHandler;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * MusicFx management.
+ */
+public class MusicFxHelper {
+ private static final String TAG = "AS.MusicFxHelper";
+
+ @NonNull private final Context mContext;
+
+ @NonNull private final AudioHandler mAudioHandler;
+
+ // Synchronization UidSessionMap access between UidObserver and AudioServiceBroadcastReceiver.
+ private final Object mClientUidMapLock = new Object();
+
+ private final String mPackageName = this.getClass().getPackage().getName();
+
+ private final String mMusicFxPackageName = "com.android.musicfx";
+
+ /*package*/ static final int MSG_EFFECT_CLIENT_GONE = MUSICFX_HELPER_MSG_START + 1;
+
+ // The binder token identifying the UidObserver registration.
+ private IBinder mUidObserverToken = null;
+
+ // Package name and list of open audio sessions for this package
+ private static class PackageSessions {
+ String mPackageName;
+ List<Integer> mSessions;
+ }
+
+ /*
+ * Override of SparseArray class to add bind/unbind and UID observer in the put/remove methods.
+ *
+ * put:
+ * - the first key/value set put into MySparseArray will trigger a procState bump (bindService)
+ * - if no valid observer token exist, will call registerUidObserver for put
+ * - for each new uid put into array, it will be added to uid observer list
+ *
+ * remove:
+ * - for each uid removed from array, it will be removed from uid observer list as well
+ * - if it's the last uid in array, no more MusicFx procState bump (unbindService), uid
+ * observer will also be removed, and observer token reset to null
+ */
+ private class MySparseArray extends SparseArray<PackageSessions> {
+ private final String mMusicFxPackageName = "com.android.musicfx";
+
+ @RequiresPermission(anyOf = {
+ android.Manifest.permission.INTERACT_ACROSS_USERS_FULL,
+ android.Manifest.permission.INTERACT_ACROSS_USERS,
+ android.Manifest.permission.INTERACT_ACROSS_PROFILES
+ })
+ @Override
+ public void put(int uid, PackageSessions pkgSessions) {
+ if (size() == 0) {
+ int procState = ActivityManager.PROCESS_STATE_NONEXISTENT;
+ try {
+ procState = ActivityManager.getService().getPackageProcessState(
+ mMusicFxPackageName, mPackageName);
+ } catch (RemoteException e) {
+ Log.e(TAG, "RemoteException with getPackageProcessState: " + e);
+ }
+ if (procState > ActivityManager.PROCESS_STATE_IMPORTANT_FOREGROUND) {
+ Intent bindIntent = new Intent().setClassName(mMusicFxPackageName,
+ "com.android.musicfx.KeepAliveService");
+ mContext.bindServiceAsUser(
+ bindIntent, mMusicFxBindConnection, Context.BIND_AUTO_CREATE,
+ UserHandle.of(getCurrentUserId()));
+ Log.i(TAG, "bindService to " + mMusicFxPackageName);
+ }
+
+ Log.i(TAG, mMusicFxPackageName + " procState " + procState);
+ }
+ try {
+ if (mUidObserverToken == null) {
+ mUidObserverToken = ActivityManager.getService().registerUidObserverForUids(
+ mEffectUidObserver, ActivityManager.UID_OBSERVER_GONE,
+ ActivityManager.PROCESS_STATE_UNKNOWN, mPackageName,
+ new int[]{uid});
+ Log.i(TAG, "registered to observer with UID " + uid);
+ } else if (get(uid) == null) { // addUidToObserver if this is a new UID
+ ActivityManager.getService().addUidToObserver(mUidObserverToken, mPackageName,
+ uid);
+ Log.i(TAG, " UID " + uid + " add to observer");
+ }
+ } catch (RemoteException e) {
+ Log.e(TAG, "RemoteException with UID observer add/register: " + e);
+ }
+
+ super.put(uid, pkgSessions);
+ }
+
+ @Override
+ public void remove(int uid) {
+ if (get(uid) != null) {
+ try {
+ ActivityManager.getService().removeUidFromObserver(mUidObserverToken,
+ mPackageName, uid);
+ } catch (RemoteException e) {
+ Log.e(TAG, "RemoteException with removeUidFromObserver: " + e);
+ }
+ }
+
+ super.remove(uid);
+
+ // stop foreground service delegate and unregister UID observers with the last UID
+ if (size() == 0) {
+ try {
+ ActivityManager.getService().unregisterUidObserver(mEffectUidObserver);
+ } catch (RemoteException e) {
+ Log.e(TAG, "RemoteException with unregisterUidObserver: " + e);
+ }
+ mUidObserverToken = null;
+ mContext.unbindService(mMusicFxBindConnection);
+ Log.i(TAG, "last session closed, unregister UID observer, and unbind "
+ + mMusicFxPackageName);
+ }
+ }
+ }
+
+ // Hashmap of UID and list of open sessions for this UID.
+ @GuardedBy("mClientUidMapLock")
+ private MySparseArray mClientUidSessionMap = new MySparseArray();
+
+ // UID observer for effect MusicFx clients
+ private final IUidObserver mEffectUidObserver = new UidObserver() {
+ @Override public void onUidGone(int uid, boolean disabled) {
+ Log.w(TAG, " send MSG_EFFECT_CLIENT_GONE");
+ mAudioHandler.sendMessageAtTime(
+ mAudioHandler.obtainMessage(MSG_EFFECT_CLIENT_GONE,
+ uid /* arg1 */, 0 /* arg2 */,
+ null /* obj */), 0 /* delay */);
+ }
+ };
+
+ // BindService connection implementation, we don't need any implementation now
+ private ServiceConnection mMusicFxBindConnection = new ServiceConnection() {
+ @Override
+ public void onServiceConnected(ComponentName name, IBinder service) {
+ Log.d(TAG, " service connected to " + name);
+ }
+
+ @Override
+ public void onServiceDisconnected(ComponentName name) {
+ Log.d(TAG, " service disconnected from " + name);
+ }
+ };
+
+ MusicFxHelper(@NonNull Context context, @NonNull AudioHandler audioHandler) {
+ mContext = context;
+ mAudioHandler = audioHandler;
+ }
+
+ /**
+ * Handle the broadcast {@link #ACTION_OPEN_AUDIO_EFFECT_CONTROL_SESSION} and
+ * {@link #ACTION_CLOSE_AUDIO_EFFECT_CONTROL_SESSION} intents.
+ *
+ * Only intents without target application package {@link android.content.Intent#getPackage}
+ * will be handled by the MusicFxHelper, all intents handled and forwarded by MusicFxHelper
+ * will have the target application package.
+ *
+ * If the intent is {@link #ACTION_OPEN_AUDIO_EFFECT_CONTROL_SESSION}:
+ * - If the MusicFx process is not running, call bindServiceAsUser with AUTO_CREATE to create.
+ * - If this is the first audio session of MusicFx, call set foreground service delegate.
+ * - If this is the first audio session for a given UID, add the UID into observer.
+ *
+ * If the intent is {@link #ACTION_CLOSE_AUDIO_EFFECT_CONTROL_SESSION}
+ * - The KeepAliveService of MusicFx will be unbound, and MusicFx will not be foreground
+ * delegated anymore if the last session of the last package was closed.
+ * - The Uid Observer will be removed when the last session of a package was closed.
+ */
+ @RequiresPermission(allOf = {android.Manifest.permission.INTERACT_ACROSS_USERS})
+ public void handleAudioEffectBroadcast(Context context, Intent intent) {
+ String target = intent.getPackage();
+ if (target != null) {
+ Log.w(TAG, "effect broadcast already targeted to " + target);
+ return;
+ }
+ final PackageManager pm = context.getPackageManager();
+ // TODO this should target a user-selected panel
+ List<ResolveInfo> ril = pm.queryBroadcastReceivers(intent, 0 /* flags */);
+ if (ril != null && ril.size() != 0) {
+ ResolveInfo ri = ril.get(0);
+ final String senderPackageName = intent.getStringExtra(AudioEffect.EXTRA_PACKAGE_NAME);
+ try {
+ if (ri != null && ri.activityInfo != null && ri.activityInfo.packageName != null) {
+ final int senderUid = pm.getPackageUidAsUser(senderPackageName,
+ PackageManager.PackageInfoFlags.of(MATCH_ANY_USER), getCurrentUserId());
+ intent.addFlags(Intent.FLAG_INCLUDE_STOPPED_PACKAGES);
+ intent.setPackage(ri.activityInfo.packageName);
+ if (setMusicFxServiceWithObserver(intent, senderUid, senderPackageName)) {
+ context.sendBroadcastAsUser(intent, UserHandle.ALL);
+ }
+ return;
+ }
+ } catch (PackageManager.NameNotFoundException e) {
+ Log.e(TAG, "Not able to find UID from package: " + senderPackageName + " error: "
+ + e);
+ }
+ }
+ Log.w(TAG, "couldn't find receiver package for effect intent");
+ }
+
+ @RequiresPermission(anyOf = {
+ android.Manifest.permission.INTERACT_ACROSS_USERS_FULL,
+ android.Manifest.permission.INTERACT_ACROSS_USERS,
+ android.Manifest.permission.INTERACT_ACROSS_PROFILES
+ })
+ @GuardedBy("mClientUidMapLock")
+ private boolean handleAudioEffectSessionOpen(
+ int senderUid, String senderPackageName, int sessionId) {
+ Log.d(TAG, senderPackageName + " UID " + senderUid + " open MusicFx session " + sessionId);
+
+ PackageSessions pkgSessions = mClientUidSessionMap.get(Integer.valueOf(senderUid));
+ if (pkgSessions != null && pkgSessions.mSessions != null) {
+ if (pkgSessions.mSessions.contains(sessionId)) {
+ Log.e(TAG, "Audio session " + sessionId + " already open for UID: "
+ + senderUid + ", package: " + senderPackageName + ", abort");
+ return false;
+ }
+ if (pkgSessions.mPackageName != senderPackageName) {
+ Log.w(TAG, "Inconsistency package names for UID open: " + senderUid + " prev: "
+ + pkgSessions.mPackageName + ", now: " + senderPackageName);
+ return false;
+ }
+ } else {
+ // first session for this UID, create a new Package/Sessions pair
+ pkgSessions = new PackageSessions();
+ pkgSessions.mSessions = new ArrayList();
+ pkgSessions.mPackageName = senderPackageName;
+ }
+
+ pkgSessions.mSessions.add(Integer.valueOf(sessionId));
+ mClientUidSessionMap.put(Integer.valueOf(senderUid), pkgSessions);
+ return true;
+ }
+
+ @RequiresPermission(anyOf = {
+ android.Manifest.permission.INTERACT_ACROSS_USERS_FULL,
+ android.Manifest.permission.INTERACT_ACROSS_USERS,
+ android.Manifest.permission.INTERACT_ACROSS_PROFILES
+ })
+ @GuardedBy("mClientUidMapLock")
+ private boolean handleAudioEffectSessionClose(
+ int senderUid, String senderPackageName, int sessionId) {
+ Log.d(TAG, senderPackageName + " UID " + senderUid + " close MusicFx session " + sessionId);
+
+ PackageSessions pkgSessions = mClientUidSessionMap.get(Integer.valueOf(senderUid));
+ if (pkgSessions == null) {
+ Log.e(TAG, senderPackageName + " UID " + senderUid + " does not exist in map, abort");
+ return false;
+ }
+ if (pkgSessions.mPackageName != senderPackageName) {
+ Log.w(TAG, "Inconsistency package names for UID " + senderUid + " close, prev: "
+ + pkgSessions.mPackageName + ", now: " + senderPackageName);
+ return false;
+ }
+
+ if (pkgSessions.mSessions != null && pkgSessions.mSessions.size() != 0) {
+ if (!pkgSessions.mSessions.contains(sessionId)) {
+ Log.e(TAG, senderPackageName + " UID " + senderUid + " session " + sessionId
+ + " does not exist in map, abort");
+ return false;
+ }
+
+ pkgSessions.mSessions.remove(Integer.valueOf(sessionId));
+ }
+
+ if (pkgSessions.mSessions == null || pkgSessions.mSessions.size() == 0) {
+ // remove UID from map as well as the UID observer with the last session close
+ mClientUidSessionMap.remove(Integer.valueOf(senderUid));
+ } else {
+ mClientUidSessionMap.put(Integer.valueOf(senderUid), pkgSessions);
+ }
+
+ return true;
+ }
+
+ /**
+ * @return true if the intent is validated and handled successfully, false with any error
+ * (invalid sender/intent for example).
+ */
+ @RequiresPermission(anyOf = {
+ android.Manifest.permission.INTERACT_ACROSS_USERS_FULL,
+ android.Manifest.permission.INTERACT_ACROSS_USERS,
+ android.Manifest.permission.INTERACT_ACROSS_PROFILES
+ })
+ private boolean setMusicFxServiceWithObserver(
+ Intent intent, int senderUid, String packageName) {
+ final int session = intent.getIntExtra(AudioEffect.EXTRA_AUDIO_SESSION,
+ AudioManager.AUDIO_SESSION_ID_GENERATE);
+ if (AudioManager.AUDIO_SESSION_ID_GENERATE == session) {
+ Log.e(TAG, packageName + " intent have no invalid audio session");
+ return false;
+ }
+
+ synchronized (mClientUidMapLock) {
+ if (intent.getAction().equals(AudioEffect.ACTION_OPEN_AUDIO_EFFECT_CONTROL_SESSION)) {
+ return handleAudioEffectSessionOpen(senderUid, packageName, session);
+ } else {
+ return handleAudioEffectSessionClose(senderUid, packageName, session);
+ }
+ }
+ }
+
+ private int getCurrentUserId() {
+ final long ident = Binder.clearCallingIdentity();
+ try {
+ UserInfo currentUser = ActivityManager.getService().getCurrentUser();
+ return currentUser.id;
+ } catch (RemoteException e) {
+ // Activity manager not running, nothing we can do assume user 0.
+ } finally {
+ Binder.restoreCallingIdentity(ident);
+ }
+ return UserHandle.USER_SYSTEM;
+ }
+
+
+ /**
+ * Handle the UidObserver onUidGone callback of MusicFx clients.
+ * Send close intent for all open audio sessions of this UID. The mClientUidSessionMap will be
+ * updated with the handling of close intent in setMusicFxServiceWithObserver.
+ */
+ @RequiresPermission(allOf = {android.Manifest.permission.INTERACT_ACROSS_USERS})
+ private void handleEffectClientUidGone(int uid) {
+ synchronized (mClientUidMapLock) {
+ Log.d(TAG, "handle MSG_EFFECT_CLIENT_GONE uid: " + uid + " mapSize: "
+ + mClientUidSessionMap.size());
+ // Once the uid is no longer running, close all remain audio session(s) for this UID
+ final PackageSessions pkgSessions = mClientUidSessionMap.get(Integer.valueOf(uid));
+ if (pkgSessions != null) {
+ Log.i(TAG, "UID " + uid + " gone, closing all sessions");
+
+ // send close intent for each open session of the gone UID
+ for (Integer sessionId : pkgSessions.mSessions) {
+ Intent closeIntent =
+ new Intent(AudioEffect.ACTION_CLOSE_AUDIO_EFFECT_CONTROL_SESSION);
+ closeIntent.putExtra(AudioEffect.EXTRA_PACKAGE_NAME, pkgSessions.mPackageName);
+ closeIntent.putExtra(AudioEffect.EXTRA_AUDIO_SESSION, sessionId);
+ closeIntent.addFlags(Intent.FLAG_INCLUDE_STOPPED_PACKAGES);
+ // set broadcast target
+ closeIntent.setPackage(mMusicFxPackageName);
+ mContext.sendBroadcastAsUser(closeIntent, UserHandle.ALL);
+ }
+ mClientUidSessionMap.remove(Integer.valueOf(uid));
+ }
+ }
+ }
+
+ @RequiresPermission(allOf = {android.Manifest.permission.INTERACT_ACROSS_USERS})
+ /*package*/ void handleMessage(Message msg) {
+ switch (msg.what) {
+ case MSG_EFFECT_CLIENT_GONE:
+ Log.w(TAG, " handle MSG_EFFECT_CLIENT_GONE");
+ handleEffectClientUidGone(msg.arg1 /* uid */);
+ break;
+ default:
+ Log.e(TAG, "Unexpected msg to handle in MusicFxHelper: " + msg.what);
+ break;
+ }
+ }
+}
diff --git a/services/core/java/com/android/server/audio/SoundDoseHelper.java b/services/core/java/com/android/server/audio/SoundDoseHelper.java
index 81365bf..6c5f3e7 100644
--- a/services/core/java/com/android/server/audio/SoundDoseHelper.java
+++ b/services/core/java/com/android/server/audio/SoundDoseHelper.java
@@ -108,11 +108,11 @@
private static final int SAFE_MEDIA_VOLUME_INACTIVE = 2; // confirmed
private static final int SAFE_MEDIA_VOLUME_ACTIVE = 3; // unconfirmed
- private static final int MSG_CONFIGURE_SAFE_MEDIA = SAFE_MEDIA_VOLUME_MSG_START + 1;
- private static final int MSG_CONFIGURE_SAFE_MEDIA_FORCED = SAFE_MEDIA_VOLUME_MSG_START + 2;
- private static final int MSG_PERSIST_SAFE_VOLUME_STATE = SAFE_MEDIA_VOLUME_MSG_START + 3;
- private static final int MSG_PERSIST_MUSIC_ACTIVE_MS = SAFE_MEDIA_VOLUME_MSG_START + 4;
- private static final int MSG_PERSIST_CSD_VALUES = SAFE_MEDIA_VOLUME_MSG_START + 5;
+ /*package*/ static final int MSG_CONFIGURE_SAFE_MEDIA = SAFE_MEDIA_VOLUME_MSG_START + 1;
+ /*package*/ static final int MSG_CONFIGURE_SAFE_MEDIA_FORCED = SAFE_MEDIA_VOLUME_MSG_START + 2;
+ /*package*/ static final int MSG_PERSIST_SAFE_VOLUME_STATE = SAFE_MEDIA_VOLUME_MSG_START + 3;
+ /*package*/ static final int MSG_PERSIST_MUSIC_ACTIVE_MS = SAFE_MEDIA_VOLUME_MSG_START + 4;
+ /*package*/ static final int MSG_PERSIST_CSD_VALUES = SAFE_MEDIA_VOLUME_MSG_START + 5;
/*package*/ static final int MSG_CSD_UPDATE_ATTENUATION = SAFE_MEDIA_VOLUME_MSG_START + 6;
private static final int UNSAFE_VOLUME_MUSIC_ACTIVE_MS_MAX = (20 * 3600 * 1000); // 20 hours
diff --git a/services/core/java/com/android/server/locksettings/LockSettingsService.java b/services/core/java/com/android/server/locksettings/LockSettingsService.java
index 0dc4467..42c2548 100644
--- a/services/core/java/com/android/server/locksettings/LockSettingsService.java
+++ b/services/core/java/com/android/server/locksettings/LockSettingsService.java
@@ -352,7 +352,6 @@
mLockSettingsService.deleteRepairModePersistentDataIfNeeded();
} else if (phase == PHASE_BOOT_COMPLETED) {
mLockSettingsService.loadEscrowData();
- mLockSettingsService.deleteRepairModePersistentDataIfNeeded();
}
}
diff --git a/services/core/jni/com_android_server_pm_PackageManagerShellCommandDataLoader.cpp b/services/core/jni/com_android_server_pm_PackageManagerShellCommandDataLoader.cpp
index 3d4f866..d66b9b9 100644
--- a/services/core/jni/com_android_server_pm_PackageManagerShellCommandDataLoader.cpp
+++ b/services/core/jni/com_android_server_pm_PackageManagerShellCommandDataLoader.cpp
@@ -182,7 +182,7 @@
auto block_count = 1 + (fileSize - 1) / INCFS_DATA_FILE_BLOCK_SIZE;
auto hash_block_count = block_count;
- for (auto i = 0; hash_block_count > 1; i++) {
+ while (hash_block_count > 1) {
hash_block_count = (hash_block_count + hash_per_block - 1) / hash_per_block;
total_tree_block_count += hash_block_count;
}
diff --git a/services/tests/servicestests/src/com/android/server/audio/MusicFxHelperTest.java b/services/tests/servicestests/src/com/android/server/audio/MusicFxHelperTest.java
new file mode 100644
index 0000000..472a82c
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/audio/MusicFxHelperTest.java
@@ -0,0 +1,642 @@
+/*
+ * Copyright 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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.server.audio;
+
+import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.ArgumentMatchers.anyObject;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+
+import android.content.Context;
+import android.content.Intent;
+import android.content.pm.ActivityInfo;
+import android.content.pm.PackageManager;
+import android.content.pm.ResolveInfo;
+import android.media.audiofx.AudioEffect;
+import android.os.Message;
+import android.util.Log;
+
+import androidx.test.filters.MediumTest;
+import androidx.test.runner.AndroidJUnit4;
+
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.InjectMocks;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+
+import java.util.ArrayList;
+import java.util.List;
+
+@MediumTest
+@RunWith(AndroidJUnit4.class)
+public class MusicFxHelperTest {
+ private static final String TAG = "MusicFxHelperTest";
+
+ @Mock private AudioService mMockAudioService;
+ @Mock private Context mMockContext;
+ @Mock private PackageManager mMockPackageManager;
+
+ private ResolveInfo mResolveInfo1 = new ResolveInfo();
+ private ResolveInfo mResolveInfo2 = new ResolveInfo();
+ private final String mTestPkg1 = "testPkg1", mTestPkg2 = "testPkg2", mTestPkg3 = "testPkg3";
+ private final String mMusicFxPkgName = "com.android.musicfx";
+ private final int mTestUid1 = 1, mTestUid2 = 2, mTestUid3 = 3, mMusicFxUid = 78;
+ private final int mTestSession1 = 11, mTestSession2 = 22, mTestSession3 = 33;
+
+ private List<ResolveInfo> mEmptyList = new ArrayList<>();
+ private List<ResolveInfo> mSingleList = new ArrayList<>();
+ private List<ResolveInfo> mDoubleList = new ArrayList<>();
+
+ // the class being unit-tested here
+ @InjectMocks private MusicFxHelper mMusicFxHelper;
+
+ @Before
+ @SuppressWarnings("DirectInvocationOnMock")
+ public void setUp() throws Exception {
+ mMockAudioService = mock(AudioService.class);
+ mMusicFxHelper = mMockAudioService.getMusicFxHelper();
+ MockitoAnnotations.initMocks(this);
+
+ mResolveInfo1.activityInfo = new ActivityInfo();
+ mResolveInfo1.activityInfo.packageName = mTestPkg1;
+ mResolveInfo2.activityInfo = new ActivityInfo();
+ mResolveInfo2.activityInfo.packageName = mTestPkg2;
+
+ mSingleList.add(mResolveInfo1);
+ mDoubleList.add(mResolveInfo1);
+ mDoubleList.add(mResolveInfo2);
+
+ Assert.assertNotNull(mMusicFxHelper);
+ }
+
+ private Intent newIntent(String action, String packageName, int sessionId) {
+ Intent intent = new Intent(action);
+ if (packageName != null) {
+ intent.putExtra(AudioEffect.EXTRA_PACKAGE_NAME, packageName);
+ }
+ intent.putExtra(AudioEffect.EXTRA_AUDIO_SESSION, sessionId);
+ return intent;
+ }
+
+ /**
+ * Helper function to send ACTION_OPEN_AUDIO_EFFECT_CONTROL_SESSION intent with verification.
+ *
+ * @throws NameNotFoundException if no such package is available to the caller.
+ */
+ private void openSessionWithResList(
+ List<ResolveInfo> list, int bind, int broadcast, String packageName, int audioSession,
+ int uid) {
+ doReturn(mMockPackageManager).when(mMockContext).getPackageManager();
+ doReturn(list).when(mMockPackageManager).queryBroadcastReceivers(anyObject(), anyInt());
+ if (list != null && list.size() != 0) {
+ try {
+ doReturn(uid).when(mMockPackageManager)
+ .getPackageUidAsUser(eq(packageName), anyObject(), anyInt());
+ doReturn(mMusicFxUid).when(mMockPackageManager)
+ .getPackageUidAsUser(eq(mMusicFxPkgName), anyObject(), anyInt());
+ } catch (PackageManager.NameNotFoundException e) {
+ Log.e(TAG, "NameNotFoundException: " + e);
+ }
+ }
+
+ Intent intent = newIntent(AudioEffect.ACTION_OPEN_AUDIO_EFFECT_CONTROL_SESSION,
+ packageName, audioSession);
+ mMusicFxHelper.handleAudioEffectBroadcast(mMockContext, intent);
+ verify(mMockContext, times(bind))
+ .bindServiceAsUser(anyObject(), anyObject(), anyInt(), anyObject());
+ verify(mMockContext, times(broadcast)).sendBroadcastAsUser(anyObject(), anyObject());
+ }
+
+ /**
+ * Helper function to send ACTION_CLOSE_AUDIO_EFFECT_CONTROL_SESSION intent with verification.
+ *
+ * @throws NameNotFoundException if no such package is available to the caller.
+ */
+ private void closeSessionWithResList(
+ List<ResolveInfo> list, int unBind, int broadcast, String packageName,
+ int audioSession, int uid) {
+ doReturn(mMockPackageManager).when(mMockContext).getPackageManager();
+ doReturn(list).when(mMockPackageManager).queryBroadcastReceivers(anyObject(), anyInt());
+ if (list != null && list.size() != 0) {
+ try {
+ doReturn(uid).when(mMockPackageManager)
+ .getPackageUidAsUser(eq(packageName), anyObject(), anyInt());
+ doReturn(mMusicFxUid).when(mMockPackageManager)
+ .getPackageUidAsUser(eq(mMusicFxPkgName), anyObject(), anyInt());
+ } catch (PackageManager.NameNotFoundException e) {
+ Log.e(TAG, "NameNotFoundException: " + e);
+ }
+ }
+
+ Intent intent = newIntent(AudioEffect.ACTION_CLOSE_AUDIO_EFFECT_CONTROL_SESSION,
+ packageName, audioSession);
+ mMusicFxHelper.handleAudioEffectBroadcast(mMockContext, intent);
+ verify(mMockContext, times(unBind)).unbindService(anyObject());
+ verify(mMockContext, times(broadcast)).sendBroadcastAsUser(anyObject(), anyObject());
+ }
+
+ /**
+ * Helper function to send MSG_EFFECT_CLIENT_GONE message with verification.
+ */
+ private void sendMessage(int msgId, int uid, int unBinds, int broadcasts) {
+ mMusicFxHelper.handleMessage(Message.obtain(null, msgId, uid /* arg1 */, 0 /* arg2 */));
+ verify(mMockContext, times(broadcasts)).sendBroadcastAsUser(anyObject(), anyObject());
+ verify(mMockContext, times(unBinds)).unbindService(anyObject());
+ }
+
+ /**
+ * Send invalid message to MusicFxHelper.
+ */
+ @Test
+ public void testInvalidMessage() {
+ Log.i(TAG, "running testInvalidMessage");
+
+ sendMessage(MusicFxHelper.MSG_EFFECT_CLIENT_GONE - 1, 0, 0, 0);
+ sendMessage(MusicFxHelper.MSG_EFFECT_CLIENT_GONE + 1, 0, 0, 0);
+ }
+
+ /**
+ * Send client gone message to MusicFxHelper when no client exist.
+ */
+ @Test
+ public void testGoneMessageWhenNoClient() {
+ Log.i(TAG, "running testGoneMessageWhenNoClient");
+
+ sendMessage(MusicFxHelper.MSG_EFFECT_CLIENT_GONE, 0, 0, 0);
+ }
+
+ /**
+ * Send ACTION_CLOSE_AUDIO_EFFECT_CONTROL_SESSION intent to MusicFxHelper when no session exist.
+ */
+ @Test
+ public void testCloseBroadcastIntent() {
+ Log.i(TAG, "running testCloseBroadcastIntent");
+
+ closeSessionWithResList(null, 0, 0, null, mTestSession1, mTestUid1);
+ }
+
+ /**
+ * OPEN/CLOSE AUDIO_EFFECT_CONTROL_SESSION intent when target application package was set.
+ * When the target application package was set for an intent, it means this intent is limited
+ * to a specific target application, as a result MusicFxHelper will not handle this intent.
+ */
+ @Test
+ public void testBroadcastIntentWithPackage() {
+ Log.i(TAG, "running testBroadcastIntentWithPackage");
+
+ Intent intent = newIntent(AudioEffect.ACTION_OPEN_AUDIO_EFFECT_CONTROL_SESSION, null, 1);
+ intent.setPackage(mTestPkg1);
+ mMusicFxHelper.handleAudioEffectBroadcast(mMockContext, intent);
+ verify(mMockContext, times(0))
+ .bindServiceAsUser(anyObject(), anyObject(), anyInt(), anyObject());
+ verify(mMockContext, times(0)).sendBroadcastAsUser(anyObject(), anyObject());
+
+ intent = newIntent(AudioEffect.ACTION_CLOSE_AUDIO_EFFECT_CONTROL_SESSION, null, 1);
+ intent.setPackage(mTestPkg2);
+ mMusicFxHelper.handleAudioEffectBroadcast(mMockContext, intent);
+ verify(mMockContext, times(0))
+ .bindServiceAsUser(anyObject(), anyObject(), anyInt(), anyObject());
+ verify(mMockContext, times(0)).sendBroadcastAsUser(anyObject(), anyObject());
+ }
+
+ /**
+ * OPEN/CLOSE AUDIO_EFFECT_CONTROL_SESSION with no broadcast receiver.
+ */
+ @Test
+ public void testBroadcastIntentWithNoPackageAndNoBroadcastReceiver() {
+ Log.i(TAG, "running testBroadcastIntentWithNoPackageAndNoBroadcastReceiver");
+
+ openSessionWithResList(mEmptyList, 0, 0, null, mTestSession1, mTestUid1);
+ closeSessionWithResList(mEmptyList, 0, 0, null, mTestSession1, mTestUid1);
+ }
+
+ /**
+ * OPEN/CLOSE AUDIO_EFFECT_CONTROL_SESSION with one broadcast receiver.
+ */
+ @Test
+ public void testBroadcastIntentWithNoPackageAndOneBroadcastReceiver() {
+ Log.i(TAG, "running testBroadcastIntentWithNoPackageAndOneBroadcastReceiver");
+
+ int broadcasts = 1, bind = 1, unbind = 1;
+ openSessionWithResList(mSingleList, bind, broadcasts, null, mTestSession1, mTestUid1);
+ broadcasts = broadcasts + 1;
+ closeSessionWithResList(mSingleList, unbind, broadcasts, null, mTestSession1, mTestUid1);
+
+ // repeat with different session ID
+ broadcasts = broadcasts + 1;
+ bind = bind + 1;
+ unbind = unbind + 1;
+ openSessionWithResList(mSingleList, bind, broadcasts, null, mTestSession2, mTestUid1);
+ broadcasts = broadcasts + 1;
+ closeSessionWithResList(mSingleList, unbind, broadcasts, null, mTestSession2, mTestUid1);
+
+ // repeat with different UID
+ broadcasts = broadcasts + 1;
+ bind = bind + 1;
+ unbind = unbind + 1;
+ openSessionWithResList(mSingleList, bind, broadcasts, null, mTestSession1, mTestUid2);
+ broadcasts = broadcasts + 1;
+ closeSessionWithResList(mSingleList, unbind, broadcasts, null, mTestSession1, mTestUid2);
+ }
+
+ /**
+ * OPEN/CLOSE AUDIO_EFFECT_CONTROL_SESSION with two broadcast receivers.
+ */
+ @Test
+ public void testBroadcastIntentWithNoPackageAndTwoBroadcastReceivers() {
+ Log.i(TAG, "running testBroadcastIntentWithNoPackageAndTwoBroadcastReceivers");
+
+ openSessionWithResList(mDoubleList, 1, 1, null, mTestSession1, mTestUid1);
+ closeSessionWithResList(mDoubleList, 1, 2, null, mTestSession1, mTestUid1);
+ }
+
+ /**
+ * Open/close session UID not matching.
+ * No broadcast for mismatching sessionID/UID/packageName.
+ */
+ @Test
+ public void testBroadcastBadIntents() {
+ Log.i(TAG, "running testBroadcastBadIntents");
+
+ int broadcasts = 1;
+ openSessionWithResList(mSingleList, 1, broadcasts, mTestPkg1, mTestSession1, mTestUid1);
+ // mismatch UID
+ closeSessionWithResList(mSingleList, 0, broadcasts, mTestPkg1, mTestSession1, mTestUid2);
+ // mismatch AudioSession
+ closeSessionWithResList(mSingleList, 0, broadcasts, mTestPkg1, mTestSession2, mTestUid1);
+ // mismatch packageName
+ closeSessionWithResList(mSingleList, 0, broadcasts, mTestPkg2, mTestSession1, mTestUid1);
+
+ // cleanup with correct UID and session ID
+ broadcasts = broadcasts + 1;
+ closeSessionWithResList(mSingleList, 1, broadcasts, mTestPkg1, mTestSession1, mTestUid1);
+ }
+
+ /**
+ * Open/close sessions with one UID, some with correct intents some with illegal intents.
+ * No broadcast for mismatching sessionID/UID/packageName.
+ */
+ @Test
+ public void testBroadcastGoodAndBadIntents() {
+ Log.i(TAG, "running testBroadcastGoodAndBadIntents");
+
+ int broadcasts = 1, bind = 1, unbind = 0;
+ openSessionWithResList(mSingleList, bind, broadcasts, mTestPkg1, mTestSession1, mTestUid1);
+ // mismatch packageName, session ID and UID
+ closeSessionWithResList(mSingleList, unbind, broadcasts, mTestPkg2, mTestSession2,
+ mTestUid2);
+ // mismatch session ID and mismatch UID
+ closeSessionWithResList(mSingleList, unbind, broadcasts, mTestPkg1, mTestSession2,
+ mTestUid2);
+ // mismatch packageName and mismatch UID
+ closeSessionWithResList(mSingleList, unbind, broadcasts, mTestPkg2, mTestSession1,
+ mTestUid2);
+ // mismatch packageName and sessionID
+ closeSessionWithResList(mSingleList, unbind, broadcasts, mTestPkg2, mTestSession2,
+ mTestUid1);
+ // inconsistency package name for same UID
+ openSessionWithResList(mSingleList, bind, broadcasts, mTestPkg2, mTestSession2, mTestUid1);
+ // open session2 with good intent
+ broadcasts = broadcasts + 1;
+ openSessionWithResList(mSingleList, bind, broadcasts, mTestPkg1, mTestSession2, mTestUid1);
+
+ // cleanup with correct UID and session ID
+ broadcasts = broadcasts + 1;
+ closeSessionWithResList(mSingleList, unbind, broadcasts, mTestPkg1, mTestSession1,
+ mTestUid1);
+ broadcasts = broadcasts + 1;
+ unbind = unbind + 1;
+ closeSessionWithResList(mSingleList, unbind, broadcasts, mTestPkg1, mTestSession2,
+ mTestUid1);
+ }
+
+ /**
+ * Send ACTION_OPEN_AUDIO_EFFECT_CONTROL_SESSION when there is no listener.
+ */
+ @Test
+ public void testBroadcastOpenSessionWithValidPackageNameAndNoListener() {
+ Log.i(TAG, "running testBroadcastOpenSessionWithValidPackageNameAndNoListener");
+
+ // null listener list should not trigger any action
+ openSessionWithResList(null, 0, 0, mTestPkg1, mTestSession1, mTestUid1);
+ // empty listener list should not trigger any action
+ openSessionWithResList(mEmptyList, 0, 0, mTestPkg1, mTestSession1, mTestUid1);
+ }
+
+ /**
+ * One MusicFx client, open session and close.
+ */
+ @Test
+ public void testOpenCloseAudioSession() {
+ Log.i(TAG, "running testOpenCloseAudioSession");
+
+ int broadcasts = 1;
+ openSessionWithResList(mDoubleList, 1, broadcasts, mTestPkg1, mTestSession1, mTestUid1);
+ broadcasts = broadcasts + 1;
+ closeSessionWithResList(mDoubleList, 1, broadcasts, mTestPkg1, mTestSession1, mTestUid1);
+ }
+
+ /**
+ * One MusicFx client, open session and close, then gone.
+ */
+ @Test
+ public void testOpenCloseAudioSessionAndGone() {
+ Log.i(TAG, "running testOpenCloseAudioSessionAndGone");
+
+ int broadcasts = 1;
+ openSessionWithResList(mDoubleList, 1, broadcasts, mTestPkg1, mTestSession1, mTestUid1);
+ broadcasts = broadcasts + 1;
+ openSessionWithResList(mDoubleList, 1, broadcasts, mTestPkg1, mTestSession2, mTestUid1);
+ broadcasts = broadcasts + 1;
+ closeSessionWithResList(mDoubleList, 0, broadcasts, mTestPkg1, mTestSession1, mTestUid1);
+
+ broadcasts = broadcasts + 1; // 1 open session left
+ sendMessage(MusicFxHelper.MSG_EFFECT_CLIENT_GONE, mTestUid1, 1, broadcasts);
+ }
+
+ /**
+ * One MusicFx client, open session, then UID gone without close.
+ */
+ @Test
+ public void testOpenOneSessionAndGo() {
+ Log.i(TAG, "running testOpenOneSessionAndGo");
+
+ int broadcasts = 1;
+ openSessionWithResList(mDoubleList, 1, broadcasts, mTestPkg1, mTestSession1, mTestUid1);
+
+ broadcasts = broadcasts + 1;
+ sendMessage(MusicFxHelper.MSG_EFFECT_CLIENT_GONE, mTestUid1, 1, broadcasts);
+ }
+
+ /**
+ * Two MusicFx clients open and close sessions.
+ */
+ @Test
+ public void testOpenTwoSessionsAndClose() {
+ Log.i(TAG, "running testOpenTwoSessionsAndClose");
+
+ int broadcasts = 1, bind = 1, unbind = 0;
+ openSessionWithResList(mDoubleList, bind, broadcasts, mTestPkg1, mTestSession1, mTestUid1);
+ broadcasts = broadcasts + 1;
+ openSessionWithResList(mDoubleList, bind, broadcasts, mTestPkg2, mTestSession2, mTestUid2);
+
+ broadcasts = broadcasts + 1;
+ closeSessionWithResList(mDoubleList, unbind, broadcasts, mTestPkg2, mTestSession2,
+ mTestUid2);
+ broadcasts = broadcasts + 1;
+ unbind = unbind + 1;
+ closeSessionWithResList(mDoubleList, unbind, broadcasts, mTestPkg1, mTestSession1,
+ mTestUid1);
+
+ broadcasts = broadcasts + 1;
+ bind = bind + 1;
+ openSessionWithResList(mDoubleList, bind, broadcasts, mTestPkg2, mTestSession2, mTestUid2);
+ broadcasts = broadcasts + 1;
+ openSessionWithResList(mDoubleList, bind, broadcasts, mTestPkg1, mTestSession1, mTestUid1);
+
+ broadcasts = broadcasts + 1;
+ closeSessionWithResList(mDoubleList, unbind, broadcasts, mTestPkg1, mTestSession1,
+ mTestUid1);
+ broadcasts = broadcasts + 1;
+ unbind = unbind + 1;
+ closeSessionWithResList(mDoubleList, unbind, broadcasts, mTestPkg2, mTestSession2,
+ mTestUid2);
+ }
+
+ /**
+ * Two MusicFx clients open sessions, then both UID gone without close.
+ */
+ @Test
+ public void testOpenTwoSessionsAndGo() {
+ Log.i(TAG, "running testOpenTwoSessionsAndGo");
+
+ int broadcasts = 1, bind = 1, unbind = 0;
+ openSessionWithResList(mDoubleList, bind, broadcasts, mTestPkg1, mTestSession1, mTestUid1);
+ broadcasts = broadcasts + 1;
+ openSessionWithResList(mDoubleList, bind, broadcasts, mTestPkg2, mTestSession2, mTestUid2);
+
+ broadcasts = broadcasts + 1;
+ sendMessage(MusicFxHelper.MSG_EFFECT_CLIENT_GONE, mTestUid1, unbind, broadcasts);
+
+ broadcasts = broadcasts + 1;
+ unbind = unbind + 1;
+ sendMessage(MusicFxHelper.MSG_EFFECT_CLIENT_GONE, mTestUid2, unbind, broadcasts);
+ }
+
+ /**
+ * Two MusicFx clients open sessions, one close but not gone, the other one gone without close.
+ */
+ @Test
+ public void testTwoSessionsOpenOneCloseOneGo() {
+ Log.i(TAG, "running testTwoSessionsOpneAndOneCloseOneGo");
+
+ int broadcasts = 1, bind = 1, unbind = 0;
+ openSessionWithResList(mDoubleList, bind, broadcasts, mTestPkg1, mTestSession1, mTestUid1);
+ broadcasts = broadcasts + 1;
+ openSessionWithResList(mDoubleList, bind, broadcasts, mTestPkg2, mTestSession2, mTestUid2);
+
+ broadcasts = broadcasts + 1;
+ closeSessionWithResList(mDoubleList, unbind, broadcasts, mTestPkg1, mTestSession1,
+ mTestUid1);
+
+ broadcasts = broadcasts + 1;
+ unbind = unbind + 1;
+ sendMessage(MusicFxHelper.MSG_EFFECT_CLIENT_GONE, mTestUid2, unbind, broadcasts);
+ }
+
+ /**
+ * One MusicFx client, open multiple audio sessions, and close all sessions.
+ */
+ @Test
+ public void testTwoSessionsInSameUidOpenClose() {
+ Log.i(TAG, "running testTwoSessionsOpneAndOneCloseOneGo");
+
+ int broadcasts = 1, bind = 1, unbind = 0;
+ openSessionWithResList(mDoubleList, bind, broadcasts, mTestPkg1, mTestSession1, mTestUid1);
+ broadcasts = broadcasts + 1;
+ openSessionWithResList(mDoubleList, bind, broadcasts, mTestPkg1, mTestSession2, mTestUid1);
+
+ broadcasts = broadcasts + 1;
+ closeSessionWithResList(mDoubleList, unbind, broadcasts, mTestPkg1, mTestSession1,
+ mTestUid1);
+ broadcasts = broadcasts + 1;
+ unbind = unbind + 1;
+ closeSessionWithResList(mDoubleList, unbind, broadcasts, mTestPkg1, mTestSession2,
+ mTestUid1);
+ }
+
+ /**
+ * Three MusicFx clients, each with multiple audio sessions, and close all sessions.
+ */
+ @Test
+ public void testThreeSessionsInThreeUidOpenClose() {
+ Log.i(TAG, "running testThreeSessionsInThreeUidOpenClose");
+
+ int broadcasts = 1, bind = 1, unbind = 0;
+ //client1
+ openSessionWithResList(mDoubleList, bind, broadcasts, mTestPkg1, mTestSession1, mTestUid1);
+ broadcasts = broadcasts + 1;
+ openSessionWithResList(mDoubleList, bind, broadcasts, mTestPkg1, mTestSession2, mTestUid1);
+ // client2
+ broadcasts = broadcasts + 1;
+ openSessionWithResList(mDoubleList, bind, broadcasts, mTestPkg2, mTestSession3, mTestUid2);
+ broadcasts = broadcasts + 1;
+ openSessionWithResList(mDoubleList, bind, broadcasts, mTestPkg2, mTestSession2, mTestUid2);
+ // client3
+ broadcasts = broadcasts + 1;
+ openSessionWithResList(mDoubleList, bind, broadcasts, mTestPkg3, mTestSession1, mTestUid3);
+ broadcasts = broadcasts + 1;
+ openSessionWithResList(mDoubleList, bind, broadcasts, mTestPkg3, mTestSession3, mTestUid3);
+
+ broadcasts = broadcasts + 1;
+ closeSessionWithResList(mDoubleList, unbind, broadcasts, mTestPkg1, mTestSession1,
+ mTestUid1);
+ broadcasts = broadcasts + 1;
+ closeSessionWithResList(mDoubleList, unbind, broadcasts, mTestPkg3, mTestSession3,
+ mTestUid3);
+ broadcasts = broadcasts + 1;
+ closeSessionWithResList(mDoubleList, unbind, broadcasts, mTestPkg2, mTestSession2,
+ mTestUid2);
+ // all sessions of client1 closed
+ broadcasts = broadcasts + 1;
+ closeSessionWithResList(mDoubleList, unbind, broadcasts, mTestPkg1, mTestSession2,
+ mTestUid1);
+ // all sessions of client3 closed
+ broadcasts = broadcasts + 1;
+ closeSessionWithResList(mDoubleList, unbind, broadcasts, mTestPkg3, mTestSession1,
+ mTestUid3);
+ // all sessions of client2 closed
+ broadcasts = broadcasts + 1;
+ // now expect unbind to happen
+ unbind = unbind + 1;
+ closeSessionWithResList(mDoubleList, unbind, broadcasts, mTestPkg2, mTestSession3,
+ mTestUid2);
+ }
+
+ /**
+ * Two MusicFx clients, with multiple audio sessions, one close all sessions, and other gone.
+ */
+ @Test
+ public void testTwoUidOneCloseOneGo() {
+ Log.i(TAG, "running testTwoUidOneCloseOneGo");
+
+ int broadcasts = 1, bind = 1, unbind = 0;
+ //client1
+ openSessionWithResList(mDoubleList, bind, broadcasts, mTestPkg1, mTestSession1, mTestUid1);
+ broadcasts = broadcasts + 1;
+ openSessionWithResList(mDoubleList, bind, broadcasts, mTestPkg1, mTestSession2, mTestUid1);
+ // client2
+ broadcasts = broadcasts + 1;
+ openSessionWithResList(mDoubleList, bind, broadcasts, mTestPkg2, mTestSession1, mTestUid2);
+ broadcasts = broadcasts + 1;
+ openSessionWithResList(mDoubleList, bind, broadcasts, mTestPkg2, mTestSession2, mTestUid2);
+
+ broadcasts = broadcasts + 1;
+ closeSessionWithResList(mDoubleList, unbind, broadcasts, mTestPkg1, mTestSession1,
+ mTestUid1);
+ // client2 gone
+ broadcasts = broadcasts + 2;
+ sendMessage(MusicFxHelper.MSG_EFFECT_CLIENT_GONE, mTestUid2, unbind, broadcasts);
+ // client 1 close all sessions
+ broadcasts = broadcasts + 1;
+ unbind = unbind + 1;
+ closeSessionWithResList(mDoubleList, unbind, broadcasts, mTestPkg1, mTestSession2,
+ mTestUid1);
+ }
+
+ /**
+ * Three MusicFx clients, with multiple audio sessions, all UID gone.
+ */
+ @Test
+ public void testThreeUidAllGo() {
+ Log.i(TAG, "running testThreeUidAllGo");
+
+ int broadcasts = 1, bind = 1, unbind = 0;
+ //client1
+ openSessionWithResList(mDoubleList, bind, broadcasts, mTestPkg1, mTestSession1, mTestUid1);
+ broadcasts = broadcasts + 1;
+ openSessionWithResList(mDoubleList, bind, broadcasts, mTestPkg1, mTestSession2, mTestUid1);
+ // client2
+ broadcasts = broadcasts + 1;
+ openSessionWithResList(mDoubleList, bind, broadcasts, mTestPkg2, mTestSession2, mTestUid2);
+ broadcasts = broadcasts + 1;
+ openSessionWithResList(mDoubleList, bind, broadcasts, mTestPkg2, mTestSession3, mTestUid2);
+ // client3
+ broadcasts = broadcasts + 1;
+ openSessionWithResList(mDoubleList, bind, broadcasts, mTestPkg3, mTestSession3, mTestUid3);
+ broadcasts = broadcasts + 1;
+ openSessionWithResList(mDoubleList, bind, broadcasts, mTestPkg3, mTestSession1, mTestUid3);
+
+ // client2 gone
+ broadcasts = broadcasts + 2;
+ sendMessage(MusicFxHelper.MSG_EFFECT_CLIENT_GONE, mTestUid2, unbind, broadcasts);
+ // client3 gone
+ broadcasts = broadcasts + 2;
+ sendMessage(MusicFxHelper.MSG_EFFECT_CLIENT_GONE, mTestUid3, unbind, broadcasts);
+ // client 1 gone
+ broadcasts = broadcasts + 2;
+ // now expect unbindService to happen
+ unbind = unbind + 1;
+ sendMessage(MusicFxHelper.MSG_EFFECT_CLIENT_GONE, mTestUid1, unbind, broadcasts);
+ }
+
+ /**
+ * Three MusicFx clients, multiple audio sessions, open and UID gone in difference sequence.
+ */
+ @Test
+ public void testThreeUidDiffSequence() {
+ Log.i(TAG, "running testThreeUidDiffSequence");
+
+ int broadcasts = 1, bind = 1, unbind = 0;
+ //client1
+ openSessionWithResList(mDoubleList, bind, broadcasts, mTestPkg1, mTestSession1, mTestUid1);
+ broadcasts = broadcasts + 1;
+ openSessionWithResList(mDoubleList, bind, broadcasts, mTestPkg1, mTestSession2, mTestUid1);
+ // client2
+ broadcasts = broadcasts + 1;
+ openSessionWithResList(mDoubleList, bind, broadcasts, mTestPkg2, mTestSession2, mTestUid2);
+ // client1 close one session
+ broadcasts = broadcasts + 1;
+ closeSessionWithResList(mDoubleList, unbind, broadcasts, mTestPkg1, mTestSession1,
+ mTestUid1);
+ // client2 open another session
+ broadcasts = broadcasts + 1;
+ openSessionWithResList(mDoubleList, bind, broadcasts, mTestPkg2, mTestSession3, mTestUid2);
+ // client3 open one session
+ broadcasts = broadcasts + 1;
+ openSessionWithResList(mDoubleList, bind, broadcasts, mTestPkg3, mTestSession3, mTestUid3);
+ // client2 gone
+ broadcasts = broadcasts + 2;
+ sendMessage(MusicFxHelper.MSG_EFFECT_CLIENT_GONE, mTestUid2, unbind, broadcasts);
+ // client3 open another session
+ broadcasts = broadcasts + 1;
+ openSessionWithResList(mDoubleList, bind, broadcasts, mTestPkg3, mTestSession1, mTestUid3);
+ // client1 close another session, and gone
+ broadcasts = broadcasts + 1;
+ closeSessionWithResList(mDoubleList, unbind, broadcasts, mTestPkg1, mTestSession2,
+ mTestUid1);
+ // last UID client3 gone, unbind
+ broadcasts = broadcasts + 2;
+ unbind = unbind + 1;
+ sendMessage(MusicFxHelper.MSG_EFFECT_CLIENT_GONE, mTestUid3, unbind, broadcasts);
+ }
+}
diff --git a/tools/aapt2/integration-tests/AutoVersionTest/Android.bp b/tools/aapt2/integration-tests/AutoVersionTest/Android.bp
index bfd3508..c901efa 100644
--- a/tools/aapt2/integration-tests/AutoVersionTest/Android.bp
+++ b/tools/aapt2/integration-tests/AutoVersionTest/Android.bp
@@ -26,4 +26,5 @@
android_test {
name: "AaptAutoVersionTest",
sdk_version: "current",
+ use_resource_processor: false,
}
diff --git a/tools/aapt2/integration-tests/BasicTest/Android.bp b/tools/aapt2/integration-tests/BasicTest/Android.bp
index 7db9d26..d0649ea 100644
--- a/tools/aapt2/integration-tests/BasicTest/Android.bp
+++ b/tools/aapt2/integration-tests/BasicTest/Android.bp
@@ -26,4 +26,5 @@
android_test {
name: "AaptBasicTest",
sdk_version: "current",
+ use_resource_processor: false,
}
diff --git a/tools/aapt2/integration-tests/StaticLibTest/App/Android.bp b/tools/aapt2/integration-tests/StaticLibTest/App/Android.bp
index 80404ee..ebb4e9f 100644
--- a/tools/aapt2/integration-tests/StaticLibTest/App/Android.bp
+++ b/tools/aapt2/integration-tests/StaticLibTest/App/Android.bp
@@ -24,9 +24,9 @@
}
android_test {
-
name: "AaptTestStaticLib_App",
sdk_version: "current",
+ use_resource_processor: false,
srcs: ["src/**/*.java"],
asset_dirs: [
"assets",
diff --git a/tools/aapt2/integration-tests/StaticLibTest/LibOne/Android.bp b/tools/aapt2/integration-tests/StaticLibTest/LibOne/Android.bp
index a84da43..ee12a929 100644
--- a/tools/aapt2/integration-tests/StaticLibTest/LibOne/Android.bp
+++ b/tools/aapt2/integration-tests/StaticLibTest/LibOne/Android.bp
@@ -26,6 +26,7 @@
android_library {
name: "AaptTestStaticLib_LibOne",
sdk_version: "current",
+ use_resource_processor: false,
srcs: ["src/**/*.java"],
resource_dirs: ["res"],
}
diff --git a/tools/aapt2/integration-tests/StaticLibTest/LibTwo/Android.bp b/tools/aapt2/integration-tests/StaticLibTest/LibTwo/Android.bp
index d386c3a..83b23624 100644
--- a/tools/aapt2/integration-tests/StaticLibTest/LibTwo/Android.bp
+++ b/tools/aapt2/integration-tests/StaticLibTest/LibTwo/Android.bp
@@ -26,6 +26,7 @@
android_library {
name: "AaptTestStaticLib_LibTwo",
sdk_version: "current",
+ use_resource_processor: false,
srcs: ["src/**/*.java"],
resource_dirs: ["res"],
libs: ["AaptTestStaticLib_LibOne"],
diff --git a/tools/aapt2/integration-tests/SymlinkTest/Android.bp b/tools/aapt2/integration-tests/SymlinkTest/Android.bp
index 1e8cf86..6fcdf1c 100644
--- a/tools/aapt2/integration-tests/SymlinkTest/Android.bp
+++ b/tools/aapt2/integration-tests/SymlinkTest/Android.bp
@@ -26,4 +26,8 @@
android_test {
name: "AaptSymlinkTest",
sdk_version: "current",
+ use_resource_processor: false,
+ compile_data: [
+ "targets/*",
+ ],
}