Implement issue #1783881 (manifest option for adb-install-only apps)

You can now use android:testOnly="true" to not allow your .apk to be installed
as a normal app.  The only way to do so is with the pm command and giving the
-t option, which sets a new INSTALL_ALLOW_TEST flag when installing.

I also used this to clean up the install API...  actually, mostly to hide
it, since it is not accessible to apps so shouldn't be in the SDK.  We
will be doing some more work on it, so this will prevent adding yet
another backwards-compatibility-for-no-reason version.
diff --git a/api/4.xml b/api/4.xml
index ab93a47..893301e 100644
--- a/api/4.xml
+++ b/api/4.xml
@@ -31801,97 +31801,6 @@
 >
 </field>
 </class>
-<interface name="IPackageInstallObserver"
- abstract="true"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-<implements name="android.os.IInterface">
-</implements>
-<method name="packageInstalled"
- return="void"
- abstract="true"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-<parameter name="packageName" type="java.lang.String">
-</parameter>
-<parameter name="returnCode" type="int">
-</parameter>
-<exception name="RemoteException" type="android.os.RemoteException">
-</exception>
-</method>
-</interface>
-<class name="IPackageInstallObserver.Stub"
- extends="android.os.Binder"
- abstract="true"
- static="true"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-<implements name="android.content.pm.IPackageInstallObserver">
-</implements>
-<constructor name="IPackageInstallObserver.Stub"
- type="android.content.pm.IPackageInstallObserver.Stub"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-</constructor>
-<method name="asBinder"
- return="android.os.IBinder"
- abstract="false"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-</method>
-<method name="asInterface"
- return="android.content.pm.IPackageInstallObserver"
- abstract="false"
- native="false"
- synchronized="false"
- static="true"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-<parameter name="obj" type="android.os.IBinder">
-</parameter>
-</method>
-<method name="onTransact"
- return="boolean"
- abstract="false"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-<parameter name="code" type="int">
-</parameter>
-<parameter name="data" type="android.os.Parcel">
-</parameter>
-<parameter name="reply" type="android.os.Parcel">
-</parameter>
-<parameter name="flags" type="int">
-</parameter>
-<exception name="RemoteException" type="android.os.RemoteException">
-</exception>
-</method>
-</class>
 <class name="InstrumentationInfo"
  extends="android.content.pm.PackageItemInfo"
  abstract="false"
@@ -33041,36 +32950,6 @@
 <parameter name="appInfo" type="android.content.pm.ApplicationInfo">
 </parameter>
 </method>
-<method name="installPackage"
- return="void"
- abstract="true"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-<parameter name="packageURI" type="android.net.Uri">
-</parameter>
-<parameter name="observer" type="android.content.pm.IPackageInstallObserver">
-</parameter>
-<parameter name="flags" type="int">
-</parameter>
-</method>
-<method name="installPackage"
- return="void"
- abstract="false"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-<parameter name="packageURI" type="android.net.Uri">
-</parameter>
-</method>
 <method name="isSafeMode"
  return="boolean"
  abstract="true"
@@ -33344,17 +33223,6 @@
  visibility="public"
 >
 </field>
-<field name="FORWARD_LOCK_PACKAGE"
- type="int"
- transient="false"
- volatile="false"
- value="1"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
 <field name="GET_ACTIVITIES"
  type="int"
  transient="false"
@@ -33531,270 +33399,6 @@
  visibility="public"
 >
 </field>
