1 /*
2  * Copyright (C) 2016 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.bips.ui;
18 
19 import android.app.AlertDialog;
20 import android.content.ComponentName;
21 import android.content.Context;
22 import android.content.Intent;
23 import android.content.ServiceConnection;
24 import android.os.Bundle;
25 import android.os.IBinder;
26 import android.preference.Preference;
27 import android.preference.PreferenceCategory;
28 import android.preference.PreferenceFragment;
29 import android.preference.SwitchPreference;
30 import android.util.Log;
31 
32 import com.android.bips.BuiltInPrintService;
33 import com.android.bips.P2pPermissionManager;
34 import com.android.bips.R;
35 import com.android.bips.discovery.DiscoveredPrinter;
36 import com.android.bips.p2p.P2pUtils;
37 
38 /**
39  * Presents a list of printers and the ability to add a new one
40  */
41 public class AddPrintersFragment extends PreferenceFragment implements ServiceConnection {
42     private static final String TAG = AddPrintersFragment.class.getSimpleName();
43     private static final boolean DEBUG = false;
44 
45     private static final String KEY_ADD_BY_IP = "add_by_ip";
46     private static final String KEY_FIND_WIFI_DIRECT = "find_wifi_direct";
47     private static final String KEY_WIFI_DIRECT_PRINTING = "wifi_direct_printing";
48     private static final String KEY_SAVED_PRINTERS = "saved_printers";
49     public static final String EXTRA_FIX_P2P_PERMISSION = "fix_p2p_permission";
50 
51     private static final int ORDER_SAVED = 2;
52 
53     private PreferenceCategory mSavedPrintersCategory;
54     private Preference mAddPrinterByIpPreference;
55     private Preference mFindP2pPrintersPreference;
56     private SwitchPreference mP2pEnablePreference;
57     private BuiltInPrintService mPrintService;
58     private P2pPermissionManager mP2pPermissionManager;
59 
60     @Override
onCreate(Bundle in)61     public void onCreate(Bundle in) {
62         if (DEBUG) Log.d(TAG, "onCreate");
63         super.onCreate(in);
64         addPreferencesFromResource(R.xml.add_printers_prefs);
65         mAddPrinterByIpPreference = getPreferenceScreen().findPreference(KEY_ADD_BY_IP);
66 
67         mFindP2pPrintersPreference = getPreferenceScreen().findPreference(
68                 KEY_FIND_WIFI_DIRECT);
69         mFindP2pPrintersPreference.setOnPreferenceClickListener(preference -> {
70             getFragmentManager().beginTransaction()
71                     .replace(android.R.id.content, new FindP2pPrintersFragment())
72                     .addToBackStack(null)
73                     .commit();
74             return true;
75         });
76         mP2pEnablePreference = (SwitchPreference) getPreferenceScreen()
77                 .findPreference(KEY_WIFI_DIRECT_PRINTING);
78         mSavedPrintersCategory = (PreferenceCategory) getPreferenceScreen()
79                 .findPreference(KEY_SAVED_PRINTERS);
80     }
81 
82     @Override
onStart()83     public void onStart() {
84         super.onStart();
85         if (DEBUG) Log.d(TAG, "onStart");
86 
87         getActivity().setTitle(R.string.title_activity_add_printer);
88         getContext().bindService(new Intent(getContext(), BuiltInPrintService.class), this,
89                 Context.BIND_AUTO_CREATE);
90 
91         mP2pPermissionManager = new P2pPermissionManager(getActivity());
92         updateP2pPreferences();
93 
94         if (getActivity().getIntent().getBooleanExtra(EXTRA_FIX_P2P_PERMISSION, false)) {
95             // Additional explanation is redundant, since the user saw it in notification.
96             mP2pPermissionManager.request(false, approve -> {
97                 updateP2pPreferences();
98                 if (!approve) {
99                     // The user is choosing to disable by denying Location.
100                     mP2pPermissionManager.setState(P2pPermissionManager.State.DISABLED);
101                 }
102             });
103         }
104 
105         mP2pEnablePreference.setOnPreferenceClickListener(preference -> {
106             if (mP2pEnablePreference.isChecked()) {
107                 mP2pEnablePreference.setChecked(false);
108                 if (mP2pPermissionManager.getState() == P2pPermissionManager.State.DISABLED) {
109                     // We're no longer disabled, just denied
110                     mP2pPermissionManager.setState(P2pPermissionManager.State.DENIED);
111                 }
112                 mP2pPermissionManager.reset();
113                 mP2pPermissionManager.request(true, approve -> updateP2pPreferences());
114             } else {
115                 // User disabled P2P
116                 mP2pPermissionManager.setState(P2pPermissionManager.State.DISABLED);
117                 updateP2pPreferences();
118             }
119             return true;
120         });
121     }
122 
123     @Override
onStop()124     public void onStop() {
125         super.onStop();
126         if (DEBUG) Log.d(TAG, "onStop");
127 
128         getContext().unbindService(this);
129     }
130 
131     @Override
onServiceConnected(ComponentName componentName, IBinder iBinder)132     public void onServiceConnected(ComponentName componentName, IBinder iBinder) {
133         if (DEBUG) Log.d(TAG, "onServiceConnected");
134         mPrintService = BuiltInPrintService.getInstance();
135 
136         mAddPrinterByIpPreference.setOnPreferenceClickListener(preference -> {
137             AlertDialog dialog = new AddManualPrinterDialog(getActivity(),
138                     mPrintService.getManualDiscovery());
139             dialog.setOnDismissListener(d -> updateSavedPrinters());
140             dialog.show();
141             return true;
142         });
143 
144         updateSavedPrinters();
145     }
146 
updateP2pPreferences()147     private void updateP2pPreferences() {
148         // Only allow the user to find new P2P printers when enabled
149         if (mP2pPermissionManager.isP2pEnabled()) {
150             mP2pEnablePreference.setChecked(true);
151             getPreferenceScreen().addPreference(mFindP2pPrintersPreference);
152             if (getActivity().getIntent().getBooleanExtra(EXTRA_FIX_P2P_PERMISSION, false)) {
153                 // If we were only here to enable P2P permissions, go back to the print now.
154                 getActivity().finish();
155             }
156         } else {
157             mP2pEnablePreference.setChecked(false);
158             getPreferenceScreen().removePreference(mFindP2pPrintersPreference);
159         }
160 
161         updateSavedPrinters();
162     }
163 
164     @Override
onServiceDisconnected(ComponentName componentName)165     public void onServiceDisconnected(ComponentName componentName) {
166         mPrintService = null;
167     }
168 
updateSavedPrinters()169     private void updateSavedPrinters() {
170         int savedCount = mPrintService == null ? 0 : mPrintService.getDiscovery()
171                 .getSavedPrinters().size();
172 
173         if (savedCount == 0) {
174             if (getPreferenceScreen().findPreference(mSavedPrintersCategory.getKey()) != null) {
175                 getPreferenceScreen().removePreference(mSavedPrintersCategory);
176             }
177         } else {
178             if (getPreferenceScreen().findPreference(mSavedPrintersCategory.getKey()) == null) {
179                 getPreferenceScreen().addPreference(mSavedPrintersCategory);
180             }
181 
182             mSavedPrintersCategory.removeAll();
183 
184             // With the service enumerate all saved printers
185             boolean p2pEnabled = mP2pPermissionManager.isP2pEnabled();
186             for (DiscoveredPrinter printer : mPrintService.getDiscovery().getSavedPrinters()) {
187                 // Don't show P2P printers while P2P is disabled.
188                 if (P2pUtils.isP2p(printer) && !p2pEnabled) {
189                     continue;
190                 }
191                 if (DEBUG) Log.d(TAG, "Adding saved printer " + printer);
192                 PrinterPreference pref = new PrinterPreference(getContext(), mPrintService,
193                         printer, false);
194                 pref.setOrder(ORDER_SAVED);
195                 pref.setOnPreferenceClickListener(preference -> {
196                     showRemovalDialog(printer);
197                     return true;
198                 });
199                 mSavedPrintersCategory.addPreference(pref);
200             }
201         }
202     }
203 
showRemovalDialog(DiscoveredPrinter printer)204     private void showRemovalDialog(DiscoveredPrinter printer) {
205         String message;
206         if (P2pUtils.isP2p(printer)) {
207             message = mPrintService.getString(R.string.connects_via_wifi_direct);
208         } else {
209             message = mPrintService.getString(R.string.connects_via_network, printer.path);
210         }
211         new AlertDialog.Builder(getContext())
212                 .setTitle(printer.name)
213                 .setMessage(message)
214                 .setNegativeButton(android.R.string.cancel, null)
215                 .setPositiveButton(R.string.forget, (dialog, which) -> {
216                     mPrintService.getDiscovery().removeSavedPrinter(printer.path);
217                     updateSavedPrinters();
218                 }).show();
219     }
220 }
221