美文网首页Android进化Android内存优化
Android AMS怎么监听异常挂掉的进程?

Android AMS怎么监听异常挂掉的进程?

作者: 锄禾豆 | 来源:发表于2020-07-21 19:57 被阅读0次

    代码分析

    1.代码路径

    frameworks/base/core/java/android/app/ActivityThread.java
    frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java 
    frameworks/base/core/java/android/os/IBinder.java 
    代码参考:Android Q
    

    2.ActivityThread

    public static void main(String[] args) {
        ······
        ActivityThread thread = new ActivityThread();
        thread.attach(false, startSeq);
        ······
    }
    
    private void attach(boolean system, long startSeq) {
        ······
        final IActivityManager mgr = ActivityManager.getService();
        try {
             mgr.attachApplication(mAppThread, startSeq);
        } catch (RemoteException ex) {
             throw ex.rethrowFromSystemServer();
        }
       ······
    }
    1.final ApplicationThread mAppThread = new ApplicationThread();
    2.private class ApplicationThread extends IApplicationThread.Stub
    

    3.ActivityManagerService.java

    public final void attachApplication(IApplicationThread thread, long startSeq) {
        ······
        attachApplicationLocked(thread, callingPid, callingUid, startSeq);
        ······
    }
    
    private final boolean attachApplicationLocked(IApplicationThread thread,
            int pid, int callingUid, long startSeq) {
         ······
         try {
             AppDeathRecipient adr = new AppDeathRecipient(
                   app, pid, thread);
             thread.asBinder().linkToDeath(adr, 0);
             app.deathRecipient = adr;
         } catch (RemoteException e) {
             app.resetPackageList(mProcessStats);
             mProcessList.startProcessLocked(app,
                   new HostingRecord("link fail", processName));
             return false;
         }
         ······       
    }
    1.重点在于thread.asBinder().linkToDeath(adr, 0)的使用
    2.如果thread被kill了,就会马上调用adr对象中的binderDied方法
    

    4.ActivityManagerService.AppDeathRecipient

    private final class AppDeathRecipient implements IBinder.DeathRecipient {
        ProcessRecord mApp = null;
        final int mPid;
        final IApplicationThread mAppThread;
    
        AppDeathRecipient(ProcessRecord app, int pid,
                IApplicationThread thread) {
            //if (DEBUG_ALL)
            Slog.v(
                TAG, "New death recipient " + this
                 + " for thread " + thread.asBinder()
                 + ", pid:" + pid + ",mApp:" + mApp);
            mApp = app;
            mPid = pid;
            mAppThread = thread;
        }
    
        @Override
        public void binderDied() {
            //if (DEBUG_ALL)
            Slog.v(
                TAG, "Death received in " + this
                + " for thread " + mAppThread.asBinder()
                + ", mPid:" + mPid + ",mApp:" + mApp);
    
            synchronized(ActivityManagerService.this) {
                appDiedLocked(mApp, mPid, mAppThread, true);
            }
        }
    }
    

    5.理论支持IBinder

    public interface IBinder {
        ·······
        /**
     * Interface for receiving a callback when the process hosting an IBinder
     * has gone away.
     * 
     * @see #linkToDeath
     */
       public interface DeathRecipient {
          public void binderDied();
      }
    
    /**
     * Register the recipient for a notification if this binder
     * goes away.  If this binder object unexpectedly goes away
     * (typically because its hosting process has been killed),
     * then the given {@link DeathRecipient}'s
     * {@link DeathRecipient#binderDied DeathRecipient.binderDied()} method
     * will be called.
     * 
     * <p>You will only receive death notifications for remote binders,
     * as local binders by definition can't die without you dying as well.
     * 
     * @throws RemoteException if the target IBinder's
     * process has already died.
     * 
     * @see #unlinkToDeath
     */
       public void linkToDeath(@NonNull DeathRecipient recipient, int flags)
            throws RemoteException;
    
    /**
     * Remove a previously registered death notification.
     * The recipient will no longer be called if this object
     * dies.
     * 
     * @return {@code true} if the <var>recipient</var> is successfully
     * unlinked, assuring you that its
     * {@link DeathRecipient#binderDied DeathRecipient.binderDied()} method
     * will not be called;  {@code false} if the target IBinder has already
     * died, meaning the method has been (or soon will be) called.
     * 
     * @throws java.util.NoSuchElementException if the given
     * <var>recipient</var> has not been registered with the IBinder, and
     * the IBinder is still alive.  Note that if the <var>recipient</var>
     * was never registered, but the IBinder has already died, then this
     * exception will <em>not</em> be thrown, and you will receive a false
     * return value instead.
     */
        public boolean unlinkToDeath(@NonNull DeathRecipient recipient, int flags);
    }
    

    总结

    对于通过跨进程通信的apk,不管是客户端还是服务端,都可以进行此方法来监听耦合的进程是否异常

    参考学习

    https://blog.csdn.net/qq_31429205/article/details/104175356
    https://www.jianshu.com/p/1180886b3ff3

    补充

    AMS有封装监听Process运行情况并对外开放了一个接口,供系统进程调用查看各种进程的运行情况,具体如下:

    一、监听
    try {
        IActivityManager am = ActivityManagerNative.getDefault();//ActivityManager.getService()
        am.registerProcessObserver(mProcessObserver);
    } catch (Exception e) {
        e.printStackTrace();
    }
    
    二、回调
    private IProcessObserver mProcessObserver = new IProcessObserver.Stub() {
        @Override
        public void onForegroundActivitiesChanged(int pid, final int uid,
                boolean foregroundActivities) {
            
        }
    
        @Override
        public void onForegroundServicesChanged(int pid, int uid, int foregroundServiceTypes){
            
        }
    
        public void onProcessStateChanged(int pid, int uid, int procState) {
            
        }
    
        @Override
        public void onProcessDied(final int pid, final int uid) {
            
        }
    };
    
    三、注意
    IProcessObserver是oneway的binder
    oneway interface IProcessObserver {
        void onForegroundActivitiesChanged(int pid, int uid, boolean foregroundActivities);
        void onForegroundServicesChanged(int pid, int uid, int serviceTypes);
        void onProcessDied(int pid, int uid);
    }
    
    四、原理分析
    1.ActivityManagerService
    
    public void registerProcessObserver(IProcessObserver observer) {
        enforceCallingPermission(android.Manifest.permission.SET_ACTIVITY_WATCHER,
                "registerProcessObserver()");
        synchronized (this) {
            mProcessObservers.register(observer);
        }
    }
    
    @Override
    public void unregisterProcessObserver(IProcessObserver observer) {
        synchronized (this) {
            mProcessObservers.unregister(observer);
        }
    }
    
    2.RemoteCallbackList
    public boolean register(E callback) {
        return register(callback, null);
    }
    
    public boolean register(E callback, Object cookie) {
        synchronized (mCallbacks) {
            if (mKilled) {
                return false;
            }
            // Flag unusual case that could be caused by a leak. b/36778087
            logExcessiveCallbacks();
            IBinder binder = callback.asBinder();
            try {
                Callback cb = new Callback(callback, cookie);
                binder.linkToDeath(cb, 0);
                mCallbacks.put(binder, cb);
                return true;
            } catch (RemoteException e) {
                return false;
            }
        }
    }
    关键点:binder.linkToDeath(cb, 0)。这里进行了linkToDeath,在进程挂了后,会调用cb.binderDied
    
    public boolean unregister(E callback) {
        synchronized (mCallbacks) {
            Callback cb = mCallbacks.remove(callback.asBinder());
            if (cb != null) {
                cb.mCallback.asBinder().unlinkToDeath(cb, 0);
                return true;
            }
            return false;
        }
    }
    

    相关文章

      网友评论

        本文标题:Android AMS怎么监听异常挂掉的进程?

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