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

Commit 27e69315 authored by Sudheer Shanka's avatar Sudheer Shanka
Browse files

Ensure network connectivity on app start.

Bug: 27803922
Test: cts-tradefed run singleCommand cts-dev --module CtsHostsideNetworkTests
Change-Id: Ifd7a52924cd6bbc809c9a3f92d52fe2df09b7fe2
parent d725de1e
Loading
Loading
Loading
Loading
+13 −0
Original line number Original line Diff line number Diff line
@@ -22,6 +22,7 @@ import android.content.ComponentName;
import android.content.IIntentSender;
import android.content.IIntentSender;
import android.content.Intent;
import android.content.Intent;
import android.content.res.Configuration;
import android.content.res.Configuration;
import android.net.NetworkPolicyManager.UidStateWithSeqObserver;
import android.os.Bundle;
import android.os.Bundle;
import android.os.IBinder;
import android.os.IBinder;
import android.service.voice.IVoiceInteractionSession;
import android.service.voice.IVoiceInteractionSession;
@@ -233,4 +234,16 @@ public abstract class ActivityManagerInternal {
     * @see android.view.WindowManager.LayoutParams#TYPE_APPLICATION_OVERLAY
     * @see android.view.WindowManager.LayoutParams#TYPE_APPLICATION_OVERLAY
     */
     */
    public abstract void setHasOverlayUi(int pid, boolean hasOverlayUi);
    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 Original line Diff line number Diff line
@@ -180,6 +180,7 @@ public final class ActivityThread {
    public static final boolean DEBUG_CONFIGURATION = false;
    public static final boolean DEBUG_CONFIGURATION = false;
    private static final boolean DEBUG_SERVICE = false;
    private static final boolean DEBUG_SERVICE = false;
    private static final boolean DEBUG_MEMORY_TRIM = 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_PROVIDER = false;
    private static final boolean DEBUG_ORDER = false;
    private static final boolean DEBUG_ORDER = false;
    private static final long MIN_TIME_BETWEEN_GCS = 5*1000;
    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.
    // Whether to invoke an activity callback after delivering new configuration.
    private static final boolean REPORT_TO_ACTIVITY = true;
    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;
    private ContextImpl mSystemContext;


    static volatile IPackageManager sPackageManager;
    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
        @Override
        public void scheduleInstallProvider(ProviderInfo provider) {
        public void scheduleInstallProvider(ProviderInfo provider) {
            sendMessage(H.INSTALL_PROVIDER, provider);
            sendMessage(H.INSTALL_PROVIDER, provider);
@@ -1388,6 +1450,13 @@ public final class ActivityThread {
        public void handleTrustStorageUpdate() {
        public void handleTrustStorageUpdate() {
            NetworkSecurityPolicy.getInstance().handleTrustStorageUpdate();
            NetworkSecurityPolicy.getInstance().handleTrustStorageUpdate();
        }
        }

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


    private int getLifecycleSeq() {
    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() {
    ActivityThread() {
        mResourcesManager = ResourcesManager.getInstance();
        mResourcesManager = ResourcesManager.getInstance();
    }
    }
@@ -2671,6 +2813,7 @@ public final class ActivityThread {
                    activity.mIntent = customIntent;
                    activity.mIntent = customIntent;
                }
                }
                r.lastNonConfigurationInstances = null;
                r.lastNonConfigurationInstances = null;
                checkAndBlockForNetworkAccess();
                activity.mStartedActivity = false;
                activity.mStartedActivity = false;
                int theme = r.activityInfo.getThemeResource();
                int theme = r.activityInfo.getThemeResource();
                if (theme != 0) {
                if (theme != 0) {
@@ -5350,6 +5493,9 @@ public final class ActivityThread {
        View.mDebugViewAttributes =
        View.mDebugViewAttributes =
                mCoreSettings.getInt(Settings.Global.DEBUG_VIEW_ATTRIBUTES, 0) != 0;
                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
         * For system applications on userdebug/eng builds, log stack
         * traces of disk and network access to dropbox for analysis.
         * traces of disk and network access to dropbox for analysis.
+11 −1
Original line number Original line Diff line number Diff line
@@ -199,7 +199,7 @@ interface IActivityManager {
    int getRequestedOrientation(in IBinder token);
    int getRequestedOrientation(in IBinder token);
    void unbindFinished(in IBinder token, in Intent service, boolean doRebind);
    void unbindFinished(in IBinder token, in Intent service, boolean doRebind);
    void setProcessForeground(in IBinder token, int pid, boolean isForeground);
    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);
            int id, in Notification notification, int flags);
    boolean moveActivityTaskToBack(in IBinder token, boolean nonRoot);
    boolean moveActivityTaskToBack(in IBinder token, boolean nonRoot);
    void getMemoryInfo(out ActivityManager.MemoryInfo outInfo);
    void getMemoryInfo(out ActivityManager.MemoryInfo outInfo);
@@ -603,6 +603,16 @@ interface IActivityManager {
    ActivityManager.TaskSnapshot getTaskSnapshot(int taskId);
    ActivityManager.TaskSnapshot getTaskSnapshot(int taskId);


    void scheduleApplicationInfoChanged(in List<String> packageNames, int userId);
    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
    // 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.
    // side. If so, make sure they are using the correct transaction ids and arguments.
+2 −0
Original line number Original line Diff line number Diff line
@@ -153,4 +153,6 @@ oneway interface IApplicationThread {
    void handleTrustStorageUpdate();
    void handleTrustStorageUpdate();
    void attachAgent(String path);
    void attachAgent(String path);
    void scheduleApplicationInfoChanged(in ApplicationInfo ai);
    void scheduleApplicationInfoChanged(in ApplicationInfo ai);
    void setBlockForNetworkState(int blockState, long procStateSeq);
    void notifyNetworkStateUpdated(long procStateSeq);
}
}
+9 −7
Original line number Original line 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) {
    public final void startForeground(int id, Notification notification) {
        try {
        try {
            mActivityManager.setServiceForeground(
            final long procStateSeq = mActivityManager.setServiceForeground(
                    new ComponentName(this, mClassName), mToken, id,
                    new ComponentName(this, mClassName), mToken, id, notification, 0);
                    notification, 0);
            if (procStateSeq != ActivityThread.INVALID_PROC_STATE_SEQ && mThread != null) {
                mThread.blockForNetworkAccessInForegroundService(procStateSeq);
            }
        } catch (RemoteException ex) {
        } catch (RemoteException ex) {
        }
        }
    }
    }
Loading