1 /* 2 * Copyright (C) 2016 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.server.media; 18 19 import android.app.ActivityManager; 20 import android.content.Context; 21 import android.content.Intent; 22 import android.media.IMediaResourceMonitor; 23 import android.os.Binder; 24 import android.os.RemoteException; 25 import android.os.UserHandle; 26 import android.os.UserManager; 27 import android.util.Log; 28 import android.util.Slog; 29 import com.android.server.SystemService; 30 31 import java.util.List; 32 33 /** This class provides a system service that monitors media resource usage. */ 34 public class MediaResourceMonitorService extends SystemService { 35 private static final String TAG = "MediaResourceMonitor"; 36 private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG); 37 38 private static final String SERVICE_NAME = "media_resource_monitor"; 39 40 private final MediaResourceMonitorImpl mMediaResourceMonitorImpl; 41 42 public MediaResourceMonitorService(Context context) { 43 super(context); 44 mMediaResourceMonitorImpl = new MediaResourceMonitorImpl(); 45 } 46 47 @Override 48 public void onStart() { 49 publishBinderService(SERVICE_NAME, mMediaResourceMonitorImpl); 50 } 51 52 class MediaResourceMonitorImpl extends IMediaResourceMonitor.Stub { 53 @Override 54 public void notifyResourceGranted(int pid, int type) 55 throws RemoteException { 56 if (DEBUG) { 57 Slog.d(TAG, "notifyResourceGranted(pid=" + pid + ", type=" + type + ")"); 58 } 59 final long identity = Binder.clearCallingIdentity(); 60 try { 61 String pkgNames[] = getPackageNamesFromPid(pid); 62 if (pkgNames == null) { 63 return; 64 } 65 UserManager manager = (UserManager) getContext().getSystemService( 66 Context.USER_SERVICE); 67 int[] userIds = manager.getEnabledProfileIds(ActivityManager.getCurrentUser()); 68 if (userIds == null || userIds.length == 0) { 69 return; 70 } 71 Intent intent = new Intent(Intent.ACTION_MEDIA_RESOURCE_GRANTED); 72 intent.putExtra(Intent.EXTRA_PACKAGES, pkgNames); 73 intent.putExtra(Intent.EXTRA_MEDIA_RESOURCE_TYPE, type); 74 for (int userId : userIds) { 75 getContext().sendBroadcastAsUser(intent, UserHandle.of(userId), 76 android.Manifest.permission.RECEIVE_MEDIA_RESOURCE_USAGE); 77 } 78 } finally { 79 Binder.restoreCallingIdentity(identity); 80 } 81 } 82 83 private String[] getPackageNamesFromPid(int pid) { 84 try { 85 for (ActivityManager.RunningAppProcessInfo proc : 86 ActivityManager.getService().getRunningAppProcesses()) { 87 if (proc.pid == pid) { 88 return proc.pkgList; 89 } 90 } 91 } catch (RemoteException e) { 92 Slog.w(TAG, "ActivityManager.getRunningAppProcesses() failed"); 93 } 94 return null; 95 } 96 } 97 } 98