-<field name="INSTALL_FAILED_ALREADY_EXISTS"
- type="int"
- transient="false"
- volatile="false"
- value="-1"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
-<field name="INSTALL_FAILED_CONFLICTING_PROVIDER"
- type="int"
- transient="false"
- volatile="false"
- value="-13"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
-<field name="INSTALL_FAILED_DEXOPT"
- type="int"
- transient="false"
- volatile="false"
- value="-11"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
-<field name="INSTALL_FAILED_DUPLICATE_PACKAGE"
- type="int"
- transient="false"
- volatile="false"
- value="-5"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
-<field name="INSTALL_FAILED_INSUFFICIENT_STORAGE"
- type="int"
- transient="false"
- volatile="false"
- value="-4"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
-<field name="INSTALL_FAILED_INVALID_APK"
- type="int"
- transient="false"
- volatile="false"
- value="-2"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
-<field name="INSTALL_FAILED_INVALID_URI"
- type="int"
- transient="false"
- volatile="false"
- value="-3"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
-<field name="INSTALL_FAILED_MISSING_SHARED_LIBRARY"
- type="int"
- transient="false"
- volatile="false"
- value="-9"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
-<field name="INSTALL_FAILED_NO_SHARED_USER"
- type="int"
- transient="false"
- volatile="false"
- value="-6"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
-<field name="INSTALL_FAILED_OLDER_SDK"
- type="int"
- transient="false"
- volatile="false"
- value="-12"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
-<field name="INSTALL_FAILED_REPLACE_COULDNT_DELETE"
- type="int"
- transient="false"
- volatile="false"
- value="-10"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
-<field name="INSTALL_FAILED_SHARED_USER_INCOMPATIBLE"
- type="int"
- transient="false"
- volatile="false"
- value="-8"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
-<field name="INSTALL_FAILED_UPDATE_INCOMPATIBLE"
- type="int"
- transient="false"
- volatile="false"
- value="-7"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
-<field name="INSTALL_PARSE_FAILED_BAD_MANIFEST"
- type="int"
- transient="false"
- volatile="false"
- value="-101"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
-<field name="INSTALL_PARSE_FAILED_BAD_PACKAGE_NAME"
- type="int"
- transient="false"
- volatile="false"
- value="-106"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
-<field name="INSTALL_PARSE_FAILED_BAD_SHARED_USER_ID"
- type="int"
- transient="false"
- volatile="false"
- value="-107"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
-<field name="INSTALL_PARSE_FAILED_CERTIFICATE_ENCODING"
- type="int"
- transient="false"
- volatile="false"
- value="-105"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
-<field name="INSTALL_PARSE_FAILED_INCONSISTENT_CERTIFICATES"
- type="int"
- transient="false"
- volatile="false"
- value="-104"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
-<field name="INSTALL_PARSE_FAILED_MANIFEST_EMPTY"
- type="int"
- transient="false"
- volatile="false"
- value="-109"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
-<field name="INSTALL_PARSE_FAILED_MANIFEST_MALFORMED"
- type="int"
- transient="false"
- volatile="false"
- value="-108"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
-<field name="INSTALL_PARSE_FAILED_NOT_APK"
- type="int"
- transient="false"
- volatile="false"
- value="-100"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
-<field name="INSTALL_PARSE_FAILED_NO_CERTIFICATES"
- type="int"
- transient="false"
- volatile="false"
- value="-103"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
-<field name="INSTALL_PARSE_FAILED_UNEXPECTED_EXCEPTION"
- type="int"
- transient="false"
- volatile="false"
- value="-102"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
-<field name="INSTALL_SUCCEEDED"
- type="int"
- transient="false"
- volatile="false"
- value="1"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
 <field name="MATCH_DEFAULT_ONLY"
  type="int"
  transient="false"
@@ -33850,17 +33454,6 @@
  visibility="public"
 >
 </field>
-<field name="REPLACE_EXISTING_PACKAGE"
- type="int"
- transient="false"
- volatile="false"
- value="2"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
 <field name="SIGNATURE_FIRST_NOT_SIGNED"
  type="int"
  transient="false"
@@ -101178,23 +100771,6 @@
 <parameter name="appInfo" type="android.content.pm.ApplicationInfo">
 </parameter>
 </method>
-<method name="installPackage"
- return="void"
- abstract="false"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-<parameter name="packageURI" type="android.net.Uri">
-</parameter>
-<parameter name="observer" type="android.content.pm.IPackageInstallObserver">
-</parameter>
-<parameter name="flags" type="int">
-</parameter>
-</method>
 <method name="isSafeMode"
  return="boolean"
  abstract="false"
diff --git a/api/current.xml b/api/current.xml
index 71b5bc2..7209b2f 100644
--- a/api/current.xml
+++ b/api/current.xml
@@ -7324,6 +7324,17 @@
  visibility="public"
 >
 </field>
+<field name="testOnly"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16843378"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 <field name="text"
  type="int"
  transient="false"
@@ -31885,6 +31896,17 @@
  visibility="public"
 >
 </field>
+<field name="FLAG_TEST_ONLY"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="512"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 <field name="FLAG_UPDATED_SYSTEM_APP"
  type="int"
  transient="false"
@@ -32300,97 +32322,6 @@
 >
 </field>
 </class>
-<interface name="IPackageInstallObserver"
- abstract="true"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-<implements name="android.os.IInterface">
-</implements>
-<method name="packageInstalled"
- return="void"
- abstract="true"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-<parameter name="packageName" type="java.lang.String">
-</parameter>
-<parameter name="returnCode" type="int">
-</parameter>
-<exception name="RemoteException" type="android.os.RemoteException">
-</exception>
-</method>
-</interface>
-<class name="IPackageInstallObserver.Stub"
- extends="android.os.Binder"
- abstract="true"
- static="true"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-<implements name="android.content.pm.IPackageInstallObserver">
-</implements>
-<constructor name="IPackageInstallObserver.Stub"
- type="android.content.pm.IPackageInstallObserver.Stub"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-</constructor>
-<method name="asBinder"
- return="android.os.IBinder"
- abstract="false"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-</method>
-<method name="asInterface"
- return="android.content.pm.IPackageInstallObserver"
- abstract="false"
- native="false"
- synchronized="false"
- static="true"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-<parameter name="obj" type="android.os.IBinder">
-</parameter>
-</method>
-<method name="onTransact"
- return="boolean"
- abstract="false"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-<parameter name="code" type="int">
-</parameter>
-<parameter name="data" type="android.os.Parcel">
-</parameter>
-<parameter name="reply" type="android.os.Parcel">
-</parameter>
-<parameter name="flags" type="int">
-</parameter>
-<exception name="RemoteException" type="android.os.RemoteException">
-</exception>
-</method>
-</class>
 <class name="InstrumentationInfo"
  extends="android.content.pm.PackageItemInfo"
  abstract="false"
