Loading core/java/android/os/ISchedulingPolicyService.aidl +9 −0 Original line number Diff line number Diff line Loading @@ -31,4 +31,13 @@ interface ISchedulingPolicyService { */ int requestPriority(int pid, int tid, int prio, boolean isForApp); /** * Move media.codec process between SP_FOREGROUND and SP_TOP_APP. * When 'enable' is 'true', server will attempt to move media.codec process * from SP_FOREGROUND into SP_TOP_APP cpuset. A valid 'client' must be * provided for the server to receive death notifications. When 'enable' * is 'false', server will attempt to move media.codec process back to * the original cpuset, and 'client' is ignored in this case. */ int requestCpusetBoost(boolean enable, IBinder client); } services/core/java/com/android/server/os/SchedulingPolicyService.java +122 −2 Original line number Diff line number Diff line Loading @@ -18,8 +18,10 @@ package com.android.server.os; import android.content.pm.PackageManager; import android.os.Binder; import android.os.IBinder; import android.os.ISchedulingPolicyService; import android.os.Process; import android.os.RemoteException; import android.util.Log; /** Loading @@ -35,7 +37,36 @@ public class SchedulingPolicyService extends ISchedulingPolicyService.Stub { private static final int PRIORITY_MIN = 1; private static final int PRIORITY_MAX = 3; private static final String[] MEDIA_PROCESS_NAMES = new String[] { "media.codec", // vendor/bin/hw/android.hardware.media.omx@1.0-service }; private final IBinder.DeathRecipient mDeathRecipient = new IBinder.DeathRecipient() { @Override public void binderDied() { requestCpusetBoost(false /*enable*/, null /*client*/); } }; // Current process that received a cpuset boost private int mBoostedPid = -1; // Current client registered to the death recipient private IBinder mClient; public SchedulingPolicyService() { // system_server (our host) could have crashed before. The app may not survive // it, but mediaserver/media.codec could have, and mediaserver probably tried // to disable the boost while we were dead. // We do a restore of media.codec to default cpuset upon service restart to // catch this case. We can't leave media.codec in boosted state, because we've // lost the death recipient of mClient from mediaserver after the restart, // if mediaserver dies in the future we won't have a notification to reset. // (Note that if mediaserver thinks we're in boosted state before the crash, // the state could go out of sync temporarily until mediaserver enables/disable // boost next time, but this won't be a big issue.) int[] nativePids = Process.getPidsForCommands(MEDIA_PROCESS_NAMES); if (nativePids != null && nativePids.length == 1) { mBoostedPid = nativePids[0]; disableCpusetBoost(nativePids[0]); } } // TODO(b/35196900) We should pass the period in time units, rather Loading Loading @@ -74,6 +105,94 @@ public class SchedulingPolicyService extends ISchedulingPolicyService.Stub { return PackageManager.PERMISSION_GRANTED; } // Request to move media.codec process between SP_FOREGROUND and SP_TOP_APP. public int requestCpusetBoost(boolean enable, IBinder client) { if (!isPermitted()) { return PackageManager.PERMISSION_DENIED; } int[] nativePids = Process.getPidsForCommands(MEDIA_PROCESS_NAMES); if (nativePids == null || nativePids.length != 1) { Log.e(TAG, "requestCpusetBoost: can't find media.codec process"); return PackageManager.PERMISSION_DENIED; } synchronized (mDeathRecipient) { if (enable) { return enableCpusetBoost(nativePids[0], client); } else { return disableCpusetBoost(nativePids[0]); } } } private int enableCpusetBoost(int pid, IBinder client) { if (mBoostedPid == pid) { return PackageManager.PERMISSION_GRANTED; } // The mediacodec process has changed, clean up the old pid and // client before we boost the new process, so that the state // is left clean if things go wrong. mBoostedPid = -1; if (mClient != null) { try { mClient.unlinkToDeath(mDeathRecipient, 0); } catch (Exception e) { } finally { mClient = null; } } try { client.linkToDeath(mDeathRecipient, 0); Log.i(TAG, "Moving " + pid + " to group " + Process.THREAD_GROUP_TOP_APP); Process.setProcessGroup(pid, Process.THREAD_GROUP_TOP_APP); mBoostedPid = pid; mClient = client; return PackageManager.PERMISSION_GRANTED; } catch (Exception e) { Log.e(TAG, "Failed enableCpusetBoost: " + e); try { // unlink if things go wrong and don't crash. client.unlinkToDeath(mDeathRecipient, 0); } catch (Exception e1) {} } return PackageManager.PERMISSION_DENIED; } private int disableCpusetBoost(int pid) { int boostedPid = mBoostedPid; // Clean up states first. mBoostedPid = -1; if (mClient != null) { try { mClient.unlinkToDeath(mDeathRecipient, 0); } catch (Exception e) { } finally { mClient = null; } } // Try restore the old thread group, no need to fail as the // mediacodec process could be dead just now. if (boostedPid == pid) { try { Log.i(TAG, "Moving " + pid + " back to group default"); Process.setProcessGroup(pid, Process.THREAD_GROUP_DEFAULT); } catch (Exception e) { Log.w(TAG, "Couldn't move pid " + pid + " back to group default"); } } return PackageManager.PERMISSION_GRANTED; } private boolean isPermitted() { // schedulerservice hidl if (Binder.getCallingPid() == Process.myPid()) { Loading @@ -82,6 +201,7 @@ public class SchedulingPolicyService extends ISchedulingPolicyService.Stub { switch (Binder.getCallingUid()) { case Process.AUDIOSERVER_UID: // fastcapture, fastmixer case Process.MEDIA_UID: // mediaserver case Process.CAMERASERVER_UID: // camera high frame rate recording case Process.BLUETOOTH_UID: // Bluetooth audio playback return true; Loading Loading
core/java/android/os/ISchedulingPolicyService.aidl +9 −0 Original line number Diff line number Diff line Loading @@ -31,4 +31,13 @@ interface ISchedulingPolicyService { */ int requestPriority(int pid, int tid, int prio, boolean isForApp); /** * Move media.codec process between SP_FOREGROUND and SP_TOP_APP. * When 'enable' is 'true', server will attempt to move media.codec process * from SP_FOREGROUND into SP_TOP_APP cpuset. A valid 'client' must be * provided for the server to receive death notifications. When 'enable' * is 'false', server will attempt to move media.codec process back to * the original cpuset, and 'client' is ignored in this case. */ int requestCpusetBoost(boolean enable, IBinder client); }
services/core/java/com/android/server/os/SchedulingPolicyService.java +122 −2 Original line number Diff line number Diff line Loading @@ -18,8 +18,10 @@ package com.android.server.os; import android.content.pm.PackageManager; import android.os.Binder; import android.os.IBinder; import android.os.ISchedulingPolicyService; import android.os.Process; import android.os.RemoteException; import android.util.Log; /** Loading @@ -35,7 +37,36 @@ public class SchedulingPolicyService extends ISchedulingPolicyService.Stub { private static final int PRIORITY_MIN = 1; private static final int PRIORITY_MAX = 3; private static final String[] MEDIA_PROCESS_NAMES = new String[] { "media.codec", // vendor/bin/hw/android.hardware.media.omx@1.0-service }; private final IBinder.DeathRecipient mDeathRecipient = new IBinder.DeathRecipient() { @Override public void binderDied() { requestCpusetBoost(false /*enable*/, null /*client*/); } }; // Current process that received a cpuset boost private int mBoostedPid = -1; // Current client registered to the death recipient private IBinder mClient; public SchedulingPolicyService() { // system_server (our host) could have crashed before. The app may not survive // it, but mediaserver/media.codec could have, and mediaserver probably tried // to disable the boost while we were dead. // We do a restore of media.codec to default cpuset upon service restart to // catch this case. We can't leave media.codec in boosted state, because we've // lost the death recipient of mClient from mediaserver after the restart, // if mediaserver dies in the future we won't have a notification to reset. // (Note that if mediaserver thinks we're in boosted state before the crash, // the state could go out of sync temporarily until mediaserver enables/disable // boost next time, but this won't be a big issue.) int[] nativePids = Process.getPidsForCommands(MEDIA_PROCESS_NAMES); if (nativePids != null && nativePids.length == 1) { mBoostedPid = nativePids[0]; disableCpusetBoost(nativePids[0]); } } // TODO(b/35196900) We should pass the period in time units, rather Loading Loading @@ -74,6 +105,94 @@ public class SchedulingPolicyService extends ISchedulingPolicyService.Stub { return PackageManager.PERMISSION_GRANTED; } // Request to move media.codec process between SP_FOREGROUND and SP_TOP_APP. public int requestCpusetBoost(boolean enable, IBinder client) { if (!isPermitted()) { return PackageManager.PERMISSION_DENIED; } int[] nativePids = Process.getPidsForCommands(MEDIA_PROCESS_NAMES); if (nativePids == null || nativePids.length != 1) { Log.e(TAG, "requestCpusetBoost: can't find media.codec process"); return PackageManager.PERMISSION_DENIED; } synchronized (mDeathRecipient) { if (enable) { return enableCpusetBoost(nativePids[0], client); } else { return disableCpusetBoost(nativePids[0]); } } } private int enableCpusetBoost(int pid, IBinder client) { if (mBoostedPid == pid) { return PackageManager.PERMISSION_GRANTED; } // The mediacodec process has changed, clean up the old pid and // client before we boost the new process, so that the state // is left clean if things go wrong. mBoostedPid = -1; if (mClient != null) { try { mClient.unlinkToDeath(mDeathRecipient, 0); } catch (Exception e) { } finally { mClient = null; } } try { client.linkToDeath(mDeathRecipient, 0); Log.i(TAG, "Moving " + pid + " to group " + Process.THREAD_GROUP_TOP_APP); Process.setProcessGroup(pid, Process.THREAD_GROUP_TOP_APP); mBoostedPid = pid; mClient = client; return PackageManager.PERMISSION_GRANTED; } catch (Exception e) { Log.e(TAG, "Failed enableCpusetBoost: " + e); try { // unlink if things go wrong and don't crash. client.unlinkToDeath(mDeathRecipient, 0); } catch (Exception e1) {} } return PackageManager.PERMISSION_DENIED; } private int disableCpusetBoost(int pid) { int boostedPid = mBoostedPid; // Clean up states first. mBoostedPid = -1; if (mClient != null) { try { mClient.unlinkToDeath(mDeathRecipient, 0); } catch (Exception e) { } finally { mClient = null; } } // Try restore the old thread group, no need to fail as the // mediacodec process could be dead just now. if (boostedPid == pid) { try { Log.i(TAG, "Moving " + pid + " back to group default"); Process.setProcessGroup(pid, Process.THREAD_GROUP_DEFAULT); } catch (Exception e) { Log.w(TAG, "Couldn't move pid " + pid + " back to group default"); } } return PackageManager.PERMISSION_GRANTED; } private boolean isPermitted() { // schedulerservice hidl if (Binder.getCallingPid() == Process.myPid()) { Loading @@ -82,6 +201,7 @@ public class SchedulingPolicyService extends ISchedulingPolicyService.Stub { switch (Binder.getCallingUid()) { case Process.AUDIOSERVER_UID: // fastcapture, fastmixer case Process.MEDIA_UID: // mediaserver case Process.CAMERASERVER_UID: // camera high frame rate recording case Process.BLUETOOTH_UID: // Bluetooth audio playback return true; Loading