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

Commit f7d420da authored by Jeff Davidson's avatar Jeff Davidson Committed by Gerrit Code Review
Browse files

Merge "Linger the carrier service binding when privileges drop."

parents fe6f1e75 92545464
Loading
Loading
Loading
Loading
+65 −13
Original line number Original line Diff line number Diff line
@@ -28,6 +28,8 @@ import android.os.Bundle;
import android.os.Handler;
import android.os.Handler;
import android.os.IBinder;
import android.os.IBinder;
import android.os.Message;
import android.os.Message;
import android.os.Process;
import android.os.SystemClock;
import android.os.UserHandle;
import android.os.UserHandle;
import android.service.carrier.CarrierService;
import android.service.carrier.CarrierService;
import android.telephony.SubscriptionManager;
import android.telephony.SubscriptionManager;
@@ -48,6 +50,12 @@ import java.util.List;
public class CarrierServiceBindHelper {
public class CarrierServiceBindHelper {
    private static final String LOG_TAG = "CarrierSvcBindHelper";
    private static final String LOG_TAG = "CarrierSvcBindHelper";


    /**
     * How long to linger a binding after an app loses carrier privileges, as long as no new
     * binding comes in to take its place.
     */
    private static final int UNBIND_DELAY_MILLIS = 30 * 1000; // 30 seconds

    private Context mContext;
    private Context mContext;
    private AppBinding[] mBindings;
    private AppBinding[] mBindings;
    private String[] mLastSimState;
    private String[] mLastSimState;
@@ -70,6 +78,7 @@ public class CarrierServiceBindHelper {
    };
    };


    private static final int EVENT_REBIND = 0;
    private static final int EVENT_REBIND = 0;
    private static final int EVENT_PERFORM_IMMEDIATE_UNBIND = 1;


    private Handler mHandler = new Handler() {
    private Handler mHandler = new Handler() {
        @Override
        @Override
@@ -83,6 +92,10 @@ public class CarrierServiceBindHelper {
                    log("Rebinding if necessary for phoneId: " + binding.getPhoneId());
                    log("Rebinding if necessary for phoneId: " + binding.getPhoneId());
                    binding.rebind();
                    binding.rebind();
                    break;
                    break;
                case EVENT_PERFORM_IMMEDIATE_UNBIND:
                    binding = (AppBinding) msg.obj;
                    binding.performImmediateUnbind();
                    break;
            }
            }
        }
        }
    };
    };
