Home | History | Annotate | Download | only in media
      1 /*
      2  * Copyright (C) 2013 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 android.support.v7.media;
     18 
     19 import android.content.BroadcastReceiver;
     20 import android.content.ComponentName;
     21 import android.content.Context;
     22 import android.content.Intent;
     23 import android.content.IntentFilter;
     24 import android.content.pm.PackageManager;
     25 import android.content.pm.ResolveInfo;
     26 import android.content.pm.ServiceInfo;
     27 
     28 import java.util.ArrayList;
     29 import java.util.Collections;
     30 
     31 /**
     32  * Watches for media route provider services to be installed.
     33  * Adds a provider to the media router for each registered service.
     34  *
     35  * @see RegisteredMediaRouteProvider
     36  */
     37 final class RegisteredMediaRouteProviderWatcher {
     38     private final Context mContext;
     39     private final MediaRouter mRouter;
     40     private final ArrayList<RegisteredMediaRouteProvider> mProviders =
     41             new ArrayList<RegisteredMediaRouteProvider>();
     42     private final PackageManager mPackageManager;
     43 
     44     public RegisteredMediaRouteProviderWatcher(Context context, MediaRouter router) {
     45         mContext = context;
     46         mRouter = router;
     47         mPackageManager = context.getPackageManager();
     48     }
     49 
     50     public void start() {
     51         IntentFilter filter = new IntentFilter();
     52         filter.addAction(Intent.ACTION_PACKAGE_ADDED);
     53         filter.addAction(Intent.ACTION_PACKAGE_REMOVED);
     54         filter.addAction(Intent.ACTION_PACKAGE_CHANGED);
     55         mContext.registerReceiver(new BroadcastReceiver() {
     56             @Override
     57             public void onReceive(Context context, Intent intent) {
     58                 scanPackages();
     59             }
     60         }, filter);
     61 
     62         scanPackages();
     63     }
     64 
     65     private void scanPackages() {
     66         // Add providers for all new services.
     67         // Reorder the list so that providers left at the end will be the ones to remove.
     68         int targetIndex = 0;
     69         Intent intent = new Intent(MediaRouteProviderService.SERVICE_INTERFACE);
     70         for (ResolveInfo resolveInfo : mPackageManager.queryIntentServices(intent, 0)) {
     71             ServiceInfo serviceInfo = resolveInfo.serviceInfo;
     72             if (serviceInfo != null) {
     73                 int sourceIndex = findProvider(serviceInfo.packageName, serviceInfo.name);
     74                 if (sourceIndex < 0) {
     75                     RegisteredMediaRouteProvider provider =
     76                             new RegisteredMediaRouteProvider(mContext,
     77                             new ComponentName(serviceInfo.packageName, serviceInfo.name));
     78                     provider.start();
     79                     mProviders.add(targetIndex++, provider);
     80                     mRouter.addProvider(provider);
     81                 } else if (sourceIndex >= targetIndex) {
     82                     RegisteredMediaRouteProvider provider = mProviders.get(sourceIndex);
     83                     provider.rebindIfDisconnected();
     84                     Collections.swap(mProviders, sourceIndex, targetIndex++);
     85                 }
     86             }
     87         }
     88 
     89         // Remove providers for missing services.
     90         if (targetIndex < mProviders.size()) {
     91             for (int i = mProviders.size() - 1; i >= targetIndex; i--) {
     92                 RegisteredMediaRouteProvider provider = mProviders.get(i);
     93                 mRouter.removeProvider(provider);
     94                 mProviders.remove(provider);
     95                 provider.stop();
     96             }
     97         }
     98     }
     99 
    100     private int findProvider(String packageName, String className) {
    101         int count = mProviders.size();
    102         for (int i = 0; i < count; i++) {
    103             RegisteredMediaRouteProvider provider = mProviders.get(i);
    104             if (provider.hasComponentName(packageName, className)) {
    105                 return i;
    106             }
    107         }
    108         return -1;
    109     }
    110 }
    111