diff --git a/core/java/com/android/internal/app/ChooserListAdapter.java b/core/java/com/android/internal/app/ChooserListAdapter.java index 6eb470fef2bc8..38f4c64768dbe 100644 --- a/core/java/com/android/internal/app/ChooserListAdapter.java +++ b/core/java/com/android/internal/app/ChooserListAdapter.java @@ -95,7 +95,7 @@ public class ChooserListAdapter extends ResolverListAdapter { // we want to separate them into a different section. super(context, payloadIntents, null, rList, filterLastUsed, resolverListController, useLayoutForBrowsables, - chooserListCommunicator); + chooserListCommunicator, false); createPlaceHolders(); mMaxShortcutTargetsPerApp = diff --git a/core/java/com/android/internal/app/ResolverActivity.java b/core/java/com/android/internal/app/ResolverActivity.java index c1c6ac9dfa893..1beb1c5e912ad 100644 --- a/core/java/com/android/internal/app/ResolverActivity.java +++ b/core/java/com/android/internal/app/ResolverActivity.java @@ -140,6 +140,9 @@ public class ResolverActivity extends Activity implements private final PackageMonitor mPackageMonitor = createPackageMonitor(); + // Intent extra for connected audio devices + public static final String EXTRA_IS_AUDIO_CAPTURE_DEVICE = "is_audio_capture_device"; + /** * Get the string resource to be used as a label for the link to the resolver activity for an * action. @@ -1038,8 +1041,14 @@ public class ResolverActivity extends Activity implements public ResolverListAdapter createAdapter(Context context, List payloadIntents, Intent[] initialIntents, List rList, boolean filterLastUsed, boolean useLayoutForBrowsables) { + + Intent startIntent = getIntent(); + boolean isAudioCaptureDevice = + startIntent.getBooleanExtra(EXTRA_IS_AUDIO_CAPTURE_DEVICE, false); + return new ResolverListAdapter(context, payloadIntents, initialIntents, rList, - filterLastUsed, createListController(), useLayoutForBrowsables, this); + filterLastUsed, createListController(), useLayoutForBrowsables, this, + isAudioCaptureDevice); } @VisibleForTesting diff --git a/core/java/com/android/internal/app/ResolverListAdapter.java b/core/java/com/android/internal/app/ResolverListAdapter.java index 4076ddaa71b00..a587936ee571d 100644 --- a/core/java/com/android/internal/app/ResolverListAdapter.java +++ b/core/java/com/android/internal/app/ResolverListAdapter.java @@ -24,6 +24,7 @@ import android.app.ActivityManager; import android.content.ComponentName; import android.content.Context; import android.content.Intent; +import android.content.PermissionChecker; import android.content.pm.ActivityInfo; import android.content.pm.ApplicationInfo; import android.content.pm.LabeledIntent; @@ -86,13 +87,15 @@ public class ResolverListAdapter extends BaseAdapter { private boolean mFilterLastUsed; private final ResolverListCommunicator mResolverListCommunicator; private Runnable mPostListReadyRunnable; + private final boolean mIsAudioCaptureDevice; public ResolverListAdapter(Context context, List payloadIntents, Intent[] initialIntents, List rList, boolean filterLastUsed, ResolverListController resolverListController, boolean useLayoutForBrowsables, - ResolverListCommunicator resolverListCommunicator) { + ResolverListCommunicator resolverListCommunicator, + boolean isAudioCaptureDevice) { mContext = context; mIntents = payloadIntents; mInitialIntents = initialIntents; @@ -105,6 +108,7 @@ public class ResolverListAdapter extends BaseAdapter { mSuspendedMatrixColorFilter = createSuspendedColorMatrix(); mUseLayoutForBrowsables = useLayoutForBrowsables; mResolverListCommunicator = resolverListCommunicator; + mIsAudioCaptureDevice = isAudioCaptureDevice; final ActivityManager am = (ActivityManager) mContext.getSystemService(ACTIVITY_SERVICE); mIconDpi = am.getLauncherLargeIconDensity(); } @@ -651,6 +655,29 @@ public class ResolverListAdapter extends BaseAdapter { protected CharSequence[] doInBackground(Void... voids) { ResolveInfoPresentationGetter pg = makePresentationGetter(mDisplayResolveInfo.getResolveInfo()); + + if (mIsAudioCaptureDevice) { + // This is an audio capture device, so check record permissions + ActivityInfo activityInfo = mDisplayResolveInfo.getResolveInfo().activityInfo; + String packageName = activityInfo.packageName; + + int uid = activityInfo.applicationInfo.uid; + boolean hasRecordPermission = + PermissionChecker.checkPermissionForPreflight( + mContext, + android.Manifest.permission.RECORD_AUDIO, -1, uid, + packageName) + == android.content.pm.PackageManager.PERMISSION_GRANTED; + + if (!hasRecordPermission) { + // Doesn't have record permission, so warn the user + return new CharSequence[] { + pg.getLabel(), + mContext.getString(R.string.usb_device_resolve_prompt_warn) + }; + } + } + return new CharSequence[] { pg.getLabel(), pg.getSubLabel() diff --git a/core/res/res/layout/resolve_list_item.xml b/core/res/res/layout/resolve_list_item.xml index 485709523e667..86f028c174fe2 100644 --- a/core/res/res/layout/resolve_list_item.xml +++ b/core/res/res/layout/resolve_list_item.xml @@ -54,7 +54,9 @@ android:minLines="1" android:maxLines="1" android:ellipsize="marquee" /> - + diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml index d39d50739e1db..585c4bba4ba9f 100644 --- a/core/res/res/values/strings.xml +++ b/core/res/res/values/strings.xml @@ -5440,4 +5440,6 @@ Apps list + + This app has not been granted record permission but could capture audio through this USB device. diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml index 8d96c79ed3d83..13139123fe556 100644 --- a/core/res/res/values/symbols.xml +++ b/core/res/res/values/symbols.xml @@ -3876,4 +3876,6 @@ + + diff --git a/core/tests/coretests/src/com/android/internal/app/ResolverWrapperAdapter.java b/core/tests/coretests/src/com/android/internal/app/ResolverWrapperAdapter.java index e41df4186a12b..a2191b5fac807 100644 --- a/core/tests/coretests/src/com/android/internal/app/ResolverWrapperAdapter.java +++ b/core/tests/coretests/src/com/android/internal/app/ResolverWrapperAdapter.java @@ -39,7 +39,7 @@ public class ResolverWrapperAdapter extends ResolverListAdapter { ResolverListCommunicator resolverListCommunicator) { super(context, payloadIntents, initialIntents, rList, filterLastUsed, resolverListController, - useLayoutForBrowsables, resolverListCommunicator); + useLayoutForBrowsables, resolverListCommunicator, false); } public CountingIdlingResource getLabelIdlingResource() { diff --git a/packages/SystemUI/src/com/android/systemui/usb/UsbResolverActivity.java b/packages/SystemUI/src/com/android/systemui/usb/UsbResolverActivity.java index 0b273274f86d3..2e30d32440ab7 100644 --- a/packages/SystemUI/src/com/android/systemui/usb/UsbResolverActivity.java +++ b/packages/SystemUI/src/com/android/systemui/usb/UsbResolverActivity.java @@ -87,8 +87,10 @@ public class UsbResolverActivity extends ResolverActivity { } mDevice = (UsbDevice)target.getParcelableExtra(UsbManager.EXTRA_DEVICE); + boolean hasAudioCapture = false; if (mDevice != null) { mDisconnectedReceiver = new UsbDisconnectedReceiver(this, mDevice); + hasAudioCapture = mDevice.getHasAudioCapture(); } else { mAccessory = (UsbAccessory)target.getParcelableExtra(UsbManager.EXTRA_ACCESSORY); if (mAccessory == null) { @@ -119,6 +121,8 @@ public class UsbResolverActivity extends ResolverActivity { } } } + getIntent().putExtra( + ResolverActivity.EXTRA_IS_AUDIO_CAPTURE_DEVICE, hasAudioCapture); CharSequence title = getResources().getText(com.android.internal.R.string.chooseUsbActivity); super.onCreate(savedInstanceState, target, title, null, rList, true);