1 /* <lambda>null2 * Copyright (C) 2024 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.android.car.docklib.media 18 19 import android.app.ActivityManager 20 import android.car.media.CarMediaIntents 21 import android.content.ComponentName 22 import android.content.Intent 23 import android.content.pm.PackageManager 24 import android.content.pm.ResolveInfo 25 import android.os.Build 26 import android.service.media.MediaBrowserService 27 import android.util.Log 28 import androidx.annotation.VisibleForTesting 29 import java.util.stream.Collectors 30 31 class MediaUtils { 32 companion object { 33 private const val TAG = "MediaUtils" 34 private val DEBUG = Build.isDebuggable() 35 36 @VisibleForTesting 37 val CAR_MEDIA_ACTIVITY = ComponentName( 38 "com.android.car.media", 39 "com.android.car.media.MediaActivity" 40 ) 41 42 @VisibleForTesting 43 const val CAR_MEDIA_DATA_SCHEME = "custom" 44 45 fun getMediaComponentName(taskInfo: ActivityManager.RunningTaskInfo): ComponentName? { 46 val data = taskInfo.baseIntent.data 47 if (data == null) { 48 if (DEBUG) Log.d(TAG, "No data attached to the base intent") 49 return null 50 } 51 if (CAR_MEDIA_DATA_SCHEME != data.scheme) { 52 if (DEBUG) Log.d(TAG, "Data scheme doesn't match") 53 return null 54 } 55 // should drop the first backslash that is part of the schemeSpecificPart 56 val ssp = data.schemeSpecificPart 57 val mediaComponentString = if (ssp.startsWith("/")) ssp.drop(1) else ssp 58 val mediaComponent = ComponentName.unflattenFromString(mediaComponentString) 59 if (DEBUG) Log.d(TAG, "Media component found: $mediaComponent") 60 return mediaComponent 61 } 62 63 fun isMediaComponent(component: ComponentName?) = component == CAR_MEDIA_ACTIVITY 64 65 fun createLaunchIntent(componentName: ComponentName) = 66 Intent(CarMediaIntents.ACTION_MEDIA_TEMPLATE) 67 .putExtra(CarMediaIntents.EXTRA_MEDIA_COMPONENT, componentName.flattenToString()) 68 69 fun fetchMediaServiceComponents( 70 packageManager: PackageManager, 71 packageName: String? = null 72 ): MutableSet<ComponentName> { 73 val intent = Intent(MediaBrowserService.SERVICE_INTERFACE) 74 if (packageName != null) intent.setPackage(packageName) 75 return packageManager.queryIntentServices( 76 intent, 77 PackageManager.GET_RESOLVED_FILTER 78 ).stream() 79 .map { resolveInfo: ResolveInfo -> resolveInfo.serviceInfo.componentName } 80 .collect(Collectors.toSet()) 81 } 82 } 83 } 84