summaryrefslogtreecommitdiffstats
path: root/services/core/java/com/android/server/audio/AudioService.java
diff options
context:
space:
mode:
authorFyodor Kupolov <fkupolov@google.com>2015-04-17 17:59:14 -0700
committerFyodor Kupolov <fkupolov@google.com>2015-05-08 17:17:16 -0700
commitb501330a1b6ef14ff512a5727f7a01bc423d6fbb (patch)
tree59796487de2723dc92a0520def552124fb3aa556 /services/core/java/com/android/server/audio/AudioService.java
parent4f434a04708e7a254afe2e0d362f715229dc15d1 (diff)
downloadframeworks_base-b501330a1b6ef14ff512a5727f7a01bc423d6fbb.zip
frameworks_base-b501330a1b6ef14ff512a5727f7a01bc423d6fbb.tar.gz
frameworks_base-b501330a1b6ef14ff512a5727f7a01bc423d6fbb.tar.bz2
Disable multi-user background recording
On user switch, kill existing processes of the background user with android.permission.RECORD_AUDIO permission. Home activity should not be killed to avoid an expensive restart of the home launcher, when the user switches back. Introduced DISALLOW_RECORD_AUDIO user restriction, which is enabled for the background user, and removed for the foreground user. Introduced a concept of system controlled user restriction, which can only be set by the system, rather than device administrator. Bug: 20346194 Change-Id: Ic942fd565e80d14424230dae612965a8e229c4ef
Diffstat (limited to 'services/core/java/com/android/server/audio/AudioService.java')
-rw-r--r--services/core/java/com/android/server/audio/AudioService.java61
1 files changed, 60 insertions, 1 deletions
diff --git a/services/core/java/com/android/server/audio/AudioService.java b/services/core/java/com/android/server/audio/AudioService.java
index 06fba34..aa365ea 100644
--- a/services/core/java/com/android/server/audio/AudioService.java
+++ b/services/core/java/com/android/server/audio/AudioService.java
@@ -21,8 +21,11 @@ import static android.media.AudioManager.RINGER_MODE_NORMAL;
import static android.media.AudioManager.RINGER_MODE_SILENT;
import static android.media.AudioManager.RINGER_MODE_VIBRATE;
+import android.Manifest;
import android.app.ActivityManager;
+import android.app.ActivityManagerInternal;
import android.app.ActivityManagerNative;
+import android.app.AppGlobals;
import android.app.AppOpsManager;
import android.app.KeyguardManager;
import android.bluetooth.BluetoothA2dp;
@@ -37,7 +40,10 @@ import android.content.ContentResolver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
+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;
import android.content.res.XmlResourceParser;
@@ -82,11 +88,13 @@ import android.os.RemoteException;
import android.os.SystemClock;
import android.os.SystemProperties;
import android.os.UserHandle;
+import android.os.UserManager;
import android.os.Vibrator;
import android.provider.Settings;
import android.provider.Settings.System;
import android.telecom.TelecomManager;
import android.text.TextUtils;
+import android.util.AndroidRuntimeException;
import android.util.ArrayMap;
import android.util.ArraySet;
import android.util.Log;
@@ -102,6 +110,7 @@ import android.view.accessibility.AccessibilityManager;
import com.android.internal.util.XmlUtils;
import com.android.server.EventLogTags;
import com.android.server.LocalServices;
+import com.android.server.pm.UserManagerService;
import org.xmlpull.v1.XmlPullParserException;
@@ -645,6 +654,8 @@ public class AudioService extends IAudioService.Stub {
intentFilter.addAction(Intent.ACTION_SCREEN_ON);
intentFilter.addAction(Intent.ACTION_SCREEN_OFF);
intentFilter.addAction(Intent.ACTION_USER_SWITCHED);
+ intentFilter.addAction(Intent.ACTION_USER_BACKGROUND);
+ intentFilter.addAction(Intent.ACTION_USER_FOREGROUND);
intentFilter.addAction(UsbManager.ACTION_USB_DEVICE_ATTACHED);
intentFilter.addAction(Intent.ACTION_CONFIGURATION_CHANGED);
@@ -668,7 +679,7 @@ public class AudioService extends IAudioService.Stub {
setRotationForAudioSystem();
}
- context.registerReceiver(mReceiver, intentFilter);
+ context.registerReceiverAsUser(mReceiver, UserHandle.ALL, intentFilter, null, null);
LocalServices.addService(AudioManagerInternal.class, new AudioServiceInternal());
}
@@ -4975,10 +4986,58 @@ public class AudioService extends IAudioService.Stub {
0,
0,
mStreamStates[AudioSystem.STREAM_MUSIC], 0);
+ } else if (action.equals(Intent.ACTION_USER_BACKGROUND)) {
+ // Disable audio recording for the background user/profile
+ int userId = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, -1);
+ if (userId >= 0) {
+ // TODO Kill recording streams instead of killing processes holding permission
+ UserInfo userInfo = UserManagerService.getInstance().getUserInfo(userId);
+ killBackgroundUserProcessesWithRecordAudioPermission(userInfo);
+ }
+ UserManagerService.getInstance().setSystemControlledUserRestriction(
+ UserManager.DISALLOW_RECORD_AUDIO, true, userId);
+ } else if (action.equals(Intent.ACTION_USER_FOREGROUND)) {
+ // Enable audio recording for foreground user/profile
+ int userId = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, -1);
+ UserManagerService.getInstance().setSystemControlledUserRestriction(
+ UserManager.DISALLOW_RECORD_AUDIO, false, userId);
}
}
} // end class AudioServiceBroadcastReceiver
+ 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,
+ // when the user switches back. For managed profiles, we should kill all recording apps
+ ComponentName homeActivityName = null;
+ if (!oldUser.isManagedProfile()) {
+ homeActivityName = LocalServices.getService(ActivityManagerInternal.class)
+ .getHomeActivityForUser(oldUser.id);
+ }
+ final String[] permissions = { Manifest.permission.RECORD_AUDIO };
+ List<PackageInfo> packages;
+ try {
+ packages = AppGlobals.getPackageManager()
+ .getPackagesHoldingPermissions(permissions, 0, oldUser.id).getList();
+ } catch (RemoteException e) {
+ throw new AndroidRuntimeException(e);
+ }
+ for (int j = packages.size() - 1; j >= 0; j--) {
+ PackageInfo pkg = packages.get(j);
+ if (homeActivityName != null
+ && pkg.packageName.equals(homeActivityName.getPackageName())
+ && pkg.applicationInfo.isSystemApp()) {
+ continue;
+ }
+ try {
+ ActivityManagerNative.getDefault().killUid(pkg.applicationInfo.uid,
+ "killBackgroundUserProcessesWithAudioRecordPermission");
+ } catch (RemoteException e) {
+ Log.w(TAG, "Error calling killUid", e);
+ }
+ }
+ }
+
//==========================================================================================
// RemoteControlDisplay / RemoteControlClient / Remote info
//==========================================================================================