Loading core/java/android/app/ActivityManagerInternal.java +1 −1 Original line number Diff line number Diff line Loading @@ -299,7 +299,7 @@ public abstract class ActivityManagerInternal { /** Starts a given process. */ public abstract void startProcess(String processName, ApplicationInfo info, boolean knownToBeDead, String hostingType, ComponentName hostingName); boolean knownToBeDead, boolean isTop, String hostingType, ComponentName hostingName); /** Starts up the starting activity process for debugging if needed. * This function needs to be called synchronously from WindowManager context so the caller Loading core/java/android/net/NetworkPolicyManager.java +5 −0 Original line number Diff line number Diff line Loading @@ -63,6 +63,8 @@ public class NetworkPolicyManager { public static final int POLICY_REJECT_ON_VPN = 0x20000; /** Reject network usage on wifi network */ public static final int POLICY_REJECT_ON_WLAN = 0x8000; /** Reject network usage on all networks at all times */ public static final int POLICY_NETWORK_ISOLATED = 0x40000; /* * Rules defining whether an uid has access to a network given its type (metered / non-metered). Loading Loading @@ -93,6 +95,8 @@ public class NetworkPolicyManager { public static final int RULE_ALLOW_ALL = 1 << 5; /** Reject traffic on all networks. */ public static final int RULE_REJECT_ALL = 1 << 6; /** Reject traffic on all networks at all times */ public static final int RULE_NETWORK_ISOLATED = 1 << 7; /** Mask used to get the {@code RULE_xxx_METERED} rules */ public static final int MASK_METERED_NETWORKS = 0b00001111; /** Mask used to get the {@code RULE_xxx_ALL} rules */ Loading @@ -104,6 +108,7 @@ public class NetworkPolicyManager { public static final String FIREWALL_CHAIN_NAME_DOZABLE = "dozable"; public static final String FIREWALL_CHAIN_NAME_STANDBY = "standby"; public static final String FIREWALL_CHAIN_NAME_POWERSAVE = "powersave"; public static final String FIREWALL_CHAIN_NAME_ISOLATED = "isolated"; private static final boolean ALLOW_PLATFORM_APP_POLICY = true; Loading core/java/android/os/Process.java +41 −3 Original line number Diff line number Diff line Loading @@ -472,6 +472,40 @@ public class Process { private static long sStartElapsedRealtime; private static long sStartUptimeMillis; /** * Value used to indicate that there is no special information about an application launch. App * launches with this policy will occur through the primary or secondary Zygote with no special * treatment. * * @hide */ public static final int ZYGOTE_POLICY_FLAG_EMPTY = 0; /** * Flag used to indicate that an application launch is user-visible and latency sensitive. Any * launch with this policy will use a Unspecialized App Process Pool if the target Zygote * supports it. * * @hide */ public static final int ZYGOTE_POLICY_FLAG_LATENCY_SENSITIVE = 1 << 0; /** * Flag used to indicate that the launch is one in a series of app launches that will be * performed in quick succession. For future use. * * @hide */ public static final int ZYGOTE_POLICY_FLAG_BATCH_LAUNCH = 1 << 1; /** * Flag used to indicate that the current launch event is for a system process. All system * processes are equally important, so none of them should be prioritized over the others. * * @hide */ public static final int ZYGOTE_POLICY_FLAG_SYSTEM_PROCESS = 1 << 2; /** * State associated with the zygote process. * @hide Loading Loading @@ -511,7 +545,8 @@ public class Process { * @param appDataDir null-ok the data directory of the app. * @param invokeWith null-ok the command to invoke with. * @param packageName null-ok the name of the package this process belongs to. * * @param zygotePolicyFlags Flags used to determine how to launch the application * @param isTopApp whether the process starts for high priority application. * @param zygoteArgs Additional arguments to supply to the zygote process. * @return An object that describes the result of the attempt to start the process. * @throws RuntimeException on fatal start failure Loading @@ -530,11 +565,13 @@ public class Process { @Nullable String appDataDir, @Nullable String invokeWith, @Nullable String packageName, int zygotePolicyFlags, boolean isTopApp, @Nullable String[] zygoteArgs) { return ZYGOTE_PROCESS.start(processClass, niceName, uid, gid, gids, runtimeFlags, mountExternal, targetSdkVersion, seInfo, abi, instructionSet, appDataDir, invokeWith, packageName, /*useUsapPool=*/ true, zygoteArgs); zygotePolicyFlags, isTopApp, zygoteArgs); } /** @hide */ Loading @@ -554,7 +591,8 @@ public class Process { return WebViewZygote.getProcess().start(processClass, niceName, uid, gid, gids, runtimeFlags, mountExternal, targetSdkVersion, seInfo, abi, instructionSet, appDataDir, invokeWith, packageName, /*useUsapPool=*/ false, zygoteArgs); /*zygotePolicyFlags=*/ ZYGOTE_POLICY_FLAG_EMPTY, /*isTopApp=*/ false, zygoteArgs); } /** Loading core/java/android/os/ZygoteProcess.java +81 −11 Original line number Diff line number Diff line Loading @@ -16,6 +16,9 @@ package android.os; import static android.os.Process.ZYGOTE_POLICY_FLAG_LATENCY_SENSITIVE; import static android.os.Process.ZYGOTE_POLICY_FLAG_SYSTEM_PROCESS; import android.annotation.NonNull; import android.annotation.Nullable; import android.annotation.UnsupportedAppUsage; Loading Loading @@ -117,6 +120,10 @@ public class ZygoteProcess { mUsapPoolSecondarySocketAddress = new LocalSocketAddress(Zygote.USAP_POOL_SECONDARY_SOCKET_NAME, LocalSocketAddress.Namespace.RESERVED); // This constructor is used to create the primary and secondary Zygotes, which can support // Unspecialized App Process Pools. mUsapPoolSupported = true; } public ZygoteProcess(LocalSocketAddress primarySocketAddress, Loading @@ -126,6 +133,10 @@ public class ZygoteProcess { mUsapPoolSocketAddress = null; mUsapPoolSecondarySocketAddress = null; // This constructor is used to create the primary and secondary Zygotes, which CAN NOT // support Unspecialized App Process Pools. mUsapPoolSupported = false; } public LocalSocketAddress getPrimarySocketAddress() { Loading Loading @@ -264,6 +275,14 @@ public class ZygoteProcess { */ private ZygoteState secondaryZygoteState; /** * If this Zygote supports the creation and maintenance of a USAP pool. * * Currently only the primary and secondary Zygotes support USAP pools. Any * child Zygotes will be unable to create or use a USAP pool. */ private final boolean mUsapPoolSupported; /** * If the USAP pool should be created and used to start applications. * Loading Loading @@ -306,8 +325,9 @@ public class ZygoteProcess { * @param appDataDir null-ok the data directory of the app. * @param invokeWith null-ok the command to invoke with. * @param packageName null-ok the name of the package this process belongs to. * @param zygoteArgs Additional arguments to supply to the zygote process. * * @param zygotePolicyFlags Flags used to determine how to launch the application. * @param isTopApp Whether the process starts for high priority application. * @param zygoteArgs Additional arguments to supply to the Zygote process. * @return An object that describes the result of the attempt to start the process. * @throws RuntimeException on fatal start failure */ Loading @@ -322,7 +342,8 @@ public class ZygoteProcess { @Nullable String appDataDir, @Nullable String invokeWith, @Nullable String packageName, boolean useUsapPool, int zygotePolicyFlags, boolean isTopApp, @Nullable String[] zygoteArgs) { // TODO (chriswailes): Is there a better place to check this value? if (fetchUsapPoolEnabledPropWithMinInterval()) { Loading @@ -333,7 +354,7 @@ public class ZygoteProcess { return startViaZygote(processClass, niceName, uid, gid, gids, runtimeFlags, mountExternal, targetSdkVersion, seInfo, abi, instructionSet, appDataDir, invokeWith, /*startChildZygote=*/ false, packageName, useUsapPool, zygoteArgs); packageName, zygotePolicyFlags, isTopApp, zygoteArgs); } catch (ZygoteStartFailedEx ex) { Log.e(LOG_TAG, "Starting VM process through Zygote failed"); Loading Loading @@ -379,7 +400,7 @@ public class ZygoteProcess { */ @GuardedBy("mLock") private Process.ProcessStartResult zygoteSendArgsAndGetResult( ZygoteState zygoteState, boolean useUsapPool, @NonNull ArrayList<String> args) ZygoteState zygoteState, int zygotePolicyFlags, @NonNull ArrayList<String> args) throws ZygoteStartFailedEx { // Throw early if any of the arguments are malformed. This means we can // avoid writing a partial response to the zygote. Loading @@ -405,7 +426,7 @@ public class ZygoteProcess { */ String msgStr = args.size() + "\n" + String.join("\n", args) + "\n"; if (useUsapPool && mUsapPoolEnabled && canAttemptUsap(args)) { if (shouldAttemptUsapLaunch(zygotePolicyFlags, args)) { try { return attemptUsapSendArgsAndGetResult(zygoteState, msgStr); } catch (IOException ex) { Loading Loading @@ -476,7 +497,43 @@ public class ZygoteProcess { } /** * Flags that may not be passed to a USAP. * Test various member properties and parameters to determine if a launch event should be * handled using an Unspecialized App Process Pool or not. * * @param zygotePolicyFlags Policy flags indicating special behavioral observations about the * Zygote command * @param args Arguments that will be passed to the Zygote * @return If the command should be sent to a USAP Pool member or an actual Zygote */ private boolean shouldAttemptUsapLaunch(int zygotePolicyFlags, ArrayList<String> args) { return mUsapPoolSupported && mUsapPoolEnabled && policySpecifiesUsapPoolLaunch(zygotePolicyFlags) && commandSupportedByUsap(args); } /** * Tests a Zygote policy flag set for various properties that determine if it is eligible for * being handled by an Unspecialized App Process Pool. * * @param zygotePolicyFlags Policy flags indicating special behavioral observations about the * Zygote command * @return If the policy allows for use of a USAP pool */ private static boolean policySpecifiesUsapPoolLaunch(int zygotePolicyFlags) { /* * Zygote USAP Pool Policy: Launch the new process from the USAP Pool iff the launch event * is latency sensitive but *NOT* a system process. All system processes are equally * important so we don't want to prioritize one over another. */ return (zygotePolicyFlags & (ZYGOTE_POLICY_FLAG_SYSTEM_PROCESS | ZYGOTE_POLICY_FLAG_LATENCY_SENSITIVE)) == ZYGOTE_POLICY_FLAG_LATENCY_SENSITIVE; } /** * Flags that may not be passed to a USAP. These may appear as prefixes to individual Zygote * arguments. */ private static final String[] INVALID_USAP_FLAGS = { "--query-abi-list", Loading @@ -493,10 +550,11 @@ public class ZygoteProcess { /** * Tests a command list to see if it is valid to send to a USAP. * * @param args Zygote/USAP command arguments * @return True if the command can be passed to a USAP; false otherwise */ private static boolean canAttemptUsap(ArrayList<String> args) { private static boolean commandSupportedByUsap(ArrayList<String> args) { for (String flag : args) { for (String badFlag : INVALID_USAP_FLAGS) { if (flag.startsWith(badFlag)) { Loading Loading @@ -534,6 +592,8 @@ public class ZygoteProcess { * @param startChildZygote Start a sub-zygote. This creates a new zygote process * that has its state cloned from this zygote process. * @param packageName null-ok the name of the package this process belongs to. * @param zygotePolicyFlags Flags used to determine how to launch the application. * @param isTopApp Whether the process starts for high priority application. * @param extraArgs Additional arguments to supply to the zygote process. * @return An object that describes the result of the attempt to start the process. * @throws ZygoteStartFailedEx if process start failed for any reason Loading @@ -551,7 +611,8 @@ public class ZygoteProcess { @Nullable String invokeWith, boolean startChildZygote, @Nullable String packageName, boolean useUsapPool, int zygotePolicyFlags, boolean isTopApp, @Nullable String[] extraArgs) throws ZygoteStartFailedEx { ArrayList<String> argsForZygote = new ArrayList<>(); Loading Loading @@ -623,6 +684,10 @@ public class ZygoteProcess { argsForZygote.add("--package-name=" + packageName); } if (isTopApp) { argsForZygote.add(Zygote.START_AS_TOP_APP_ARG); } argsForZygote.add(processClass); if (extraArgs != null) { Loading @@ -633,7 +698,7 @@ public class ZygoteProcess { // The USAP pool can not be used if the application will not use the systems graphics // driver. If that driver is requested use the Zygote application start path. return zygoteSendArgsAndGetResult(openZygoteSocketIfNeeded(abi), useUsapPool, zygotePolicyFlags, argsForZygote); } } Loading Loading @@ -663,6 +728,10 @@ public class ZygoteProcess { private long mLastPropCheckTimestamp = 0; private boolean fetchUsapPoolEnabledPropWithMinInterval() { // If this Zygote doesn't support USAPs there is no need to fetch any // properties. if (!mUsapPoolSupported) return false; final long currentTimestamp = SystemClock.elapsedRealtime(); if (SystemProperties.get("dalvik.vm.boot-image", "").endsWith("apex.art")) { Loading Loading @@ -1144,7 +1213,8 @@ public class ZygoteProcess { gids, runtimeFlags, 0 /* mountExternal */, 0 /* targetSdkVersion */, seInfo, abi, instructionSet, null /* appDataDir */, null /* invokeWith */, true /* startChildZygote */, null /* packageName */, false /* useUsapPool */, extraArgs); ZYGOTE_POLICY_FLAG_SYSTEM_PROCESS /* zygotePolicyFlags */, false /* isTopApp */, extraArgs); } catch (ZygoteStartFailedEx ex) { throw new RuntimeException("Starting child-zygote through Zygote failed", ex); } Loading core/java/android/widget/SelectionActionModeHelper.java +55 −17 Original line number Diff line number Diff line Loading @@ -104,17 +104,44 @@ public final class SelectionActionModeHelper { } } /** * Swap the selection index if the start index is greater than end index. * * @return the swap result, index 0 is the start index and index 1 is the end index. */ private static int[] sortSelectionIndices(int selectionStart, int selectionEnd) { if (selectionStart < selectionEnd) { return new int[]{selectionStart, selectionEnd}; } return new int[]{selectionEnd, selectionStart}; } /** * The {@link TextView} selection start and end index may not be sorted, this method will swap * the {@link TextView} selection index if the start index is greater than end index. * * @param textView the selected TextView. * @return the swap result, index 0 is the start index and index 1 is the end index. */ private static int[] sortSelectionIndicesFromTextView(TextView textView) { int selectionStart = textView.getSelectionStart(); int selectionEnd = textView.getSelectionEnd(); return sortSelectionIndices(selectionStart, selectionEnd); } /** * Starts Selection ActionMode. */ public void startSelectionActionModeAsync(boolean adjustSelection) { // Check if the smart selection should run for editable text. adjustSelection &= getTextClassificationSettings().isSmartSelectionEnabled(); int[] sortedSelectionIndices = sortSelectionIndicesFromTextView(mTextView); mSelectionTracker.onOriginalSelection( getText(mTextView), mTextView.getSelectionStart(), mTextView.getSelectionEnd(), sortedSelectionIndices[0], sortedSelectionIndices[1], false /*isLink*/); cancelAsyncTask(); if (skipTextClassification()) { Loading @@ -139,12 +166,14 @@ public final class SelectionActionModeHelper { * Starts Link ActionMode. */ public void startLinkActionModeAsync(int start, int end) { mSelectionTracker.onOriginalSelection(getText(mTextView), start, end, true /*isLink*/); int[] indexResult = sortSelectionIndices(start, end); mSelectionTracker.onOriginalSelection(getText(mTextView), indexResult[0], indexResult[1], true /*isLink*/); cancelAsyncTask(); if (skipTextClassification()) { startLinkActionMode(null); } else { resetTextClassificationHelper(start, end); resetTextClassificationHelper(indexResult[0], indexResult[1]); mTextClassificationAsyncTask = new TextClassificationAsyncTask( mTextView, mTextClassificationHelper.getTimeoutDuration(), Loading Loading @@ -173,19 +202,23 @@ public final class SelectionActionModeHelper { /** Reports a selection action event. */ public void onSelectionAction(int menuItemId, @Nullable String actionLabel) { int[] sortedSelectionIndices = sortSelectionIndicesFromTextView(mTextView); mSelectionTracker.onSelectionAction( mTextView.getSelectionStart(), mTextView.getSelectionEnd(), sortedSelectionIndices[0], sortedSelectionIndices[1], getActionType(menuItemId), actionLabel, mTextClassification); } public void onSelectionDrag() { int[] sortedSelectionIndices = sortSelectionIndicesFromTextView(mTextView); mSelectionTracker.onSelectionAction( mTextView.getSelectionStart(), mTextView.getSelectionEnd(), sortedSelectionIndices[0], sortedSelectionIndices[1], SelectionEvent.ACTION_DRAG, /* actionLabel= */ null, mTextClassification); } public void onTextChanged(int start, int end) { mSelectionTracker.onTextChanged(start, end, mTextClassification); int[] sortedSelectionIndices = sortSelectionIndices(start, end); mSelectionTracker.onTextChanged(sortedSelectionIndices[0], sortedSelectionIndices[1], mTextClassification); } public boolean resetSelection(int textIndex) { Loading Loading @@ -302,9 +335,10 @@ public final class SelectionActionModeHelper { startSelectionActionMode(startSelectionResult); }; // TODO do not trigger the animation if the change included only non-printable characters int[] sortedSelectionIndices = sortSelectionIndicesFromTextView(mTextView); final boolean didSelectionChange = result != null && (mTextView.getSelectionStart() != result.mStart || mTextView.getSelectionEnd() != result.mEnd); result != null && (sortedSelectionIndices[0] != result.mStart || sortedSelectionIndices[1] != result.mEnd); if (!didSelectionChange) { onAnimationEndCallback.run(); Loading Loading @@ -454,16 +488,18 @@ public final class SelectionActionModeHelper { if (actionMode != null) { actionMode.invalidate(); } final int[] sortedSelectionIndices = sortSelectionIndicesFromTextView(mTextView); mSelectionTracker.onSelectionUpdated( mTextView.getSelectionStart(), mTextView.getSelectionEnd(), mTextClassification); sortedSelectionIndices[0], sortedSelectionIndices[1], mTextClassification); mTextClassificationAsyncTask = null; } private void resetTextClassificationHelper(int selectionStart, int selectionEnd) { if (selectionStart < 0 || selectionEnd < 0) { // Use selection indices selectionStart = mTextView.getSelectionStart(); selectionEnd = mTextView.getSelectionEnd(); int[] sortedSelectionIndices = sortSelectionIndicesFromTextView(mTextView); selectionStart = sortedSelectionIndices[0]; selectionEnd = sortedSelectionIndices[1]; } mTextClassificationHelper.init( mTextView::getTextClassifier, Loading Loading @@ -603,10 +639,11 @@ public final class SelectionActionModeHelper { mAllowReset = false; boolean selected = editor.selectCurrentWord(); if (selected) { mSelectionStart = editor.getTextView().getSelectionStart(); mSelectionEnd = editor.getTextView().getSelectionEnd(); final int[] sortedSelectionIndices = sortSelectionIndicesFromTextView(textView); mSelectionStart = sortedSelectionIndices[0]; mSelectionEnd = sortedSelectionIndices[1]; mLogger.logSelectionAction( textView.getSelectionStart(), textView.getSelectionEnd(), sortedSelectionIndices[0], sortedSelectionIndices[1], SelectionEvent.ACTION_RESET, /* actionLabel= */ null, /* classification= */ null); } Loading Loading @@ -1179,8 +1216,9 @@ public final class SelectionActionModeHelper { SelectionResult(int start, int end, @Nullable TextClassification classification, @Nullable TextSelection selection) { mStart = start; mEnd = end; int[] sortedIndices = sortSelectionIndices(start, end); mStart = sortedIndices[0]; mEnd = sortedIndices[1]; mClassification = classification; mSelection = selection; } Loading Loading
core/java/android/app/ActivityManagerInternal.java +1 −1 Original line number Diff line number Diff line Loading @@ -299,7 +299,7 @@ public abstract class ActivityManagerInternal { /** Starts a given process. */ public abstract void startProcess(String processName, ApplicationInfo info, boolean knownToBeDead, String hostingType, ComponentName hostingName); boolean knownToBeDead, boolean isTop, String hostingType, ComponentName hostingName); /** Starts up the starting activity process for debugging if needed. * This function needs to be called synchronously from WindowManager context so the caller Loading
core/java/android/net/NetworkPolicyManager.java +5 −0 Original line number Diff line number Diff line Loading @@ -63,6 +63,8 @@ public class NetworkPolicyManager { public static final int POLICY_REJECT_ON_VPN = 0x20000; /** Reject network usage on wifi network */ public static final int POLICY_REJECT_ON_WLAN = 0x8000; /** Reject network usage on all networks at all times */ public static final int POLICY_NETWORK_ISOLATED = 0x40000; /* * Rules defining whether an uid has access to a network given its type (metered / non-metered). Loading Loading @@ -93,6 +95,8 @@ public class NetworkPolicyManager { public static final int RULE_ALLOW_ALL = 1 << 5; /** Reject traffic on all networks. */ public static final int RULE_REJECT_ALL = 1 << 6; /** Reject traffic on all networks at all times */ public static final int RULE_NETWORK_ISOLATED = 1 << 7; /** Mask used to get the {@code RULE_xxx_METERED} rules */ public static final int MASK_METERED_NETWORKS = 0b00001111; /** Mask used to get the {@code RULE_xxx_ALL} rules */ Loading @@ -104,6 +108,7 @@ public class NetworkPolicyManager { public static final String FIREWALL_CHAIN_NAME_DOZABLE = "dozable"; public static final String FIREWALL_CHAIN_NAME_STANDBY = "standby"; public static final String FIREWALL_CHAIN_NAME_POWERSAVE = "powersave"; public static final String FIREWALL_CHAIN_NAME_ISOLATED = "isolated"; private static final boolean ALLOW_PLATFORM_APP_POLICY = true; Loading
core/java/android/os/Process.java +41 −3 Original line number Diff line number Diff line Loading @@ -472,6 +472,40 @@ public class Process { private static long sStartElapsedRealtime; private static long sStartUptimeMillis; /** * Value used to indicate that there is no special information about an application launch. App * launches with this policy will occur through the primary or secondary Zygote with no special * treatment. * * @hide */ public static final int ZYGOTE_POLICY_FLAG_EMPTY = 0; /** * Flag used to indicate that an application launch is user-visible and latency sensitive. Any * launch with this policy will use a Unspecialized App Process Pool if the target Zygote * supports it. * * @hide */ public static final int ZYGOTE_POLICY_FLAG_LATENCY_SENSITIVE = 1 << 0; /** * Flag used to indicate that the launch is one in a series of app launches that will be * performed in quick succession. For future use. * * @hide */ public static final int ZYGOTE_POLICY_FLAG_BATCH_LAUNCH = 1 << 1; /** * Flag used to indicate that the current launch event is for a system process. All system * processes are equally important, so none of them should be prioritized over the others. * * @hide */ public static final int ZYGOTE_POLICY_FLAG_SYSTEM_PROCESS = 1 << 2; /** * State associated with the zygote process. * @hide Loading Loading @@ -511,7 +545,8 @@ public class Process { * @param appDataDir null-ok the data directory of the app. * @param invokeWith null-ok the command to invoke with. * @param packageName null-ok the name of the package this process belongs to. * * @param zygotePolicyFlags Flags used to determine how to launch the application * @param isTopApp whether the process starts for high priority application. * @param zygoteArgs Additional arguments to supply to the zygote process. * @return An object that describes the result of the attempt to start the process. * @throws RuntimeException on fatal start failure Loading @@ -530,11 +565,13 @@ public class Process { @Nullable String appDataDir, @Nullable String invokeWith, @Nullable String packageName, int zygotePolicyFlags, boolean isTopApp, @Nullable String[] zygoteArgs) { return ZYGOTE_PROCESS.start(processClass, niceName, uid, gid, gids, runtimeFlags, mountExternal, targetSdkVersion, seInfo, abi, instructionSet, appDataDir, invokeWith, packageName, /*useUsapPool=*/ true, zygoteArgs); zygotePolicyFlags, isTopApp, zygoteArgs); } /** @hide */ Loading @@ -554,7 +591,8 @@ public class Process { return WebViewZygote.getProcess().start(processClass, niceName, uid, gid, gids, runtimeFlags, mountExternal, targetSdkVersion, seInfo, abi, instructionSet, appDataDir, invokeWith, packageName, /*useUsapPool=*/ false, zygoteArgs); /*zygotePolicyFlags=*/ ZYGOTE_POLICY_FLAG_EMPTY, /*isTopApp=*/ false, zygoteArgs); } /** Loading
core/java/android/os/ZygoteProcess.java +81 −11 Original line number Diff line number Diff line Loading @@ -16,6 +16,9 @@ package android.os; import static android.os.Process.ZYGOTE_POLICY_FLAG_LATENCY_SENSITIVE; import static android.os.Process.ZYGOTE_POLICY_FLAG_SYSTEM_PROCESS; import android.annotation.NonNull; import android.annotation.Nullable; import android.annotation.UnsupportedAppUsage; Loading Loading @@ -117,6 +120,10 @@ public class ZygoteProcess { mUsapPoolSecondarySocketAddress = new LocalSocketAddress(Zygote.USAP_POOL_SECONDARY_SOCKET_NAME, LocalSocketAddress.Namespace.RESERVED); // This constructor is used to create the primary and secondary Zygotes, which can support // Unspecialized App Process Pools. mUsapPoolSupported = true; } public ZygoteProcess(LocalSocketAddress primarySocketAddress, Loading @@ -126,6 +133,10 @@ public class ZygoteProcess { mUsapPoolSocketAddress = null; mUsapPoolSecondarySocketAddress = null; // This constructor is used to create the primary and secondary Zygotes, which CAN NOT // support Unspecialized App Process Pools. mUsapPoolSupported = false; } public LocalSocketAddress getPrimarySocketAddress() { Loading Loading @@ -264,6 +275,14 @@ public class ZygoteProcess { */ private ZygoteState secondaryZygoteState; /** * If this Zygote supports the creation and maintenance of a USAP pool. * * Currently only the primary and secondary Zygotes support USAP pools. Any * child Zygotes will be unable to create or use a USAP pool. */ private final boolean mUsapPoolSupported; /** * If the USAP pool should be created and used to start applications. * Loading Loading @@ -306,8 +325,9 @@ public class ZygoteProcess { * @param appDataDir null-ok the data directory of the app. * @param invokeWith null-ok the command to invoke with. * @param packageName null-ok the name of the package this process belongs to. * @param zygoteArgs Additional arguments to supply to the zygote process. * * @param zygotePolicyFlags Flags used to determine how to launch the application. * @param isTopApp Whether the process starts for high priority application. * @param zygoteArgs Additional arguments to supply to the Zygote process. * @return An object that describes the result of the attempt to start the process. * @throws RuntimeException on fatal start failure */ Loading @@ -322,7 +342,8 @@ public class ZygoteProcess { @Nullable String appDataDir, @Nullable String invokeWith, @Nullable String packageName, boolean useUsapPool, int zygotePolicyFlags, boolean isTopApp, @Nullable String[] zygoteArgs) { // TODO (chriswailes): Is there a better place to check this value? if (fetchUsapPoolEnabledPropWithMinInterval()) { Loading @@ -333,7 +354,7 @@ public class ZygoteProcess { return startViaZygote(processClass, niceName, uid, gid, gids, runtimeFlags, mountExternal, targetSdkVersion, seInfo, abi, instructionSet, appDataDir, invokeWith, /*startChildZygote=*/ false, packageName, useUsapPool, zygoteArgs); packageName, zygotePolicyFlags, isTopApp, zygoteArgs); } catch (ZygoteStartFailedEx ex) { Log.e(LOG_TAG, "Starting VM process through Zygote failed"); Loading Loading @@ -379,7 +400,7 @@ public class ZygoteProcess { */ @GuardedBy("mLock") private Process.ProcessStartResult zygoteSendArgsAndGetResult( ZygoteState zygoteState, boolean useUsapPool, @NonNull ArrayList<String> args) ZygoteState zygoteState, int zygotePolicyFlags, @NonNull ArrayList<String> args) throws ZygoteStartFailedEx { // Throw early if any of the arguments are malformed. This means we can // avoid writing a partial response to the zygote. Loading @@ -405,7 +426,7 @@ public class ZygoteProcess { */ String msgStr = args.size() + "\n" + String.join("\n", args) + "\n"; if (useUsapPool && mUsapPoolEnabled && canAttemptUsap(args)) { if (shouldAttemptUsapLaunch(zygotePolicyFlags, args)) { try { return attemptUsapSendArgsAndGetResult(zygoteState, msgStr); } catch (IOException ex) { Loading Loading @@ -476,7 +497,43 @@ public class ZygoteProcess { } /** * Flags that may not be passed to a USAP. * Test various member properties and parameters to determine if a launch event should be * handled using an Unspecialized App Process Pool or not. * * @param zygotePolicyFlags Policy flags indicating special behavioral observations about the * Zygote command * @param args Arguments that will be passed to the Zygote * @return If the command should be sent to a USAP Pool member or an actual Zygote */ private boolean shouldAttemptUsapLaunch(int zygotePolicyFlags, ArrayList<String> args) { return mUsapPoolSupported && mUsapPoolEnabled && policySpecifiesUsapPoolLaunch(zygotePolicyFlags) && commandSupportedByUsap(args); } /** * Tests a Zygote policy flag set for various properties that determine if it is eligible for * being handled by an Unspecialized App Process Pool. * * @param zygotePolicyFlags Policy flags indicating special behavioral observations about the * Zygote command * @return If the policy allows for use of a USAP pool */ private static boolean policySpecifiesUsapPoolLaunch(int zygotePolicyFlags) { /* * Zygote USAP Pool Policy: Launch the new process from the USAP Pool iff the launch event * is latency sensitive but *NOT* a system process. All system processes are equally * important so we don't want to prioritize one over another. */ return (zygotePolicyFlags & (ZYGOTE_POLICY_FLAG_SYSTEM_PROCESS | ZYGOTE_POLICY_FLAG_LATENCY_SENSITIVE)) == ZYGOTE_POLICY_FLAG_LATENCY_SENSITIVE; } /** * Flags that may not be passed to a USAP. These may appear as prefixes to individual Zygote * arguments. */ private static final String[] INVALID_USAP_FLAGS = { "--query-abi-list", Loading @@ -493,10 +550,11 @@ public class ZygoteProcess { /** * Tests a command list to see if it is valid to send to a USAP. * * @param args Zygote/USAP command arguments * @return True if the command can be passed to a USAP; false otherwise */ private static boolean canAttemptUsap(ArrayList<String> args) { private static boolean commandSupportedByUsap(ArrayList<String> args) { for (String flag : args) { for (String badFlag : INVALID_USAP_FLAGS) { if (flag.startsWith(badFlag)) { Loading Loading @@ -534,6 +592,8 @@ public class ZygoteProcess { * @param startChildZygote Start a sub-zygote. This creates a new zygote process * that has its state cloned from this zygote process. * @param packageName null-ok the name of the package this process belongs to. * @param zygotePolicyFlags Flags used to determine how to launch the application. * @param isTopApp Whether the process starts for high priority application. * @param extraArgs Additional arguments to supply to the zygote process. * @return An object that describes the result of the attempt to start the process. * @throws ZygoteStartFailedEx if process start failed for any reason Loading @@ -551,7 +611,8 @@ public class ZygoteProcess { @Nullable String invokeWith, boolean startChildZygote, @Nullable String packageName, boolean useUsapPool, int zygotePolicyFlags, boolean isTopApp, @Nullable String[] extraArgs) throws ZygoteStartFailedEx { ArrayList<String> argsForZygote = new ArrayList<>(); Loading Loading @@ -623,6 +684,10 @@ public class ZygoteProcess { argsForZygote.add("--package-name=" + packageName); } if (isTopApp) { argsForZygote.add(Zygote.START_AS_TOP_APP_ARG); } argsForZygote.add(processClass); if (extraArgs != null) { Loading @@ -633,7 +698,7 @@ public class ZygoteProcess { // The USAP pool can not be used if the application will not use the systems graphics // driver. If that driver is requested use the Zygote application start path. return zygoteSendArgsAndGetResult(openZygoteSocketIfNeeded(abi), useUsapPool, zygotePolicyFlags, argsForZygote); } } Loading Loading @@ -663,6 +728,10 @@ public class ZygoteProcess { private long mLastPropCheckTimestamp = 0; private boolean fetchUsapPoolEnabledPropWithMinInterval() { // If this Zygote doesn't support USAPs there is no need to fetch any // properties. if (!mUsapPoolSupported) return false; final long currentTimestamp = SystemClock.elapsedRealtime(); if (SystemProperties.get("dalvik.vm.boot-image", "").endsWith("apex.art")) { Loading Loading @@ -1144,7 +1213,8 @@ public class ZygoteProcess { gids, runtimeFlags, 0 /* mountExternal */, 0 /* targetSdkVersion */, seInfo, abi, instructionSet, null /* appDataDir */, null /* invokeWith */, true /* startChildZygote */, null /* packageName */, false /* useUsapPool */, extraArgs); ZYGOTE_POLICY_FLAG_SYSTEM_PROCESS /* zygotePolicyFlags */, false /* isTopApp */, extraArgs); } catch (ZygoteStartFailedEx ex) { throw new RuntimeException("Starting child-zygote through Zygote failed", ex); } Loading
core/java/android/widget/SelectionActionModeHelper.java +55 −17 Original line number Diff line number Diff line Loading @@ -104,17 +104,44 @@ public final class SelectionActionModeHelper { } } /** * Swap the selection index if the start index is greater than end index. * * @return the swap result, index 0 is the start index and index 1 is the end index. */ private static int[] sortSelectionIndices(int selectionStart, int selectionEnd) { if (selectionStart < selectionEnd) { return new int[]{selectionStart, selectionEnd}; } return new int[]{selectionEnd, selectionStart}; } /** * The {@link TextView} selection start and end index may not be sorted, this method will swap * the {@link TextView} selection index if the start index is greater than end index. * * @param textView the selected TextView. * @return the swap result, index 0 is the start index and index 1 is the end index. */ private static int[] sortSelectionIndicesFromTextView(TextView textView) { int selectionStart = textView.getSelectionStart(); int selectionEnd = textView.getSelectionEnd(); return sortSelectionIndices(selectionStart, selectionEnd); } /** * Starts Selection ActionMode. */ public void startSelectionActionModeAsync(boolean adjustSelection) { // Check if the smart selection should run for editable text. adjustSelection &= getTextClassificationSettings().isSmartSelectionEnabled(); int[] sortedSelectionIndices = sortSelectionIndicesFromTextView(mTextView); mSelectionTracker.onOriginalSelection( getText(mTextView), mTextView.getSelectionStart(), mTextView.getSelectionEnd(), sortedSelectionIndices[0], sortedSelectionIndices[1], false /*isLink*/); cancelAsyncTask(); if (skipTextClassification()) { Loading @@ -139,12 +166,14 @@ public final class SelectionActionModeHelper { * Starts Link ActionMode. */ public void startLinkActionModeAsync(int start, int end) { mSelectionTracker.onOriginalSelection(getText(mTextView), start, end, true /*isLink*/); int[] indexResult = sortSelectionIndices(start, end); mSelectionTracker.onOriginalSelection(getText(mTextView), indexResult[0], indexResult[1], true /*isLink*/); cancelAsyncTask(); if (skipTextClassification()) { startLinkActionMode(null); } else { resetTextClassificationHelper(start, end); resetTextClassificationHelper(indexResult[0], indexResult[1]); mTextClassificationAsyncTask = new TextClassificationAsyncTask( mTextView, mTextClassificationHelper.getTimeoutDuration(), Loading Loading @@ -173,19 +202,23 @@ public final class SelectionActionModeHelper { /** Reports a selection action event. */ public void onSelectionAction(int menuItemId, @Nullable String actionLabel) { int[] sortedSelectionIndices = sortSelectionIndicesFromTextView(mTextView); mSelectionTracker.onSelectionAction( mTextView.getSelectionStart(), mTextView.getSelectionEnd(), sortedSelectionIndices[0], sortedSelectionIndices[1], getActionType(menuItemId), actionLabel, mTextClassification); } public void onSelectionDrag() { int[] sortedSelectionIndices = sortSelectionIndicesFromTextView(mTextView); mSelectionTracker.onSelectionAction( mTextView.getSelectionStart(), mTextView.getSelectionEnd(), sortedSelectionIndices[0], sortedSelectionIndices[1], SelectionEvent.ACTION_DRAG, /* actionLabel= */ null, mTextClassification); } public void onTextChanged(int start, int end) { mSelectionTracker.onTextChanged(start, end, mTextClassification); int[] sortedSelectionIndices = sortSelectionIndices(start, end); mSelectionTracker.onTextChanged(sortedSelectionIndices[0], sortedSelectionIndices[1], mTextClassification); } public boolean resetSelection(int textIndex) { Loading Loading @@ -302,9 +335,10 @@ public final class SelectionActionModeHelper { startSelectionActionMode(startSelectionResult); }; // TODO do not trigger the animation if the change included only non-printable characters int[] sortedSelectionIndices = sortSelectionIndicesFromTextView(mTextView); final boolean didSelectionChange = result != null && (mTextView.getSelectionStart() != result.mStart || mTextView.getSelectionEnd() != result.mEnd); result != null && (sortedSelectionIndices[0] != result.mStart || sortedSelectionIndices[1] != result.mEnd); if (!didSelectionChange) { onAnimationEndCallback.run(); Loading Loading @@ -454,16 +488,18 @@ public final class SelectionActionModeHelper { if (actionMode != null) { actionMode.invalidate(); } final int[] sortedSelectionIndices = sortSelectionIndicesFromTextView(mTextView); mSelectionTracker.onSelectionUpdated( mTextView.getSelectionStart(), mTextView.getSelectionEnd(), mTextClassification); sortedSelectionIndices[0], sortedSelectionIndices[1], mTextClassification); mTextClassificationAsyncTask = null; } private void resetTextClassificationHelper(int selectionStart, int selectionEnd) { if (selectionStart < 0 || selectionEnd < 0) { // Use selection indices selectionStart = mTextView.getSelectionStart(); selectionEnd = mTextView.getSelectionEnd(); int[] sortedSelectionIndices = sortSelectionIndicesFromTextView(mTextView); selectionStart = sortedSelectionIndices[0]; selectionEnd = sortedSelectionIndices[1]; } mTextClassificationHelper.init( mTextView::getTextClassifier, Loading Loading @@ -603,10 +639,11 @@ public final class SelectionActionModeHelper { mAllowReset = false; boolean selected = editor.selectCurrentWord(); if (selected) { mSelectionStart = editor.getTextView().getSelectionStart(); mSelectionEnd = editor.getTextView().getSelectionEnd(); final int[] sortedSelectionIndices = sortSelectionIndicesFromTextView(textView); mSelectionStart = sortedSelectionIndices[0]; mSelectionEnd = sortedSelectionIndices[1]; mLogger.logSelectionAction( textView.getSelectionStart(), textView.getSelectionEnd(), sortedSelectionIndices[0], sortedSelectionIndices[1], SelectionEvent.ACTION_RESET, /* actionLabel= */ null, /* classification= */ null); } Loading Loading @@ -1179,8 +1216,9 @@ public final class SelectionActionModeHelper { SelectionResult(int start, int end, @Nullable TextClassification classification, @Nullable TextSelection selection) { mStart = start; mEnd = end; int[] sortedIndices = sortSelectionIndices(start, end); mStart = sortedIndices[0]; mEnd = sortedIndices[1]; mClassification = classification; mSelection = selection; } Loading