美文网首页
全志Android 10 第三方应用bindservice失败的

全志Android 10 第三方应用bindservice失败的

作者: gale_小米 | 来源:发表于2022-04-20 16:27 被阅读0次

    1.Android Q Service启动流程梳理——bindService
    跟读一下源码大致流程如下:


    image.png

    1.ContextImpl

    --- base/core/java/android/app/ContextImpl.java 
    +++ base/core/java/android/app/ContextImpl.java 
        @Override
        public boolean bindService(Intent service, ServiceConnection conn, int flags) {
            warnIfCallingFromSystemProcess();
            return bindServiceCommon(service, conn, flags, null, mMainThread.getHandler(), null,
                    getUser());
        }
    
        ....
    
    
    private boolean bindServiceCommon(Intent service, ServiceConnection conn, int flags,
                String instanceName, Handler handler, Executor executor, UserHandle user) {
            // Keep this in sync with DevicePolicyManager.bindDeviceAdminServiceAsUser.
            IServiceConnection sd;
            if (conn == null) {
                throw new IllegalArgumentException("connection is null");
            }
            if (handler != null && executor != null) {
                throw new IllegalArgumentException("Handler and Executor both supplied");
            }
            if (mPackageInfo != null) {
                if (executor != null) {
                    sd = mPackageInfo.getServiceDispatcher(conn, getOuterContext(), executor, flags);
                } else {
                    sd = mPackageInfo.getServiceDispatcher(conn, getOuterContext(), handler, flags);
                }
            } else {
                throw new RuntimeException("Not supported in system context");
            }
            validateServiceIntent(service);
            Slog.e(TAG, "validateServiceIntent service="+service);
            try {
                IBinder token = getActivityToken();
                if (token == null && (flags&BIND_AUTO_CREATE) == 0 && mPackageInfo != null
                        && mPackageInfo.getApplicationInfo().targetSdkVersion
                        < android.os.Build.VERSION_CODES.ICE_CREAM_SANDWICH) {
                    flags |= BIND_WAIVE_PRIORITY;
                }
                service.prepareToLeaveProcess(this);
                Slog.e(TAG, "prepareToLeaveProcess");
                int res = ActivityManager.getService().bindIsolatedService(
                    mMainThread.getApplicationThread(), getActivityToken(), service,
                    service.resolveTypeIfNeeded(getContentResolver()),
                    sd, flags, instanceName, getOpPackageName(), user.getIdentifier());
                Slog.e(TAG, "bindIsolatedService res="+res);
                if (res < 0) {
                    throw new SecurityException(
                            "Not allowed to bind to service " + service);
                }
                return res != 0;
            } catch (RemoteException e) {
                throw e.rethrowFromSystemServer();
            }
        }
    
    

    下面会调用到AMS,在此之前看下LoadedApk这段初始化IServiceConnection的内部实现。

    Index: base/core/java/android/app/LoadedApk.java
    ===================================================================
     @UnsupportedAppUsage
        public final IServiceConnection getServiceDispatcher(ServiceConnection c,
                Context context, Handler handler, int flags) {
            return getServiceDispatcherCommon(c, context, handler, null, flags);
        }
    
        private IServiceConnection getServiceDispatcherCommon(ServiceConnection c,
                Context context, Handler handler, Executor executor, int flags) {
            synchronized (mServices) {
                LoadedApk.ServiceDispatcher sd = null;
                ArrayMap<ServiceConnection, LoadedApk.ServiceDispatcher> map = mServices.get(context);
                if (map != null) {
                    if (DEBUG) Slog.d(TAG, "Returning existing dispatcher " + sd + " for conn " + c);
                    sd = map.get(c);
                }
                if (sd == null) {
                    if (executor != null) {
                        sd = new ServiceDispatcher(c, context, executor, flags);
                    } else {
                        sd = new ServiceDispatcher(c, context, handler, flags);
                    }
                    if (DEBUG) Slog.d(TAG, "Creating new dispatcher " + sd + " for conn " + c);
                    if (map == null) {
                        map = new ArrayMap<>();
                        mServices.put(context, map);
                    }
                    map.put(c, sd);
                } else {
                    sd.validate(context, handler, executor);
                }
                return sd.getIServiceConnection();
            }
        }
    
    
    ......
    static final class ServiceDispatcher {
            private final ServiceDispatcher.InnerConnection mIServiceConnection;
            @UnsupportedAppUsage
            private final ServiceConnection mConnection;
            @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
            private final Context mContext;
            private final Handler mActivityThread;
            private final Executor mActivityExecutor;
            private final ServiceConnectionLeaked mLocation;
            private final int mFlags;
    
            private RuntimeException mUnbindLocation;
    
            private boolean mForgotten;
    
            private static class ConnectionInfo {
                IBinder binder;
                IBinder.DeathRecipient deathMonitor;
            }
    
            private static class InnerConnection extends IServiceConnection.Stub {
                @UnsupportedAppUsage
                final WeakReference<LoadedApk.ServiceDispatcher> mDispatcher;
    
                InnerConnection(LoadedApk.ServiceDispatcher sd) {
                    mDispatcher = new WeakReference<LoadedApk.ServiceDispatcher>(sd);
                }
    
                public void connected(ComponentName name, IBinder service, boolean dead)
                        throws RemoteException {
                    LoadedApk.ServiceDispatcher sd = mDispatcher.get();
                    if (sd != null) {
                        sd.connected(name, service, dead);
                    }
                }
            }
    
            private final ArrayMap<ComponentName, ServiceDispatcher.ConnectionInfo> mActiveConnections
                = new ArrayMap<ComponentName, ServiceDispatcher.ConnectionInfo>();
    
            @UnsupportedAppUsage
            ServiceDispatcher(ServiceConnection conn,
                    Context context, Handler activityThread, int flags) {
                mIServiceConnection = new InnerConnection(this);
                mConnection = conn;
                mContext = context;
                mActivityThread = activityThread;
                mActivityExecutor = null;
                mLocation = new ServiceConnectionLeaked(null);
                mLocation.fillInStackTrace();
                mFlags = flags;
            }
    
            ServiceDispatcher(ServiceConnection conn,
                    Context context, Executor activityExecutor, int flags) {
                mIServiceConnection = new InnerConnection(this);
                mConnection = conn;
                mContext = context;
                mActivityThread = null;
                mActivityExecutor = activityExecutor;
                mLocation = new ServiceConnectionLeaked(null);
                mLocation.fillInStackTrace();
                mFlags = flags;
            }
    
            void validate(Context context, Handler activityThread, Executor activityExecutor) {
                if (mContext != context) {
                    throw new RuntimeException(
                        "ServiceConnection " + mConnection +
                        " registered with differing Context (was " +
                        mContext + " now " + context + ")");
                }
                if (mActivityThread != activityThread) {
                    throw new RuntimeException(
                        "ServiceConnection " + mConnection +
                        " registered with differing handler (was " +
                        mActivityThread + " now " + activityThread + ")");
                }
                if (mActivityExecutor != activityExecutor) {
                    throw new RuntimeException(
                        "ServiceConnection " + mConnection +
                        " registered with differing executor (was " +
                        mActivityExecutor + " now " + activityExecutor + ")");
                }
            }
    
            void doForget() {
                synchronized(this) {
                    for (int i=0; i<mActiveConnections.size(); i++) {
                        ServiceDispatcher.ConnectionInfo ci = mActiveConnections.valueAt(i);
                        ci.binder.unlinkToDeath(ci.deathMonitor, 0);
                    }
                    mActiveConnections.clear();
                    mForgotten = true;
                }
            }
    
            ServiceConnectionLeaked getLocation() {
                return mLocation;
            }
    
            ServiceConnection getServiceConnection() {
                return mConnection;
            }
    
            @UnsupportedAppUsage
            IServiceConnection getIServiceConnection() {
                return mIServiceConnection;
            }
    
            int getFlags() {
                return mFlags;
            }
    
            void setUnbindLocation(RuntimeException ex) {
                mUnbindLocation = ex;
            }
    
            RuntimeException getUnbindLocation() {
                return mUnbindLocation;
            }
    
            public void connected(ComponentName name, IBinder service, boolean dead) {
                Log.e(TAG,"connected  name "+name+",service="+service +"dead="+dead+",mActivityExecutor = " +(mActivityExecutor != null) );
                if (mActivityExecutor != null) {
                    mActivityExecutor.execute(new RunConnection(name, service, 0, dead));
                } else if (mActivityThread != null) {
                    mActivityThread.post(new RunConnection(name, service, 0, dead));
                } else {
                    doConnected(name, service, dead);
                }
            }
    
            public void death(ComponentName name, IBinder service) {
                if (mActivityExecutor != null) {
                    mActivityExecutor.execute(new RunConnection(name, service, 1, false));
                } else if (mActivityThread != null) {
                    mActivityThread.post(new RunConnection(name, service, 1, false));
                } else {
                    doDeath(name, service);
                }
            }
    
            public void doConnected(ComponentName name, IBinder service, boolean dead) {
                ServiceDispatcher.ConnectionInfo old;
                ServiceDispatcher.ConnectionInfo info;
    
                Log.e(TAG,"doConnected ");
                synchronized (this) {
                    if (mForgotten) {
                        // We unbound before receiving the connection; ignore
                        // any connection received.
                        return;
                    }
                    old = mActiveConnections.get(name);
                    if (old != null && old.binder == service) {
                        // Huh, already have this one.  Oh well!
                        return;
                    }
    
                    if (service != null) {
                        // A new service is being connected... set it all up.
                        info = new ConnectionInfo();
                        info.binder = service;
                        info.deathMonitor = new DeathMonitor(name, service);
                        try {
                            service.linkToDeath(info.deathMonitor, 0);
                            mActiveConnections.put(name, info);
                        } catch (RemoteException e) {
                            // This service was dead before we got it...  just
                            // don't do anything with it.
                            mActiveConnections.remove(name);
                            return;
                        }
    
                    } else {
                        // The named service is being disconnected... clean up.
                        mActiveConnections.remove(name);
                    }
    
                    if (old != null) {
                        old.binder.unlinkToDeath(old.deathMonitor, 0);
                    }
                }
    
                // If there was an old service, it is now disconnected.
                if (old != null) {
                    mConnection.onServiceDisconnected(name);
                }
                if (dead) {
                    mConnection.onBindingDied(name);
                }
                // If there is a new viable service, it is now connected.
                Log.e(TAG,"service!=null "+(service != null));
                if (service != null) {
                    mConnection.onServiceConnected(name, service);
                } else {
                    // The binding machinery worked, but the remote returned null from onBind().
                    mConnection.onNullBinding(name);
                }
            }
    
            public void doDeath(ComponentName name, IBinder service) {
                synchronized (this) {
                    ConnectionInfo old = mActiveConnections.get(name);
                    if (old == null || old.binder != service) {
                        // Death for someone different than who we last
                        // reported...  just ignore it.
                        return;
                    }
                    mActiveConnections.remove(name);
                    old.binder.unlinkToDeath(old.deathMonitor, 0);
                }
    
                mConnection.onServiceDisconnected(name);
            }
    
            private final class RunConnection implements Runnable {
                RunConnection(ComponentName name, IBinder service, int command, boolean dead) {
                    mName = name;
                    mService = service;
                    mCommand = command;
                    mDead = dead;
                }
    
                public void run() {
                    if (mCommand == 0) {
                        doConnected(mName, mService, mDead);
                    } else if (mCommand == 1) {
                        doDeath(mName, mService);
                    }
                }
    
                final ComponentName mName;
                final IBinder mService;
                final int mCommand;
                final boolean mDead;
            }
    
            private final class DeathMonitor implements IBinder.DeathRecipient
            {
                DeathMonitor(ComponentName name, IBinder service) {
                    mName = name;
                    mService = service;
                }
    
                public void binderDied() {
                    death(mName, mService);
                }
    
                final ComponentName mName;
                final IBinder mService;
            }
        }
    

    ActivityManagerService ,bindserver失败的原因就是这里 在这里会BackgroundManager.skipService(service)为true的时候会返回0,不在往下执行。

    
    
        public int bindIsolatedService(IApplicationThread caller, IBinder token, Intent service,
                String resolvedType, IServiceConnection connection, int flags, String instanceName,
                String callingPackage, int userId) throws TransactionTooLargeException {
            enforceNotIsolatedCaller("bindService");
    
            Slog.e(TAG, "bindIsolatedService enforceNotIsolatedCaller bindService");
            // Refuse possible leaked file descriptors
            if (service != null && service.hasFileDescriptors() == true) {
                throw new IllegalArgumentException("File descriptors passed in Intent");
            }
    
            if (callingPackage == null) {
                throw new IllegalArgumentException("callingPackage cannot be null");
            }
    
            // Ensure that instanceName, which is caller provided, does not contain
            // unusual characters.
            if (instanceName != null) {
                for (int i = 0; i < instanceName.length(); ++i) {
                    char c = instanceName.charAt(i);
                    if (!((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z')
                                || (c >= '0' && c <= '9') || c == '_' || c == '.')) {
                        throw new IllegalArgumentException("Illegal instanceName");
                    }
                }
            }
    
                Slog.e(TAG, "bindIsolatedService skipService=" + BackgroundManager.skipService(service));
                if (BackgroundManager.skipService(service)) return 0;
            synchronized(this) {
                return mServices.bindServiceLocked(caller, token, service,
                        resolvedType, connection, flags, instanceName, callingPackage, userId);
            }
        }
    
    
    

    下面是一些添加和打印一些日志

    Index: base/core/java/android/app/ActivityThread.java
    ===================================================================
    --- base/core/java/android/app/ActivityThread.java  (revision 16364)
    +++ base/core/java/android/app/ActivityThread.java  (working copy)
    @@ -227,7 +227,7 @@
         private static final boolean DEBUG_RESULTS = false;
         private static final boolean DEBUG_BACKUP = false;
         public static final boolean DEBUG_CONFIGURATION = false;
    -    private static final boolean DEBUG_SERVICE = false;
    +    private static final boolean DEBUG_SERVICE = true;
         public static final boolean DEBUG_MEMORY_TRIM = false;
         private static final boolean DEBUG_PROVIDER = false;
         public static final boolean DEBUG_ORDER = false;
    
    Index: base/core/java/android/aw/BackgroundManager.java
    ===================================================================
    --- base/core/java/android/aw/BackgroundManager.java    (revision 16364)
    +++ base/core/java/android/aw/BackgroundManager.java    (working copy)
    @@ -125,6 +125,7 @@
          */
         public static boolean skipService(Intent service) {
             IBackgroundManager bm = getService();
    +        Log.w(TAG, "bm " +(bm ==null)+",service="+service);
             if (bm == null) return false;
             try {
                 return bm.skipService(service);
    Index: base/services/core/java/com/android/server/am/ActivityManagerDebugConfig.java
    ===================================================================
    --- base/services/core/java/com/android/server/am/ActivityManagerDebugConfig.java   (revision 16364)
    +++ base/services/core/java/com/android/server/am/ActivityManagerDebugConfig.java   (working copy)
    @@ -28,7 +28,7 @@
         // to figure-out the origin of a log message while debugging the activity manager a little
         // painful. By setting this constant to true, log messages from the activity manager package
         // will be tagged with their class names instead fot the generic tag.
    -    static final boolean TAG_WITH_CLASS_NAME = false;
    +    static final boolean TAG_WITH_CLASS_NAME = true;
     
         // While debugging it is sometimes useful to have the category name of the log appended to the
         // base log tag to make sifting through logs with the same base tag easier. By setting this
    @@ -39,7 +39,7 @@
         static final String TAG_AM = "ActivityManager";
     
         // Enable all debug log categories.
    -    static final boolean DEBUG_ALL = false;
    +    static final boolean DEBUG_ALL = true;
     
         // Available log categories in the activity manager package.
         static final boolean DEBUG_ANR = false;
    Index: base/services/core/java/com/android/server/am/ActivityManagerService.java
    ===================================================================
    --- base/services/core/java/com/android/server/am/ActivityManagerService.java   (revision 16364)
    +++ base/services/core/java/com/android/server/am/ActivityManagerService.java   (working copy)
    @@ -14108,6 +14108,7 @@
                 String callingPackage, int userId) throws TransactionTooLargeException {
             enforceNotIsolatedCaller("bindService");
     
    +        Slog.e(TAG, "bindIsolatedService enforceNotIsolatedCaller bindService");
             // Refuse possible leaked file descriptors
             if (service != null && service.hasFileDescriptors() == true) {
                 throw new IllegalArgumentException("File descriptors passed in Intent");
    @@ -14129,8 +14130,9 @@
                 }
             }
     
    -        if (BackgroundManager.skipService(service)) return 0;
             synchronized(this) {
    +            Slog.e(TAG, "bindIsolatedService skipService=" + BackgroundManager.skipService(service));
    +            if (BackgroundManager.skipService(service)) return 0;
                 return mServices.bindServiceLocked(caller, token, service,
                         resolvedType, connection, flags, instanceName, callingPackage, userId);
             }
    
    

    方式1:关闭后台管理限制

    android\device\softwinner\common\pad.mk
        
    # background manager
    #PRODUCT_PACKAGES += awbms.jar AwManager
    

    方式2:关闭 skipService awbms_config

    android\device\softwinner\common\config\awbms_config 
    
    skipService: false
    
    

    方式3:根据对应的action来添加白名单

    android\device\softwinner\common\config\awbms_config 
    
    action:
    android.service.wallpaper.WallpaperService
    com.android.cts.verifier.camera.its.START
    com.softwinner.c2dm.intent.REGISTER
    kr.hwangti.batterylog.BatteryLogService
    com.system.ftools.util.FoSvc
    
    

    Android O Service启动流程梳理——bindService

    相关文章

      网友评论

          本文标题:全志Android 10 第三方应用bindservice失败的

          本文链接:https://www.haomeiwen.com/subject/pccerrtx.html