@@ -129,6 +142,7 @@ public class CarrierServiceBindHelper {
        private long lastUnbindMillis;
        private long lastUnbindMillis;
        private String carrierPackage;
        private String carrierPackage;
        private String carrierServiceClass;
        private String carrierServiceClass;
        private long mUnbindScheduledUptimeMillis = -1;


        public AppBinding(int phoneId) {
        public AppBinding(int phoneId) {
            this.phoneId = phoneId;
            this.phoneId = phoneId;
@@ -158,15 +172,16 @@ public class CarrierServiceBindHelper {


            if (carrierPackageNames == null || carrierPackageNames.size() <= 0) {
            if (carrierPackageNames == null || carrierPackageNames.size() <= 0) {
                log("No carrier app for: " + phoneId);
                log("No carrier app for: " + phoneId);
                unbind();
                // Unbind after a delay in case this is a temporary blip in carrier privileges.
                unbind(false /* immediate */);
                return;
                return;
            }
            }


            log("Found carrier app: " + carrierPackageNames);
            log("Found carrier app: " + carrierPackageNames);
            String candidateCarrierPackage = carrierPackageNames.get(0);
            String candidateCarrierPackage = carrierPackageNames.get(0);
            // If we are binding to a different package, unbind from the current one.
            // If we are binding to a different package, unbind immediately from the current one.
            if (!TextUtils.equals(carrierPackage, candidateCarrierPackage)) {
            if (!TextUtils.equals(carrierPackage, candidateCarrierPackage)) {
                unbind();
                unbind(true /* immediate */);
            }
            }


            // Look up the carrier service
            // Look up the carrier service
@@ -187,15 +202,17 @@ public class CarrierServiceBindHelper {
            if (metadata == null ||
            if (metadata == null ||
                !metadata.getBoolean("android.service.carrier.LONG_LIVED_BINDING", false)) {
                !metadata.getBoolean("android.service.carrier.LONG_LIVED_BINDING", false)) {
                log("Carrier app does not want a long lived binding");
                log("Carrier app does not want a long lived binding");
                unbind();
                unbind(true /* immediate */);
                return;
                return;
            }
            }


            if (!TextUtils.equals(carrierServiceClass, candidateServiceClass)) {
            if (!TextUtils.equals(carrierServiceClass, candidateServiceClass)) {
                // Unbind if the carrier service component has changed.
                // Unbind immediately if the carrier service component has changed.
                unbind();
                unbind(true /* immediate */);
            } else if (connection != null) {
            } else if (connection != null) {
                // Component is unchanged and connection is up - do nothing.
                // Component is unchanged and connection is up - do nothing, but cancel any
                // scheduled unbinds.
                cancelScheduledUnbind();
                return;
                return;
            }
            }


@@ -212,8 +229,9 @@ public class CarrierServiceBindHelper {


            String error;
            String error;
            try {
            try {
                if (mContext.bindService(carrierService, connection, Context.BIND_AUTO_CREATE |
                if (mContext.bindServiceAsUser(carrierService, connection,
                            Context.BIND_FOREGROUND_SERVICE)) {
                        Context.BIND_AUTO_CREATE |  Context.BIND_FOREGROUND_SERVICE,
                        mHandler, Process.myUserHandle())) {
                    return;
                    return;
                }
                }


@@ -224,19 +242,46 @@ public class CarrierServiceBindHelper {


            log("Unable to bind to " + carrierPackage + " for phone " + phoneId +
            log("Unable to bind to " + carrierPackage + " for phone " + phoneId +
                ". Error: " + error);
                ". Error: " + error);
            unbind();
            unbind(true /* immediate */);
        }
        }


        void unbind() {
        /**
         * Release the binding.
         *
         * @param immediate whether the binding should be released immediately or after a short
         *                  delay. This should be true unless the reason for the unbind is that no
         *                  app has carrier privileges, in which case it is useful to delay
         *                  unbinding in case this is a temporary SIM blip.
         */
        void unbind(boolean immediate) {
            if (connection == null) {
            if (connection == null) {
                // Already fully unbound.
                return;
                return;
            }
            }


            // Only let the binding linger if a delayed unbind is requested *and* the connection is
            // currently active. If the connection is down, unbind immediately as the app is likely
            // not running anyway and it may be a permanent disconnection (e.g. the app was
            // disabled).
            if (immediate || !connection.connected) {
                cancelScheduledUnbind();
                performImmediateUnbind();
            } else if (mUnbindScheduledUptimeMillis == -1) {
                long currentUptimeMillis = SystemClock.uptimeMillis();
                mUnbindScheduledUptimeMillis = currentUptimeMillis + UNBIND_DELAY_MILLIS;
                log("Scheduling unbind in " + UNBIND_DELAY_MILLIS + " millis");
                mHandler.sendMessageAtTime(
                        mHandler.obtainMessage(EVENT_PERFORM_IMMEDIATE_UNBIND, this),
                        mUnbindScheduledUptimeMillis);
            }
        }

        private void performImmediateUnbind() {
            // Log debug information
            // Log debug information
            unbindCount++;
            unbindCount++;
            lastUnbindMillis = System.currentTimeMillis();
            lastUnbindMillis = System.currentTimeMillis();


            // Clear package state now that no binding is present.
            // Clear package state now that no binding is desired.
            carrierPackage = null;
            carrierPackage = null;
            carrierServiceClass = null;
            carrierServiceClass = null;


@@ -244,6 +289,12 @@ public class CarrierServiceBindHelper {
            log("Unbinding from carrier app");
            log("Unbinding from carrier app");
            mContext.unbindService(connection);
            mContext.unbindService(connection);
            connection = null;
            connection = null;
            mUnbindScheduledUptimeMillis = -1;
        }

        private void cancelScheduledUnbind() {
            mHandler.removeMessages(EVENT_PERFORM_IMMEDIATE_UNBIND);
            mUnbindScheduledUptimeMillis = -1;
        }
        }


        public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
        public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
@@ -253,6 +304,7 @@ public class CarrierServiceBindHelper {
            pw.println("  lastBindStartMillis: " + lastBindStartMillis);
            pw.println("  lastBindStartMillis: " + lastBindStartMillis);
            pw.println("  unbindCount: " + unbindCount);
            pw.println("  unbindCount: " + unbindCount);
            pw.println("  lastUnbindMillis: " + lastUnbindMillis);
            pw.println("  lastUnbindMillis: " + lastUnbindMillis);
            pw.println("  mUnbindScheduledUptimeMillis: " + mUnbindScheduledUptimeMillis);
            pw.println();
            pw.println();
        }
        }
    }
    }
@@ -322,7 +374,7 @@ public class CarrierServiceBindHelper {
                }
                }
                if (appBindingPackage == null || isBindingForPackage) {
                if (appBindingPackage == null || isBindingForPackage) {
                    if (forceUnbind) {
                    if (forceUnbind) {
                        appBinding.unbind();
                        appBinding.unbind(true /* immediate */);
                    }
                    }
                    appBinding.rebind();
                    appBinding.rebind();
                }
                }