Intent should not transmit large amounts of data

Bundle type data can be stored in the Intent, and the bundle data can be used to store key-value pair data, and can also store arrays. It is very convenient to transfer data in process communication, but it should be noted that the essence of intent transfer is the binder method. It is determined that it cannot be used to transmit large amounts of data, otherwise problems will occur.
Binder is suitable for a small amount of data transmission. I have done an experiment before. In the event processing in the sensorManager, the binder is called. The call is 30 times per second, and there is basically no lag.

Regarding the transfer of intents, take the call of bindService as an example. The essence of sendBroadcast is the same.

protected void onCreate(Bundle savedInstanceState) {
	super.onCreate(savedInstanceState);
	setContentView(R.layout.activity_main);

	bindService(new Intent("com.sunday.aidl.IMathService"), 
			serviceConnection, BIND_AUTO_CREATE);
	
	
	Button aButton = (Button)findViewById(R.id.button1);
	aButton.setOnClickListener(this);
}

public class ContextWrapper extends Context {
Context mBase;

public ContextWrapper(Context base) {
    mBase = base;
}

public boolean bindService(Intent service, ServiceConnection conn,
        int flags) {
    return mBase.bindService(service, conn, flags);
}

ContextImpl.java
// bindService
@Override
public boolean bindService(Intent service, ServiceConnection conn, int flags) {
warnIfCallingFromSystemProcess();
return bindServiceCommon(service, conn, flags, Process.myUserHandle());
}

// bindServiceCommon
private boolean bindServiceCommon(Intent service, ServiceConnection conn, int flags, UserHandle user) {
    IServiceConnection sd;
    ...

// 包装 ServiceConnection
sd = mPackageInfo.getServiceDispatcher (conn, getOuterContext (),
mMainThread.getHandler (), flags);

    ...

    int res = ActivityManagerNative.getDefault().bindService(
            mMainThread.getApplicationThread(), getActivityToken(), service,
            service.resolveTypeIfNeeded(getContentResolver()),
            sd, flags, getOpPackageName(), user.getIdentifier());

    ...

}

Here is the communication through binder and AMS, a binder calls
ActivityManagerNative.java
private static final Singleton gDefault = new Singleton() { protected IActivityManager create() { IBinder b = ServiceManager.getService("activity"); if (false) { Log .v("ActivityManager", "default service binder = "+ b); } IActivityManager am = asInterface(b); if (false) { Log.v("ActivityManager", "default service =" + am); } return am; } }; }












static public IActivityManager asInterface(IBinder obj) {
    if (obj == null) {
        return null;
    }
    IActivityManager in =
        (IActivityManager)obj.queryLocalInterface(descriptor);
    if (in != null) {
        return in;
    }

    return new ActivityManagerProxy(obj);
}

public abstract class Singleton {
private T mInstance;

protected abstract T create();

public final T get() {
    synchronized (this) {
        if (mInstance == null) {
            mInstance = create();
        }
        return mInstance;
    }
}

}

即包装ServiceManager.getService(“activity”);
继续查看bindServiceCommon方法
private boolean bindServiceCommon(Intent service, ServiceConnection conn, int flags, Handler
handler, UserHandle user) {
IServiceConnection sd;
if (conn == null) {
throw new IllegalArgumentException(“connection is null”);
}
if (mPackageInfo != null) {
sd = mPackageInfo.getServiceDispatcher(conn, getOuterContext(), handler, flags);
} else {
throw new RuntimeException(“Not supported in system context”);
}
validateServiceIntent(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);
int res = ActivityManagerNative.getDefault().bindService(
mMainThread.getApplicationThread(), getActivityToken(), service,
service.resolveTypeIfNeeded(getContentResolver()),
sd, flags, getOpPackageName(), user.getIdentifier());

How does this sd come from?
ServiceDispatcher is used to wrap ServiceConnection to
create binder entity objects, which are used to respond to the callback
LoadedApk.java
public final IServiceConnection getServiceDispatcher(ServiceConnection c,
Context context, Handler handler, int flags) { synchronized (mServices) { LoadedApk.ServiceDispatcher sd = null; ArrayMap<ServiceConnection, LoadedApk.ServiceDispatcher> map = mServices.get(context); if (map != null) { sd = map.get©; } if (sd == null) { sd = new ServiceDispatcher( c, context, handler, flags); if (map == null) { map = new ArrayMap<ServiceConnection, LoadedApk.ServiceDispatcher>(); mServices.put(context, map); }












map.put(c, sd);
} else {
sd.validate(context, handler);
}
return sd.getIServiceConnection();
}
}

    ServiceDispatcher(ServiceConnection conn,
            Context context, Handler activityThread, int flags) {
        mIServiceConnection = new InnerConnection(this);
        mConnection = conn;
        mContext = context;
        mActivityThread = activityThread;
        mLocation = new ServiceConnectionLeaked(null);
        mLocation.fillInStackTrace();
        mFlags = flags;
    }

InnerConnection用来进行binder通信
private static class InnerConnection extends IServiceConnection.Stub {
final WeakReference<LoadedApk.ServiceDispatcher> mDispatcher;

        InnerConnection(LoadedApk.ServiceDispatcher sd) {
            mDispatcher = new WeakReference<LoadedApk.ServiceDispatcher>(sd);
        }

        public void connected(ComponentName name, IBinder service) throws RemoteException {
            LoadedApk.ServiceDispatcher sd = mDispatcher.get();
            if (sd != null) {
                sd.connected(name, service);
            }
        }
    }

The AMS side acts as a Proxy to call the connected method

Guess you like

Origin blog.csdn.net/aaajj/article/details/111456470