Loading core/java/android/os/ZygoteProcess.java +54 −2 Original line number Diff line number Diff line Loading @@ -32,6 +32,7 @@ import java.io.OutputStreamWriter; import java.nio.charset.StandardCharsets; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import java.util.List; import java.util.UUID; Loading Loading @@ -157,6 +158,13 @@ public class ZygoteProcess { */ private final Object mLock = new Object(); /** * List of exemptions to the API blacklist. These are prefix matches on the runtime format * symbol signature. Any matching symbol is treated by the runtime as being on the light grey * list. */ private List<String> mApiBlacklistExemptions = Collections.emptyList(); /** * The state of the connection to the primary zygote. */ Loading @@ -175,7 +183,7 @@ public class ZygoteProcess { * The process will continue running after this function returns. * * <p>If processes are not enabled, a new thread in the caller's * process is created and main() of <var>processClass</var> called there. * process is created and main() of <var>processclass</var> called there. * * <p>The niceName parameter, if not an empty string, is a custom name to * give to the process instead of using processClass. This allows you to Loading Loading @@ -453,6 +461,49 @@ public class ZygoteProcess { } } /** * Push hidden API blacklisting exemptions into the zygote process(es). * * <p>The list of exemptions will take affect for all new processes forked from the zygote after * this call. * * @param exemptions List of hidden API exemption prefixes. */ public void setApiBlacklistExemptions(List<String> exemptions) { synchronized (mLock) { mApiBlacklistExemptions = exemptions; maybeSetApiBlacklistExemptions(primaryZygoteState, true); maybeSetApiBlacklistExemptions(secondaryZygoteState, true); } } @GuardedBy("mLock") private void maybeSetApiBlacklistExemptions(ZygoteState state, boolean sendIfEmpty) { if (state == null || state.isClosed()) { return; } if (!sendIfEmpty && mApiBlacklistExemptions.isEmpty()) { return; } try { state.writer.write(Integer.toString(mApiBlacklistExemptions.size() + 1)); state.writer.newLine(); state.writer.write("--set-api-blacklist-exemptions"); state.writer.newLine(); for (int i = 0; i < mApiBlacklistExemptions.size(); ++i) { state.writer.write(mApiBlacklistExemptions.get(i)); state.writer.newLine(); } state.writer.flush(); int status = state.inputStream.readInt(); if (status != 0) { Slog.e(LOG_TAG, "Failed to set API blacklist exemptions; status " + status); } } catch (IOException ioe) { Slog.e(LOG_TAG, "Failed to set API blacklist exemptions", ioe); } } /** * Tries to open socket to Zygote process if not already open. If * already open, does nothing. May block and retry. Requires that mLock be held. Loading @@ -467,8 +518,8 @@ public class ZygoteProcess { } catch (IOException ioe) { throw new ZygoteStartFailedEx("Error connecting to primary zygote", ioe); } maybeSetApiBlacklistExemptions(primaryZygoteState, false); } if (primaryZygoteState.matches(abi)) { return primaryZygoteState; } Loading @@ -480,6 +531,7 @@ public class ZygoteProcess { } catch (IOException ioe) { throw new ZygoteStartFailedEx("Error connecting to secondary zygote", ioe); } maybeSetApiBlacklistExemptions(secondaryZygoteState, false); } if (secondaryZygoteState.matches(abi)) { Loading core/java/com/android/internal/os/ZygoteConnection.java +28 −1 Original line number Diff line number Diff line Loading @@ -47,6 +47,8 @@ import java.io.IOException; import java.io.InputStreamReader; import java.nio.charset.StandardCharsets; import java.util.ArrayList; import java.util.Arrays; import libcore.io.IoUtils; /** Loading Loading @@ -159,6 +161,11 @@ class ZygoteConnection { return null; } if (parsedArgs.apiBlacklistExemptions != null) { handleApiBlacklistExemptions(parsedArgs.apiBlacklistExemptions); return null; } if (parsedArgs.permittedCapabilities != 0 || parsedArgs.effectiveCapabilities != 0) { throw new ZygoteSecurityException("Client may not specify capabilities: " + "permitted=0x" + Long.toHexString(parsedArgs.permittedCapabilities) + Loading Loading @@ -278,6 +285,15 @@ class ZygoteConnection { } } private void handleApiBlacklistExemptions(String[] exemptions) { try { ZygoteInit.setApiBlacklistExemptions(exemptions); mSocketOutStream.writeInt(0); } catch (IOException ioe) { throw new IllegalStateException("Error writing to command socket", ioe); } } protected void preload() { ZygoteInit.lazyPreload(); } Loading Loading @@ -438,6 +454,12 @@ class ZygoteConnection { */ boolean startChildZygote; /** * Exemptions from API blacklisting. These are sent to the pre-forked zygote at boot time, * or when they change, via --set-api-blacklist-exemptions. */ String[] apiBlacklistExemptions; /** * Constructs instance and parses args * @param args zygote command-line args Loading Loading @@ -592,6 +614,11 @@ class ZygoteConnection { preloadDefault = true; } else if (arg.equals("--start-child-zygote")) { startChildZygote = true; } else if (arg.equals("--set-api-blacklist-exemptions")) { // consume all remaining args; this is a stand-alone command, never included // with the regular fork command. apiBlacklistExemptions = Arrays.copyOfRange(args, curArg + 1, args.length); curArg = args.length; } else { break; } Loading @@ -606,7 +633,7 @@ class ZygoteConnection { throw new IllegalArgumentException( "Unexpected arguments after --preload-package."); } } else if (!preloadDefault) { } else if (!preloadDefault && apiBlacklistExemptions == null) { if (!seenRuntimeArgs) { throw new IllegalArgumentException("Unexpected argument : " + args[curArg]); } Loading core/java/com/android/internal/os/ZygoteInit.java +4 −0 Original line number Diff line number Diff line Loading @@ -514,6 +514,10 @@ public class ZygoteInit { /* should never reach here */ } public static void setApiBlacklistExemptions(String[] exemptions) { VMRuntime.getRuntime().setHiddenApiExemptions(exemptions); } /** * Creates a PathClassLoader for the given class path that is associated with a shared * namespace, i.e., this classloader can access platform-private native libraries. The Loading services/core/java/com/android/server/am/ActivityManagerService.java +19 −3 Original line number Diff line number Diff line Loading @@ -2873,13 +2873,15 @@ public class ActivityManagerService extends IActivityManager.Stub } /** * Encapsulates the globla setting "hidden_api_blacklist_exemptions", including tracking the * Encapsulates the global setting "hidden_api_blacklist_exemptions", including tracking the * latest value via a content observer. */ static class HiddenApiBlacklist extends ContentObserver { private final Context mContext; private boolean mBlacklistDisabled; private String mExemptionsStr; private List<String> mExemptions = Collections.emptyList(); public HiddenApiBlacklist(Handler handler, Context context) { super(handler); Loading @@ -2895,8 +2897,22 @@ public class ActivityManagerService extends IActivityManager.Stub } private void update() { mBlacklistDisabled = "*".equals(Settings.Global.getString(mContext.getContentResolver(), Settings.Global.HIDDEN_API_BLACKLIST_EXEMPTIONS)); String exemptions = Settings.Global.getString(mContext.getContentResolver(), Settings.Global.HIDDEN_API_BLACKLIST_EXEMPTIONS); if (!TextUtils.equals(exemptions, mExemptionsStr)) { mExemptionsStr = exemptions; if ("*".equals(exemptions)) { mBlacklistDisabled = true; mExemptions = Collections.emptyList(); } else { mBlacklistDisabled = false; mExemptions = TextUtils.isEmpty(exemptions) ? Collections.emptyList() : Arrays.asList(exemptions.split(":")); } zygoteProcess.setApiBlacklistExemptions(mExemptions); } } boolean isDisabled() { Loading
core/java/android/os/ZygoteProcess.java +54 −2 Original line number Diff line number Diff line Loading @@ -32,6 +32,7 @@ import java.io.OutputStreamWriter; import java.nio.charset.StandardCharsets; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import java.util.List; import java.util.UUID; Loading Loading @@ -157,6 +158,13 @@ public class ZygoteProcess { */ private final Object mLock = new Object(); /** * List of exemptions to the API blacklist. These are prefix matches on the runtime format * symbol signature. Any matching symbol is treated by the runtime as being on the light grey * list. */ private List<String> mApiBlacklistExemptions = Collections.emptyList(); /** * The state of the connection to the primary zygote. */ Loading @@ -175,7 +183,7 @@ public class ZygoteProcess { * The process will continue running after this function returns. * * <p>If processes are not enabled, a new thread in the caller's * process is created and main() of <var>processClass</var> called there. * process is created and main() of <var>processclass</var> called there. * * <p>The niceName parameter, if not an empty string, is a custom name to * give to the process instead of using processClass. This allows you to Loading Loading @@ -453,6 +461,49 @@ public class ZygoteProcess { } } /** * Push hidden API blacklisting exemptions into the zygote process(es). * * <p>The list of exemptions will take affect for all new processes forked from the zygote after * this call. * * @param exemptions List of hidden API exemption prefixes. */ public void setApiBlacklistExemptions(List<String> exemptions) { synchronized (mLock) { mApiBlacklistExemptions = exemptions; maybeSetApiBlacklistExemptions(primaryZygoteState, true); maybeSetApiBlacklistExemptions(secondaryZygoteState, true); } } @GuardedBy("mLock") private void maybeSetApiBlacklistExemptions(ZygoteState state, boolean sendIfEmpty) { if (state == null || state.isClosed()) { return; } if (!sendIfEmpty && mApiBlacklistExemptions.isEmpty()) { return; } try { state.writer.write(Integer.toString(mApiBlacklistExemptions.size() + 1)); state.writer.newLine(); state.writer.write("--set-api-blacklist-exemptions"); state.writer.newLine(); for (int i = 0; i < mApiBlacklistExemptions.size(); ++i) { state.writer.write(mApiBlacklistExemptions.get(i)); state.writer.newLine(); } state.writer.flush(); int status = state.inputStream.readInt(); if (status != 0) { Slog.e(LOG_TAG, "Failed to set API blacklist exemptions; status " + status); } } catch (IOException ioe) { Slog.e(LOG_TAG, "Failed to set API blacklist exemptions", ioe); } } /** * Tries to open socket to Zygote process if not already open. If * already open, does nothing. May block and retry. Requires that mLock be held. Loading @@ -467,8 +518,8 @@ public class ZygoteProcess { } catch (IOException ioe) { throw new ZygoteStartFailedEx("Error connecting to primary zygote", ioe); } maybeSetApiBlacklistExemptions(primaryZygoteState, false); } if (primaryZygoteState.matches(abi)) { return primaryZygoteState; } Loading @@ -480,6 +531,7 @@ public class ZygoteProcess { } catch (IOException ioe) { throw new ZygoteStartFailedEx("Error connecting to secondary zygote", ioe); } maybeSetApiBlacklistExemptions(secondaryZygoteState, false); } if (secondaryZygoteState.matches(abi)) { Loading
core/java/com/android/internal/os/ZygoteConnection.java +28 −1 Original line number Diff line number Diff line Loading @@ -47,6 +47,8 @@ import java.io.IOException; import java.io.InputStreamReader; import java.nio.charset.StandardCharsets; import java.util.ArrayList; import java.util.Arrays; import libcore.io.IoUtils; /** Loading Loading @@ -159,6 +161,11 @@ class ZygoteConnection { return null; } if (parsedArgs.apiBlacklistExemptions != null) { handleApiBlacklistExemptions(parsedArgs.apiBlacklistExemptions); return null; } if (parsedArgs.permittedCapabilities != 0 || parsedArgs.effectiveCapabilities != 0) { throw new ZygoteSecurityException("Client may not specify capabilities: " + "permitted=0x" + Long.toHexString(parsedArgs.permittedCapabilities) + Loading Loading @@ -278,6 +285,15 @@ class ZygoteConnection { } } private void handleApiBlacklistExemptions(String[] exemptions) { try { ZygoteInit.setApiBlacklistExemptions(exemptions); mSocketOutStream.writeInt(0); } catch (IOException ioe) { throw new IllegalStateException("Error writing to command socket", ioe); } } protected void preload() { ZygoteInit.lazyPreload(); } Loading Loading @@ -438,6 +454,12 @@ class ZygoteConnection { */ boolean startChildZygote; /** * Exemptions from API blacklisting. These are sent to the pre-forked zygote at boot time, * or when they change, via --set-api-blacklist-exemptions. */ String[] apiBlacklistExemptions; /** * Constructs instance and parses args * @param args zygote command-line args Loading Loading @@ -592,6 +614,11 @@ class ZygoteConnection { preloadDefault = true; } else if (arg.equals("--start-child-zygote")) { startChildZygote = true; } else if (arg.equals("--set-api-blacklist-exemptions")) { // consume all remaining args; this is a stand-alone command, never included // with the regular fork command. apiBlacklistExemptions = Arrays.copyOfRange(args, curArg + 1, args.length); curArg = args.length; } else { break; } Loading @@ -606,7 +633,7 @@ class ZygoteConnection { throw new IllegalArgumentException( "Unexpected arguments after --preload-package."); } } else if (!preloadDefault) { } else if (!preloadDefault && apiBlacklistExemptions == null) { if (!seenRuntimeArgs) { throw new IllegalArgumentException("Unexpected argument : " + args[curArg]); } Loading
core/java/com/android/internal/os/ZygoteInit.java +4 −0 Original line number Diff line number Diff line Loading @@ -514,6 +514,10 @@ public class ZygoteInit { /* should never reach here */ } public static void setApiBlacklistExemptions(String[] exemptions) { VMRuntime.getRuntime().setHiddenApiExemptions(exemptions); } /** * Creates a PathClassLoader for the given class path that is associated with a shared * namespace, i.e., this classloader can access platform-private native libraries. The Loading
services/core/java/com/android/server/am/ActivityManagerService.java +19 −3 Original line number Diff line number Diff line Loading @@ -2873,13 +2873,15 @@ public class ActivityManagerService extends IActivityManager.Stub } /** * Encapsulates the globla setting "hidden_api_blacklist_exemptions", including tracking the * Encapsulates the global setting "hidden_api_blacklist_exemptions", including tracking the * latest value via a content observer. */ static class HiddenApiBlacklist extends ContentObserver { private final Context mContext; private boolean mBlacklistDisabled; private String mExemptionsStr; private List<String> mExemptions = Collections.emptyList(); public HiddenApiBlacklist(Handler handler, Context context) { super(handler); Loading @@ -2895,8 +2897,22 @@ public class ActivityManagerService extends IActivityManager.Stub } private void update() { mBlacklistDisabled = "*".equals(Settings.Global.getString(mContext.getContentResolver(), Settings.Global.HIDDEN_API_BLACKLIST_EXEMPTIONS)); String exemptions = Settings.Global.getString(mContext.getContentResolver(), Settings.Global.HIDDEN_API_BLACKLIST_EXEMPTIONS); if (!TextUtils.equals(exemptions, mExemptionsStr)) { mExemptionsStr = exemptions; if ("*".equals(exemptions)) { mBlacklistDisabled = true; mExemptions = Collections.emptyList(); } else { mBlacklistDisabled = false; mExemptions = TextUtils.isEmpty(exemptions) ? Collections.emptyList() : Arrays.asList(exemptions.split(":")); } zygoteProcess.setApiBlacklistExemptions(mExemptions); } } boolean isDisabled() {