@@ -33540,36 +33471,6 @@
 <parameter name="appInfo" type="android.content.pm.ApplicationInfo">
 </parameter>
 </method>
-<method name="installPackage"
- return="void"
- abstract="false"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-<parameter name="packageURI" type="android.net.Uri">
-</parameter>
-<parameter name="observer" type="android.content.pm.IPackageInstallObserver">
-</parameter>
-<parameter name="flags" type="int">
-</parameter>
-</method>
-<method name="installPackage"
- return="void"
- abstract="false"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-<parameter name="packageURI" type="android.net.Uri">
-</parameter>
-</method>
 <method name="isSafeMode"
  return="boolean"
  abstract="true"
@@ -33843,17 +33744,6 @@
  visibility="public"
 >
 </field>
-<field name="FORWARD_LOCK_PACKAGE"
- type="int"
- transient="false"
- volatile="false"
- value="1"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
 <field name="GET_ACTIVITIES"
  type="int"
  transient="false"
@@ -34041,281 +33931,6 @@
  visibility="public"
 >
 </field>
-<field name="INSTALL_FAILED_ALREADY_EXISTS"
- type="int"
- transient="false"
- volatile="false"
- value="-1"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
-<field name="INSTALL_FAILED_CONFLICTING_PROVIDER"
- type="int"
- transient="false"
- volatile="false"
- value="-13"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
-<field name="INSTALL_FAILED_DEXOPT"
- type="int"
- transient="false"
- volatile="false"
- value="-11"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
-<field name="INSTALL_FAILED_DUPLICATE_PACKAGE"
- type="int"
- transient="false"
- volatile="false"
- value="-5"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
-<field name="INSTALL_FAILED_INSUFFICIENT_STORAGE"
- type="int"
- transient="false"
- volatile="false"
- value="-4"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
-<field name="INSTALL_FAILED_INVALID_APK"
- type="int"
- transient="false"
- volatile="false"
- value="-2"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
-<field name="INSTALL_FAILED_INVALID_URI"
- type="int"
- transient="false"
- volatile="false"
- value="-3"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
-<field name="INSTALL_FAILED_MISSING_SHARED_LIBRARY"
- type="int"
- transient="false"
- volatile="false"
- value="-9"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
-<field name="INSTALL_FAILED_NEWER_SDK"
- type="int"
- transient="false"
- volatile="false"
- value="-14"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
-<field name="INSTALL_FAILED_NO_SHARED_USER"
- type="int"
- transient="false"
- volatile="false"
- value="-6"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
-<field name="INSTALL_FAILED_OLDER_SDK"
- type="int"
- transient="false"
- volatile="false"
- value="-12"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
-<field name="INSTALL_FAILED_REPLACE_COULDNT_DELETE"
- type="int"
- transient="false"
- volatile="false"
- value="-10"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
-<field name="INSTALL_FAILED_SHARED_USER_INCOMPATIBLE"
- type="int"
- transient="false"
- volatile="false"
- value="-8"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
-<field name="INSTALL_FAILED_UPDATE_INCOMPATIBLE"
- type="int"
- transient="false"
- volatile="false"
- value="-7"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
-<field name="INSTALL_PARSE_FAILED_BAD_MANIFEST"
- type="int"
- transient="false"
- volatile="false"
- value="-101"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
-<field name="INSTALL_PARSE_FAILED_BAD_PACKAGE_NAME"
- type="int"
- transient="false"
- volatile="false"
- value="-106"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
-<field name="INSTALL_PARSE_FAILED_BAD_SHARED_USER_ID"
- type="int"
- transient="false"
- volatile="false"
- value="-107"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
-<field name="INSTALL_PARSE_FAILED_CERTIFICATE_ENCODING"
- type="int"
- transient="false"
- volatile="false"
- value="-105"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
-<field name="INSTALL_PARSE_FAILED_INCONSISTENT_CERTIFICATES"
- type="int"
- transient="false"
- volatile="false"
- value="-104"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
-<field name="INSTALL_PARSE_FAILED_MANIFEST_EMPTY"
- type="int"
- transient="false"
- volatile="false"
- value="-109"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
-<field name="INSTALL_PARSE_FAILED_MANIFEST_MALFORMED"
- type="int"
- transient="false"
- volatile="false"
- value="-108"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
-<field name="INSTALL_PARSE_FAILED_NOT_APK"
- type="int"
- transient="false"
- volatile="false"
- value="-100"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
-<field name="INSTALL_PARSE_FAILED_NO_CERTIFICATES"
- type="int"
- transient="false"
- volatile="false"
- value="-103"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
-<field name="INSTALL_PARSE_FAILED_UNEXPECTED_EXCEPTION"
- type="int"
- transient="false"
- volatile="false"
- value="-102"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
-<field name="INSTALL_SUCCEEDED"
- type="int"
- transient="false"
- volatile="false"
- value="1"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
 <field name="MATCH_DEFAULT_ONLY"
  type="int"
  transient="false"
@@ -34371,17 +33986,6 @@
  visibility="public"
 >
 </field>
