Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit fe930f20 authored by Mathew Inwood's avatar Mathew Inwood Committed by Android (Google) Code Review
Browse files

Merge "Configurable hidden API exemptions." into pi-dev

parents 50c069e4 8faeab87
Loading
Loading
Loading
Loading
+54 −2
Original line number Diff line number Diff line
@@ -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;

@@ -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.
     */
@@ -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
@@ -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.
@@ -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;
        }
@@ -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)) {
+28 −1
Original line number Diff line number Diff line
@@ -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;

/**
@@ -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) +
@@ -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();
    }
@@ -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
@@ -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;
                }
@@ -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]);
                }
+4 −0
Original line number Diff line number Diff line
@@ -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
+19 −3
Original line number Diff line number Diff line
@@ -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);
@@ -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() {