1 /*
2  * Copyright (C) 2014 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 
17 package com.android.camera.app;
18 
19 import android.app.Dialog;
20 import android.content.Context;
21 import android.content.DialogInterface;
22 import android.view.ViewGroup;
23 
24 import com.android.camera.device.CameraId;
25 import com.android.camera.exif.Rational;
26 import com.android.camera.one.OneCamera.Facing;
27 import com.android.camera.one.OneCameraAccessException;
28 import com.android.camera.one.OneCameraManager;
29 import com.android.camera.settings.Keys;
30 import com.android.camera.settings.ResolutionSetting;
31 import com.android.camera.settings.ResolutionUtil;
32 import com.android.camera.settings.SettingsManager;
33 import com.android.camera.util.ApiHelper;
34 import com.android.camera.widget.AspectRatioDialogLayout;
35 import com.android.camera.widget.LocationDialogLayout;
36 
37 /**
38  * The dialog to show when users open the app for the first time.
39  */
40 public class FirstRunDialog {
41 
42     public interface FirstRunDialogListener {
onFirstRunStateReady()43         public void onFirstRunStateReady();
onFirstRunDialogCancelled()44         public void onFirstRunDialogCancelled();
onCameraAccessException()45         public void onCameraAccessException();
46     }
47 
48     /** The default preference of aspect ratio. */
49     private static final Rational DEFAULT_ASPECT_RATIO = ResolutionUtil.ASPECT_RATIO_4x3;
50 
51     /** The default preference of whether enabling location recording. */
52     private static final boolean DEFAULT_LOCATION_RECORDING_ENABLED = true;
53 
54     /** Listener to receive events. */
55     private final FirstRunDialogListener mListener;
56 
57     /** The app controller. */
58     private final AppController mAppController;
59 
60     /** The hardware manager. */
61     private final OneCameraManager mOneCameraManager;
62 
63     /** The app context. */
64     private final Context mContext;
65 
66     /** The resolution settings. */
67     private final ResolutionSetting mResolutionSetting;
68 
69     /** The settings manager. */
70     private final SettingsManager mSettingsManager;
71 
72     /** Aspect ratio preference dialog */
73     private Dialog mAspectRatioPreferenceDialog;
74 
75     /** Location preference dialog */
76     private Dialog mLocationPreferenceDialog;
77 
78     /**
79      * Constructs a first run dialog.
80      *
81      */
FirstRunDialog( AppController appController, Context androidContext, ResolutionSetting resolutionSetting, SettingsManager settingManager, OneCameraManager hardwareManager, FirstRunDialogListener listener)82     public FirstRunDialog(
83           AppController appController,
84           Context androidContext,
85           ResolutionSetting resolutionSetting,
86           SettingsManager settingManager,
87           OneCameraManager hardwareManager,
88           FirstRunDialogListener listener) {
89         mAppController = appController;
90         mContext = androidContext;
91         mResolutionSetting = resolutionSetting;
92         mSettingsManager = settingManager;
93         mOneCameraManager = hardwareManager;
94         mListener = listener;
95     }
96 
97     /**
98      * Shows first run dialogs if necessary.
99      */
showIfNecessary()100     public void showIfNecessary() {
101         if (shouldShowLocationDialog()) {
102             // When people open the app for the first time, prompt two dialogs to
103             // ask preferences about location and aspect ratio. The first dialog is
104             // location reference.
105             promptLocationPreferenceDialog();
106         } else if (shouldShowAspectRatioDialog()) {
107             /**
108              * If people already set location preference, prompt aspect ratio dialog.
109              */
110             promptAspectRatioPreferenceDialog();
111         } else {
112             mListener.onFirstRunStateReady();
113         }
114     }
115 
116     /**
117      * Dismiss all shown dialogs.
118      */
dismiss()119     public void dismiss() {
120         if (mAspectRatioPreferenceDialog != null) {
121             // Remove the listener since we actively dismiss the dialog.
122             mAspectRatioPreferenceDialog.setOnDismissListener(null);
123             mAspectRatioPreferenceDialog.dismiss();
124             mAspectRatioPreferenceDialog = null;
125         }
126         if (mLocationPreferenceDialog != null) {
127             // Remove the listener since we actively dismiss the dialog.
128             mLocationPreferenceDialog.setOnDismissListener(null);
129             mLocationPreferenceDialog.dismiss();
130             mLocationPreferenceDialog = null;
131         }
132     }
133 
134     /**
135      * Whether first run dialogs should be presented to the user.
136      *
137      * @return Whether first run dialogs should be presented to the user.
138      */
shouldShowLocationDialog()139     private boolean shouldShowLocationDialog() {
140         return !mSettingsManager.isSet(SettingsManager.SCOPE_GLOBAL, Keys.KEY_RECORD_LOCATION);
141     }
142 
shouldShowAspectRatioDialog()143     private boolean shouldShowAspectRatioDialog() {
144         return mAppController.getCameraAppUI().shouldShowAspectRatioDialog();
145     }
146 
147     /**
148      * Prompts a dialog to allow people to choose aspect ratio preference when
149      * people open the app for the first time. If the preference has been set,
150      * this will return false.
151      */
promptAspectRatioPreferenceDialog()152     private void promptAspectRatioPreferenceDialog() {
153         // Create a content view for the dialog.
154         final AspectRatioDialogLayout dialogLayout = new AspectRatioDialogLayout(
155                 mContext, DEFAULT_ASPECT_RATIO);
156         dialogLayout.setListener(new AspectRatioDialogLayout.AspectRatioDialogListener() {
157             @Override
158             public void onConfirm(Rational aspectRatio) {
159                 // Change resolution setting based on the chosen aspect ratio.
160                 try {
161                     CameraId backCameraId = mOneCameraManager.findFirstCameraFacing(Facing.BACK);
162                     if (backCameraId != null) {
163                         mResolutionSetting.setPictureAspectRatio(backCameraId, aspectRatio);
164                     }
165                     CameraId frontCameraId = mOneCameraManager.findFirstCameraFacing(Facing.FRONT);
166                     if (frontCameraId != null) {
167                         mResolutionSetting.setPictureAspectRatio(frontCameraId, aspectRatio);
168                     }
169                 } catch (OneCameraAccessException ex) {
170                     mListener.onCameraAccessException();
171                     return;
172                 }
173 
174                 // Mark that user has made the choice.
175                 mSettingsManager.set(
176                         SettingsManager.SCOPE_GLOBAL,
177                         Keys.KEY_USER_SELECTED_ASPECT_RATIO,
178                         true);
179 
180                 // Dismiss all dialogs.
181                 dismiss();
182 
183                 // Notify that the app is ready to go.
184                 mListener.onFirstRunStateReady();
185             }
186         });
187 
188         // Create the dialog.
189         mAspectRatioPreferenceDialog = mAppController.createDialog();
190         mAspectRatioPreferenceDialog.setContentView(dialogLayout, new ViewGroup.LayoutParams(
191                 ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT));
192         // Detect if the dialog is dismissed by back button.
193         mAspectRatioPreferenceDialog.setOnDismissListener(new DialogInterface.OnDismissListener() {
194             @Override
195             public void onDismiss(DialogInterface dialog) {
196                 mAspectRatioPreferenceDialog = null;
197                 dismiss();
198                 mListener.onFirstRunDialogCancelled();
199             }
200         });
201 
202         // Show the dialog.
203         mAspectRatioPreferenceDialog.show();
204     }
205 
206     /**
207      * Prompts a dialog to allow people to choose location preference when
208      * people open the app for the first time. If the preference has been set,
209      * this will return false.
210      */
promptLocationPreferenceDialog()211     private void promptLocationPreferenceDialog() {
212         // Create a content view for the dialog.
213         final LocationDialogLayout dialogLayout = new LocationDialogLayout(
214                 mContext, DEFAULT_LOCATION_RECORDING_ENABLED);
215         dialogLayout.setListener(new LocationDialogLayout.LocationDialogListener() {
216             @Override
217             public void onConfirm(boolean locationRecordingEnabled) {
218                 // Change the location preference setting.
219                 mSettingsManager.set(
220                         SettingsManager.SCOPE_GLOBAL,
221                         Keys.KEY_RECORD_LOCATION,
222                         locationRecordingEnabled);
223 
224                 if (shouldShowAspectRatioDialog()) {
225                     // Prompt the second dialog about aspect ratio preference.
226                     promptAspectRatioPreferenceDialog();
227                 } else {
228                     // Dismiss all dialogs.
229                     dismiss();
230                     // Notify that the app is ready to go.
231                     mListener.onFirstRunStateReady();
232                 }
233             }
234         });
235 
236         // Create the dialog.
237         mLocationPreferenceDialog = mAppController.createDialog();
238         mLocationPreferenceDialog.setContentView(dialogLayout, new ViewGroup.LayoutParams(
239                 ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT));
240         // Detect if the dialog is dismissed by back button.
241         mLocationPreferenceDialog.setOnDismissListener(new DialogInterface.OnDismissListener() {
242             @Override
243             public void onDismiss(DialogInterface dialog) {
244                 mLocationPreferenceDialog = null;
245                 dismiss();
246                 mListener.onFirstRunDialogCancelled();
247             }
248         });
249 
250         // Show the dialog.
251         mLocationPreferenceDialog.show();
252     }
253 }
254