PackageManager keeps track of who installed what.

Stores the package name of the installer app in packages.xml
diff --git a/api/current.xml b/api/current.xml
index f227605..643ea23 100644
--- a/api/current.xml
+++ b/api/current.xml
@@ -35526,6 +35526,19 @@
 <parameter name="flags" type="int">
 </parameter>
 </method>
+<method name="getInstallerPackageName"
+ return="java.lang.String"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="packageName" type="java.lang.String">
+</parameter>
+</method>
 <method name="getInstrumentationInfo"
  return="android.content.pm.InstrumentationInfo"
  abstract="true"
@@ -35821,7 +35834,7 @@
 </method>
 <method name="installPackage"
  return="void"
- abstract="true"
+ abstract="false"
  native="false"
  synchronized="false"
  static="false"
@@ -114343,6 +114356,19 @@
 <parameter name="flags" type="int">
 </parameter>
 </method>
+<method name="getInstallerPackageName"
+ return="java.lang.String"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="packageName" type="java.lang.String">
+</parameter>
+</method>
 <method name="getInstrumentationInfo"
  return="android.content.pm.InstrumentationInfo"
  abstract="false"
@@ -114635,6 +114661,8 @@
 </parameter>
 <parameter name="flags" type="int">
 </parameter>
+<parameter name="installerPackageName" type="java.lang.String">
+</parameter>
 </method>
 <method name="isSafeMode"
  return="boolean"
