RegisteredMediaRouteProviderWatcher.java revision fa326a4649d9d0e8113e315f6c8251fe686abce4
1fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown/* 2fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown * Copyright (C) 2013 The Android Open Source Project 3fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown * 4fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown * Licensed under the Apache License, Version 2.0 (the "License"); 5fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown * you may not use this file except in compliance with the License. 6fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown * You may obtain a copy of the License at 7fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown * 8fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown * http://www.apache.org/licenses/LICENSE-2.0 9fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown * 10fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown * Unless required by applicable law or agreed to in writing, software 11fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown * distributed under the License is distributed on an "AS IS" BASIS, 12fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown * See the License for the specific language governing permissions and 14fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown * limitations under the License. 15fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown */ 16fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown 17fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brownpackage android.support.v4.media; 18fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown 19fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brownimport android.content.BroadcastReceiver; 20fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brownimport android.content.ComponentName; 21fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brownimport android.content.Context; 22fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brownimport android.content.Intent; 23fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brownimport android.content.IntentFilter; 24fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brownimport android.content.pm.PackageManager; 25fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brownimport android.content.pm.ResolveInfo; 26fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brownimport android.content.pm.ServiceInfo; 27fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown 28fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brownimport java.util.ArrayList; 29fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brownimport java.util.Collections; 30fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown 31fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown/** 32fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown * Watches for media route provider services to be installed. 33fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown * Adds a provider to the media router for each registered service. 34fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown * 35fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown * @see RegisteredMediaRouteProvider 36fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown */ 37fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brownfinal class RegisteredMediaRouteProviderWatcher { 38fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown private final Context mContext; 39fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown private final MediaRouter mRouter; 40fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown private final ArrayList<RegisteredMediaRouteProvider> mProviders = 41fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown new ArrayList<RegisteredMediaRouteProvider>(); 42fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown private final PackageManager mPackageManager; 43fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown 44fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown public RegisteredMediaRouteProviderWatcher(Context context, MediaRouter router) { 45fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown mContext = context; 46fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown mRouter = router; 47fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown mPackageManager = context.getPackageManager(); 48fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown } 49fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown 50fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown public void start() { 51fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown IntentFilter filter = new IntentFilter(); 52fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown filter.addAction(Intent.ACTION_PACKAGE_ADDED); 53fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown filter.addAction(Intent.ACTION_PACKAGE_REMOVED); 54fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown filter.addAction(Intent.ACTION_PACKAGE_CHANGED); 55fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown mContext.registerReceiver(new BroadcastReceiver() { 56fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown @Override 57fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown public void onReceive(Context context, Intent intent) { 58fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown scanPackages(); 59fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown } 60fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown }, filter); 61fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown 62fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown scanPackages(); 63fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown } 64fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown 65fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown private void scanPackages() { 66fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown // Add providers for all new services. 67fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown // Reorder the list so that providers left at the end will be the ones to remove. 68fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown int targetIndex = 0; 69fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown Intent intent = new Intent(MediaRouteProviderService.SERVICE_INTERFACE); 70fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown for (ResolveInfo resolveInfo : mPackageManager.queryIntentServices(intent, 0)) { 71fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown ServiceInfo serviceInfo = resolveInfo.serviceInfo; 72fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown if (serviceInfo != null) { 73fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown int sourceIndex = findProvider(serviceInfo.packageName, serviceInfo.name); 74fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown if (sourceIndex < 0) { 75fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown RegisteredMediaRouteProvider provider = 76fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown new RegisteredMediaRouteProvider(mContext, 77fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown new ComponentName(serviceInfo.packageName, serviceInfo.name)); 78fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown provider.bind(); 79fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown mProviders.add(targetIndex++, provider); 80fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown mRouter.addProvider(provider); 81fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown } else if (sourceIndex >= targetIndex) { 82fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown RegisteredMediaRouteProvider provider = mProviders.get(sourceIndex); 83fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown provider.rebindIfDisconnected(); 84fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown Collections.swap(mProviders, sourceIndex, targetIndex++); 85fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown } 86fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown } 87fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown } 88fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown 89fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown // Remove providers for missing services. 90fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown if (targetIndex < mProviders.size()) { 91fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown for (int i = mProviders.size() - 1; i >= targetIndex; i--) { 92fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown RegisteredMediaRouteProvider provider = mProviders.get(i); 93fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown mRouter.removeProvider(provider); 94fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown mProviders.remove(provider); 95fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown provider.unbind(); 96fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown } 97fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown } 98fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown } 99fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown 100fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown private int findProvider(String packageName, String className) { 101fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown int count = mProviders.size(); 102fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown for (int i = 0; i < count; i++) { 103fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown RegisteredMediaRouteProvider provider = mProviders.get(i); 104fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown if (provider.hasComponentName(packageName, className)) { 105fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown return i; 106fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown } 107fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown } 108fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown return -1; 109fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown } 110fa326a4649d9d0e8113e315f6c8251fe686abce4Jeff Brown} 111