Android进化Android内存优化

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

2020-07-21  本文已影响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;
    }
}
上一篇 下一篇

猜你喜欢

热点阅读