diff --git a/cmds/pm/src/com/android/commands/pm/Pm.java b/cmds/pm/src/com/android/commands/pm/Pm.java
index 04e69e3..ac62757 100644
--- a/cmds/pm/src/com/android/commands/pm/Pm.java
+++ b/cmds/pm/src/com/android/commands/pm/Pm.java
@@ -579,6 +579,7 @@
     
     private void runInstall() {
         int installFlags = 0;
+        String installerPackageName = null;
 
         String opt;
         while ((opt=nextOption()) != null) {
@@ -586,6 +587,13 @@
                 installFlags |= PackageManager.FORWARD_LOCK_PACKAGE;
             } else if (opt.equals("-r")) {
                 installFlags |= PackageManager.REPLACE_EXISTING_PACKAGE;
+            } else if (opt.equals("-i")) {
+                installerPackageName = nextOptionData();
+                if (installerPackageName == null) {
+                    System.err.println("Error: no value specified for -i");
+                    showUsage();
+                    return;
+                }
             } else {
                 System.err.println("Error: Unknown option: " + opt);
                 showUsage();
@@ -603,7 +611,8 @@
 
         PackageInstallObserver obs = new PackageInstallObserver();
         try {
-            mPm.installPackage(Uri.fromFile(new File(apkFilePath)), obs, installFlags);
+            mPm.installPackage(Uri.fromFile(new File(apkFilePath)), obs, installFlags,
+                    installerPackageName);
             
             synchronized (obs) {
                 while (!obs.finished) {
@@ -812,7 +821,7 @@
         System.err.println("       pm list permissions [-g] [-f] [-d] [-u] [GROUP]");
         System.err.println("       pm list instrumentation [-f] [TARGET-PACKAGE]");        
         System.err.println("       pm path PACKAGE");
-        System.err.println("       pm install [-l] [-r] PATH");
+        System.err.println("       pm install [-l] [-r] [-i INSTALLER_PACKAGE_NAME] PATH");
         System.err.println("       pm uninstall [-k] PACKAGE");
         System.err.println("       pm enable PACKAGE_OR_COMPONENT");
         System.err.println("       pm disable PACKAGE_OR_COMPONENT");
@@ -840,6 +849,7 @@
         System.err.println("The install command installs a package to the system.  Use");
         System.err.println("the -l option to install the package with FORWARD_LOCK. Use");
         System.err.println("the -r option to reinstall an exisiting app, keeping its data.");
+        System.err.println("the -i option to specify the installer package name.");
         System.err.println("");
         System.err.println("The uninstall command removes a package from the system. Use");
         System.err.println("the -k option to keep the data and cache directories around");
diff --git a/core/java/android/app/ApplicationContext.java b/core/java/android/app/ApplicationContext.java
index 72d9e3d..d235832 100644
--- a/core/java/android/app/ApplicationContext.java
+++ b/core/java/android/app/ApplicationContext.java
@@ -2326,15 +2326,26 @@
         }
 
         @Override
-        public void installPackage(Uri packageURI, IPackageInstallObserver observer, int flags) {
+        public void installPackage(Uri packageURI, IPackageInstallObserver observer, int flags,
+                String installerPackageName) {
             try {
-                mPM.installPackage(packageURI, observer, flags);
+                mPM.installPackage(packageURI, observer, flags, installerPackageName);
             } catch (RemoteException e) {
                 // Should never happen!
             }
         }
 
         @Override
+        public String getInstallerPackageName(String packageName) {
+            try {
+                return mPM.getInstallerPackageName(packageName);
+            } catch (RemoteException e) {
+                // Should never happen!
+            }
+            return null;
+        }
+
+        @Override
         public void deletePackage(String packageName, IPackageDeleteObserver observer, int flags) {
             try {
                 mPM.deletePackage(packageName, observer, flags);
diff --git a/core/java/android/content/pm/IPackageManager.aidl b/core/java/android/content/pm/IPackageManager.aidl
index bf963ff..57b84b2 100644
--- a/core/java/android/content/pm/IPackageManager.aidl
+++ b/core/java/android/content/pm/IPackageManager.aidl
@@ -140,8 +140,11 @@
      * @param observer a callback to use to notify when the package installation in finished.
      * @param flags - possible values: {@link #FORWARD_LOCK_PACKAGE},
      * {@link #REPLACE_EXISITING_PACKAGE}
+     * @param installerPackageName Optional package name of the application that is performing the
+     * installation. This identifies which market the package came from.
      */
-    void installPackage(in Uri packageURI, IPackageInstallObserver observer, int flags);
+    void installPackage(in Uri packageURI, IPackageInstallObserver observer, int flags,
+            in String installerPackageName);
 
     /**
      * Delete a package.
@@ -152,6 +155,8 @@
      */
     void deletePackage(in String packageName, IPackageDeleteObserver observer, int flags);
 
+    String getInstallerPackageName(in String packageName);
+
     void addPackageToPreferred(String packageName);
     
     void removePackageFromPreferred(String packageName);
diff --git a/core/java/android/content/pm/PackageManager.java b/core/java/android/content/pm/PackageManager.java
index e2f0ce4..18e4548 100644
--- a/core/java/android/content/pm/PackageManager.java
+++ b/core/java/android/content/pm/PackageManager.java
@@ -1354,8 +1354,35 @@
      *
      * @see #installPackage(android.net.Uri)
      */
+    public void installPackage(
+            Uri packageURI, IPackageInstallObserver observer, int flags) {
+        installPackage(packageURI, observer, flags, null);
+    }
+
+    /**
+     * Install a package. Since this may take a little while, the result will
+     * be posted back to the given observer.  An installation will fail if the calling context
+     * lacks the {@link android.Manifest.permission#INSTALL_PACKAGES} permission, if the
+     * package named in the package file's manifest is already installed, or if there's no space
+     * available on the device.
+     *
+     * @param packageURI The location of the package file to install.  This can be a 'file:' or a
+     * 'content:' URI.
+     * @param observer An observer callback to get notified when the package installation is
+     * complete. {@link IPackageInstallObserver#packageInstalled(String, int)} will be
+     * called when that happens.  observer may be null to indicate that no callback is desired.
+     * @param flags - possible values: {@link #FORWARD_LOCK_PACKAGE},
+     * {@link #REPLACE_EXISTING_PACKAGE}
+     * @param installerPackageName Optional package name of the application that is performing the
+     * installation. This identifies which market the package came from.
+     *
+     * @see #installPackage(android.net.Uri)
+     * 
+     * @hide
+     */
     public abstract void installPackage(
-            Uri packageURI, IPackageInstallObserver observer, int flags);
+            Uri packageURI, IPackageInstallObserver observer, int flags,
+            String installerPackageName);
 
     /**
      * Attempts to delete a package.  Since this may take a little while, the result will
@@ -1374,6 +1401,15 @@
      */
     public abstract void deletePackage(
             String packageName, IPackageDeleteObserver observer, int flags);
+
+    /**
+     * Retrieve the package name of the application that installed a package. This identifies
+     * which market the package came from.
+     * 
+     * @param packageName The name of the package to query
+     */
+    public abstract String getInstallerPackageName(String packageName);
+    
     /**
      * Attempts to clear the user data directory of an application.
      * Since this may take a little while, the result will
@@ -1483,7 +1519,7 @@
      *
      * @param packageURI The location of the package file to install
      *
-     * @see #installPackage(android.net.Uri, IPackageInstallObserver, int)
+     * @see #installPackage(android.net.Uri, IPackageInstallObserver, int, String)
      */
     public void installPackage(Uri packageURI) {
         installPackage(packageURI, null, 0);
diff --git a/services/java/com/android/server/PackageManagerService.java b/services/java/com/android/server/PackageManagerService.java
index 1a11902..d3bb03c 100644
--- a/services/java/com/android/server/PackageManagerService.java
+++ b/services/java/com/android/server/PackageManagerService.java
@@ -3234,20 +3234,27 @@
         private final String mRootDir;
         private final boolean mIsRom;
     }
-    
+
     /* Called when a downloaded package installation has been confirmed by the user */
     public void installPackage(
             final Uri packageURI, final IPackageInstallObserver observer, final int flags) {
+        installPackage(packageURI, observer, flags, null);
+    }
+    
+    /* Called when a downloaded package installation has been confirmed by the user */
+    public void installPackage(
+            final Uri packageURI, final IPackageInstallObserver observer, final int flags,
+            final String installerPackageName) {
         mContext.enforceCallingOrSelfPermission(
                 android.Manifest.permission.INSTALL_PACKAGES, null);
-
+        
         // Queue up an async operation since the package installation may take a little while.
         mHandler.post(new Runnable() {
             public void run() {
                 mHandler.removeCallbacks(this);
                 PackageInstalledInfo res;
                 synchronized (mInstallLock) {
-                    res = installPackageLI(packageURI, flags, true);
+                    res = installPackageLI(packageURI, flags, true, installerPackageName);
                 }
                 if (observer != null) {
                     try {
@@ -3295,7 +3302,7 @@
             File tmpPackageFile, 
             String destFilePath, File destPackageFile, File destResourceFile,
             PackageParser.Package pkg, boolean forwardLocked, boolean newInstall,
-            PackageInstalledInfo res) {
+            String installerPackageName, PackageInstalledInfo res) {
         // Remember this for later, in case we need to rollback this install
         boolean dataDirExists = (new File(mAppDataDir, pkgName)).exists();
         res.name = pkgName;
@@ -3331,7 +3338,8 @@
                     destResourceFile, pkg, 
                     newPackage,
                     true,
-                    forwardLocked,  
+                    forwardLocked,
+                    installerPackageName,
                     res);
             // delete the partially installed application. the data directory will have to be
             // restored if it was already existing
@@ -3352,7 +3360,8 @@
             File tmpPackageFile, 
             String destFilePath, File destPackageFile, File destResourceFile,
             PackageParser.Package pkg, boolean forwardLocked, boolean newInstall,
-            PackageInstalledInfo res) {
+            String installerPackageName, PackageInstalledInfo res) {
+
         PackageParser.Package oldPackage;
         // First find the old package info and check signatures
         synchronized(mPackages) {
@@ -3367,11 +3376,11 @@
             replaceSystemPackageLI(oldPackage,
                     tmpPackageFile, destFilePath, 
                     destPackageFile, destResourceFile, pkg, forwardLocked,
-                    newInstall, res);
+                    newInstall, installerPackageName, res);
         } else {
             replaceNonSystemPackageLI(oldPackage, tmpPackageFile, destFilePath,
                     destPackageFile, destResourceFile, pkg, forwardLocked,
-                    newInstall, res);
+                    newInstall, installerPackageName, res);
         }
     }
     
@@ -3379,11 +3388,17 @@
             File tmpPackageFile, 
             String destFilePath, File destPackageFile, File destResourceFile,
             PackageParser.Package pkg, boolean forwardLocked, boolean newInstall,
-            PackageInstalledInfo res) {
+            String installerPackageName, PackageInstalledInfo res) {
         PackageParser.Package newPackage = null;
         String pkgName = deletedPackage.packageName;
         boolean deletedPkg = true;
         boolean updatedSettings = false;
+        
+        String oldInstallerPackageName = null;
+        synchronized (mPackages) {
+            oldInstallerPackageName = mSettings.getInstallerPackageName(pkgName);
+        }
+        
         int parseFlags = PackageManager.REPLACE_EXISTING_PACKAGE;
         // First delete the existing package while retaining the data directory
         if (!deletePackageLI(pkgName, false, PackageManager.DONT_DELETE_DATA,
@@ -3412,6 +3427,7 @@
                         newPackage,
                         true,
                         forwardLocked,  
+                        installerPackageName,
                         res);
                 updatedSettings = true;
             }
@@ -3456,7 +3472,7 @@
                         Uri.fromFile(new File(deletedPackage.mPath)),
                         isForwardLocked(deletedPackage)
                         ? PackageManager.FORWARD_LOCK_PACKAGE
-                                : 0, false);
+                                : 0, false, oldInstallerPackageName);
             }
         }
     }
@@ -3465,7 +3481,7 @@
             File tmpPackageFile, 
             String destFilePath, File destPackageFile, File destResourceFile,
             PackageParser.Package pkg, boolean forwardLocked, boolean newInstall,
-            PackageInstalledInfo res) {
+            String installerPackageName, PackageInstalledInfo res) {
         PackageParser.Package newPackage = null;
         boolean updatedSettings = false;
         int parseFlags = PackageManager.REPLACE_EXISTING_PACKAGE |
@@ -3515,7 +3531,8 @@
                     destResourceFile, pkg, 
                     newPackage,
                     true,
-                    forwardLocked,  
+                    forwardLocked,
+                    installerPackageName,
                     res);
             updatedSettings = true;
         }
@@ -3542,6 +3559,8 @@
             synchronized(mPackages) {
                 if(updatedSettings) {
                     mSettings.enableSystemPackageLP(packageName);
+                    mSettings.setInstallerPackageName(packageName,
+                            oldPkgSetting.installerPackageName);
                 }
                 mSettings.writeLP();
             }
@@ -3555,7 +3574,7 @@
             PackageParser.Package newPackage,
             boolean replacingExistingPackage,
             boolean forwardLocked,  
-            PackageInstalledInfo res) {
+            String installerPackageName, PackageInstalledInfo res) {
         synchronized (mPackages) {
             //write settings. the installStatus will be incomplete at this stage.
             //note that the new package setting would have already been
@@ -3602,6 +3621,7 @@
             res.uid = newPackage.applicationInfo.uid;
             res.pkg = newPackage;
             mSettings.setInstallStatus(pkgName, PKG_INSTALL_COMPLETE);
+            mSettings.setInstallerPackageName(pkgName, installerPackageName);
             res.returnCode = PackageManager.INSTALL_SUCCEEDED;
             //to update install status
             mSettings.writeLP();
@@ -3609,7 +3629,7 @@
     }
     
     private PackageInstalledInfo installPackageLI(Uri pPackageURI,
-            int pFlags, boolean newInstall) {
+            int pFlags, boolean newInstall, String installerPackageName) {
         File tmpPackageFile = null;
         String pkgName = null;
         boolean forwardLocked = false;
@@ -3722,13 +3742,13 @@
                 replacePackageLI(pkgName,
                         tmpPackageFile, 
                         destFilePath, destPackageFile, destResourceFile,
-                        pkg, forwardLocked, newInstall,
+                        pkg, forwardLocked, newInstall, installerPackageName,
                         res);
             } else {
                 installNewPackageLI(pkgName,
                         tmpPackageFile, 
                         destFilePath, destPackageFile, destResourceFile,
-                        pkg, forwardLocked, newInstall,
+                        pkg, forwardLocked, newInstall, installerPackageName,
                         res);
             }
         } finally {
@@ -4546,6 +4566,16 @@
         }
     }
 
+    public String getInstallerPackageName(String packageName) {
+        synchronized (mPackages) {
+            PackageSetting pkg = mSettings.mPackages.get(packageName);
+            if (pkg == null) {
+                throw new IllegalArgumentException("Unknown package: " + packageName);
+            }
+            return pkg.installerPackageName;
+        }
+    }
+    
     public int getApplicationEnabledSetting(String appPackageName) {
         synchronized (mPackages) {
             PackageSetting pkg = mSettings.mPackages.get(appPackageName);
@@ -5195,6 +5225,9 @@
         HashSet<String> enabledComponents = new HashSet<String>(0);
         int enabled = COMPONENT_ENABLED_STATE_DEFAULT;
         int installStatus = PKG_INSTALL_COMPLETE;
+        
+        /* package name of the app that installed this package */
+        String installerPackageName;
 
         PackageSettingBase(String name, File codePath, File resourcePath,
                 int pVersionCode, int pkgFlags) {
@@ -5207,6 +5240,14 @@
             this.versionCode = pVersionCode;
         }
 
+        public void setInstallerPackageName(String packageName) {
+            installerPackageName = packageName;
+        }
+        
+        String getInstallerPackageName() {
+            return installerPackageName;
+        }
+        
         public void setInstallStatus(int newStatus) {
             installStatus = newStatus;
         }
@@ -5437,6 +5478,19 @@
             }
         }
         
+        void setInstallerPackageName(String pkgName,
+                String installerPkgName) {
+            PackageSetting p = mPackages.get(pkgName);
+            if(p != null) {
+                p.setInstallerPackageName(installerPkgName);
+            }
+        }
+        
+        String getInstallerPackageName(String pkgName) {
+            PackageSetting p = mPackages.get(pkgName);
+            return (p == null) ? null : p.getInstallerPackageName(); 
+        }
+
         int getInstallStatus(String pkgName) {
             PackageSetting p = mPackages.get(pkgName);
             if(p != null) {
@@ -5912,6 +5966,9 @@
             if(pkg.installStatus == PKG_INSTALL_INCOMPLETE) {
                 serializer.attribute(null, "installStatus", "false");
             }
+            if (pkg.installerPackageName != null) {
+                serializer.attribute(null, "installer", pkg.installerPackageName);
+            }
             pkg.signatures.writeXml(serializer, "sigs", mPastSignatures);
             if ((pkg.pkgFlags&ApplicationInfo.FLAG_SYSTEM) == 0) {
                 serializer.startTag(null, "perms");
@@ -5946,6 +6003,7 @@
                 }
                 serializer.endTag(null, "enabled-components");
             }
+            
             serializer.endTag(null, "package");
         }
         
@@ -6267,6 +6325,7 @@
             String codePathStr = null;
             String resourcePathStr = null;
             String systemStr = null;
+            String installerPackageName = null;
             int pkgFlags = 0;
             String timeStampStr;
             long timeStamp = 0;
@@ -6287,6 +6346,7 @@
                     }
                 }
                 systemStr = parser.getAttributeValue(null, "system");
+                installerPackageName = parser.getAttributeValue(null, "installer");
                 if (systemStr != null) {
                     if ("true".equals(systemStr)) {
                         pkgFlags |= ApplicationInfo.FLAG_SYSTEM;
@@ -6360,6 +6420,7 @@
                         + parser.getPositionDescription());
             }
             if (packageSetting != null) {
+                packageSetting.installerPackageName = installerPackageName;
                 final String enabledStr = parser.getAttributeValue(null, "enabled");
                 if (enabledStr != null) {
                     if (enabledStr.equalsIgnoreCase("true")) {
diff --git a/test-runner/android/test/mock/MockPackageManager.java b/test-runner/android/test/mock/MockPackageManager.java
index ea190e2..20929a3 100644
--- a/test-runner/android/test/mock/MockPackageManager.java
+++ b/test-runner/android/test/mock/MockPackageManager.java
@@ -286,7 +286,12 @@
 
     @Override
     public void installPackage(Uri packageURI, IPackageInstallObserver observer,
-            int flags) {
+            int flags, String installerPackageName) {
+        throw new UnsupportedOperationException();
+    }
+    
+    @Override
+    public String getInstallerPackageName(String packageName) {
         throw new UnsupportedOperationException();
     }