Fix issue #9074296: Device Admins can activate in a way...

...that makes it impossible to deactive/uninstall them

Don't allow device admins to directly launch the add UI if
they are malformed.

(cherry picked from commit 8274b6770219a469ab8a5254206d0d81bd5c96d3)

Changes due to make the cherry-pick apply:
* Replaced PackageManager.GET_DISABLED_UNTIL_USED_COMPONENTS with 0
  in the PackageManager.queryBroadcastReceivers invocation. The above
  constant was introduced in API Level 18 only. DeviceAdminSettings
  class from which this fix was extracted is not passing in the above
  flag when it invokes queryBroadcastReceivers either.

Change-Id: I64d2792cd06bacbd4bfc600a10046d51a9383606
diff --git a/src/com/android/settings/DeviceAdminAdd.java b/src/com/android/settings/DeviceAdminAdd.java
index b2145b0..c0d615c 100644
--- a/src/com/android/settings/DeviceAdminAdd.java
+++ b/src/com/android/settings/DeviceAdminAdd.java
@@ -50,6 +50,8 @@
 
 import java.io.IOException;
 import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.List;
 
 public class DeviceAdminAdd extends Activity {
     static final String TAG = "DeviceAdminAdd";
@@ -104,7 +106,7 @@
             finish();
             return;
         }
-        
+
         ActivityInfo ai;
         try {
             ai = getPackageManager().getReceiverInfo(cn, PackageManager.GET_META_DATA);
@@ -113,7 +115,37 @@
             finish();
             return;
         }
-        
+
+        // Make sure the given component name is actually a valid device admin.
+        List<ResolveInfo> avail = getPackageManager().queryBroadcastReceivers(
+                new Intent(DeviceAdminReceiver.ACTION_DEVICE_ADMIN_ENABLED),
+                0);
+        int count = avail == null ? 0 : avail.size();
+        boolean found = false;
+        for (int i=0; i<count; i++) {
+            ResolveInfo ri = avail.get(i);
+            if (ai.packageName.equals(ri.activityInfo.packageName)
+                    && ai.name.equals(ri.activityInfo.name)) {
+                try {
+                    // We didn't retrieve the meta data for all possible matches, so
+                    // need to use the activity info of this specific one that was retrieved.
+                    ri.activityInfo = ai;
+                    DeviceAdminInfo dpi = new DeviceAdminInfo(this, ri);
+                    found = true;
+                } catch (XmlPullParserException e) {
+                    Log.w(TAG, "Bad " + ri.activityInfo, e);
+                } catch (IOException e) {
+                    Log.w(TAG, "Bad " + ri.activityInfo, e);
+                }
+                break;
+            }
+        }
+        if (!found) {
+            Log.w(TAG, "Request to add invalid device admin: " + cn);
+            finish();
+            return;
+        }
+
         ResolveInfo ri = new ResolveInfo();
         ri.activityInfo = ai;
         try {