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