Allow setting photos in managed profile

Bug: 20628786
Change-Id: I42bc27574d40b7725e64743961c250a5682f66f7
diff --git a/res/values/strings.xml b/res/values/strings.xml
index 8ebf1fc..1fc144a 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -275,6 +275,9 @@
     <!-- Toast displayed when saving a contact failed. [CHAR LIMIT=NONE] -->
     <string name="contactSavedErrorToast">Couldn\'t save contact changes.</string>
 
+    <!-- Toast displayed when saving a contact photo failed. [CHAR LIMIT=NONE] -->
+    <string name="contactPhotoSavedErrorToast">Couldn\'t save contact photo changes.</string>
+
     <!-- Toast displayed when a group is saved [CHAR LIMIT=NONE] -->
     <string name="groupSavedToast">Group saved.</string>
 
diff --git a/src/com/android/contacts/activities/AttachPhotoActivity.java b/src/com/android/contacts/activities/AttachPhotoActivity.java
index 5573123..cf3bfc8 100644
--- a/src/com/android/contacts/activities/AttachPhotoActivity.java
+++ b/src/com/android/contacts/activities/AttachPhotoActivity.java
@@ -23,6 +23,8 @@
 import android.content.Intent;
 import android.content.Loader;
 import android.content.Loader.OnLoadCompleteListener;
+import android.content.pm.PackageManager;
+import android.content.pm.ResolveInfo;
 import android.database.Cursor;
 import android.graphics.Bitmap;
 import android.net.Uri;
@@ -52,6 +54,7 @@
 import com.android.contacts.util.ContactPhotoUtils;
 
 import java.io.FileNotFoundException;
+import java.util.List;
 
 /**
  * Provides an external interface for other applications to attach images
@@ -167,7 +170,7 @@
             final Intent myIntent = getIntent();
             final Uri inputUri = myIntent.getData();
 
-            final Uri toCrop;
+
             // Save the URI into a temporary file provider URI so that
             // we can add the FLAG_GRANT_WRITE_URI_PERMISSION flag to the eventual
             // crop intent for read-only URI's.
@@ -176,14 +179,26 @@
                 finish();
                 return;
             }
-            toCrop = mTempPhotoUri;
 
-            final Intent intent = new Intent("com.android.camera.action.CROP", toCrop);
+            final Intent intent = new Intent("com.android.camera.action.CROP", mTempPhotoUri);
             if (myIntent.getStringExtra("mimeType") != null) {
-                intent.setDataAndType(toCrop, myIntent.getStringExtra("mimeType"));
+                intent.setDataAndType(mTempPhotoUri, myIntent.getStringExtra("mimeType"));
             }
             ContactPhotoUtils.addPhotoPickerExtras(intent, mCroppedPhotoUri);
             ContactPhotoUtils.addCropExtras(intent, mPhotoDim != 0 ? mPhotoDim : mDefaultPhotoDim);
+            if (!hasIntentHandler(intent)) {
+                // No activity supports the crop action. So skip cropping and set the photo
+                // without performing any cropping.
+                mCroppedPhotoUri = mTempPhotoUri;
+                mContactUri = result.getData();
+                loadContact(mContactUri, new Listener() {
+                    @Override
+                    public void onContactLoaded(Contact contact) {
+                        saveContact(contact);
+                    }
+                });
+                return;
+            }
 
             try {
                 startActivityForResult(intent, REQUEST_CROP_PHOTO);
@@ -211,6 +226,12 @@
         }
     }
 
+    private boolean hasIntentHandler(Intent intent) {
+        final List<ResolveInfo> resolveInfo = getPackageManager()
+                .queryIntentActivities(intent, PackageManager.MATCH_DEFAULT_ONLY);
+        return resolveInfo != null && resolveInfo.size() > 0;
+    }
+
     // TODO: consider moving this to ContactLoader, especially if we keep adding similar
     // code elsewhere (ViewNotificationService is another case).  The only concern is that,
     // although this is convenient, it isn't quite as robust as using LoaderManager... for
diff --git a/src/com/android/contacts/detail/PhotoSelectionHandler.java b/src/com/android/contacts/detail/PhotoSelectionHandler.java
index 8b9a381..405bbfc 100644
--- a/src/com/android/contacts/detail/PhotoSelectionHandler.java
+++ b/src/com/android/contacts/detail/PhotoSelectionHandler.java
@@ -21,6 +21,8 @@
 import android.content.ContentValues;
 import android.content.Context;
 import android.content.Intent;
+import android.content.pm.PackageManager;
+import android.content.pm.ResolveInfo;
 import android.database.Cursor;
 import android.net.Uri;
 import android.provider.ContactsContract.CommonDataKinds.Photo;
@@ -46,6 +48,7 @@
 import com.android.contacts.util.UiClosables;
 
 import java.io.FileNotFoundException;
+import java.util.List;
 
 /**
  * Handles displaying a photo selection popup for a given photo view and dealing with the results
@@ -237,9 +240,19 @@
      * Sends a newly acquired photo to Gallery for cropping
      */
     private void doCropPhoto(Uri inputUri, Uri outputUri) {
+        final Intent intent = getCropImageIntent(inputUri, outputUri);
+        if (!hasIntentHandler(intent)) {
+            try {
+                getListener().onPhotoSelected(inputUri);
+            } catch (FileNotFoundException e) {
+                Log.e(TAG, "Cannot save uncropped photo", e);
+                Toast.makeText(mContext, R.string.contactPhotoSavedErrorToast,
+                        Toast.LENGTH_LONG).show();
+            }
+            return;
+        }
         try {
             // Launch gallery to crop the photo
-            final Intent intent = getCropImageIntent(inputUri, outputUri);
             startPhotoActivity(intent, REQUEST_CROP_PHOTO, inputUri);
         } catch (Exception e) {
             Log.e(TAG, "Cannot crop image", e);
@@ -308,6 +321,12 @@
         return intent;
     }
 
+    private boolean hasIntentHandler(Intent intent) {
+        final List<ResolveInfo> resolveInfo = mContext.getPackageManager()
+                .queryIntentActivities(intent, PackageManager.MATCH_DEFAULT_ONLY);
+        return resolveInfo != null && resolveInfo.size() > 0;
+    }
+
     /**
      * Constructs an intent for image cropping.
      */