Enforce permissions for PhoneStateListener events.

PhoneStateListener events like LISTEN_CALL_STATE_CHANGED,
have privacy information like phone numbers and hence,
need to be protected with a permission. The permission
READ_PHONE_STATE is used for this purpose. Use the permission
trick to ensure backward compatability.
diff --git a/core/java/android/content/pm/PackageParser.java b/core/java/android/content/pm/PackageParser.java
index 78462f1..ee20aee 100644
--- a/core/java/android/content/pm/PackageParser.java
+++ b/core/java/android/content/pm/PackageParser.java
@@ -74,10 +74,12 @@
      * added to older SDKs appearing before those added to newer SDKs.
      * @hide
      */
-    public static final PackageParser.NewPermissionInfo NEW_PERMISSIONS[] = new PackageParser.NewPermissionInfo[] {
-        new PackageParser.NewPermissionInfo(android.Manifest.permission.WRITE_SDCARD,
-                android.os.Build.VERSION_CODES.DONUT,
-                0)
+    public static final PackageParser.NewPermissionInfo NEW_PERMISSIONS[] =
+        new PackageParser.NewPermissionInfo[] {
+            new PackageParser.NewPermissionInfo(android.Manifest.permission.WRITE_SDCARD,
+                    android.os.Build.VERSION_CODES.DONUT, 0),
+            new PackageParser.NewPermissionInfo(android.Manifest.permission.READ_PHONE_STATE,
+                    android.os.Build.VERSION_CODES.DONUT, 0)
     };
 
     private String mArchiveSourcePath;
diff --git a/services/java/com/android/server/TelephonyRegistry.java b/services/java/com/android/server/TelephonyRegistry.java
index 88f47fd..b601ece 100644
--- a/services/java/com/android/server/TelephonyRegistry.java
+++ b/services/java/com/android/server/TelephonyRegistry.java
@@ -92,6 +92,13 @@
 
     private Bundle mCellLocation = new Bundle();
 
+    static final int PHONE_STATE_PERMISSION_MASK =
+                PhoneStateListener.LISTEN_CALL_FORWARDING_INDICATOR |
+                PhoneStateListener.LISTEN_CALL_STATE |
+                PhoneStateListener.LISTEN_DATA_ACTIVITY |
+                PhoneStateListener.LISTEN_DATA_CONNECTION_STATE |
+                PhoneStateListener.LISTEN_MESSAGE_WAITING_INDICATOR;
+
     // we keep a copy of all of the state so we can send it out when folks
     // register for it
     //
@@ -110,16 +117,8 @@
         // Log.d(TAG, "listen pkg=" + pkgForDebug + " events=0x" +
         // Integer.toHexString(events));
         if (events != 0) {
-            // check permissions
-            if ((events & PhoneStateListener.LISTEN_CELL_LOCATION) != 0) {
-                // ACCESS_FINE_LOCATION implies ACCESS_COARSE_LOCATION
-                if (mContext.checkCallingPermission(
-                        android.Manifest.permission.ACCESS_FINE_LOCATION)
-                        != PackageManager.PERMISSION_GRANTED) {
-                    mContext.enforceCallingOrSelfPermission(
-                            android.Manifest.permission.ACCESS_COARSE_LOCATION, null);
-                }
-            }
+            /* Checks permission and throws Security exception */
+            checkListenerPermission(events);
 
             synchronized (mRecords) {
                 // register
@@ -219,7 +218,7 @@
     }
 
     public void notifyCallState(int state, String incomingNumber) {
-        if (!checkPhoneStatePermission("notifyCallState()")) {
+        if (!checkNotifyPermission("notifyCallState()")) {
             return;
         }
         synchronized (mRecords) {
@@ -240,7 +239,7 @@
     }
 
     public void notifyServiceState(ServiceState state) {
-        if (!checkPhoneStatePermission("notifyServiceState()")) {
+        if (!checkNotifyPermission("notifyServiceState()")){
             return;
         }
         synchronized (mRecords) {
@@ -256,7 +255,7 @@
     }
 
     public void notifySignalStrength(SignalStrength signalStrength) {
-        if (!checkPhoneStatePermission("notifySignalStrength()")) {
+        if (!checkNotifyPermission("notifySignalStrength()")) {
             return;
         }
         synchronized (mRecords) {
@@ -281,7 +280,7 @@
     }
 
     public void notifyMessageWaitingChanged(boolean mwi) {
-        if (!checkPhoneStatePermission("notifyMessageWaitingChanged()")) {
+        if (!checkNotifyPermission("notifyMessageWaitingChanged()")) {
             return;
         }
         synchronized (mRecords) {
@@ -300,7 +299,7 @@
     }
 
     public void notifyCallForwardingChanged(boolean cfi) {
-        if (!checkPhoneStatePermission("notifyCallForwardingChanged()")) {
+        if (!checkNotifyPermission("notifyCallForwardingChanged()")) {
             return;
         }
         synchronized (mRecords) {
@@ -319,7 +318,7 @@
     }
 
     public void notifyDataActivity(int state) {
-        if (!checkPhoneStatePermission("notifyDataActivity()")) {
+        if (!checkNotifyPermission("notifyDataActivity()" )) {
             return;
         }
         synchronized (mRecords) {
@@ -337,9 +336,9 @@
         }
     }
 
-    public void notifyDataConnection(int state, boolean isDataConnectivityPossible, String reason,
-            String apn, String interfaceName) {
-        if (!checkPhoneStatePermission("notifyDataConnection()")) {
+    public void notifyDataConnection(int state, boolean isDataConnectivityPossible,
+            String reason, String apn, String interfaceName) {
+        if (!checkNotifyPermission("notifyDataConnection()" )) {
             return;
         }
         synchronized (mRecords) {
@@ -364,7 +363,7 @@
     }
 
     public void notifyDataConnectionFailed(String reason) {
-        if (!checkPhoneStatePermission("notifyDataConnectionFailed()")) {
+        if (!checkNotifyPermission("notifyDataConnectionFailed()")) {
             return;
         }
         /*
@@ -385,7 +384,7 @@
     }
 
     public void notifyCellLocation(Bundle cellLocation) {
-        if (!checkPhoneStatePermission("notifyCellLocation()")) {
+        if (!checkNotifyPermission("notifyCellLocation()")) {
             return;
         }
         synchronized (mRecords) {
@@ -402,7 +401,7 @@
     /**
      * Copy the service state object so they can't mess it up in the local calls
      */
-    private void sendServiceState(Record r, ServiceState state) {
+    public void sendServiceState(Record r, ServiceState state) {
         try {
             r.callback.onServiceStateChanged(new ServiceState(state));
         } catch (RemoteException ex) {
@@ -533,7 +532,7 @@
         mContext.sendStickyBroadcast(intent);
     }
 
-    private boolean checkPhoneStatePermission(String method) {
+    private boolean checkNotifyPermission(String method) {
         if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.MODIFY_PHONE_STATE)
                 == PackageManager.PERMISSION_GRANTED) {
             return true;
@@ -543,4 +542,17 @@
         Log.w(TAG, msg);
         return false;
     }
+
+    private void checkListenerPermission(int events) {
+        if ((events & PhoneStateListener.LISTEN_CELL_LOCATION) != 0) {
+            mContext.enforceCallingOrSelfPermission(
+                    android.Manifest.permission.ACCESS_COARSE_LOCATION, null);
+
+        }
+
+        if ((events & PHONE_STATE_PERMISSION_MASK) != 0) {
+            mContext.enforceCallingOrSelfPermission(
+                    android.Manifest.permission.READ_PHONE_STATE, null);
+        }
+    }
 }
diff --git a/telephony/java/android/telephony/PhoneStateListener.java b/telephony/java/android/telephony/PhoneStateListener.java
index 8abafae..e113680 100644
--- a/telephony/java/android/telephony/PhoneStateListener.java
+++ b/telephony/java/android/telephony/PhoneStateListener.java
@@ -42,6 +42,9 @@
 
     /**
      * Listen for changes to the network signal strength (cellular).
+     * {@more}
+     * Requires Permission: {@link android.Manifest.permission#READ_PHONE_STATE
+     * READ_PHONE_STATE}
      * <p>
      *
      * @see #onSignalStrengthChanged
@@ -52,6 +55,9 @@
 
     /**
      * Listen for changes to the message-waiting indicator.
+     * {@more}
+     * Requires Permission: {@link android.Manifest.permission#READ_PHONE_STATE
+     * READ_PHONE_STATE}
      * <p>
      * Example: The status bar uses this to determine when to display the
      * voicemail icon.
@@ -62,7 +68,9 @@
 
     /**
      * Listen for changes to the call-forwarding indicator.
-     *
+     * {@more}
+     * Requires Permission: {@link android.Manifest.permission#READ_PHONE_STATE
+     * READ_PHONE_STATE}
      * @see #onCallForwardingIndicatorChanged
      */
     public static final int LISTEN_CALL_FORWARDING_INDICATOR                = 0x00000008;
@@ -85,7 +93,9 @@
 
     /**
      * Listen for changes to the device call state.
-     *
+     * {@more}
+     * Requires Permission: {@link android.Manifest.permission#READ_PHONE_STATE
+     * READ_PHONE_STATE}
      * @see #onCallStateChanged
      */
     public static final int LISTEN_CALL_STATE                               = 0x00000020;
@@ -100,7 +110,9 @@
     /**
      * Listen for changes to the direction of data traffic on the data
      * connection (cellular).
-     *
+     * {@more}
+     * Requires Permission: {@link android.Manifest.permission#READ_PHONE_STATE
+     * READ_PHONE_STATE}
      * Example: The status bar uses this to display the appropriate
      * data-traffic icon.
      *