ContentProvider原理分析二 MediaProvider publish .

本文仅讨论ContentProvider的Publish过程。


在Android启动后,会自动launch application,如果Application用到ContentProvider则会在handleBindApplication()时publish该ContentProvider。另外如果ContentProvider进程中途死掉,则在有调用ContentProvider接口如query,update等时创建。本文即专注于此流程。

Application通过在AndroidManifest.xml中说明<provider android:name="MediaProvider" android.authority="media" android.multiprocess="false" />,则PackageManager可以知道对应ContentProvider的apk文件,从而加载该apk完成Contentprovider publish.


步骤:

通过ContentResolver先查找对应给定Uri的ContentProvider,返回对应的BinderProxy

a.通过ServiceManager查找activity service得到ActivityManagerService对应BinderProxy

b.调用BinderProxy的transcat方法发送GET_CONTENT_PROVIDER_TRANSACTION命令,得到对应ContentProvider的BinderProxy

一旦得到ActivityManager对应的binder 代理对象,则使用如下代码可以发送请求得到名字为name的Contentprovider。


调用顺序图:

源代码调用路径:

frameworks/base/core/java/android/app/ActivityManagerNative.java

  1. class ActivityManagerProxy implements IActivityManager  
  2. {  
  3. ...  
  4.     public ContentProviderHolder getContentProvider(IApplicationThread caller,  
  5.                                                     String name) throws RemoteException  
  6.     {  
  7.         Parcel data = Parcel.obtain();  
  8.         Parcel reply = Parcel.obtain();  
  9.         data.writeInterfaceToken(IActivityManager.descriptor);  
  10.         data.writeStrongBinder(caller != null ? caller.asBinder() : null);  
  11.         data.writeString(name);                                                   //ContentProvider名字   
  12.         mRemote.transact(GET_CONTENT_PROVIDER_TRANSACTION, data, reply, 0);       //取得ContentProvider   
  13.         reply.readException();  
  14.         int res = reply.readInt();  
  15.         ContentProviderHolder cph = null;  
  16.         if (res != 0) {  
  17.             cph = ContentProviderHolder.CREATOR.createFromParcel(reply);  
  18.         }  
  19.         data.recycle();  
  20.         reply.recycle();  
  21.         return cph;  
  22.     }  
class ActivityManagerProxy implements IActivityManager
{
...
    public ContentProviderHolder getContentProvider(IApplicationThread caller,
                                                    String name) throws RemoteException
    {
        Parcel data = Parcel.obtain();
        Parcel reply = Parcel.obtain();
        data.writeInterfaceToken(IActivityManager.descriptor);
        data.writeStrongBinder(caller != null ? caller.asBinder() : null);
        data.writeString(name);                                                   //ContentProvider名字
        mRemote.transact(GET_CONTENT_PROVIDER_TRANSACTION, data, reply, 0);       //取得ContentProvider
        reply.readException();
        int res = reply.readInt();
        ContentProviderHolder cph = null;
        if (res != 0) {
            cph = ContentProviderHolder.CREATOR.createFromParcel(reply);
        }
        data.recycle();
        reply.recycle();
        return cph;
    }


frameworks/base/core/java/android/app/ActivityManagerService.java

  1.     public final ContentProviderHolder getContentProvider(  
  2.             IApplicationThread caller, String name) {  
  3.         if (caller == null) {  
  4.             String msg = "null IApplicationThread when getting content provider "  
  5.                     + name;  
  6.             Slog.w(TAG, msg);  
  7.             throw new SecurityException(msg);  
  8.         }  
  9.   
  10.         return getContentProviderImpl(caller, name);  
  11.     }  
  12.     private final ContentProviderHolder getContentProviderImpl(  
  13.         IApplicationThread caller, String name) {  
  14.         ContentProviderRecord cpr;  
  15.         ProviderInfo cpi = null;  
  16.   
  17.         synchronized(this) {  
  18.             ProcessRecord r = null;  
  19.             if (caller != null) {  
  20.                 r = getRecordForAppLocked(caller);  
  21.                 if (r == null) {  
  22.                     throw new SecurityException(  
  23.                             "Unable to find app for caller " + caller  
  24.                           + " (pid=" + Binder.getCallingPid()  
  25.                           + ") when getting content provider " + name);  
  26.                 }  
  27.             }  
  28.   
  29.             // First check if this content provider has been published...   
  30.             cpr = mProvidersByName.get(name);  
  31.             if (cpr != null) {  
  32. ...  
  33.   
  34.             } else {  
  35.                 try {  
  36.                     cpi = AppGlobals.getPackageManager().  
  37.                         resolveContentProvider(name,  
  38.                                 STOCK_PM_FLAGS | PackageManager.GET_URI_PERMISSION_PATTERNS);  
  39.                 } catch (RemoteException ex) {  
  40.                 }  
  41.                 if (cpi == null) {  
  42.                     return null;  
  43.                 }  
  44.   
  45.                 String msg;  
  46.                 if ((msg=checkContentProviderPermissionLocked(cpi, r)) != null) {  
  47.                     throw new SecurityException(msg);  
  48.                 }  
  49.   
  50.                 if (!mProcessesReady && !mDidUpdate && !mWaitingUpdate  
  51.                         && !cpi.processName.equals("system")) {  
  52.                     // If this content provider does not run in the system   
  53.                     // process, and the system is not yet ready to run other   
  54.                     // processes, then fail fast instead of hanging.   
  55.                     throw new IllegalArgumentException(  
  56.                             "Attempt to launch content provider before system ready");  
  57.                 }  
  58.                   
  59.                 cpr = mProvidersByClass.get(cpi.name);  
  60.                 final boolean firstClass = cpr == null;  
  61.                 if (firstClass) {  
  62.                     try {  
  63.                         ApplicationInfo ai =  
  64.                             AppGlobals.getPackageManager().  
  65.                                 getApplicationInfo(  
  66.                                         cpi.applicationInfo.packageName,  
  67.                                         STOCK_PM_FLAGS);  
  68.                         if (ai == null) {  
  69.                             Slog.w(TAG, "No package info for content provider "  
  70.                                     + cpi.name);  
  71.                             return null;  
  72.                         }  
  73.                         cpr = new ContentProviderRecord(cpi, ai);  
  74.                     } catch (RemoteException ex) {  
  75.                         // pm is in same process, this will never happen.   
  76.                     }  
  77.                 }  
  78.   
  79.                 if (r != null && cpr.canRunHere(r)) {  
  80.                     // If this is a multiprocess provider, then just return its   
  81.                     // info and allow the caller to instantiate it.  Only do   
  82.                     // this if the provider is the same user as the caller's   
  83.                     // process, or can run as root (so can be in any process).   
  84.                     return cpr;  
  85.                 }  
  86.   
  87.                 if (DEBUG_PROVIDER) {  
  88.                     RuntimeException e = new RuntimeException("here");  
  89.                     Slog.w(TAG, "LAUNCHING REMOTE PROVIDER (myuid " + r.info.uid  
  90.                           + " pruid " + cpr.appInfo.uid + "): " + cpr.info.name, e);  
  91.                 }  
  92.   
  93.                 // This is single process, and our app is now connecting to it.   
  94.                 // See if we are already in the process of launching this   
  95.                 // provider.   
  96.                 final int N = mLaunchingProviders.size();  
  97.                 int i;  
  98.                 for (i=0; i<N; i++) {  
  99.                     if (mLaunchingProviders.get(i) == cpr) {  
  100.                         break;  
  101.                     }  
  102.                 }  
  103.   
  104.                 // If the provider is not already being launched, then get it   
  105.                 // started.   
  106.                 if (i >= N) {  
  107.                     final long origId = Binder.clearCallingIdentity();  
  108.                     ProcessRecord proc = startProcessLocked(cpi.processName,  
  109.                             cpr.appInfo, false0"content provider",  
  110.                             new ComponentName(cpi.applicationInfo.packageName,  
  111.                                     cpi.name), false);  
  112.                     if (proc == null) {  
  113.                         Slog.w(TAG, "Unable to launch app "  
  114.                                 + cpi.applicationInfo.packageName + "/"  
  115.                                 + cpi.applicationInfo.uid + " for provider "  
  116.                                 + name + ": process is bad");  
  117.                         return null;  
  118.                     }  
  119.                     cpr.launchingApp = proc;  
  120.                     mLaunchingProviders.add(cpr);  
  121.                     Binder.restoreCallingIdentity(origId);  
  122.                 }  
  123.   
  124.                 // Make sure the provider is published (the same provider class   
  125.                 // may be published under multiple names).   
  126.                 if (firstClass) {  
  127.                     mProvidersByClass.put(cpi.name, cpr);  
  128.                 }  
  129.                 mProvidersByName.put(name, cpr);  
  130.   
  131.                 if (r != null) {  
  132.                     if (DEBUG_PROVIDER) Slog.v(TAG,  
  133.                             "Adding provider requested by "  
  134.                             + r.processName + " from process "  
  135.                             + cpr.info.processName);  
  136.                     Integer cnt = r.conProviders.get(cpr);  
  137.                     if (cnt == null) {  
  138.                         r.conProviders.put(cpr, new Integer(1));  
  139.                     } else {  
  140.                         r.conProviders.put(cpr, new Integer(cnt.intValue()+1));  
  141.                     }  
  142.                     cpr.clients.add(r);  
  143.                 } else {  
  144.                     cpr.externals++;  
  145.                 }  
  146.             }  
  147.         }  
  148.   
  149.         // Wait for the provider to be published...   
  150.         synchronized (cpr) {  
  151.             while (cpr.provider == null) {  
  152.                 if (cpr.launchingApp == null) {  
  153.                     Slog.w(TAG, "Unable to launch app "  
  154.                             + cpi.applicationInfo.packageName + "/"  
  155.                             + cpi.applicationInfo.uid + " for provider "  
  156.                             + name + ": launching app became null");  
  157.                     EventLog.writeEvent(EventLogTags.AM_PROVIDER_LOST_PROCESS,  
  158.                             cpi.applicationInfo.packageName,  
  159.                             cpi.applicationInfo.uid, name);  
  160.                     return null;  
  161.                 }  
  162.                 try {  
  163.                     cpr.wait();  
  164.                 } catch (InterruptedException ex) {  
  165.                 }  
  166.             }  
  167.         }  
  168.         return cpr;  
  169.     }  
  170.     final ProcessRecord startProcessLocked(String processName,  
  171.             ApplicationInfo info, boolean knownToBeDead, int intentFlags,  
  172.             String hostingType, ComponentName hostingName, boolean allowWhileBooting) {  
  173.         ProcessRecord app = getProcessRecordLocked(processName, info.uid);  
  174.         // We don't have to do anything more if:   
  175.         // (1) There is an existing application record; and   
  176.         // (2) The caller doesn't think it is dead, OR there is no thread   
  177.         //     object attached to it so we know it couldn't have crashed; and   
  178.         // (3) There is a pid assigned to it, so it is either starting or   
  179.         //     already running.   
  180.         if (DEBUG_PROCESSES) Slog.v(TAG, "startProcess: name=" + processName  
  181.                 + " app=" + app + " knownToBeDead=" + knownToBeDead  
  182.                 + " thread=" + (app != null ? app.thread : null)  
  183.                 + " pid=" + (app != null ? app.pid : -1));  
  184.         if (app != null && app.pid > 0) {  
  185.             if (!knownToBeDead || app.thread == null) {  
  186.                 // We already have the app running, or are waiting for it to   
  187.                 // come up (we have a pid but not yet its thread), so keep it.   
  188.                 if (DEBUG_PROCESSES) Slog.v(TAG, "App already running: " + app);  
  189.                 return app;  
  190.             } else {  
  191.                 // An application record is attached to a previous process,   
  192.                 // clean it up now.   
  193.                 if (DEBUG_PROCESSES) Slog.v(TAG, "App died: " + app);  
  194.                 handleAppDiedLocked(app, true);  
  195.             }  
  196.         }  
  197.   
  198.         String hostingNameStr = hostingName != null  
  199.                 ? hostingName.flattenToShortString() : null;  
  200.           
  201.         if ((intentFlags&Intent.FLAG_FROM_BACKGROUND) != 0) {  
  202.             // If we are in the background, then check to see if this process   
  203.             // is bad.  If so, we will just silently fail.   
  204.             if (mBadProcesses.get(info.processName, info.uid) != null) {  
  205.                 if (DEBUG_PROCESSES) Slog.v(TAG, "Bad process: " + info.uid  
  206.                         + "/" + info.processName);  
  207.                 return null;  
  208.             }  
  209.         } else {  
  210.             // When the user is explicitly starting a process, then clear its   
  211.             // crash count so that we won't make it bad until they see at   
  212.             // least one crash dialog again, and make the process good again   
  213.             // if it had been bad.   
  214.             if (DEBUG_PROCESSES) Slog.v(TAG, "Clearing bad process: " + info.uid  
  215.                     + "/" + info.processName);  
  216.             mProcessCrashTimes.remove(info.processName, info.uid);  
  217.             if (mBadProcesses.get(info.processName, info.uid) != null) {  
  218.                 EventLog.writeEvent(EventLogTags.AM_PROC_GOOD, info.uid,  
  219.                         info.processName);  
  220.                 mBadProcesses.remove(info.processName, info.uid);  
  221.                 if (app != null) {  
  222.                     app.bad = false;  
  223.                 }  
  224.             }  
  225.         }  
  226.           
  227.         if (app == null) {  
  228.             app = newProcessRecordLocked(null, info, processName);  
  229.             mProcessNames.put(processName, info.uid, app);  
  230.         } else {  
  231.             // If this is a new package in the process, add the package to the list   
  232.             app.addPackage(info.packageName);  
  233.         }  
  234.   
  235.         // If the system is not ready yet, then hold off on starting this   
  236.         // process until it is.   
  237.         if (!mProcessesReady  
  238.                 && !isAllowedWhileBooting(info)  
  239.                 && !allowWhileBooting) {  
  240.             if (!mProcessesOnHold.contains(app)) {  
  241.                 mProcessesOnHold.add(app);  
  242.             }  
  243.             if (DEBUG_PROCESSES) Slog.v(TAG, "System not ready, putting on hold: " + app);  
  244.             return app;  
  245.         }  
  246.   
  247.         startProcessLocked(app, hostingType, hostingNameStr);  
  248.         return (app.pid != 0) ? app : null;  
  249.     }  
    public final ContentProviderHolder getContentProvider(
            IApplicationThread caller, String name) {
        if (caller == null) {
            String msg = "null IApplicationThread when getting content provider "
                    + name;
            Slog.w(TAG, msg);
            throw new SecurityException(msg);
        }

        return getContentProviderImpl(caller, name);
    }
    private final ContentProviderHolder getContentProviderImpl(
        IApplicationThread caller, String name) {
        ContentProviderRecord cpr;
        ProviderInfo cpi = null;

        synchronized(this) {
            ProcessRecord r = null;
            if (caller != null) {
                r = getRecordForAppLocked(caller);
                if (r == null) {
                    throw new SecurityException(
                            "Unable to find app for caller " + caller
                          + " (pid=" + Binder.getCallingPid()
                          + ") when getting content provider " + name);
                }
            }

            // First check if this content provider has been published...
            cpr = mProvidersByName.get(name);
            if (cpr != null) {
...

            } else {
                try {
                    cpi = AppGlobals.getPackageManager().
                        resolveContentProvider(name,
                                STOCK_PM_FLAGS | PackageManager.GET_URI_PERMISSION_PATTERNS);
                } catch (RemoteException ex) {
                }
                if (cpi == null) {
                    return null;
                }

                String msg;
                if ((msg=checkContentProviderPermissionLocked(cpi, r)) != null) {
                    throw new SecurityException(msg);
                }

                if (!mProcessesReady && !mDidUpdate && !mWaitingUpdate
                        && !cpi.processName.equals("system")) {
                    // If this content provider does not run in the system
                    // process, and the system is not yet ready to run other
                    // processes, then fail fast instead of hanging.
                    throw new IllegalArgumentException(
                            "Attempt to launch content provider before system ready");
                }
                
                cpr = mProvidersByClass.get(cpi.name);
                final boolean firstClass = cpr == null;
                if (firstClass) {
                    try {
                        ApplicationInfo ai =
                            AppGlobals.getPackageManager().
                                getApplicationInfo(
                                        cpi.applicationInfo.packageName,
                                        STOCK_PM_FLAGS);
                        if (ai == null) {
                            Slog.w(TAG, "No package info for content provider "
                                    + cpi.name);
                            return null;
                        }
                        cpr = new ContentProviderRecord(cpi, ai);
                    } catch (RemoteException ex) {
                        // pm is in same process, this will never happen.
                    }
                }

                if (r != null && cpr.canRunHere(r)) {
                    // If this is a multiprocess provider, then just return its
                    // info and allow the caller to instantiate it.  Only do
                    // this if the provider is the same user as the caller's
                    // process, or can run as root (so can be in any process).
                    return cpr;
                }

                if (DEBUG_PROVIDER) {
                    RuntimeException e = new RuntimeException("here");
                    Slog.w(TAG, "LAUNCHING REMOTE PROVIDER (myuid " + r.info.uid
                          + " pruid " + cpr.appInfo.uid + "): " + cpr.info.name, e);
                }

                // This is single process, and our app is now connecting to it.
                // See if we are already in the process of launching this
                // provider.
                final int N = mLaunchingProviders.size();
                int i;
                for (i=0; i<N; i++) {
                    if (mLaunchingProviders.get(i) == cpr) {
                        break;
                    }
                }

                // If the provider is not already being launched, then get it
                // started.
                if (i >= N) {
                    final long origId = Binder.clearCallingIdentity();
                    ProcessRecord proc = startProcessLocked(cpi.processName,
                            cpr.appInfo, false, 0, "content provider",
                            new ComponentName(cpi.applicationInfo.packageName,
                                    cpi.name), false);
                    if (proc == null) {
                        Slog.w(TAG, "Unable to launch app "
                                + cpi.applicationInfo.packageName + "/"
                                + cpi.applicationInfo.uid + " for provider "
                                + name + ": process is bad");
                        return null;
                    }
                    cpr.launchingApp = proc;
                    mLaunchingProviders.add(cpr);
                    Binder.restoreCallingIdentity(origId);
                }

                // Make sure the provider is published (the same provider class
                // may be published under multiple names).
                if (firstClass) {
                    mProvidersByClass.put(cpi.name, cpr);
                }
                mProvidersByName.put(name, cpr);

                if (r != null) {
                    if (DEBUG_PROVIDER) Slog.v(TAG,
                            "Adding provider requested by "
                            + r.processName + " from process "
                            + cpr.info.processName);
                    Integer cnt = r.conProviders.get(cpr);
                    if (cnt == null) {
                        r.conProviders.put(cpr, new Integer(1));
                    } else {
                        r.conProviders.put(cpr, new Integer(cnt.intValue()+1));
                    }
                    cpr.clients.add(r);
                } else {
                    cpr.externals++;
                }
            }
        }

        // Wait for the provider to be published...
        synchronized (cpr) {
            while (cpr.provider == null) {
                if (cpr.launchingApp == null) {
                    Slog.w(TAG, "Unable to launch app "
                            + cpi.applicationInfo.packageName + "/"
                            + cpi.applicationInfo.uid + " for provider "
                            + name + ": launching app became null");
                    EventLog.writeEvent(EventLogTags.AM_PROVIDER_LOST_PROCESS,
                            cpi.applicationInfo.packageName,
                            cpi.applicationInfo.uid, name);
                    return null;
                }
                try {
                    cpr.wait();
                } catch (InterruptedException ex) {
                }
            }
        }
        return cpr;
    }
    final ProcessRecord startProcessLocked(String processName,
            ApplicationInfo info, boolean knownToBeDead, int intentFlags,
            String hostingType, ComponentName hostingName, boolean allowWhileBooting) {
        ProcessRecord app = getProcessRecordLocked(processName, info.uid);
        // We don't have to do anything more if:
        // (1) There is an existing application record; and
        // (2) The caller doesn't think it is dead, OR there is no thread
        //     object attached to it so we know it couldn't have crashed; and
        // (3) There is a pid assigned to it, so it is either starting or
        //     already running.
        if (DEBUG_PROCESSES) Slog.v(TAG, "startProcess: name=" + processName
                + " app=" + app + " knownToBeDead=" + knownToBeDead
                + " thread=" + (app != null ? app.thread : null)
                + " pid=" + (app != null ? app.pid : -1));
        if (app != null && app.pid > 0) {
            if (!knownToBeDead || app.thread == null) {
                // We already have the app running, or are waiting for it to
                // come up (we have a pid but not yet its thread), so keep it.
                if (DEBUG_PROCESSES) Slog.v(TAG, "App already running: " + app);
                return app;
            } else {
                // An application record is attached to a previous process,
                // clean it up now.
                if (DEBUG_PROCESSES) Slog.v(TAG, "App died: " + app);
                handleAppDiedLocked(app, true);
            }
        }

        String hostingNameStr = hostingName != null
                ? hostingName.flattenToShortString() : null;
        
        if ((intentFlags&Intent.FLAG_FROM_BACKGROUND) != 0) {
            // If we are in the background, then check to see if this process
            // is bad.  If so, we will just silently fail.
            if (mBadProcesses.get(info.processName, info.uid) != null) {
                if (DEBUG_PROCESSES) Slog.v(TAG, "Bad process: " + info.uid
                        + "/" + info.processName);
                return null;
            }
        } else {
            // When the user is explicitly starting a process, then clear its
            // crash count so that we won't make it bad until they see at
            // least one crash dialog again, and make the process good again
            // if it had been bad.
            if (DEBUG_PROCESSES) Slog.v(TAG, "Clearing bad process: " + info.uid
                    + "/" + info.processName);
            mProcessCrashTimes.remove(info.processName, info.uid);
            if (mBadProcesses.get(info.processName, info.uid) != null) {
                EventLog.writeEvent(EventLogTags.AM_PROC_GOOD, info.uid,
                        info.processName);
                mBadProcesses.remove(info.processName, info.uid);
                if (app != null) {
                    app.bad = false;
                }
            }
        }
        
        if (app == null) {
            app = newProcessRecordLocked(null, info, processName);
            mProcessNames.put(processName, info.uid, app);
        } else {
            // If this is a new package in the process, add the package to the list
            app.addPackage(info.packageName);
        }

        // If the system is not ready yet, then hold off on starting this
        // process until it is.
        if (!mProcessesReady
                && !isAllowedWhileBooting(info)
                && !allowWhileBooting) {
            if (!mProcessesOnHold.contains(app)) {
                mProcessesOnHold.add(app);
            }
            if (DEBUG_PROCESSES) Slog.v(TAG, "System not ready, putting on hold: " + app);
            return app;
        }

        startProcessLocked(app, hostingType, hostingNameStr);
        return (app.pid != 0) ? app : null;
    }


startProcessLocked通过调用Process.start()用来创建新的进程,其随后调用startViaZygote@Process.java, 通过socket通知runSelectLoopMode@ZygoteInit.java调用runOnce@ZygoteConnection.java,最后调用Zygote.forkAndSpecialize()来创建进程并调用handleChildProc,在其中调用ZygoteInit.invokeStaticMain。 详见http://blog.csdn.net/windskier/article/details/6417061。


frameworks/base/core/java/com/android/os/Process.java

  1.     public static final int start(final String processClass,  
  2.                                   final String niceName,  
  3.                                   int uid, int gid, int[] gids,  
  4.                                   int debugFlags,  
  5.                                   String[] zygoteArgs)  
  6.     {  
  7.         if (supportsProcesses()) {  
  8.             try {  
  9.                 return startViaZygote(processClass, niceName, uid, gid, gids,  
  10.                         debugFlags, zygoteArgs);  
  11.             } catch (ZygoteStartFailedEx ex) {  
  12.                 Log.e(LOG_TAG,  
  13.                         "Starting VM process through Zygote failed");  
  14.                 throw new RuntimeException(  
  15.                         "Starting VM process through Zygote failed", ex);  
  16.             }  
  17.         } ...  
  18.      }  
  19.    
  20.     private static int startViaZygote(final String processClass,  
  21.                                   final String niceName,  
  22.                                   final int uid, final int gid,  
  23.                                   final int[] gids,  
  24.                                   int debugFlags,  
  25.                                   String[] extraArgs)  
  26.                                   throws ZygoteStartFailedEx {  
  27.         int pid;  
  28.   
  29.         synchronized(Process.class) {  
  30.             ArrayList<String> argsForZygote = new ArrayList<String>();  
  31.   
  32.             // --runtime-init, --setuid=, --setgid=,   
  33.             // and --setgroups= must go first   
  34.             argsForZygote.add("--runtime-init");  
  35.             argsForZygote.add("--setuid=" + uid);  
  36.             argsForZygote.add("--setgid=" + gid);  
  37. ...  
  38.    
  39.             // --setgroups is a comma-separated list   
  40.             if (gids != null && gids.length > 0) {  
  41.                 StringBuilder sb = new StringBuilder();  
  42.                 sb.append("--setgroups=");  
  43.   
  44.                 int sz = gids.length;  
  45.                 for (int i = 0; i < sz; i++) {  
  46.                     if (i != 0) {  
  47.                         sb.append(',');  
  48.                     }  
  49.                     sb.append(gids[i]);  
  50.                 }  
  51.   
  52.                 argsForZygote.add(sb.toString());  
  53.             }  
  54.   
  55.             if (niceName != null) {  
  56.                 argsForZygote.add("--nice-name=" + niceName);  
  57.             }  
  58.   
  59.             argsForZygote.add(processClass);  
  60.   
  61.             if (extraArgs != null) {  
  62.                 for (String arg : extraArgs) {  
  63.                     argsForZygote.add(arg);  
  64.                 }  
  65.             }  
  66.               
  67.             pid = zygoteSendArgsAndGetPid(argsForZygote);  //写入到Zygote端口,触发创建进程   
  68.         }  
  69.   
  70.     private static int zygoteSendArgsAndGetPid(ArrayList<String> args)  
  71.             throws ZygoteStartFailedEx {  
  72.   
  73.         int pid;  
  74.   
  75.         openZygoteSocketIfNeeded();  //打开Zygote端口   
  76.   
  77.         try {  
  78.             /** 
  79.              * See com.android.internal.os.ZygoteInit.readArgumentList() 
  80.              * Presently the wire format to the zygote process is: 
  81.              * a) a count of arguments (argc, in essence) 
  82.              * b) a number of newline-separated argument strings equal to count 
  83.              * 
  84.              * After the zygote process reads these it will write the pid of 
  85.              * the child or -1 on failure. 
  86.              */  
  87.   
  88.             sZygoteWriter.write(Integer.toString(args.size()));  
  89.             sZygoteWriter.newLine();  
  90.   
  91.             int sz = args.size();  
  92.             for (int i = 0; i < sz; i++) {  
  93.                 String arg = args.get(i);  
  94.                 if (arg.indexOf('\n') >= 0) {  
  95.                     throw new ZygoteStartFailedEx(  
  96.                             "embedded newlines not allowed");  
  97.                 }  
  98.                 sZygoteWriter.write(arg);  
  99.                 sZygoteWriter.newLine();  
  100.             }  
  101.   
  102.             sZygoteWriter.flush(); //写入数据到端口   
  103.   
  104.             // Should there be a timeout on this?   
  105.             pid = sZygoteInputStream.readInt();      //等待读端口数据,即进程完成创建   
  106.   
  107.             if (pid < 0) {  
  108.                 throw new ZygoteStartFailedEx("fork() failed");  
  109.             }  
  110.         } catch (IOException ex) {  
  111.             try {  
  112.                 if (sZygoteSocket != null) {  
  113.                     sZygoteSocket.close();  
  114.                 }  
  115.             } catch (IOException ex2) {  
  116.                 // we're going to fail anyway   
  117.                 Log.e(LOG_TAG,"I/O exception on routine close", ex2);  
  118.             }  
  119.   
  120.             sZygoteSocket = null;  
  121.   
  122.             throw new ZygoteStartFailedEx(ex);  
  123.         }  
  124.   
  125.         return pid;  
  126.     }  
    public static final int start(final String processClass,
                                  final String niceName,
                                  int uid, int gid, int[] gids,
                                  int debugFlags,
                                  String[] zygoteArgs)
    {
        if (supportsProcesses()) {
            try {
                return startViaZygote(processClass, niceName, uid, gid, gids,
                        debugFlags, zygoteArgs);
            } catch (ZygoteStartFailedEx ex) {
                Log.e(LOG_TAG,
                        "Starting VM process through Zygote failed");
                throw new RuntimeException(
                        "Starting VM process through Zygote failed", ex);
            }
        } ...
     }
 
    private static int startViaZygote(final String processClass,
                                  final String niceName,
                                  final int uid, final int gid,
                                  final int[] gids,
                                  int debugFlags,
                                  String[] extraArgs)
                                  throws ZygoteStartFailedEx {
        int pid;

        synchronized(Process.class) {
            ArrayList<String> argsForZygote = new ArrayList<String>();

            // --runtime-init, --setuid=, --setgid=,
            // and --setgroups= must go first
            argsForZygote.add("--runtime-init");
            argsForZygote.add("--setuid=" + uid);
            argsForZygote.add("--setgid=" + gid);
...
 
            // --setgroups is a comma-separated list
            if (gids != null && gids.length > 0) {
                StringBuilder sb = new StringBuilder();
                sb.append("--setgroups=");

                int sz = gids.length;
                for (int i = 0; i < sz; i++) {
                    if (i != 0) {
                        sb.append(',');
                    }
                    sb.append(gids[i]);
                }

                argsForZygote.add(sb.toString());
            }

            if (niceName != null) {
                argsForZygote.add("--nice-name=" + niceName);
            }

            argsForZygote.add(processClass);

            if (extraArgs != null) {
                for (String arg : extraArgs) {
                    argsForZygote.add(arg);
                }
            }
            
            pid = zygoteSendArgsAndGetPid(argsForZygote);  //写入到Zygote端口,触发创建进程
        }

    private static int zygoteSendArgsAndGetPid(ArrayList<String> args)
            throws ZygoteStartFailedEx {

        int pid;

        openZygoteSocketIfNeeded();  //打开Zygote端口

        try {
            /**
             * See com.android.internal.os.ZygoteInit.readArgumentList()
             * Presently the wire format to the zygote process is:
             * a) a count of arguments (argc, in essence)
             * b) a number of newline-separated argument strings equal to count
             *
             * After the zygote process reads these it will write the pid of
             * the child or -1 on failure.
             */

            sZygoteWriter.write(Integer.toString(args.size()));
            sZygoteWriter.newLine();

            int sz = args.size();
            for (int i = 0; i < sz; i++) {
                String arg = args.get(i);
                if (arg.indexOf('\n') >= 0) {
                    throw new ZygoteStartFailedEx(
                            "embedded newlines not allowed");
                }
                sZygoteWriter.write(arg);
                sZygoteWriter.newLine();
            }

            sZygoteWriter.flush(); //写入数据到端口

            // Should there be a timeout on this?
            pid = sZygoteInputStream.readInt();      //等待读端口数据,即进程完成创建

            if (pid < 0) {
                throw new ZygoteStartFailedEx("fork() failed");
            }
        } catch (IOException ex) {
            try {
                if (sZygoteSocket != null) {
                    sZygoteSocket.close();
                }
            } catch (IOException ex2) {
                // we're going to fail anyway
                Log.e(LOG_TAG,"I/O exception on routine close", ex2);
            }

            sZygoteSocket = null;

            throw new ZygoteStartFailedEx(ex);
        }

        return pid;
    }


frameworks/base/core/java/com/android/internal/os/ZygoteConnection.java

  1. class ZygoteConnection {  
  2.   
  3.     void run() throws ZygoteInit.MethodAndArgsCaller {  
  4.         int loopCount = ZygoteInit.GC_LOOP_COUNT;  
  5.   
  6.         while (true) {  
  7. ...  
  8.             if (runOnce()) {  
  9.                 break;  
  10.             }  
  11.         }  
  12.     }  
  13.   
  14.     boolean runOnce() throws ZygoteInit.MethodAndArgsCaller {  
  15.         String args[];  
  16.         Arguments parsedArgs = null;  
  17.         FileDescriptor[] descriptors;  
  18.   
  19.         try {  
  20.             args = readArgumentList(); //监听Zygote端口等待创建进程命令,如无则阻塞   
  21.             descriptors = mSocket.getAncillaryFileDescriptors();  
  22.         } catch (IOException ex) {  
  23.             Log.w(TAG, "IOException on command socket " + ex.getMessage());  
  24.             closeSocket();  
  25.             return true;  
  26.         }  
  27. ...  
  28.             pid = Zygote.forkAndSpecialize(parsedArgs.uid, parsedArgs.gid,  
  29.                     parsedArgs.gids, parsedArgs.debugFlags, rlimits); //这里调用fork创建进程   
  30. ...  
  31.         if (pid == 0) {  
  32.             // in child   
  33.             handleChildProc(parsedArgs, descriptors, newStderr);  
  34.             // should never happen   
  35.             return true;  
  36.         } else { /* pid != 0 */  
  37.             // in parent...pid of < 0 means failure   
  38.             return handleParentProc(pid, descriptors, parsedArgs);  
  39.         }  
  40.     }  
  41.   
  42. private void handleChildProc(Arguments parsedArgs, FileDescriptor[] descriptors, PrintStream newStderr) throws ZygoteInit.MethodAndArgsCaller {...  
  43.         if (parsedArgs.runtimeInit) {  
  44.             RuntimeInit.zygoteInit(parsedArgs.remainingArgs);  
  45.         }  
  46. ... }  
class ZygoteConnection {

    void run() throws ZygoteInit.MethodAndArgsCaller {
        int loopCount = ZygoteInit.GC_LOOP_COUNT;

        while (true) {
...
            if (runOnce()) {
                break;
            }
        }
    }

    boolean runOnce() throws ZygoteInit.MethodAndArgsCaller {
        String args[];
        Arguments parsedArgs = null;
        FileDescriptor[] descriptors;

        try {
            args = readArgumentList(); //监听Zygote端口等待创建进程命令,如无则阻塞
            descriptors = mSocket.getAncillaryFileDescriptors();
        } catch (IOException ex) {
            Log.w(TAG, "IOException on command socket " + ex.getMessage());
            closeSocket();
            return true;
        }
...
            pid = Zygote.forkAndSpecialize(parsedArgs.uid, parsedArgs.gid,
                    parsedArgs.gids, parsedArgs.debugFlags, rlimits); //这里调用fork创建进程
...
        if (pid == 0) {
            // in child
            handleChildProc(parsedArgs, descriptors, newStderr);
            // should never happen
            return true;
        } else { /* pid != 0 */
            // in parent...pid of < 0 means failure
            return handleParentProc(pid, descriptors, parsedArgs);
        }
    }

private void handleChildProc(Arguments parsedArgs, FileDescriptor[] descriptors, PrintStream newStderr) throws ZygoteInit.MethodAndArgsCaller {...
        if (parsedArgs.runtimeInit) {
            RuntimeInit.zygoteInit(parsedArgs.remainingArgs);
        }
... }


 

frameworks/base/core/java/com/android/internal/os/RuntimeInit.java

  1.     public static final void zygoteInit(String[] argv)  
  2.             throws ZygoteInit.MethodAndArgsCaller {  
  3.         commonInit();  
  4.         zygoteInitNative();  
  5. ...  
  6.         invokeStaticMain(startClass, startArgs);       //调用main方法   
  7.     }  
    public static final void zygoteInit(String[] argv)
            throws ZygoteInit.MethodAndArgsCaller {
        commonInit();
        zygoteInitNative();
...
        invokeStaticMain(startClass, startArgs);       //调用main方法
    }



 

frameworks/base/core/jni/AndroidRuntime.cpp

  1. static void com_android_internal_os_RuntimeInit_zygoteInit(JNIEnv* env, jobject clazz)  
  2. {  
  3.     gCurRuntime->onZygoteInit();  
  4. }  
static void com_android_internal_os_RuntimeInit_zygoteInit(JNIEnv* env, jobject clazz)
{
    gCurRuntime->onZygoteInit();
}


frameworks/base/cmds/app_process/App_main.cpp

  1. class AppRuntime : public AndroidRuntime{  
  2.     virtual void onZygoteInit()  
  3.     {  
  4.         sp<ProcessState> proc = ProcessState::self();  
  5.         if (proc->supportsProcesses()) {  
  6.             proc->startThreadPool();       //对于应用来讲,此处创建1个线程池以处理Binder事件。注意此处只有一个Loop,而Native mediaserver进程则创建了两个线程循环。   
  7.         }         
  8.     }  
class AppRuntime : public AndroidRuntime{
    virtual void onZygoteInit()
    {
        sp<ProcessState> proc = ProcessState::self();
        if (proc->supportsProcesses()) {
            proc->startThreadPool();       //对于应用来讲,此处创建1个线程池以处理Binder事件。注意此处只有一个Loop,而Native mediaserver进程则创建了两个线程循环。
        }       
    }


frameworks/base/core/java/android/app/ActivityThread.java


  1.     public static final void main(String[] args) {  
  2.         SamplingProfilerIntegration.start();  
  3.   
  4.         Process.setArgV0("<pre-initialized>");  
  5.   
  6.         Looper.prepareMainLooper();  
  7.         if (sMainThreadHandler == null) {  
  8.             sMainThreadHandler = new Handler();  
  9.         }  
  10.   
  11.         ActivityThread thread = new ActivityThread();  
  12.         thread.attach(false);  
  13.   
  14.         if (false) {  
  15.             Looper.myLooper().setMessageLogging(new  
  16.                     LogPrinter(Log.DEBUG, "ActivityThread"));  
  17.         }  
  18.   
  19.         Looper.loop();  
  20.   
  21.     private final void attach(boolean system) {  
  22.         sThreadLocal.set(this);  
  23.         mSystemThread = system;  
  24.         if (!system) {  
  25.             ViewRoot.addFirstDrawHandler(new Runnable() {  
  26.                 public void run() {  
  27.                     ensureJitEnabled();  
  28.                 }  
  29.             });  
  30.             android.ddm.DdmHandleAppName.setAppName("<pre-initialized>");  
  31.             RuntimeInit.setApplicationObject(mAppThread.asBinder());  
  32.             IActivityManager mgr = ActivityManagerNative.getDefault();  
  33.             try {  
  34.                 mgr.attachApplication(mAppThread);  
  35.             } catch (RemoteException ex) {  
  36.             }  
  37. ...  
  38. }  
    public static final void main(String[] args) {
        SamplingProfilerIntegration.start();

        Process.setArgV0("<pre-initialized>");

        Looper.prepareMainLooper();
        if (sMainThreadHandler == null) {
            sMainThreadHandler = new Handler();
        }

        ActivityThread thread = new ActivityThread();
        thread.attach(false);

        if (false) {
            Looper.myLooper().setMessageLogging(new
                    LogPrinter(Log.DEBUG, "ActivityThread"));
        }

        Looper.loop();

    private final void attach(boolean system) {
        sThreadLocal.set(this);
        mSystemThread = system;
        if (!system) {
            ViewRoot.addFirstDrawHandler(new Runnable() {
                public void run() {
                    ensureJitEnabled();
                }
            });
            android.ddm.DdmHandleAppName.setAppName("<pre-initialized>");
            RuntimeInit.setApplicationObject(mAppThread.asBinder());
            IActivityManager mgr = ActivityManagerNative.getDefault();
            try {
                mgr.attachApplication(mAppThread);
            } catch (RemoteException ex) {
            }
...
}


frameworks/base/services/java/com/android/server/am/ActivityManagerService.java

  1. public final void attachApplication(IApplicationThread thread) {  
  2.     synchronized (this) {  
  3.         int callingPid = Binder.getCallingPid();  
  4.         final long origId = Binder.clearCallingIdentity();  
  5.         attachApplicationLocked(thread, callingPid);  
  6.         Binder.restoreCallingIdentity(origId);  
  7.     }  
  8. }  
  9.   
  10. private final boolean attachApplicationLocked(IApplicationThread thread,  
  11.         int pid) {  
  12.   
  13.     // Find the application record that is being attached...  either via   
  14.     // the pid if we are running in multiple processes, or just pull the   
  15.     // next app record if we are emulating process with anonymous threads.   
  16.     ProcessRecord app;  
  17.     if (pid != MY_PID && pid >= 0) {  
  18.         synchronized (mPidsSelfLocked) {  
  19.             app = mPidsSelfLocked.get(pid);  
  20.         }  
  21.     } else if (mStartingProcesses.size() > 0) {  
  22.         app = mStartingProcesses.remove(0);  
  23.         app.setPid(pid);  
  24.     } else {  
  25.         app = null;  
  26.     }  
  27.   
  28.     if (app == null) {  
  29.         Slog.w(TAG, "No pending application record for pid " + pid  
  30.                 + " (IApplicationThread " + thread + "); dropping process");  
  31.         EventLog.writeEvent(EventLogTags.AM_DROP_PROCESS, pid);  
  32.         if (pid > 0 && pid != MY_PID) {  
  33.             Process.killProcess(pid);  
  34.         } else {  
  35.             try {  
  36.                 thread.scheduleExit();  
  37.             } catch (Exception e) {  
  38.                 // Ignore exceptions.   
  39.             }  
  40.         }  
  41.         return false;  
  42.     }  
  43.   
  44.     // If this application record is still attached to a previous   
  45.     // process, clean it up now.   
  46.     if (app.thread != null) {  
  47.         handleAppDiedLocked(app, true);  
  48.     }  
  49.   
  50.     // Tell the process all about itself.   
  51.   
  52.     if (localLOGV) Slog.v(  
  53.             TAG, "Binding process pid " + pid + " to record " + app);  
  54.   
  55.     String processName = app.processName;  
  56.     try {  
  57.         thread.asBinder().linkToDeath(new AppDeathRecipient(  
  58.                 app, pid, thread), 0);  
  59.     } catch (RemoteException e) {  
  60.         app.resetPackageList();  
  61.         startProcessLocked(app, "link fail", processName);  
  62.         return false;  
  63.     }  
  64.   
  65.     EventLog.writeEvent(EventLogTags.AM_PROC_BOUND, app.pid, app.processName);  
  66.       
  67.     app.thread = thread;  
  68.     app.curAdj = app.setAdj = -100;  
  69.     app.curSchedGroup = Process.THREAD_GROUP_DEFAULT;  
  70.     app.setSchedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE;  
  71.     app.forcingToForeground = null;  
  72.     app.foregroundServices = false;  
  73.     app.debugging = false;  
  74.   
  75.     mHandler.removeMessages(PROC_START_TIMEOUT_MSG, app);  
  76.   
  77.     boolean normalMode = mProcessesReady || isAllowedWhileBooting(app.info);  
  78.     List providers = normalMode ? generateApplicationProvidersLocked(app) : null;  
  79.   
  80.     if (!normalMode) {  
  81.         Slog.i(TAG, "Launching preboot mode app: " + app);  
  82.     }  
  83.       
  84.     if (localLOGV) Slog.v(  
  85.         TAG, "New app record " + app  
  86.         + " thread=" + thread.asBinder() + " pid=" + pid);  
  87.     try {  
  88.         int testMode = IApplicationThread.DEBUG_OFF;  
  89.         if (mDebugApp != null && mDebugApp.equals(processName)) {  
  90.             testMode = mWaitForDebugger  
  91.                 ? IApplicationThread.DEBUG_WAIT  
  92.                 : IApplicationThread.DEBUG_ON;  
  93.             app.debugging = true;  
  94.             if (mDebugTransient) {  
  95.                 mDebugApp = mOrigDebugApp;  
  96.                 mWaitForDebugger = mOrigWaitForDebugger;  
  97.             }  
  98.         }  
  99.           
  100.         // If the app is being launched for restore or full backup, set it up specially   
  101.         boolean isRestrictedBackupMode = false;  
  102.         if (mBackupTarget != null && mBackupAppName.equals(processName)) {  
  103.             isRestrictedBackupMode = (mBackupTarget.backupMode == BackupRecord.RESTORE)  
  104.                     || (mBackupTarget.backupMode == BackupRecord.BACKUP_FULL);  
  105.         }  
  106.           
  107.         ensurePackageDexOpt(app.instrumentationInfo != null  
  108.                 ? app.instrumentationInfo.packageName  
  109.                 : app.info.packageName);  
  110.         if (app.instrumentationClass != null) {  
  111.             ensurePackageDexOpt(app.instrumentationClass.getPackageName());  
  112.         }  
  113.         if (DEBUG_CONFIGURATION) Slog.v(TAG, "Binding proc "  
  114.                 + processName + " with config " + mConfiguration);  
  115.         thread.bindApplication(processName, app.instrumentationInfo != null  
  116.                 ? app.instrumentationInfo : app.info, providers,  
  117.                 app.instrumentationClass, app.instrumentationProfileFile,  
  118.                 app.instrumentationArguments, app.instrumentationWatcher, testMode,   
  119.                 isRestrictedBackupMode || !normalMode,  
  120.                 mConfiguration, getCommonServicesLocked());  
  121.         updateLruProcessLocked(app, falsetrue);  
  122.         app.lastRequestedGc = app.lastLowMemory = SystemClock.uptimeMillis();  
  123.     } catch (Exception e) {  
  124.         // todo: Yikes!  What should we do?  For now we will try to   
  125.         // start another process, but that could easily get us in   
  126.         // an infinite loop of restarting processes...   
  127.         Slog.w(TAG, "Exception thrown during bind!", e);  
  128.   
  129.         app.resetPackageList();  
  130.         startProcessLocked(app, "bind fail", processName);  
  131.         return false;  
  132.     }  
  133.   
  134.     // Remove this record from the list of starting applications.   
  135.     mPersistentStartingProcesses.remove(app);  
  136.     if (DEBUG_PROCESSES && mProcessesOnHold.contains(app)) Slog.v(TAG,  
  137.             "Attach application locked removing on hold: " + app);  
  138.     mProcessesOnHold.remove(app);  
  139.   
  140.     boolean badApp = false;  
  141.     boolean didSomething = false;  
  142.   
  143.     // See if the top visible activity is waiting to run in this process...   
  144.     ActivityRecord hr = mMainStack.topRunningActivityLocked(null);  
  145.     if (hr != null && normalMode) {  
  146.         if (hr.app == null && app.info.uid == hr.info.applicationInfo.uid  
  147.                 && processName.equals(hr.processName)) {  
  148.             try {  
  149.                 if (mMainStack.realStartActivityLocked(hr, app, truetrue)) {  
  150.                     didSomething = true;  
  151.                 }  
  152.             } catch (Exception e) {  
  153.                 Slog.w(TAG, "Exception in new application when starting activity "  
  154.                       + hr.intent.getComponent().flattenToShortString(), e);  
  155.                 badApp = true;  
  156.             }  
  157.         } else {  
  158.             mMainStack.ensureActivitiesVisibleLocked(hr, null, processName, 0);  
  159.         }  
  160.     }  
  161.   
  162.     // Find any services that should be running in this process...   
  163.     if (!badApp && mPendingServices.size() > 0) {  
  164.         ServiceRecord sr = null;  
  165.         try {  
  166.             for (int i=0; i<mPendingServices.size(); i++) {  
  167.                 sr = mPendingServices.get(i);  
  168.                 if (app.info.uid != sr.appInfo.uid  
  169.                         || !processName.equals(sr.processName)) {  
  170.                     continue;  
  171.                 }  
  172.   
  173.                 mPendingServices.remove(i);  
  174.                 i--;  
  175.                 realStartServiceLocked(sr, app);  
  176.                 didSomething = true;  
  177.             }  
  178.         } catch (Exception e) {  
  179.             Slog.w(TAG, "Exception in new application when starting service "  
  180.                   + sr.shortName, e);  
  181.             badApp = true;  
  182.         }  
  183.     }  
  184.   
  185.     // Check if the next broadcast receiver is in this process...   
  186.     BroadcastRecord br = mPendingBroadcast;  
  187.     if (!badApp && br != null && br.curApp == app) {  
  188.         try {  
  189.             mPendingBroadcast = null;  
  190.             processCurBroadcastLocked(br, app);  
  191.             didSomething = true;  
  192.         } catch (Exception e) {  
  193.             Slog.w(TAG, "Exception in new application when starting receiver "  
  194.                   + br.curComponent.flattenToShortString(), e);  
  195.             badApp = true;  
  196.             logBroadcastReceiverDiscardLocked(br);  
  197.             finishReceiverLocked(br.receiver, br.resultCode, br.resultData,  
  198.                     br.resultExtras, br.resultAbort, true);  
  199.             scheduleBroadcastsLocked();  
  200.             // We need to reset the state if we fails to start the receiver.   
  201.             br.state = BroadcastRecord.IDLE;  
  202.         }  
  203.     }  
  204.   
  205.     // Check whether the next backup agent is in this process...   
  206.     if (!badApp && mBackupTarget != null && mBackupTarget.appInfo.uid == app.info.uid) {  
  207.         if (DEBUG_BACKUP) Slog.v(TAG, "New app is backup target, launching agent for " + app);  
  208.         ensurePackageDexOpt(mBackupTarget.appInfo.packageName);  
  209.         try {  
  210.             thread.scheduleCreateBackupAgent(mBackupTarget.appInfo, mBackupTarget.backupMode);  
  211.         } catch (Exception e) {  
  212.             Slog.w(TAG, "Exception scheduling backup agent creation: ");  
  213.             e.printStackTrace();  
  214.         }  
  215.     }  
  216.   
  217.     if (badApp) {  
  218.         // todo: Also need to kill application to deal with all   
  219.         // kinds of exceptions.   
  220.         handleAppDiedLocked(app, false);  
  221.         return false;  
  222.     }  
  223.   
  224.     if (!didSomething) {  
  225.         updateOomAdjLocked();  
  226.     }  
  227.   
  228.     return true;  
  229. }  
    public final void attachApplication(IApplicationThread thread) {
        synchronized (this) {
            int callingPid = Binder.getCallingPid();
            final long origId = Binder.clearCallingIdentity();
            attachApplicationLocked(thread, callingPid);
            Binder.restoreCallingIdentity(origId);
        }
    }

    private final boolean attachApplicationLocked(IApplicationThread thread,
            int pid) {

        // Find the application record that is being attached...  either via
        // the pid if we are running in multiple processes, or just pull the
        // next app record if we are emulating process with anonymous threads.
        ProcessRecord app;
        if (pid != MY_PID && pid >= 0) {
            synchronized (mPidsSelfLocked) {
                app = mPidsSelfLocked.get(pid);
            }
        } else if (mStartingProcesses.size() > 0) {
            app = mStartingProcesses.remove(0);
            app.setPid(pid);
        } else {
            app = null;
        }

        if (app == null) {
            Slog.w(TAG, "No pending application record for pid " + pid
                    + " (IApplicationThread " + thread + "); dropping process");
            EventLog.writeEvent(EventLogTags.AM_DROP_PROCESS, pid);
            if (pid > 0 && pid != MY_PID) {
                Process.killProcess(pid);
            } else {
                try {
                    thread.scheduleExit();
                } catch (Exception e) {
                    // Ignore exceptions.
                }
            }
            return false;
        }

        // If this application record is still attached to a previous
        // process, clean it up now.
        if (app.thread != null) {
            handleAppDiedLocked(app, true);
        }

        // Tell the process all about itself.

        if (localLOGV) Slog.v(
                TAG, "Binding process pid " + pid + " to record " + app);

        String processName = app.processName;
        try {
            thread.asBinder().linkToDeath(new AppDeathRecipient(
                    app, pid, thread), 0);
        } catch (RemoteException e) {
            app.resetPackageList();
            startProcessLocked(app, "link fail", processName);
            return false;
        }

        EventLog.writeEvent(EventLogTags.AM_PROC_BOUND, app.pid, app.processName);
        
        app.thread = thread;
        app.curAdj = app.setAdj = -100;
        app.curSchedGroup = Process.THREAD_GROUP_DEFAULT;
        app.setSchedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE;
        app.forcingToForeground = null;
        app.foregroundServices = false;
        app.debugging = false;

        mHandler.removeMessages(PROC_START_TIMEOUT_MSG, app);

        boolean normalMode = mProcessesReady || isAllowedWhileBooting(app.info);
        List providers = normalMode ? generateApplicationProvidersLocked(app) : null;

        if (!normalMode) {
            Slog.i(TAG, "Launching preboot mode app: " + app);
        }
        
        if (localLOGV) Slog.v(
            TAG, "New app record " + app
            + " thread=" + thread.asBinder() + " pid=" + pid);
        try {
            int testMode = IApplicationThread.DEBUG_OFF;
            if (mDebugApp != null && mDebugApp.equals(processName)) {
                testMode = mWaitForDebugger
                    ? IApplicationThread.DEBUG_WAIT
                    : IApplicationThread.DEBUG_ON;
                app.debugging = true;
                if (mDebugTransient) {
                    mDebugApp = mOrigDebugApp;
                    mWaitForDebugger = mOrigWaitForDebugger;
                }
            }
            
            // If the app is being launched for restore or full backup, set it up specially
            boolean isRestrictedBackupMode = false;
            if (mBackupTarget != null && mBackupAppName.equals(processName)) {
                isRestrictedBackupMode = (mBackupTarget.backupMode == BackupRecord.RESTORE)
                        || (mBackupTarget.backupMode == BackupRecord.BACKUP_FULL);
            }
            
            ensurePackageDexOpt(app.instrumentationInfo != null
                    ? app.instrumentationInfo.packageName
                    : app.info.packageName);
            if (app.instrumentationClass != null) {
                ensurePackageDexOpt(app.instrumentationClass.getPackageName());
            }
            if (DEBUG_CONFIGURATION) Slog.v(TAG, "Binding proc "
                    + processName + " with config " + mConfiguration);
            thread.bindApplication(processName, app.instrumentationInfo != null
                    ? app.instrumentationInfo : app.info, providers,
                    app.instrumentationClass, app.instrumentationProfileFile,
                    app.instrumentationArguments, app.instrumentationWatcher, testMode, 
                    isRestrictedBackupMode || !normalMode,
                    mConfiguration, getCommonServicesLocked());
            updateLruProcessLocked(app, false, true);
            app.lastRequestedGc = app.lastLowMemory = SystemClock.uptimeMillis();
        } catch (Exception e) {
            // todo: Yikes!  What should we do?  For now we will try to
            // start another process, but that could easily get us in
            // an infinite loop of restarting processes...
            Slog.w(TAG, "Exception thrown during bind!", e);

            app.resetPackageList();
            startProcessLocked(app, "bind fail", processName);
            return false;
        }

        // Remove this record from the list of starting applications.
        mPersistentStartingProcesses.remove(app);
        if (DEBUG_PROCESSES && mProcessesOnHold.contains(app)) Slog.v(TAG,
                "Attach application locked removing on hold: " + app);
        mProcessesOnHold.remove(app);

        boolean badApp = false;
        boolean didSomething = false;

        // See if the top visible activity is waiting to run in this process...
        ActivityRecord hr = mMainStack.topRunningActivityLocked(null);
        if (hr != null && normalMode) {
            if (hr.app == null && app.info.uid == hr.info.applicationInfo.uid
                    && processName.equals(hr.processName)) {
                try {
                    if (mMainStack.realStartActivityLocked(hr, app, true, true)) {
                        didSomething = true;
                    }
                } catch (Exception e) {
                    Slog.w(TAG, "Exception in new application when starting activity "
                          + hr.intent.getComponent().flattenToShortString(), e);
                    badApp = true;
                }
            } else {
                mMainStack.ensureActivitiesVisibleLocked(hr, null, processName, 0);
            }
        }

        // Find any services that should be running in this process...
        if (!badApp && mPendingServices.size() > 0) {
            ServiceRecord sr = null;
            try {
                for (int i=0; i<mPendingServices.size(); i++) {
                    sr = mPendingServices.get(i);
                    if (app.info.uid != sr.appInfo.uid
                            || !processName.equals(sr.processName)) {
                        continue;
                    }

                    mPendingServices.remove(i);
                    i--;
                    realStartServiceLocked(sr, app);
                    didSomething = true;
                }
            } catch (Exception e) {
                Slog.w(TAG, "Exception in new application when starting service "
                      + sr.shortName, e);
                badApp = true;
            }
        }

        // Check if the next broadcast receiver is in this process...
        BroadcastRecord br = mPendingBroadcast;
        if (!badApp && br != null && br.curApp == app) {
            try {
                mPendingBroadcast = null;
                processCurBroadcastLocked(br, app);
                didSomething = true;
            } catch (Exception e) {
                Slog.w(TAG, "Exception in new application when starting receiver "
                      + br.curComponent.flattenToShortString(), e);
                badApp = true;
                logBroadcastReceiverDiscardLocked(br);
                finishReceiverLocked(br.receiver, br.resultCode, br.resultData,
                        br.resultExtras, br.resultAbort, true);
                scheduleBroadcastsLocked();
                // We need to reset the state if we fails to start the receiver.
                br.state = BroadcastRecord.IDLE;
            }
        }

        // Check whether the next backup agent is in this process...
        if (!badApp && mBackupTarget != null && mBackupTarget.appInfo.uid == app.info.uid) {
            if (DEBUG_BACKUP) Slog.v(TAG, "New app is backup target, launching agent for " + app);
            ensurePackageDexOpt(mBackupTarget.appInfo.packageName);
            try {
                thread.scheduleCreateBackupAgent(mBackupTarget.appInfo, mBackupTarget.backupMode);
            } catch (Exception e) {
                Slog.w(TAG, "Exception scheduling backup agent creation: ");
                e.printStackTrace();
            }
        }

        if (badApp) {
            // todo: Also need to kill application to deal with all
            // kinds of exceptions.
            handleAppDiedLocked(app, false);
            return false;
        }

        if (!didSomething) {
            updateOomAdjLocked();
        }

        return true;
    }



 

frameworks/base/core/java/android/app/ActivityThread.java


  1. private final class ApplicationThread extends ApplicationThreadNative {  
  2.      public final void bindApplication(String processName,  
  3.              ApplicationInfo appInfo, List<ProviderInfo> providers,  
  4.              ComponentName instrumentationName, String profileFile,  
  5.              Bundle instrumentationArgs, IInstrumentationWatcher instrumentationWatcher,  
  6.              int debugMode, boolean isRestrictedBackupMode, Configuration config,  
  7.              Map<String, IBinder> services) {  
  8.   
  9.          if (services != null) {  
  10.              // Setup the service cache in the ServiceManager   
  11.              ServiceManager.initServiceCache(services);  
  12.          }  
  13.   
  14.          AppBindData data = new AppBindData();  
  15.          data.processName = processName;  
  16.          data.appInfo = appInfo;  
  17.          data.providers = providers;  
  18.          data.instrumentationName = instrumentationName;  
  19.          data.profileFile = profileFile;  
  20.          data.instrumentationArgs = instrumentationArgs;  
  21.          data.instrumentationWatcher = instrumentationWatcher;  
  22.          data.debugMode = debugMode;  
  23.          data.restrictedBackupMode = isRestrictedBackupMode;  
  24.          data.config = config;  
  25.          queueOrSendMessage(H.BIND_APPLICATION, data);  
  26.      }  
   private final class ApplicationThread extends ApplicationThreadNative {
        public final void bindApplication(String processName,
                ApplicationInfo appInfo, List<ProviderInfo> providers,
                ComponentName instrumentationName, String profileFile,
                Bundle instrumentationArgs, IInstrumentationWatcher instrumentationWatcher,
                int debugMode, boolean isRestrictedBackupMode, Configuration config,
                Map<String, IBinder> services) {

            if (services != null) {
                // Setup the service cache in the ServiceManager
                ServiceManager.initServiceCache(services);
            }

            AppBindData data = new AppBindData();
            data.processName = processName;
            data.appInfo = appInfo;
            data.providers = providers;
            data.instrumentationName = instrumentationName;
            data.profileFile = profileFile;
            data.instrumentationArgs = instrumentationArgs;
            data.instrumentationWatcher = instrumentationWatcher;
            data.debugMode = debugMode;
            data.restrictedBackupMode = isRestrictedBackupMode;
            data.config = config;
            queueOrSendMessage(H.BIND_APPLICATION, data);
        }


 

  1. public void handleMessage(Message msg) {  
  2.   
  3.         case BIND_APPLICATION:  
  4.             AppBindData data = (AppBindData)msg.obj;  
  5.             handleBindApplication(data);  
  6.             break;  
        public void handleMessage(Message msg) {
...
                case BIND_APPLICATION:
                    AppBindData data = (AppBindData)msg.obj;
                    handleBindApplication(data);
                    break;


 

  1. private final void handleBindApplication(AppBindData data) {  
  2.     mBoundApplication = data;  
  3.     mConfiguration = new Configuration(data.config);  
  4.   
  5.     // send up app name; do this *before* waiting for debugger   
  6.     Process.setArgV0(data.processName);  
  7.     android.ddm.DdmHandleAppName.setAppName(data.processName);  
  8.   
  9.     /* 
  10.      * Before spawning a new process, reset the time zone to be the system time zone. 
  11.      * This needs to be done because the system time zone could have changed after the 
  12.      * the spawning of this process. Without doing this this process would have the incorrect 
  13.      * system time zone. 
  14.      */  
  15.     TimeZone.setDefault(null);  
  16.   
  17.     /* 
  18.      * Initialize the default locale in this process for the reasons we set the time zone. 
  19.      */  
  20.     Locale.setDefault(data.config.locale);  
  21.   
  22.     /* 
  23.      * Update the system configuration since its preloaded and might not 
  24.      * reflect configuration changes. The configuration object passed 
  25.      * in AppBindData can be safely assumed to be up to date 
  26.      */  
  27.     Resources.getSystem().updateConfiguration(mConfiguration, null);  
  28.   
  29.     data.info = getPackageInfoNoCheck(data.appInfo);  
  30.   
  31.     /** 
  32.      * For system applications on userdebug/eng builds, log stack 
  33.      * traces of disk and network access to dropbox for analysis. 
  34.      */  
  35.     if ((data.appInfo.flags &  
  36.          (ApplicationInfo.FLAG_SYSTEM |  
  37.           ApplicationInfo.FLAG_UPDATED_SYSTEM_APP)) != 0) {  
  38.         StrictMode.conditionallyEnableDebugLogging();  
  39.     }  
  40.   
  41.     /** 
  42.      * Switch this process to density compatibility mode if needed. 
  43.      */  
  44.     if ((data.appInfo.flags&ApplicationInfo.FLAG_SUPPORTS_SCREEN_DENSITIES)  
  45.             == 0) {  
  46.         Bitmap.setDefaultDensity(DisplayMetrics.DENSITY_DEFAULT);  
  47.     }  
  48.   
  49.     if (data.debugMode != IApplicationThread.DEBUG_OFF) {  
  50.         // XXX should have option to change the port.   
  51.         Debug.changeDebugPort(8100);  
  52.         if (data.debugMode == IApplicationThread.DEBUG_WAIT) {  
  53.             Slog.w(TAG, "Application " + data.info.getPackageName()  
  54.                   + " is waiting for the debugger on port 8100...");  
  55.   
  56.             IActivityManager mgr = ActivityManagerNative.getDefault();  
  57.             try {  
  58.                 mgr.showWaitingForDebugger(mAppThread, true);  
  59.             } catch (RemoteException ex) {  
  60.             }  
  61.   
  62.             Debug.waitForDebugger();  
  63.   
  64.             try {  
  65.                 mgr.showWaitingForDebugger(mAppThread, false);  
  66.             } catch (RemoteException ex) {  
  67.             }  
  68.   
  69.         } else {  
  70.             Slog.w(TAG, "Application " + data.info.getPackageName()  
  71.                   + " can be debugged on port 8100...");  
  72.         }  
  73.     }  
  74.   
  75.     if (data.instrumentationName != null) {  
  76.         ContextImpl appContext = new ContextImpl();  
  77.         appContext.init(data.info, nullthis);  
  78.         InstrumentationInfo ii = null;  
  79.         try {  
  80.             ii = appContext.getPackageManager().  
  81.                 getInstrumentationInfo(data.instrumentationName, 0);  
  82.         } catch (PackageManager.NameNotFoundException e) {  
  83.         }  
  84.         if (ii == null) {  
  85.             throw new RuntimeException(  
  86.                 "Unable to find instrumentation info for: "  
  87.                 + data.instrumentationName);  
  88.         }  
  89.   
  90.         mInstrumentationAppDir = ii.sourceDir;  
  91.         mInstrumentationAppPackage = ii.packageName;  
  92.         mInstrumentedAppDir = data.info.getAppDir();  
  93.   
  94.         ApplicationInfo instrApp = new ApplicationInfo();  
  95.         instrApp.packageName = ii.packageName;  
  96.         instrApp.sourceDir = ii.sourceDir;  
  97.         instrApp.publicSourceDir = ii.publicSourceDir;  
  98.         instrApp.dataDir = ii.dataDir;  
  99.         instrApp.nativeLibraryDir = ii.nativeLibraryDir;  
  100.         LoadedApk pi = getPackageInfo(instrApp,  
  101.                 appContext.getClassLoader(), falsetrue);  
  102.         ContextImpl instrContext = new ContextImpl();  
  103.         instrContext.init(pi, nullthis);  
  104.   
  105.         try {  
  106.             java.lang.ClassLoader cl = instrContext.getClassLoader();  
  107.             mInstrumentation = (Instrumentation)  
  108.                 cl.loadClass(data.instrumentationName.getClassName()).newInstance();  
  109.         } catch (Exception e) {  
  110.             throw new RuntimeException(  
  111.                 "Unable to instantiate instrumentation "  
  112.                 + data.instrumentationName + ": " + e.toString(), e);  
  113.         }  
  114.   
  115.         mInstrumentation.init(this, instrContext, appContext,  
  116.                 new ComponentName(ii.packageName, ii.name), data.instrumentationWatcher);  
  117.   
  118.         if (data.profileFile != null && !ii.handleProfiling) {  
  119.             data.handlingProfiling = true;  
  120.             File file = new File(data.profileFile);  
  121.             file.getParentFile().mkdirs();  
  122.             Debug.startMethodTracing(file.toString(), 8 * 1024 * 1024);  
  123.         }  
  124.   
  125.         try {  
  126.             mInstrumentation.onCreate(data.instrumentationArgs);  
  127.         }  
  128.         catch (Exception e) {  
  129.             throw new RuntimeException(  
  130.                 "Exception thrown in onCreate() of "  
  131.                 + data.instrumentationName + ": " + e.toString(), e);  
  132.         }  
  133.   
  134.     } else {  
  135.         mInstrumentation = new Instrumentation();  
  136.     }  
  137.   
  138.     // If the app is being launched for full backup or restore, bring it up in   
  139.     // a restricted environment with the base application class.   
  140.     Application app = data.info.makeApplication(data.restrictedBackupMode, null);  
  141.     mInitialApplication = app;  
  142.   
  143.     List<ProviderInfo> providers = data.providers;  
  144.     if (providers != null) {  
  145.         installContentProviders(app, providers);  
  146.         // For process that contain content providers, we want to   
  147.         // ensure that the JIT is enabled "at some point".   
  148.         mH.sendEmptyMessageDelayed(H.ENABLE_JIT, 10*1000);  
  149.     }  
  150.   
  151.     try {  
  152.         mInstrumentation.callApplicationOnCreate(app);  
  153.     } catch (Exception e) {  
  154.         if (!mInstrumentation.onException(app, e)) {  
  155.             throw new RuntimeException(  
  156.                 "Unable to create application " + app.getClass().getName()  
  157.                 + ": " + e.toString(), e);  
  158.         }  
  159.     }  
  160. }  
    private final void handleBindApplication(AppBindData data) {
        mBoundApplication = data;
        mConfiguration = new Configuration(data.config);

        // send up app name; do this *before* waiting for debugger
        Process.setArgV0(data.processName);
        android.ddm.DdmHandleAppName.setAppName(data.processName);

        /*
         * Before spawning a new process, reset the time zone to be the system time zone.
         * This needs to be done because the system time zone could have changed after the
         * the spawning of this process. Without doing this this process would have the incorrect
         * system time zone.
         */
        TimeZone.setDefault(null);

        /*
         * Initialize the default locale in this process for the reasons we set the time zone.
         */
        Locale.setDefault(data.config.locale);

        /*
         * Update the system configuration since its preloaded and might not
         * reflect configuration changes. The configuration object passed
         * in AppBindData can be safely assumed to be up to date
         */
        Resources.getSystem().updateConfiguration(mConfiguration, null);

        data.info = getPackageInfoNoCheck(data.appInfo);

        /**
         * For system applications on userdebug/eng builds, log stack
         * traces of disk and network access to dropbox for analysis.
         */
        if ((data.appInfo.flags &
             (ApplicationInfo.FLAG_SYSTEM |
              ApplicationInfo.FLAG_UPDATED_SYSTEM_APP)) != 0) {
            StrictMode.conditionallyEnableDebugLogging();
        }

        /**
         * Switch this process to density compatibility mode if needed.
         */
        if ((data.appInfo.flags&ApplicationInfo.FLAG_SUPPORTS_SCREEN_DENSITIES)
                == 0) {
            Bitmap.setDefaultDensity(DisplayMetrics.DENSITY_DEFAULT);
        }

        if (data.debugMode != IApplicationThread.DEBUG_OFF) {
            // XXX should have option to change the port.
            Debug.changeDebugPort(8100);
            if (data.debugMode == IApplicationThread.DEBUG_WAIT) {
                Slog.w(TAG, "Application " + data.info.getPackageName()
                      + " is waiting for the debugger on port 8100...");

                IActivityManager mgr = ActivityManagerNative.getDefault();
                try {
                    mgr.showWaitingForDebugger(mAppThread, true);
                } catch (RemoteException ex) {
                }

                Debug.waitForDebugger();

                try {
                    mgr.showWaitingForDebugger(mAppThread, false);
                } catch (RemoteException ex) {
                }

            } else {
                Slog.w(TAG, "Application " + data.info.getPackageName()
                      + " can be debugged on port 8100...");
            }
        }

        if (data.instrumentationName != null) {
            ContextImpl appContext = new ContextImpl();
            appContext.init(data.info, null, this);
            InstrumentationInfo ii = null;
            try {
                ii = appContext.getPackageManager().
                    getInstrumentationInfo(data.instrumentationName, 0);
            } catch (PackageManager.NameNotFoundException e) {
            }
            if (ii == null) {
                throw new RuntimeException(
                    "Unable to find instrumentation info for: "
                    + data.instrumentationName);
            }

            mInstrumentationAppDir = ii.sourceDir;
            mInstrumentationAppPackage = ii.packageName;
            mInstrumentedAppDir = data.info.getAppDir();

            ApplicationInfo instrApp = new ApplicationInfo();
            instrApp.packageName = ii.packageName;
            instrApp.sourceDir = ii.sourceDir;
            instrApp.publicSourceDir = ii.publicSourceDir;
            instrApp.dataDir = ii.dataDir;
            instrApp.nativeLibraryDir = ii.nativeLibraryDir;
            LoadedApk pi = getPackageInfo(instrApp,
                    appContext.getClassLoader(), false, true);
            ContextImpl instrContext = new ContextImpl();
            instrContext.init(pi, null, this);

            try {
                java.lang.ClassLoader cl = instrContext.getClassLoader();
                mInstrumentation = (Instrumentation)
                    cl.loadClass(data.instrumentationName.getClassName()).newInstance();
            } catch (Exception e) {
                throw new RuntimeException(
                    "Unable to instantiate instrumentation "
                    + data.instrumentationName + ": " + e.toString(), e);
            }

            mInstrumentation.init(this, instrContext, appContext,
                    new ComponentName(ii.packageName, ii.name), data.instrumentationWatcher);

            if (data.profileFile != null && !ii.handleProfiling) {
                data.handlingProfiling = true;
                File file = new File(data.profileFile);
                file.getParentFile().mkdirs();
                Debug.startMethodTracing(file.toString(), 8 * 1024 * 1024);
            }

            try {
                mInstrumentation.onCreate(data.instrumentationArgs);
            }
            catch (Exception e) {
                throw new RuntimeException(
                    "Exception thrown in onCreate() of "
                    + data.instrumentationName + ": " + e.toString(), e);
            }

        } else {
            mInstrumentation = new Instrumentation();
        }

        // If the app is being launched for full backup or restore, bring it up in
        // a restricted environment with the base application class.
        Application app = data.info.makeApplication(data.restrictedBackupMode, null);
        mInitialApplication = app;

        List<ProviderInfo> providers = data.providers;
        if (providers != null) {
            installContentProviders(app, providers);
            // For process that contain content providers, we want to
            // ensure that the JIT is enabled "at some point".
            mH.sendEmptyMessageDelayed(H.ENABLE_JIT, 10*1000);
        }

        try {
            mInstrumentation.callApplicationOnCreate(app);
        } catch (Exception e) {
            if (!mInstrumentation.onException(app, e)) {
                throw new RuntimeException(
                    "Unable to create application " + app.getClass().getName()
                    + ": " + e.toString(), e);
            }
        }
    }

frameworks/base/core/java/android/content/ContentProvider.java

  1. <PRE class=java name="code">  public void attachInfo(Context context, ProviderInfo info) {  
  2.   
  3.         /* 
  4.          * Only allow it to be set once, so after the content service gives 
  5.          * this to us clients can't change it. 
  6.          */  
  7.         if (mContext == null) {  
  8.             mContext = context;  
  9.             mMyUid = Process.myUid();  
  10.             if (info != null) {  
  11.                 setReadPermission(info.readPermission);  
  12.                 setWritePermission(info.writePermission);  
  13.                 setPathPermissions(info.pathPermissions);  
  14.                 mExported = info.exported;  
  15.             }  
  16.             ContentProvider.this.onCreate();  
  17.         }  
  18.     }</PRE>  
  19. <PRE></PRE>  
  20. <P></P>  
  21. <PRE></PRE>  
  22. <P></P>  
  23. <P>frameworks/base/services/java/com/android/server/am/ActivityManagerService.java </P>  
  24. <P></P>  
  25. <P></P>  
  26. <PRE class=cpp name="code">    public final void publishContentProviders(IApplicationThread caller,  
  27.             List<ContentProviderHolder> providers) {  
  28.         if (providers == null) {  
  29.             return;  
  30.         }  
  31.   
  32.         synchronized(this) {  
  33.             final ProcessRecord r = getRecordForAppLocked(caller);  
  34.             if (r == null) {  
  35.                 throw new SecurityException(  
  36.                         "Unable to find app for caller " + caller  
  37.                       + " (pid=" + Binder.getCallingPid()  
  38.                       + ") when publishing content providers");  
  39.             }  
  40.   
  41.             final long origId = Binder.clearCallingIdentity();  
  42.   
  43.             final int N = providers.size();  
  44.             for (int i=0; i<N; i++) {  
  45.                 ContentProviderHolder src = providers.get(i);  
  46.                 if (src == null || src.info == null || src.provider == null) {  
  47.                     continue;  
  48.                 }  
  49.                 ContentProviderRecord dst = r.pubProviders.get(src.info.name);  
  50.                 if (dst != null) {  
  51.                     mProvidersByClass.put(dst.info.name, dst);  
  52.                     String names[] = dst.info.authority.split(";");  
  53.                     for (int j = 0; j < names.length; j++) {  
  54.                         mProvidersByName.put(names[j], dst);  
  55.                     }  
  56.   
  57.                     int NL = mLaunchingProviders.size();  
  58.                     int j;  
  59.                     for (j=0; j<NL; j++) {  
  60.                         if (mLaunchingProviders.get(j) == dst) {  
  61.                             mLaunchingProviders.remove(j);  
  62.                             j--;  
  63.                             NL--;  
  64.                         }  
  65.                     }  
  66.                     synchronized (dst) {  
  67.                         dst.provider = src.provider;  
  68.                         dst.app = r;  
  69.                         dst.notifyAll();  
  70.                     }  
  71.                     updateOomAdjLocked(r);  
  72.                 }  
  73.             }  
  74.   
  75.             Binder.restoreCallingIdentity(origId);  
  76.         }  
  77.     }  
  78. </PRE><BR>  
  79. <P></P>  
  80. <P>frameworks/base/core/java/android/app/ActivityThread.java</P>  
  81. <P></P>  
  82. <P><BR>  
  83. </P>  
  84. <PRE class=cpp name="code"><PRE class=java name="code">    private final void installContentProviders(  
  85.             Context context, List<ProviderInfo> providers) {  
  86.         final ArrayList<IActivityManager.ContentProviderHolder> results =  
  87.             new ArrayList<IActivityManager.ContentProviderHolder>();  
  88.   
  89.         Iterator<ProviderInfo> i = providers.iterator();  
  90.         while (i.hasNext()) {  
  91.             ProviderInfo cpi = i.next();  
  92.             StringBuilder buf = new StringBuilder(128);  
  93.             buf.append("Pub ");  
  94.             buf.append(cpi.authority);  
  95.             buf.append(": ");  
  96.             buf.append(cpi.name);  
  97.             Log.i(TAG, buf.toString());  
  98.             IContentProvider cp = installProvider(context, null, cpi, false);  
  99.             if (cp != null) {  
  100.                 IActivityManager.ContentProviderHolder cph =  
  101.                     new IActivityManager.ContentProviderHolder(cpi);  
  102.                 cph.provider = cp;  
  103.                 results.add(cph);  
  104.                 // Don't ever unload this provider from the process.   
  105.                 synchronized(mProviderMap) {  
  106.                     mProviderRefCountMap.put(cp.asBinder(), new ProviderRefCount(10000));  
  107.                 }  
  108.             }  
  109.         }  
  110.   
  111.         try {  
  112.             ActivityManagerNative.getDefault().publishContentProviders(  
  113.                 getApplicationThread(), results);  
  114.         } catch (RemoteException ex) {  
  115.         }  
  116.     }  
  117. </PRE>  
  118. <PRE></PRE>  
  119. <P>In the following code,ContentProvider is instantiated.</P>  
  120. <P></P>  
  121. <PRE class=cpp name="code"><PRE class=java name="code">    private final IContentProvider installProvider(Context context,  
  122.             IContentProvider provider, ProviderInfo info, boolean noisy) {  
  123.         ContentProvider localProvider = null;  
  124.         if (provider == null) {  
  125.             if (noisy) {  
  126.                 Slog.d(TAG, "Loading provider " + info.authority + ": "  
  127.                         + info.name);  
  128.             }  
  129.             Context c = null;  
  130.             ApplicationInfo ai = info.applicationInfo;  
  131.             if (context.getPackageName().equals(ai.packageName)) {  
  132.                 c = context;  
  133.             } else if (mInitialApplication != null &&  
  134.                     mInitialApplication.getPackageName().equals(ai.packageName)) {  
  135.                 c = mInitialApplication;  
  136.             } else {  
  137.                 try {  
  138.                     c = context.createPackageContext(ai.packageName,  
  139.                             Context.CONTEXT_INCLUDE_CODE);  
  140.                 } catch (PackageManager.NameNotFoundException e) {  
  141.                 }  
  142.             }  
  143.             if (c == null) {  
  144.                 Slog.w(TAG, "Unable to get context for package " +  
  145.                       ai.packageName +  
  146.                       " while loading content provider " +  
  147.                       info.name);  
  148.                 return null;  
  149.             }  
  150.             try {  
  151.                 final java.lang.ClassLoader cl = c.getClassLoader();  
  152.                 localProvider = (ContentProvider)cl.  
  153.                     loadClass(info.name).newInstance();               //这里构造ContentProvider实例,例如:new MediaProvider   
  154.                 provider = localProvider.getIContentProvider();       //得到对应的Binder操作实例   
  155.                 if (provider == null) {  
  156.                     Slog.e(TAG, "Failed to instantiate class " +  
  157.                           info.name + " from sourceDir " +  
  158.                           info.applicationInfo.sourceDir);  
  159.                     return null;  
  160.                 }  
  161.                 if (Config.LOGV) Slog.v(  
  162.                     TAG, "Instantiating local provider " + info.name);  
  163.                 // XXX Need to create the correct context for this provider.   
  164.                 localProvider.attachInfo(c, info);          //在这里调用ContentProvider.attachInfo,那里调用onCreate开始初始化Provider   
  165.             } catch (java.lang.Exception e) {  
  166.                 if (!mInstrumentation.onException(null, e)) {  
  167.                     throw new RuntimeException(  
  168.                             "Unable to get provider " + info.name  
  169.                             + ": " + e.toString(), e);  
  170.                 }  
  171.                 return null;  
  172.             }  
  173.         } else if (localLOGV) {  
  174.             Slog.v(TAG, "Installing external provider " + info.authority + ": "  
  175.                     + info.name);  
  176.         }  
  177.   
  178.         synchronized (mProviderMap) {  
  179.             // Cache the pointer for the remote provider.   
  180.             String names[] = PATTERN_SEMICOLON.split(info.authority); //同一个ContentProvider可能支持多个authority   
  181.             for (int i=0; i<names.length; i++) { //对每一个authority,构建对应的ProviderClientRecord   
  182.                 ProviderClientRecord pr = new ProviderClientRecord(names[i], provider,  
  183.                         localProvider);  
  184.                 try {  
  185.                     provider.asBinder().linkToDeath(pr, 0);  
  186.                     mProviderMap.put(names[i], pr);  
  187.                 } catch (RemoteException e) {  
  188.                     return null;  
  189.                 }  
  190.             }  
  191.             if (localProvider != null) { //如果provider早已创建出来了   
  192.                 mLocalProviders.put(provider.asBinder(),  
  193.                         new ProviderClientRecord(null, provider, localProvider));   
  194.             }  
  195.         }  
  196.   
  197.         return provider;  
  198.     }</PRE>  
  199. <PRE></PRE>  
  200. <P></P>  
  201. <PRE></PRE>  
  202. frameworks/base/services/java/com/android/server/am/ActivityManagerService.java  
  203. <P></P>  
  204. <P></P>  
  205. <PRE class=cpp name="code"><PRE class=java name="code">    public final void publishContentProviders(IApplicationThread caller,  
  206.             List<ContentProviderHolder> providers) {  
  207.         if (providers == null) {  
  208.             return;  
  209.         }  
  210.   
  211.         synchronized(this) {  
  212.             final ProcessRecord r = getRecordForAppLocked(caller);  
  213.             if (r == null) {  
  214.                 throw new SecurityException(  
  215.                         "Unable to find app for caller " + caller  
  216.                       + " (pid=" + Binder.getCallingPid()  
  217.                       + ") when publishing content providers");  
  218.             }  
  219.   
  220.             final long origId = Binder.clearCallingIdentity();  
  221.   
  222.             final int N = providers.size();  
  223.             for (int i=0; i<N; i++) {  
  224.                 ContentProviderHolder src = providers.get(i);  
  225.                 if (src == null || src.info == null || src.provider == null) {  
  226.                     continue;  
  227.                 }  
  228.                 ContentProviderRecord dst = r.pubProviders.get(src.info.name);  
  229.                 if (dst != null) {  
  230.                     mProvidersByClass.put(dst.info.name, dst);  
  231.                     String names[] = dst.info.authority.split(";");  
  232.                     for (int j = 0; j < names.length; j++) {  
  233.                         mProvidersByName.put(names[j], dst);  
  234.                     }  
  235.   
  236.                     int NL = mLaunchingProviders.size();  
  237.                     int j;  
  238.                     for (j=0; j<NL; j++) {  
  239.                         if (mLaunchingProviders.get(j) == dst) {  
  240.                             mLaunchingProviders.remove(j);  
  241.                             j--;  
  242.                             NL--;  
  243.                         }  
  244.                     }  
  245.                     synchronized (dst) {  
  246.                         dst.provider = src.provider;  
  247.                         dst.app = r;  
  248.                         dst.notifyAll();  
  249.                     }  
  250.                     updateOomAdjLocked(r);  
  251.                 }  
  252.             }  
  253.   
  254.             Binder.restoreCallingIdentity(origId);  
  255.         }  
  256.     }</PRE>  
  257. <PRE></PRE>  
  258. <P></P>  
  259. <PRE></PRE>  
  260. <P></P>  
  261. <P><BR>  
  262. </P>  
  263. <P><BR>  
  264. </P>  
  265. <P><BR>  
  266. </P>  
  267. <P><BR>  
  268. </P>  
  269. <P><BR>  
  270. </P>  
  271. <BR>  
  272. <PRE></PRE>  
  273. <PRE></PRE>  
  274. <PRE></PRE>  
  275. <PRE></PRE>  
  276. <PRE></PRE>  
  277. <PRE></PRE>  
  278. <PRE></PRE>  
  279. <PRE></PRE>  
  280. <PRE></PRE>  
  281. <PRE></PRE>  
  282. <PRE></PRE>  
  283. <PRE></PRE>  
  284. <PRE></PRE>  
  285. <PRE></PRE>  
  286. <PRE></PRE>  
  287. <PRE></PRE>  
  288. <PRE></PRE>  
  289. <PRE></PRE>  
  290. <PRE></PRE>  
  291. <PRE></PRE>  
  292. <PRE></PRE>  
  293. <PRE></PRE>  
  294. <PRE></PRE>  
  295. <PRE></PRE>  
  296. <PRE></PRE>  
  297. <PRE></PRE>  
  298. <PRE></PRE>  
  299. <PRE></PRE>  
  300. <PRE></PRE>  
  301. <PRE></PRE>  
  302. <PRE></PRE>  
  303. <PRE></PRE>  
  304. <PRE></PRE>  
  305. <PRE></PRE>  
  306. <PRE></PRE>  
  307. <PRE></PRE>  
  308. <PRE></PRE>  
  309. <PRE></PRE>  
  310. <PRE></PRE>  
  311. <PRE></PRE>  
  312. <PRE></PRE>  
  313. <PRE></PRE>  
  314. <PRE></PRE>  
  315.   
  316. </PRE></PRE></PRE>

 

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值