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

Commit 858a5d99 authored by TreeHugger Robot's avatar TreeHugger Robot Committed by Android (Google) Code Review
Browse files

Merge "Ensure network connectivity on app start."

parents d7fd4aff 27e69315
Loading
Loading
Loading
Loading
+13 −0
Original line number Diff line number Diff line
@@ -22,6 +22,7 @@ import android.content.ComponentName;
import android.content.IIntentSender;
import android.content.Intent;
import android.content.res.Configuration;
import android.net.NetworkPolicyManager.UidStateWithSeqObserver;
import android.os.Bundle;
import android.os.IBinder;
import android.service.voice.IVoiceInteractionSession;
@@ -233,4 +234,16 @@ public abstract class ActivityManagerInternal {
     * @see android.view.WindowManager.LayoutParams#TYPE_APPLICATION_OVERLAY
     */
    public abstract void setHasOverlayUi(int pid, boolean hasOverlayUi);

    /**
     * Set observer which listens to uid state changes. Uid state change along with the sequence
     * number associated with it needs to be passed to {@link UidStateWithSeqObserver}.
     */
    public abstract void setUidStateWithSeqObserver(UidStateWithSeqObserver observer);

    /**
     * Notifies that NetworkPolicyManagerService has updated the network policy rules for
     * a specific {@param uid} and {@param procStateSeq}.
     */
    public abstract void notifyNetworkPolicyRulesUpdated(int uid, long procStateSeq);
}
+146 −0
Original line number Diff line number Diff line
@@ -180,6 +180,7 @@ public final class ActivityThread {
    public static final boolean DEBUG_CONFIGURATION = false;
    private static final boolean DEBUG_SERVICE = false;
    private static final boolean DEBUG_MEMORY_TRIM = false;
    private static final boolean DEBUG_NETWORK = false;
    private static final boolean DEBUG_PROVIDER = false;
    private static final boolean DEBUG_ORDER = false;
    private static final long MIN_TIME_BETWEEN_GCS = 5*1000;
@@ -202,6 +203,55 @@ public final class ActivityThread {
    // Whether to invoke an activity callback after delivering new configuration.
    private static final boolean REPORT_TO_ACTIVITY = true;

    /**
     * This is the time main thread waits for the NetworkPolicyManagerService to notify
     * that network is unrestricted. After this the app components will be launched anyway.
     */
    private long mWaitForNetworkTimeoutMs;

    /**
     * This is only for logging purposes. This will help us identify if the waiting for network
     * is responsible for any lag that user might see.
     */
    private static final int WAIT_FOR_NETWORK_THRESHOLD_MS = 100; // 0.1 sec

    /**
     * State indicating that there is no need for any blocking for network.
     */
    public static final int NETWORK_STATE_NO_CHANGE = 0;

    /**
     * State indicating that main thread should wait for ActivityManagerService to notify
     * before the app components are launched.
     */
    public static final int NETWORK_STATE_BLOCK = 1;

    /**
     * State indicating that any threads waiting for ActivityManagerService to notify should
     * be unblocked.
     */
    public static final int NETWORK_STATE_UNBLOCK = 2;

    /**
     * Constant for indicating a invalid sequence number.
     */
    public static final long INVALID_PROC_STATE_SEQ = -1;

    /**
     * Current sequence number associated with the process state change.
     */
    @GuardedBy("mNetworkPolicyLock")
    private long mCurProcStateSeq;

    /**
     * Indicates whether any component being launched should block for network before
     * proceeding.
     */
    @GuardedBy("mNetworkPolicyLock")
    private boolean mShouldBlockForNetwork;

    private Object mNetworkPolicyLock = new Object();

    private ContextImpl mSystemContext;

    static volatile IPackageManager sPackageManager;
@@ -1305,6 +1355,18 @@ public final class ActivityThread {
            }
        }

        @Override
        public void setBlockForNetworkState(int blockState, long targetProcStateSeq) {
            synchronized (mNetworkPolicyLock) {
                if (blockState == NETWORK_STATE_UNBLOCK) {
                    unblockForNetworkAccessLN(targetProcStateSeq);
                } else if (blockState == NETWORK_STATE_BLOCK) {
                    mShouldBlockForNetwork = true;
                }
                mCurProcStateSeq = targetProcStateSeq;
            }
        }

        @Override
        public void scheduleInstallProvider(ProviderInfo provider) {
            sendMessage(H.INSTALL_PROVIDER, provider);
@@ -1388,6 +1450,13 @@ public final class ActivityThread {
        public void handleTrustStorageUpdate() {
            NetworkSecurityPolicy.getInstance().handleTrustStorageUpdate();
        }

        @Override
        public void notifyNetworkStateUpdated(long curProcStateSeq) {
            synchronized (mNetworkPolicyLock) {
                unblockForNetworkAccessLN(curProcStateSeq);
            }
        }
    }

    private int getLifecycleSeq() {
@@ -2079,6 +2148,79 @@ public final class ActivityThread {
        }
    }

    void blockForNetworkAccessInForegroundService(long procStateSeq) {
        synchronized (mNetworkPolicyLock) {
            if (mCurProcStateSeq >= procStateSeq) {
                if (mShouldBlockForNetwork) {
                    blockForNetworkAccessLN();
                }
            } else {
                mCurProcStateSeq = procStateSeq;
                mShouldBlockForNetwork = true;
                blockForNetworkAccessLN();
            }
        }
    }

    /**
     * Block for unrestricted network. It will register a listener to AMS and wait for it to
     * notify that network policy rules are updated. This method is called before relevant app
     * components are launched.
     */
    private void blockForNetworkAccessLN() {
        try {
            if (ActivityManager.getService().registerNetworkRulesUpdateListener(
                    mAppThread, mCurProcStateSeq)) {
                try {
                    Slog.d(TAG, "Uid: " + mBoundApplication.appInfo.uid
                            + " seq: " + mCurProcStateSeq
                            + ". Blocking for network. callers: " + Debug.getCallers(3));
                    final long blockStartTime = SystemClock.elapsedRealtime();
                    mNetworkPolicyLock.wait(mWaitForNetworkTimeoutMs);
                    final long totalWaitTime = (SystemClock.elapsedRealtime() - blockStartTime);
                    if (totalWaitTime >= mWaitForNetworkTimeoutMs) {
                        Slog.wtf(TAG, "Timed out waiting for the network rules to get updated."
                                + " Uid: " + mBoundApplication.appInfo.uid + " seq: "
                                + mCurProcStateSeq);
                    } else if (totalWaitTime >= WAIT_FOR_NETWORK_THRESHOLD_MS) {
                        Slog.d(TAG, "Waited for time greater than threshold."
                                + " Uid: " + mBoundApplication.appInfo.uid + " seq: "
                                + mCurProcStateSeq);
                    }
                    if (DEBUG_NETWORK) {
                        Slog.d(TAG, "Uid: " + mBoundApplication.appInfo.uid
                                + " seq: " + mCurProcStateSeq
                                + ". Time waited for network: " + totalWaitTime);
                    }
                } catch (InterruptedException ignored) {
                }
            }
        } catch (RemoteException ignored) {
        }
    }

    public void checkAndBlockForNetworkAccess() {
        synchronized (mNetworkPolicyLock) {
            if (mWaitForNetworkTimeoutMs > 0 && mShouldBlockForNetwork) {
                blockForNetworkAccessLN();
            }
        }
    }

    /**
     * Unblock the main thread if it is waiting for network.
     */
    private void unblockForNetworkAccessLN(long procStateSeq) {
        if (mShouldBlockForNetwork && procStateSeq >= mCurProcStateSeq) {
            if (DEBUG_NETWORK) {
                Slog.d(TAG, "Unblocking threads waiting for network. uid: "
                        + mBoundApplication.appInfo.uid + " procStateSeq: " + procStateSeq);
            }
            mNetworkPolicyLock.notifyAll();
            mShouldBlockForNetwork = false;
        }
    }

    ActivityThread() {
        mResourcesManager = ResourcesManager.getInstance();
    }
@@ -2671,6 +2813,7 @@ public final class ActivityThread {
                    activity.mIntent = customIntent;
                }
                r.lastNonConfigurationInstances = null;
                checkAndBlockForNetworkAccess();
                activity.mStartedActivity = false;
                int theme = r.activityInfo.getThemeResource();
                if (theme != 0) {
@@ -5350,6 +5493,9 @@ public final class ActivityThread {
        View.mDebugViewAttributes =
                mCoreSettings.getInt(Settings.Global.DEBUG_VIEW_ATTRIBUTES, 0) != 0;

        mWaitForNetworkTimeoutMs = mCoreSettings.getLong(
                Settings.Global.WAIT_FOR_NETWORK_TIMEOUT_MS);

        /**
         * For system applications on userdebug/eng builds, log stack
         * traces of disk and network access to dropbox for analysis.
+11 −1
Original line number Diff line number Diff line
@@ -199,7 +199,7 @@ interface IActivityManager {
    int getRequestedOrientation(in IBinder token);
    void unbindFinished(in IBinder token, in Intent service, boolean doRebind);
    void setProcessForeground(in IBinder token, int pid, boolean isForeground);
    void setServiceForeground(in ComponentName className, in IBinder token,
    long setServiceForeground(in ComponentName className, in IBinder token,
            int id, in Notification notification, int flags);
    boolean moveActivityTaskToBack(in IBinder token, boolean nonRoot);
    void getMemoryInfo(out ActivityManager.MemoryInfo outInfo);
@@ -603,6 +603,16 @@ interface IActivityManager {
    ActivityManager.TaskSnapshot getTaskSnapshot(int taskId);

    void scheduleApplicationInfoChanged(in List<String> packageNames, int userId);
     /**
      * Registers a listener for network rules state. When the network policy rules in
      * NetworkPolicyManagerService are updated, ActivityManagerService will notify these
      * registered listeners.
      *
      * @param procStateSeq The sequence number for which the listener is interested in knowing
      *                     the network policy rules state.
      * @return true if the listener is registered, false otherwise.
      */
    boolean registerNetworkRulesUpdateListener(IApplicationThread listener, long procStateSeq);

    // WARNING: when these transactions are updated, check if they are any callers on the native
    // side. If so, make sure they are using the correct transaction ids and arguments.
+2 −0
Original line number Diff line number Diff line
@@ -153,4 +153,6 @@ oneway interface IApplicationThread {
    void handleTrustStorageUpdate();
    void attachAgent(String path);
    void scheduleApplicationInfoChanged(in ApplicationInfo ai);
    void setBlockForNetworkState(int blockState, long procStateSeq);
    void notifyNetworkStateUpdated(long procStateSeq);
}
+9 −7
Original line number Diff line number Diff line
@@ -700,9 +700,11 @@ public abstract class Service extends ContextWrapper implements ComponentCallbac
     */
    public final void startForeground(int id, Notification notification) {
        try {
            mActivityManager.setServiceForeground(
                    new ComponentName(this, mClassName), mToken, id,
                    notification, 0);
            final long procStateSeq = mActivityManager.setServiceForeground(
                    new ComponentName(this, mClassName), mToken, id, notification, 0);
            if (procStateSeq != ActivityThread.INVALID_PROC_STATE_SEQ && mThread != null) {
                mThread.blockForNetworkAccessInForegroundService(procStateSeq);
            }
        } catch (RemoteException ex) {
        }
    }
Loading