-<field name="REPLACE_EXISTING_PACKAGE"
- type="int"
- transient="false"
- volatile="false"
- value="2"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
 <field name="SIGNATURE_FIRST_NOT_SIGNED"
  type="int"
  transient="false"
@@ -112323,25 +111927,6 @@
 <parameter name="appInfo" type="android.content.pm.ApplicationInfo">
 </parameter>
 </method>
-<method name="installPackage"
- return="void"
- abstract="false"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-<parameter name="packageURI" type="android.net.Uri">
-</parameter>
-<parameter name="observer" type="android.content.pm.IPackageInstallObserver">
-</parameter>
-<parameter name="flags" type="int">
-</parameter>
-<parameter name="installerPackageName" type="java.lang.String">
-</parameter>
-</method>
 <method name="isSafeMode"
  return="boolean"
  abstract="false"
diff --git a/cmds/pm/src/com/android/commands/pm/Pm.java b/cmds/pm/src/com/android/commands/pm/Pm.java
index ac62757..8212b92 100644
--- a/cmds/pm/src/com/android/commands/pm/Pm.java
+++ b/cmds/pm/src/com/android/commands/pm/Pm.java
@@ -540,6 +540,9 @@
         case PackageManager.INSTALL_FAILED_NEWER_SDK:
             s = "INSTALL_FAILED_NEWER_SDK";
             break;
+        case PackageManager.INSTALL_FAILED_TEST_ONLY:
+            s = "INSTALL_FAILED_TEST_ONLY";
+            break;
         case PackageManager.INSTALL_PARSE_FAILED_NOT_APK:
             s = "INSTALL_PARSE_FAILED_NOT_APK";
             break;
