blob: 4298d7ca1c13400c35f41adf7e56dd9eb8ce5a15 [file] [log] [blame]
Walter Jang3f990ba2015-01-27 17:38:30 +00001/*
2 * Copyright (C) 2015 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License
15 */
16
17package com.android.contacts.activities;
18
Walter Jang8d45cdb2016-09-01 09:25:44 -070019import android.app.Dialog;
Walter Jang31a74ad2015-10-02 19:17:39 -070020import android.app.FragmentTransaction;
Walter Jang8d45cdb2016-09-01 09:25:44 -070021import android.content.ContentValues;
Walter Jang3f990ba2015-01-27 17:38:30 +000022import android.content.Intent;
23import android.net.Uri;
24import android.os.Bundle;
Walter Jang581585d2016-09-21 19:21:13 -070025import android.provider.ContactsContract.QuickContact;
Walter Jang8d45cdb2016-09-01 09:25:44 -070026import android.util.Log;
27import android.view.View;
28import android.view.inputmethod.InputMethodManager;
Gary Mai15646ce2016-11-17 10:54:01 -080029import android.widget.Toolbar;
Walter Jang3f990ba2015-01-27 17:38:30 +000030
Gary Maida20b472016-09-20 14:46:40 -070031import com.android.contacts.ContactSaveService;
32import com.android.contacts.ContactsActivity;
Marcus Hagerott082273b2016-10-04 13:31:43 -070033import com.android.contacts.DynamicShortcuts;
Gary Maida20b472016-09-20 14:46:40 -070034import com.android.contacts.R;
35import com.android.contacts.common.activity.RequestPermissionsActivity;
Gary Maida20b472016-09-20 14:46:40 -070036import com.android.contacts.common.model.RawContactDeltaList;
Gary Maida20b472016-09-20 14:46:40 -070037import com.android.contacts.common.util.ImplicitIntentsUtil;
38import com.android.contacts.detail.PhotoSelectionHandler;
Gary Mai363af602016-09-28 10:01:23 -070039import com.android.contacts.editor.ContactEditorFragment;
Gary Maida20b472016-09-20 14:46:40 -070040import com.android.contacts.editor.EditorIntents;
41import com.android.contacts.editor.PhotoSourceDialogFragment;
42import com.android.contacts.interactions.ContactDeletionInteraction;
43import com.android.contacts.util.DialogManager;
44
Walter Jang31a74ad2015-10-02 19:17:39 -070045import java.io.FileNotFoundException;
46import java.util.ArrayList;
47
Walter Jang3f990ba2015-01-27 17:38:30 +000048/**
49 * Contact editor with only the most important fields displayed initially.
50 */
Gary Mai363af602016-09-28 10:01:23 -070051public class ContactEditorActivity extends ContactsActivity implements
Gary Maida20b472016-09-20 14:46:40 -070052 PhotoSourceDialogFragment.Listener,
Walter Jang8d45cdb2016-09-01 09:25:44 -070053 DialogManager.DialogShowingViewActivity {
54 private static final String TAG = "ContactEditorActivity";
55
56 public static final String ACTION_JOIN_COMPLETED = "joinCompleted";
57 public static final String ACTION_SAVE_COMPLETED = "saveCompleted";
58
59 public static final int RESULT_CODE_SPLIT = 2;
60 // 3 used for ContactDeletionInteraction.RESULT_CODE_DELETED
61 public static final int RESULT_CODE_EDITED = 4;
Walter Jang3f990ba2015-01-27 17:38:30 +000062
Marcus Hagerott935b56a2016-09-07 11:59:35 -070063 /**
64 * The contact will be saved to the device local account when this is set for an insert. This
65 * is necessary because {@link android.accounts.Account} cannot be created with null values
66 * for the name and type and an Account is needed for
67 * {@link android.provider.ContactsContract.Intents.Insert#EXTRA_ACCOUNT}
68 */
69 public static final String EXTRA_SAVE_TO_DEVICE_FLAG =
70 "com.android.contacts.SAVE_TO_DEVICE_FLAG";
71
Gary Mai363af602016-09-28 10:01:23 -070072 private static final String TAG_EDITOR_FRAGMENT = "editor_fragment";
Walter Jang31a74ad2015-10-02 19:17:39 -070073
74 private static final String STATE_PHOTO_MODE = "photo_mode";
Wenyi Wangbfea74f2015-10-19 13:30:18 -070075 private static final String STATE_ACTION_BAR_TITLE = "action_bar_title";
Wenyi Wanga9242e12015-11-30 18:08:56 -080076 private static final String STATE_PHOTO_URI = "photo_uri";
Walter Jang31a74ad2015-10-02 19:17:39 -070077
78 /**
Walter Jang8d45cdb2016-09-01 09:25:44 -070079 * Boolean intent key that specifies that this activity should finish itself
80 * (instead of launching a new view intent) after the editor changes have been
81 * saved.
82 */
83 public static final String INTENT_KEY_FINISH_ACTIVITY_ON_SAVE_COMPLETED =
84 "finishActivityOnSaveCompleted";
85
86 /**
87 * Contract for contact editors Fragments that are managed by this Activity.
88 */
89 public interface ContactEditor {
90
91 /**
92 * Modes that specify what the AsyncTask has to perform after saving
93 */
94 interface SaveMode {
95 /**
96 * Close the editor after saving
97 */
98 int CLOSE = 0;
99
100 /**
101 * Reload the data so that the user can continue editing
102 */
103 int RELOAD = 1;
104
105 /**
106 * Split the contact after saving
107 */
108 int SPLIT = 2;
109
110 /**
111 * Join another contact after saving
112 */
113 int JOIN = 3;
114
115 /**
Gary Mai363af602016-09-28 10:01:23 -0700116 * Navigate to the editor view after saving.
Walter Jang8d45cdb2016-09-01 09:25:44 -0700117 */
Gary Mai363af602016-09-28 10:01:23 -0700118 int EDITOR = 4;
Walter Jang8d45cdb2016-09-01 09:25:44 -0700119 }
120
121 /**
122 * The status of the contact editor.
123 */
124 interface Status {
125 /**
126 * The loader is fetching data
127 */
128 int LOADING = 0;
129
130 /**
131 * Not currently busy. We are waiting for the user to enter data
132 */
133 int EDITING = 1;
134
135 /**
136 * The data is currently being saved. This is used to prevent more
137 * auto-saves (they shouldn't overlap)
138 */
139 int SAVING = 2;
140
141 /**
142 * Prevents any more saves. This is used if in the following cases:
143 * - After Save/Close
144 * - After Revert
145 * - After the user has accepted an edit suggestion
Gary Mai363af602016-09-28 10:01:23 -0700146 * - After the user chooses to expand the editor
Walter Jang8d45cdb2016-09-01 09:25:44 -0700147 */
148 int CLOSING = 3;
149
150 /**
151 * Prevents saving while running a child activity.
152 */
153 int SUB_ACTIVITY = 4;
154 }
155
156 /**
157 * Sets the hosting Activity that will receive callbacks from the contact editor.
158 */
Gary Mai363af602016-09-28 10:01:23 -0700159 void setListener(ContactEditorFragment.Listener listener);
Walter Jang8d45cdb2016-09-01 09:25:44 -0700160
161 /**
162 * Initialize the contact editor.
163 */
164 void load(String action, Uri lookupUri, Bundle intentExtras);
165
166 /**
Gary Mai5336e6e2016-10-23 14:17:03 -0700167 * Applies extras from the hosting Activity to the writable raw contact.
Walter Jang8d45cdb2016-09-01 09:25:44 -0700168 */
169 void setIntentExtras(Bundle extras);
170
171 /**
172 * Saves or creates the contact based on the mode, and if successful
173 * finishes the activity.
174 */
175 boolean save(int saveMode);
176
177 /**
178 * If there are no unsaved changes, just close the editor, otherwise the user is prompted
179 * before discarding unsaved changes.
180 */
181 boolean revert();
182
183 /**
184 * Invoked after the contact is saved.
185 */
186 void onSaveCompleted(boolean hadChanges, int saveMode, boolean saveSucceeded,
187 Uri contactLookupUri, Long joinContactId);
188
189 /**
190 * Invoked after the contact is joined.
191 */
192 void onJoinCompleted(Uri uri);
193 }
194
195 /**
Walter Jang31a74ad2015-10-02 19:17:39 -0700196 * Displays a PopupWindow with photo edit options.
197 */
Gary Mai363af602016-09-28 10:01:23 -0700198 private final class EditorPhotoSelectionHandler extends PhotoSelectionHandler {
Walter Jang31a74ad2015-10-02 19:17:39 -0700199
200 /**
201 * Receiver of photo edit option callbacks.
202 */
Gary Mai363af602016-09-28 10:01:23 -0700203 private final class EditorPhotoActionListener extends PhotoActionListener {
Walter Jang31a74ad2015-10-02 19:17:39 -0700204
205 @Override
206 public void onRemovePictureChosen() {
207 getEditorFragment().removePhoto();
Walter Jang31a74ad2015-10-02 19:17:39 -0700208 }
209
210 @Override
211 public void onPhotoSelected(Uri uri) throws FileNotFoundException {
212 mPhotoUri = uri;
213 getEditorFragment().updatePhoto(uri);
Walter Jang31a74ad2015-10-02 19:17:39 -0700214
215 // Re-create the photo handler the next time we need it so that additional photo
216 // selections create a new temp file (and don't hit the one that was just added
217 // to the cache).
218 mPhotoSelectionHandler = null;
219 }
220
221 @Override
222 public Uri getCurrentPhotoUri() {
223 return mPhotoUri;
224 }
225
226 @Override
227 public void onPhotoSelectionDismissed() {
Walter Jang31a74ad2015-10-02 19:17:39 -0700228 }
229 }
230
Gary Mai363af602016-09-28 10:01:23 -0700231 private final EditorPhotoActionListener mPhotoActionListener;
Walter Jang31a74ad2015-10-02 19:17:39 -0700232
Gary Mai363af602016-09-28 10:01:23 -0700233 public EditorPhotoSelectionHandler(int photoMode) {
Walter Jang31a74ad2015-10-02 19:17:39 -0700234 // We pass a null changeAnchorView since we are overriding onClick so that we
235 // can show the photo options in a dialog instead of a ListPopupWindow (which would
236 // be anchored at changeAnchorView).
237
238 // TODO: empty raw contact delta list
Gary Mai363af602016-09-28 10:01:23 -0700239 super(ContactEditorActivity.this, /* changeAnchorView =*/ null, photoMode,
Walter Jang31a74ad2015-10-02 19:17:39 -0700240 /* isDirectoryContact =*/ false, new RawContactDeltaList());
Gary Mai363af602016-09-28 10:01:23 -0700241 mPhotoActionListener = new EditorPhotoActionListener();
Walter Jang31a74ad2015-10-02 19:17:39 -0700242 }
243
244 @Override
245 public PhotoActionListener getListener() {
246 return mPhotoActionListener;
247 }
248
249 @Override
250 protected void startPhotoActivity(Intent intent, int requestCode, Uri photoUri) {
251 mPhotoUri = photoUri;
252 startActivityForResult(intent, requestCode);
253 }
254 }
255
Walter Jang8d45cdb2016-09-01 09:25:44 -0700256 private int mActionBarTitleResId;
257 private ContactEditor mFragment;
Gary Mai15646ce2016-11-17 10:54:01 -0800258 private Toolbar mToolbar;
Walter Jang8d45cdb2016-09-01 09:25:44 -0700259 private boolean mFinishActivityOnSaveCompleted;
260 private DialogManager mDialogManager = new DialogManager(this);
261
Gary Mai363af602016-09-28 10:01:23 -0700262 private EditorPhotoSelectionHandler mPhotoSelectionHandler;
Walter Jang31a74ad2015-10-02 19:17:39 -0700263 private Uri mPhotoUri;
264 private int mPhotoMode;
Walter Jange2797da2015-04-23 11:08:46 -0700265
Gary Mai363af602016-09-28 10:01:23 -0700266 private final ContactEditorFragment.Listener mFragmentListener =
267 new ContactEditorFragment.Listener() {
Walter Jang8d45cdb2016-09-01 09:25:44 -0700268
269 @Override
270 public void onDeleteRequested(Uri contactUri) {
271 ContactDeletionInteraction.start(
Gary Mai363af602016-09-28 10:01:23 -0700272 ContactEditorActivity.this, contactUri, true);
Walter Jang8d45cdb2016-09-01 09:25:44 -0700273 }
274
275 @Override
276 public void onReverted() {
277 finish();
278 }
279
280 @Override
281 public void onSaveFinished(Intent resultIntent) {
282 if (mFinishActivityOnSaveCompleted) {
283 setResult(resultIntent == null ? RESULT_CANCELED : RESULT_OK, resultIntent);
284 } else if (resultIntent != null) {
Walter Jang581585d2016-09-21 19:21:13 -0700285 // If it's a smart profile Intent it must be started "for result"
286 if (QuickContact.ACTION_QUICK_CONTACT.equals(resultIntent.getAction())) {
287 ImplicitIntentsUtil.startActivityInApp(
Gary Mai363af602016-09-28 10:01:23 -0700288 ContactEditorActivity.this, resultIntent);
Walter Jang581585d2016-09-21 19:21:13 -0700289 } else {
290 startActivityForResult(resultIntent, /* requestCode */ 0);
291 }
Walter Jang8d45cdb2016-09-01 09:25:44 -0700292 }
293 finish();
294 }
295
296 @Override
297 public void onContactSplit(Uri newLookupUri) {
298 setResult(RESULT_CODE_SPLIT, /* data */ null);
299 finish();
300 }
301
302 @Override
303 public void onContactNotFound() {
304 finish();
305 }
306
307 @Override
Gary Mai678108e2016-10-26 14:34:33 -0700308 public void onEditOtherRawContactRequested(
309 Uri contactLookupUri, long rawContactId, ArrayList<ContentValues> values) {
310 final Intent intent = EditorIntents.createEditOtherRawContactIntent(
311 ContactEditorActivity.this, contactLookupUri, rawContactId, values);
Walter Jang8d45cdb2016-09-01 09:25:44 -0700312 ImplicitIntentsUtil.startActivityInApp(
Gary Mai363af602016-09-28 10:01:23 -0700313 ContactEditorActivity.this, intent);
Walter Jang8d45cdb2016-09-01 09:25:44 -0700314 finish();
315 }
Walter Jang8d45cdb2016-09-01 09:25:44 -0700316 };
317
Walter Jang3f990ba2015-01-27 17:38:30 +0000318 @Override
319 public void onCreate(Bundle savedState) {
320 super.onCreate(savedState);
321
Brian Attwellbdd32642015-05-08 17:03:15 -0700322 if (RequestPermissionsActivity.startPermissionActivity(this)) {
323 return;
324 }
325
Walter Jang8d45cdb2016-09-01 09:25:44 -0700326 final Intent intent = getIntent();
327 final String action = intent.getAction();
328
329 // Determine whether or not this activity should be finished after the user is done
330 // editing the contact or if this activity should launch another activity to view the
331 // contact's details.
332 mFinishActivityOnSaveCompleted = intent.getBooleanExtra(
333 INTENT_KEY_FINISH_ACTIVITY_ON_SAVE_COMPLETED, false);
334
335 // The only situation where action could be ACTION_JOIN_COMPLETED is if the
336 // user joined the contact with another and closed the activity before
337 // the save operation was completed. The activity should remain closed then.
338 if (ACTION_JOIN_COMPLETED.equals(action)) {
339 finish();
340 return;
341 }
342
343 if (ACTION_SAVE_COMPLETED.equals(action)) {
344 finish();
345 return;
346 }
347
Gary Mai363af602016-09-28 10:01:23 -0700348 setContentView(R.layout.contact_editor_activity);
Gary Mai15646ce2016-11-17 10:54:01 -0800349 mToolbar = (Toolbar) findViewById(R.id.toolbar);
350 if (Intent.ACTION_EDIT.equals(action)) {
351 mActionBarTitleResId = R.string.contact_editor_title_existing_contact;
352 } else {
353 mActionBarTitleResId = R.string.contact_editor_title_new_contact;
354 }
355 mToolbar.setTitle(mActionBarTitleResId);
Gary Maid8f3da62016-11-18 11:47:20 -0800356 // Set activity title for Talkback
357 setTitle(mActionBarTitleResId);
Gary Mai15646ce2016-11-17 10:54:01 -0800358 setActionBar(mToolbar);
Walter Jang3f990ba2015-01-27 17:38:30 +0000359
Walter Jang31a74ad2015-10-02 19:17:39 -0700360 if (savedState == null) {
361 // Create the editor and photo selection fragments
Gary Mai363af602016-09-28 10:01:23 -0700362 mFragment = new ContactEditorFragment();
Walter Janga69f58f2015-04-02 10:26:56 -0700363 getFragmentManager().beginTransaction()
Gary Mai363af602016-09-28 10:01:23 -0700364 .add(R.id.fragment_container, getEditorFragment(), TAG_EDITOR_FRAGMENT)
Walter Janga69f58f2015-04-02 10:26:56 -0700365 .commit();
Walter Jang31a74ad2015-10-02 19:17:39 -0700366 } else {
367 // Restore state
368 mPhotoMode = savedState.getInt(STATE_PHOTO_MODE);
Wenyi Wangbfea74f2015-10-19 13:30:18 -0700369 mActionBarTitleResId = savedState.getInt(STATE_ACTION_BAR_TITLE);
Wenyi Wanga9242e12015-11-30 18:08:56 -0800370 mPhotoUri = Uri.parse(savedState.getString(STATE_PHOTO_URI));
Walter Jang3f990ba2015-01-27 17:38:30 +0000371
Walter Jang31a74ad2015-10-02 19:17:39 -0700372 // Show/hide the editor and photo selection fragments (w/o animations)
Gary Mai363af602016-09-28 10:01:23 -0700373 mFragment = (ContactEditorFragment) getFragmentManager()
374 .findFragmentByTag(TAG_EDITOR_FRAGMENT);
Walter Jang31a74ad2015-10-02 19:17:39 -0700375 final FragmentTransaction fragmentTransaction = getFragmentManager().beginTransaction();
Gary Maida20b472016-09-20 14:46:40 -0700376 fragmentTransaction.show(getEditorFragment()).commit();
Gary Mai15646ce2016-11-17 10:54:01 -0800377 mToolbar.setTitle(mActionBarTitleResId);
Walter Jang31a74ad2015-10-02 19:17:39 -0700378 }
379
380 // Set listeners
381 mFragment.setListener(mFragmentListener);
Walter Jang31a74ad2015-10-02 19:17:39 -0700382
383 // Load editor data (even if it's hidden)
Walter Jang3f990ba2015-01-27 17:38:30 +0000384 final Uri uri = Intent.ACTION_EDIT.equals(action) ? getIntent().getData() : null;
385 mFragment.load(action, uri, getIntent().getExtras());
Marcus Hagerott082273b2016-10-04 13:31:43 -0700386
387 if (Intent.ACTION_INSERT.equals(action)) {
388 DynamicShortcuts.reportShortcutUsed(this, DynamicShortcuts.SHORTCUT_ADD_CONTACT);
389 }
Walter Jang3f990ba2015-01-27 17:38:30 +0000390 }
Walter Jang31a74ad2015-10-02 19:17:39 -0700391
Walter Jang8d45cdb2016-09-01 09:25:44 -0700392 @Override
393 protected void onPause() {
394 super.onPause();
395 final InputMethodManager imm = (InputMethodManager) getSystemService(INPUT_METHOD_SERVICE);
396 final View currentFocus = getCurrentFocus();
397 if (imm != null && currentFocus != null) {
398 imm.hideSoftInputFromWindow(currentFocus.getWindowToken(), 0);
399 }
400 }
401
402 @Override
403 protected void onNewIntent(Intent intent) {
404 super.onNewIntent(intent);
405
406 if (mFragment == null) {
407 return;
408 }
409
410 final String action = intent.getAction();
411 if (Intent.ACTION_EDIT.equals(action)) {
412 mFragment.setIntentExtras(intent.getExtras());
413 } else if (ACTION_SAVE_COMPLETED.equals(action)) {
414 mFragment.onSaveCompleted(true,
Gary Mai363af602016-09-28 10:01:23 -0700415 intent.getIntExtra(ContactEditorFragment.SAVE_MODE_EXTRA_KEY,
Walter Jang8d45cdb2016-09-01 09:25:44 -0700416 ContactEditor.SaveMode.CLOSE),
417 intent.getBooleanExtra(ContactSaveService.EXTRA_SAVE_SUCCEEDED, false),
418 intent.getData(),
Gary Mai363af602016-09-28 10:01:23 -0700419 intent.getLongExtra(ContactEditorFragment.JOIN_CONTACT_ID_EXTRA_KEY, -1));
Walter Jang8d45cdb2016-09-01 09:25:44 -0700420 } else if (ACTION_JOIN_COMPLETED.equals(action)) {
421 mFragment.onJoinCompleted(intent.getData());
422 }
423 }
424
425 @Override
426 protected Dialog onCreateDialog(int id, Bundle args) {
427 if (DialogManager.isManagedId(id)) return mDialogManager.onCreateDialog(id, args);
428
429 // Nobody knows about the Dialog
430 Log.w(TAG, "Unknown dialog requested, id: " + id + ", args: " + args);
431 return null;
432 }
433
434 @Override
435 public DialogManager getDialogManager() {
436 return mDialogManager;
437 }
438
439 @Override
Walter Jang31a74ad2015-10-02 19:17:39 -0700440 protected void onSaveInstanceState(Bundle outState) {
441 super.onSaveInstanceState(outState);
Wenyi Wangbfea74f2015-10-19 13:30:18 -0700442 outState.putInt(STATE_PHOTO_MODE, mPhotoMode);
Wenyi Wangbfea74f2015-10-19 13:30:18 -0700443 outState.putInt(STATE_ACTION_BAR_TITLE, mActionBarTitleResId);
Wenyi Wanga9242e12015-11-30 18:08:56 -0800444 outState.putString(STATE_PHOTO_URI,
445 mPhotoUri != null ? mPhotoUri.toString() : Uri.EMPTY.toString());
Walter Jang31a74ad2015-10-02 19:17:39 -0700446 }
447
448 @Override
449 public void onActivityResult(int requestCode, int resultCode, Intent data) {
Wenyi Wanga9242e12015-11-30 18:08:56 -0800450 if (mPhotoSelectionHandler == null) {
Gary Mai363af602016-09-28 10:01:23 -0700451 mPhotoSelectionHandler = (EditorPhotoSelectionHandler) getPhotoSelectionHandler();
Wenyi Wanga9242e12015-11-30 18:08:56 -0800452 }
453 if (mPhotoSelectionHandler.handlePhotoActivityResult(requestCode, resultCode, data)) {
Walter Jang3f18d612015-10-07 16:01:05 -0700454 return;
455 }
456 super.onActivityResult(requestCode, resultCode, data);
Walter Jang31a74ad2015-10-02 19:17:39 -0700457 }
458
459 @Override
460 public void onBackPressed() {
Gary Maida20b472016-09-20 14:46:40 -0700461 if (mFragment != null) {
Walter Jang8d45cdb2016-09-01 09:25:44 -0700462 mFragment.revert();
Walter Jang31a74ad2015-10-02 19:17:39 -0700463 }
464 }
465
466 /**
Walter Jang31a74ad2015-10-02 19:17:39 -0700467 * Opens a dialog showing options for the user to change their photo (take, choose, or remove
468 * photo).
469 */
470 public void changePhoto(int photoMode) {
471 mPhotoMode = photoMode;
Walter Jang31a74ad2015-10-02 19:17:39 -0700472 PhotoSourceDialogFragment.show(this, mPhotoMode);
473 }
474
Gary Mai15646ce2016-11-17 10:54:01 -0800475 public Toolbar getToolbar() {
476 return mToolbar;
477 }
478
Walter Jang31a74ad2015-10-02 19:17:39 -0700479 @Override
480 public void onRemovePictureChosen() {
481 getPhotoSelectionHandler().getListener().onRemovePictureChosen();
482 }
483
484 @Override
485 public void onTakePhotoChosen() {
486 getPhotoSelectionHandler().getListener().onTakePhotoChosen();
487 }
488
489 @Override
490 public void onPickFromGalleryChosen() {
491 getPhotoSelectionHandler().getListener().onPickFromGalleryChosen();
492 }
493
Walter Jang31a74ad2015-10-02 19:17:39 -0700494 private PhotoSelectionHandler getPhotoSelectionHandler() {
495 if (mPhotoSelectionHandler == null) {
Gary Mai363af602016-09-28 10:01:23 -0700496 mPhotoSelectionHandler = new EditorPhotoSelectionHandler(mPhotoMode);
Walter Jang31a74ad2015-10-02 19:17:39 -0700497 }
498 return mPhotoSelectionHandler;
499 }
500
Gary Mai363af602016-09-28 10:01:23 -0700501 private ContactEditorFragment getEditorFragment() {
502 return (ContactEditorFragment) mFragment;
Walter Jang31a74ad2015-10-02 19:17:39 -0700503 }
Walter Jang3f990ba2015-01-27 17:38:30 +0000504}