@@ -584,9 +587,9 @@
         String opt;
         while ((opt=nextOption()) != null) {
             if (opt.equals("-l")) {
-                installFlags |= PackageManager.FORWARD_LOCK_PACKAGE;
+                installFlags |= PackageManager.INSTALL_FORWARD_LOCK;
             } else if (opt.equals("-r")) {
-                installFlags |= PackageManager.REPLACE_EXISTING_PACKAGE;
+                installFlags |= PackageManager.INSTALL_REPLACE_EXISTING;
             } else if (opt.equals("-i")) {
                 installerPackageName = nextOptionData();
                 if (installerPackageName == null) {
@@ -594,6 +597,8 @@
                     showUsage();
                     return;
                 }
+            } else if (opt.equals("-t")) {
+                installFlags |= PackageManager.INSTALL_ALLOW_TEST;
             } else {
                 System.err.println("Error: Unknown option: " + opt);
                 showUsage();
@@ -821,38 +826,39 @@
         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] [-i INSTALLER_PACKAGE_NAME] PATH");
+        System.err.println("       pm install [-l] [-r] [-t] [-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");
         System.err.println("");
-        System.err.println("The list packages command prints all packages.  Use");
-        System.err.println("the -f option to see their associated file.");
+        System.err.println("The list packages command prints all packages.  Options:");
+        System.err.println("  -f: see their associated file.");
         System.err.println("");
         System.err.println("The list permission-groups command prints all known");
         System.err.println("permission groups.");
         System.err.println("");
         System.err.println("The list permissions command prints all known");
-        System.err.println("permissions, optionally only those in GROUP.  Use");
-        System.err.println("the -g option to organize by group.  Use");
-        System.err.println("the -f option to print all information.  Use");
-        System.err.println("the -s option for a short summary.  Use");
-        System.err.println("the -d option to only list dangerous permissions.  Use");
-        System.err.println("the -u option to list only the permissions users will see.");
+        System.err.println("permissions, optionally only those in GROUP.  Options:");
+        System.err.println("  -g: organize by group.");
+        System.err.println("  -f: print all information.");
+        System.err.println("  -s: short summary.");
+        System.err.println("  -d: only list dangerous permissions.");
+        System.err.println("  -u: list only the permissions users will see.");
         System.err.println("");
         System.err.println("The list instrumentation command prints all instrumentations,");
-        System.err.println("or only those that target a specified package.  Use the -f option");
-        System.err.println("to see their associated file.");
+        System.err.println("or only those that target a specified package.  Options:");
+        System.err.println("  -f: see their associated file.");
         System.err.println("");
         System.err.println("The path command prints the path to the .apk of a package.");
         System.err.println("");
-        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("The install command installs a package to the system.  Options:");
+        System.err.println("  -l: install the package with FORWARD_LOCK.");
+        System.err.println("  -r: reinstall an exisiting app, keeping its data.");
+        System.err.println("  -t: allow test .apks to be installed.");
+        System.err.println("  -i: 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");
+        System.err.println("The uninstall command removes a package from the system. Options:");
+        System.err.println("  -k: keep the data and cache directories around.");
         System.err.println("after the package removal.");
         System.err.println("");
         System.err.println("The enable and disable commands change the enabled state of");
diff --git a/core/java/android/content/pm/ApplicationInfo.java b/core/java/android/content/pm/ApplicationInfo.java
index fa9ec6e..88ac04c 100644
--- a/core/java/android/content/pm/ApplicationInfo.java
+++ b/core/java/android/content/pm/ApplicationInfo.java
@@ -126,6 +126,12 @@
     public static final int FLAG_TARGETS_SDK = 1<<8;
 
     /**
+     * Value for {@link #flags}: this is set of the application has set
+     * its android:targetSdkVersion to something >= the current SDK version.
+     */
+    public static final int FLAG_TEST_ONLY = 1<<9;
+
+    /**
      * Flags associated with the application.  Any combination of
      * {@link #FLAG_SYSTEM}, {@link #FLAG_DEBUGGABLE}, {@link #FLAG_HAS_CODE},
      * {@link #FLAG_PERSISTENT}, {@link #FLAG_FACTORY_TEST}, and
diff --git a/core/java/android/content/pm/IPackageInstallObserver.aidl b/core/java/android/content/pm/IPackageInstallObserver.aidl
index e83bbc6..6133365 100644
--- a/core/java/android/content/pm/IPackageInstallObserver.aidl
+++ b/core/java/android/content/pm/IPackageInstallObserver.aidl
@@ -19,7 +19,7 @@
 
 /**
  * API for installation callbacks from the Package Manager.
- *
+ * @hide
  */
 oneway interface IPackageInstallObserver {
     void packageInstalled(in String packageName, int returnCode);
diff --git a/core/java/android/content/pm/PackageManager.java b/core/java/android/content/pm/PackageManager.java
index 3695516..3a192f7 100644
--- a/core/java/android/content/pm/PackageManager.java
+++ b/core/java/android/content/pm/PackageManager.java
@@ -235,14 +235,24 @@
      * Flag parameter for {@link #installPackage(android.net.Uri, IPackageInstallObserver, int)} to
      * indicate that this package should be installed as forward locked, i.e. only the app itself
      * should have access to it's code and non-resource assets.
+     * @hide
      */
-    public static final int FORWARD_LOCK_PACKAGE = 0x00000001;
+    public static final int INSTALL_FORWARD_LOCK = 0x00000001;
 
     /**
      * Flag parameter for {@link #installPackage} to indicate that you want to replace an already
-     * installed package, if one exists
+     * installed package, if one exists.
+     * @hide
      */
-    public static final int REPLACE_EXISTING_PACKAGE = 0x00000002;
+    public static final int INSTALL_REPLACE_EXISTING = 0x00000002;
+
+    /**
+     * Flag parameter for {@link #installPackage} to indicate that you want to 
+     * allow test packages (those that have set android:testOnly in their
+     * manifest) to be installed.
+     * @hide
+     */
+    public static final int INSTALL_ALLOW_TEST = 0x00000004;
 
     /**
      * Flag parameter for
@@ -255,6 +265,7 @@
     /**
      * Installation return code: this is passed to the {@link IPackageInstallObserver} by
      * {@link #installPackage(android.net.Uri, IPackageInstallObserver, int)} on success.
+     * @hide
      */
     public static final int INSTALL_SUCCEEDED = 1;
 
@@ -262,6 +273,7 @@
      * Installation return code: this is passed to the {@link IPackageInstallObserver} by
      * {@link #installPackage(android.net.Uri, IPackageInstallObserver, int)} if the package is
      * already installed.
+     * @hide
      */
     public static final int INSTALL_FAILED_ALREADY_EXISTS = -1;
 
@@ -269,6 +281,7 @@
      * Installation return code: this is passed to the {@link IPackageInstallObserver} by
      * {@link #installPackage(android.net.Uri, IPackageInstallObserver, int)} if the package archive
      * file is invalid.
+     * @hide
      */
     public static final int INSTALL_FAILED_INVALID_APK = -2;
 
@@ -276,13 +289,15 @@
      * Installation return code: this is passed to the {@link IPackageInstallObserver} by
      * {@link #installPackage(android.net.Uri, IPackageInstallObserver, int)} if the URI passed in
      * is invalid.
+     * @hide
      */
     public static final int INSTALL_FAILED_INVALID_URI = -3;
 
     /**
      * Installation return code: this is passed to the {@link IPackageInstallObserver} by
      * {@link #installPackage(android.net.Uri, IPackageInstallObserver, int)} if the package manager
-     * service found that the device didn't have enough storage space to install the app
+     * service found that the device didn't have enough storage space to install the app.
+     * @hide
      */
     public static final int INSTALL_FAILED_INSUFFICIENT_STORAGE = -4;
 
@@ -290,6 +305,7 @@
      * Installation return code: this is passed to the {@link IPackageInstallObserver} by
      * {@link #installPackage(android.net.Uri, IPackageInstallObserver, int)} if a
      * package is already installed with the same name.
+     * @hide
      */
     public static final int INSTALL_FAILED_DUPLICATE_PACKAGE = -5;
 
@@ -297,6 +313,7 @@
      * Installation return code: this is passed to the {@link IPackageInstallObserver} by
      * {@link #installPackage(android.net.Uri, IPackageInstallObserver, int)} if
      * the requested shared user does not exist.
+     * @hide
      */
     public static final int INSTALL_FAILED_NO_SHARED_USER = -6;
 
@@ -305,6 +322,7 @@
      * {@link #installPackage(android.net.Uri, IPackageInstallObserver, int)} if
      * a previously installed package of the same name has a different signature
      * than the new package (and the old package's data was not removed).
+     * @hide
      */
     public static final int INSTALL_FAILED_UPDATE_INCOMPATIBLE = -7;
 
@@ -313,6 +331,7 @@
      * {@link #installPackage(android.net.Uri, IPackageInstallObserver, int)} if
      * the new package is requested a shared user which is already installed on the
      * device and does not have matching signature.
+     * @hide
      */
     public static final int INSTALL_FAILED_SHARED_USER_INCOMPATIBLE = -8;
 
@@ -320,6 +339,7 @@
      * Installation return code: this is passed to the {@link IPackageInstallObserver} by
      * {@link #installPackage(android.net.Uri, IPackageInstallObserver, int)} if
      * the new package uses a shared library that is not available.
+     * @hide
      */
     public static final int INSTALL_FAILED_MISSING_SHARED_LIBRARY = -9;
 
@@ -327,6 +347,7 @@
      * Installation return code: this is passed to the {@link IPackageInstallObserver} by
      * {@link #installPackage(android.net.Uri, IPackageInstallObserver, int)} if
      * the new package uses a shared library that is not available.
+     * @hide
      */
     public static final int INSTALL_FAILED_REPLACE_COULDNT_DELETE = -10;
 
@@ -335,6 +356,7 @@
      * {@link #installPackage(android.net.Uri, IPackageInstallObserver, int)} if
      * the new package failed while optimizing and validating its dex files,
      * either because there was not enough storage or the validation failed.
+     * @hide
      */
     public static final int INSTALL_FAILED_DEXOPT = -11;
 
@@ -343,6 +365,7 @@
      * {@link #installPackage(android.net.Uri, IPackageInstallObserver, int)} if
      * the new package failed because the current SDK version is older than
      * that required by the package.
+     * @hide
      */
     public static final int INSTALL_FAILED_OLDER_SDK = -12;
 
@@ -351,6 +374,7 @@
      * {@link #installPackage(android.net.Uri, IPackageInstallObserver, int)} if
      * the new package failed because it contains a content provider with the
      * same authority as a provider already installed in the system.
+     * @hide
      */
     public static final int INSTALL_FAILED_CONFLICTING_PROVIDER = -13;
 
@@ -359,14 +383,26 @@
      * {@link #installPackage(android.net.Uri, IPackageInstallObserver, int)} if
      * the new package failed because the current SDK version is newer than
      * that required by the package.
+     * @hide
      */
     public static final int INSTALL_FAILED_NEWER_SDK = -14;
 
     /**
+     * Installation return code: this is passed to the {@link IPackageInstallObserver} by
+     * {@link #installPackage(android.net.Uri, IPackageInstallObserver, int)} if
+     * the new package failed because it has specified that it is a test-only
+     * package and the caller has not supplied the {@link #INSTALL_ALLOW_TEST}
+     * flag.
+     * @hide
+     */
+    public static final int INSTALL_FAILED_TEST_ONLY = -15;
+
+    /**
      * Installation parse return code: this is passed to the {@link IPackageInstallObserver} by
      * {@link #installPackage(android.net.Uri, IPackageInstallObserver, int)}
      * if the parser was given a path that is not a file, or does not end with the expected
      * '.apk' extension.
+     * @hide
      */
     public static final int INSTALL_PARSE_FAILED_NOT_APK = -100;
 
@@ -374,6 +410,7 @@
      * Installation parse return code: this is passed to the {@link IPackageInstallObserver} by
      * {@link #installPackage(android.net.Uri, IPackageInstallObserver, int)}
      * if the parser was unable to retrieve the AndroidManifest.xml file.
+     * @hide
      */
     public static final int INSTALL_PARSE_FAILED_BAD_MANIFEST = -101;
 
@@ -381,6 +418,7 @@
      * Installation parse return code: this is passed to the {@link IPackageInstallObserver} by
      * {@link #installPackage(android.net.Uri, IPackageInstallObserver, int)}
      * if the parser encountered an unexpected exception.
+     * @hide
      */
     public static final int INSTALL_PARSE_FAILED_UNEXPECTED_EXCEPTION = -102;
 
@@ -388,6 +426,7 @@
      * Installation parse return code: this is passed to the {@link IPackageInstallObserver} by
      * {@link #installPackage(android.net.Uri, IPackageInstallObserver, int)}
      * if the parser did not find any certificates in the .apk.
+     * @hide
      */
     public static final int INSTALL_PARSE_FAILED_NO_CERTIFICATES = -103;
 
@@ -395,6 +434,7 @@
      * Installation parse return code: this is passed to the {@link IPackageInstallObserver} by
      * {@link #installPackage(android.net.Uri, IPackageInstallObserver, int)}
      * if the parser found inconsistent certificates on the files in the .apk.
+     * @hide
      */
     public static final int INSTALL_PARSE_FAILED_INCONSISTENT_CERTIFICATES = -104;
 
@@ -403,6 +443,7 @@
      * {@link #installPackage(android.net.Uri, IPackageInstallObserver, int)}
      * if the parser encountered a CertificateEncodingException in one of the
      * files in the .apk.
+     * @hide
      */
     public static final int INSTALL_PARSE_FAILED_CERTIFICATE_ENCODING = -105;
 
@@ -410,6 +451,7 @@
      * Installation parse return code: this is passed to the {@link IPackageInstallObserver} by
      * {@link #installPackage(android.net.Uri, IPackageInstallObserver, int)}
      * if the parser encountered a bad or missing package name in the manifest.
+     * @hide
      */
     public static final int INSTALL_PARSE_FAILED_BAD_PACKAGE_NAME = -106;
 
@@ -417,6 +459,7 @@
      * Installation parse return code: this is passed to the {@link IPackageInstallObserver} by
      * {@link #installPackage(android.net.Uri, IPackageInstallObserver, int)}
      * if the parser encountered a bad shared user id name in the manifest.
+     * @hide
      */
     public static final int INSTALL_PARSE_FAILED_BAD_SHARED_USER_ID = -107;
 
@@ -424,6 +467,7 @@
      * Installation parse return code: this is passed to the {@link IPackageInstallObserver} by
      * {@link #installPackage(android.net.Uri, IPackageInstallObserver, int)}
      * if the parser encountered some structural problem in the manifest.
+     * @hide
      */
     public static final int INSTALL_PARSE_FAILED_MANIFEST_MALFORMED = -108;
 
@@ -432,6 +476,7 @@
      * {@link #installPackage(android.net.Uri, IPackageInstallObserver, int)}
      * if the parser did not find any actionable tags (instrumentation or application)
      * in the manifest.
+     * @hide
      */
     public static final int INSTALL_PARSE_FAILED_MANIFEST_EMPTY = -109;
 
@@ -1338,6 +1383,8 @@
     }
 
     /**
+     * @hide
+     * 
      * 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
@@ -1349,36 +1396,10 @@
      * @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}
-     *
-     * @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 flags - possible values: {@link #INSTALL_FORWARD_LOCK},
+     * {@link #INSTALL_REPLACE_EXISTING}, {@link #INSTALL_ALLOW_TEST}.
      * @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,
@@ -1517,17 +1538,6 @@
             IPackageStatsObserver observer);
 
     /**
-     * Install a package.
-     *
-     * @param packageURI The location of the package file to install
-     *
-     * @see #installPackage(android.net.Uri, IPackageInstallObserver, int, String)
-     */
-    public void installPackage(Uri packageURI) {
-        installPackage(packageURI, null, 0);
-    }
-
-    /**
      * Add a new package to the list of preferred packages.  This new package
      * will be added to the front of the list (removed from its current location
      * if already listed), meaning it will now be preferred over all other
diff --git a/core/java/android/content/pm/PackageParser.java b/core/java/android/content/pm/PackageParser.java
index 12df5bd..a1c0f48 100644
--- a/core/java/android/content/pm/PackageParser.java
+++ b/core/java/android/content/pm/PackageParser.java
@@ -1187,6 +1187,12 @@
             ai.flags |= ApplicationInfo.FLAG_ALLOW_CLEAR_USER_DATA;
         }
 
+        if (sa.getBoolean(
+                com.android.internal.R.styleable.AndroidManifestApplication_testOnly,
+                true)) {
+            ai.flags |= ApplicationInfo.FLAG_TEST_ONLY;
+        }
+
         String str;
         str = sa.getNonResourceString(
                 com.android.internal.R.styleable.AndroidManifestApplication_permission);
diff --git a/core/res/res/values/attrs_manifest.xml b/core/res/res/values/attrs_manifest.xml
index 1319c77..7b48267 100644
--- a/core/res/res/values/attrs_manifest.xml
+++ b/core/res/res/values/attrs_manifest.xml
@@ -79,6 +79,13 @@
          by applications. -->
     <attr name="allowClearUserData" format="boolean" />
     
+    <!-- Option to indicate this application is only for testing purposes.
+         For example, it may expose functionality or data outside of itself
+         that would cause a security hole, but is useful for testing.  This
+         kind of application can not be installed without the
+         INSTALL_ALLOW_TEST flag, which means only through adb install.  -->
+    <attr name="testOnly" format="boolean" />
+    
     <!-- A unique name for the given item.  This must use a Java-style naming
          convention to ensure the name is unique, for example
          "com.mycompany.MyName". -->  
@@ -635,6 +642,7 @@
         <!-- Name of activity to be launched for managing the application's space on the device. -->
         <attr name="manageSpaceActivity" />
         <attr name="allowClearUserData" />
+        <attr name="testOnly" />
     </declare-styleable>
     
     <!-- The <code>permission</code> tag declares a security permission that can be
diff --git a/core/res/res/values/public.xml b/core/res/res/values/public.xml
index df5d879..f90c6b8 100644
--- a/core/res/res/values/public.xml
+++ b/core/res/res/values/public.xml
@@ -1099,6 +1099,7 @@
    <public type="attr" name="onClick" id="0x0101026f" />
    <public type="attr" name="targetSdkVersion" id="0x01010270" />
    <public type="attr" name="maxSdkVersion" id="0x01010271" />
+   <public type="attr" name="testOnly" id="0x01010272" />
 
    <public type="anim" name="anticipate_interpolator" id="0x010a0007" />
    <public type="anim" name="overshoot_interpolator" id="0x010a0008" />
diff --git a/services/java/com/android/server/PackageManagerService.java b/services/java/com/android/server/PackageManagerService.java
index b17a941..4ee0c91 100644
--- a/services/java/com/android/server/PackageManagerService.java
+++ b/services/java/com/android/server/PackageManagerService.java
@@ -3396,7 +3396,7 @@
             oldInstallerPackageName = mSettings.getInstallerPackageName(pkgName);
         }
         
-        int parseFlags = PackageManager.REPLACE_EXISTING_PACKAGE;
+        int parseFlags = PackageManager.INSTALL_REPLACE_EXISTING;
         // First delete the existing package while retaining the data directory
         if (!deletePackageLI(pkgName, false, PackageManager.DONT_DELETE_DATA,
                 res.removedInfo)) {
@@ -3468,7 +3468,7 @@
                 installPackageLI(
                         Uri.fromFile(new File(deletedPackage.mPath)),
                         isForwardLocked(deletedPackage)
-                        ? PackageManager.FORWARD_LOCK_PACKAGE
+                        ? PackageManager.INSTALL_FORWARD_LOCK
                                 : 0, false, oldInstallerPackageName);
             }
         }
@@ -3481,7 +3481,7 @@
             String installerPackageName, PackageInstalledInfo res) {
         PackageParser.Package newPackage = null;
         boolean updatedSettings = false;
-        int parseFlags = PackageManager.REPLACE_EXISTING_PACKAGE |
+        int parseFlags = PackageManager.INSTALL_REPLACE_EXISTING |
                 PackageParser.PARSE_IS_SYSTEM;
         String packageName = deletedPackage.packageName;
         res.returnCode = PackageManager.INSTALL_FAILED_REPLACE_COULDNT_DELETE;
@@ -3697,13 +3697,13 @@
             res.name = pkgName;
             //initialize some variables before installing pkg
             final String pkgFileName = pkgName + ".apk";
-            final File destDir = ((pFlags&PackageManager.FORWARD_LOCK_PACKAGE) != 0)
+            final File destDir = ((pFlags&PackageManager.INSTALL_FORWARD_LOCK) != 0)
                                  ?  mDrmAppPrivateInstallDir
                                  : mAppInstallDir;
             final File destPackageFile = new File(destDir, pkgFileName);
             final String destFilePath = destPackageFile.getAbsolutePath();
             File destResourceFile;
-            if ((pFlags&PackageManager.FORWARD_LOCK_PACKAGE) != 0) {
+            if ((pFlags&PackageManager.INSTALL_FORWARD_LOCK) != 0) {
                 final String publicZipFileName = pkgName + ".zip";
                 destResourceFile = new File(mAppInstallDir, publicZipFileName);
                 forwardLocked = true;
@@ -3722,6 +3722,12 @@
                 res.returnCode = pp.getParseError();
                 break main_flow;
             }
+            if ((pkg.applicationInfo.flags&ApplicationInfo.FLAG_TEST_ONLY) != 0) {
+                if ((pFlags&PackageManager.INSTALL_ALLOW_TEST) == 0) {
+                    res.returnCode = PackageManager.INSTALL_FAILED_TEST_ONLY;
+                    break main_flow;
+                }
+            }
             if (GET_CERTIFICATES && !pp.collectCertificates(pkg, parseFlags)) {
                 res.returnCode = pp.getParseError();
                 break main_flow;
@@ -3729,7 +3735,7 @@
             
             synchronized (mPackages) {
                 //check if installing already existing package
-                if ((pFlags&PackageManager.REPLACE_EXISTING_PACKAGE) != 0
+                if ((pFlags&PackageManager.INSTALL_REPLACE_EXISTING) != 0
                         && mPackages.containsKey(pkgName)) {
                     replacingExistingPackage = true;
                 }
diff --git a/test-runner/android/test/mock/MockPackageManager.java b/test-runner/android/test/mock/MockPackageManager.java
index 4769057..bf1629f 100644
--- a/test-runner/android/test/mock/MockPackageManager.java
+++ b/test-runner/android/test/mock/MockPackageManager.java
@@ -284,6 +284,9 @@
         throw new UnsupportedOperationException();
     }
 
+    /**
+     * @hide - to match hiding in superclass
+     */
     @Override
     public void installPackage(Uri packageURI, IPackageInstallObserver observer,
             int flags, String installerPackageName) {
@@ -399,11 +402,6 @@
     }
 
     @Override
-    public void installPackage(Uri packageURI) {
-        throw new UnsupportedOperationException();
-    }
-
-    @Override
     public int getPreferredActivities(List<IntentFilter> outFilters,
             List<ComponentName> outActivities, String packageName) {
         throw new UnsupportedOperationException();