1 /*
2  * Copyright (C) 2017 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.settings.backup;
18 
19 
20 import android.app.backup.BackupManager;
21 import android.app.backup.IBackupManager;
22 import android.content.Context;
23 import android.content.Intent;
24 import android.os.RemoteException;
25 import android.os.ServiceManager;
26 import android.os.UserHandle;
27 import android.os.UserManager;
28 import android.text.TextUtils;
29 import android.util.Log;
30 
31 import androidx.annotation.VisibleForTesting;
32 
33 import com.android.settings.R;
34 import com.android.settings.Settings.PrivacySettingsActivity;
35 
36 import java.net.URISyntaxException;
37 
38 /**
39  * Helper class for {@link UserBackupSettingsActivity} that interacts with {@link IBackupManager}.
40  */
41 public class BackupSettingsHelper {
42     private static final String TAG = "BackupSettingsHelper";
43 
44     private IBackupManager mBackupManager = IBackupManager.Stub.asInterface(
45             ServiceManager.getService(Context.BACKUP_SERVICE));
46 
47     private Context mContext;
48 
BackupSettingsHelper(Context context)49     public BackupSettingsHelper(Context context) {
50         mContext = context;
51     }
52 
53     /**
54      * If there is only one profile, show whether the backup is on or off.
55      * Otherwise, show nothing.
56      */
getSummary()57     public String getSummary() {
58         UserManager userManager = (UserManager) mContext.getSystemService(Context.USER_SERVICE);
59         if (userManager.getUserProfiles().size() == 1) {
60             try {
61                 int resId = mBackupManager.isBackupEnabled() ? R.string.backup_summary_state_on
62                     : R.string.backup_summary_state_off;
63                 return mContext.getText(resId).toString();
64             } catch (RemoteException e) {
65                 Log.e(TAG, "Error getting isBackupEnabled", e);
66             }
67         }
68         return null;
69     }
70 
71     /**
72      * Returns an intent to launch backup settings from backup transport if the intent was provided
73      * by the transport. Otherwise returns the intent to launch the default backup settings screen.
74      *
75      * @return Intent for launching backup settings
76      */
getIntentForBackupSettings()77     public Intent getIntentForBackupSettings() {
78         Intent intent;
79         if (isIntentProvidedByTransport()) {
80             intent = getIntentForBackupSettingsFromTransport();
81         } else {
82             Log.e(TAG, "Backup transport has not provided an intent"
83                     + " or the component for the intent is not found!");
84             intent = getIntentForDefaultBackupSettings();
85         }
86         return intent;
87     }
88 
89     /**
90      * Returns a label for the settings item that will point to the backup settings provided by
91      * the transport. If no label was provided by transport, returns the default string.
92      *
93      * @return Label for the backup settings item.
94      */
getLabelForBackupSettings()95     public CharSequence getLabelForBackupSettings() {
96         CharSequence label = getLabelFromBackupTransport();
97         if (TextUtils.isEmpty(label)) {
98             label = mContext.getString(R.string.privacy_settings_title);
99         }
100         return label;
101     }
102 
103     /**
104      * Returns a summary string for the settings item that will point to the backup settings
105      * provided by the transport. If no summary was provided by transport, returns the default
106      * string.
107      *
108      * @return Summary for the backup settings item.
109      */
getSummaryForBackupSettings()110     public String getSummaryForBackupSettings() {
111         String summary = getSummaryFromBackupTransport();
112         if (summary == null) {
113             summary = mContext.getString(R.string.backup_configure_account_default_summary);
114         }
115         return summary;
116     }
117 
118 
119     /**
120      * Checks if the manufacturer provided an intent to launch its backup settings screen
121      * in the config file.
122      */
isBackupProvidedByManufacturer()123     public boolean isBackupProvidedByManufacturer() {
124         if (Log.isLoggable(TAG, Log.DEBUG)) {
125             Log.d(TAG, "Checking if intent provided by manufacturer");
126         }
127         String intentString =
128                 mContext.getResources().getString(R.string.config_backup_settings_intent);
129 
130         return intentString != null && !intentString.isEmpty();
131     }
132 
133     /**
134      * Returns the label for the backup settings item provided by the manufacturer.
135      */
getLabelProvidedByManufacturer()136     public String getLabelProvidedByManufacturer() {
137         return mContext.getResources().getString(R.string.config_backup_settings_label);
138     }
139 
140     /**
141      * Returns the intent to the backup settings screen provided by the manufacturer.
142      */
getIntentProvidedByManufacturer()143     public Intent getIntentProvidedByManufacturer() {
144         if (Log.isLoggable(TAG, Log.DEBUG)) {
145             Log.d(TAG, "Getting a backup settings intent provided by manufacturer");
146         }
147         String intentString =
148                 mContext.getResources().getString(R.string.config_backup_settings_intent);
149         if (intentString != null && !intentString.isEmpty()) {
150             try {
151                 return Intent.parseUri(intentString, 0);
152             } catch (URISyntaxException e) {
153                 Log.e(TAG, "Invalid intent provided by the manufacturer.", e);
154             }
155         }
156         return null;
157     }
158 
159     /**
160      * Gets the intent from Backup transport and adds the extra depending on whether the user has
161      * rights to see backup settings.
162      *
163      * @return Intent to launch Backup settings provided by the Backup transport.
164      */
165     @VisibleForTesting
getIntentForBackupSettingsFromTransport()166     Intent getIntentForBackupSettingsFromTransport() {
167         Intent intent = getIntentFromBackupTransport();
168         if (intent != null) {
169             intent.putExtra(BackupManager.EXTRA_BACKUP_SERVICES_AVAILABLE, isBackupServiceActive());
170         }
171         return intent;
172     }
173 
getIntentForDefaultBackupSettings()174     private Intent getIntentForDefaultBackupSettings() {
175         return new Intent(mContext, PrivacySettingsActivity.class);
176     }
177 
178     /**
179      * Checks if the transport provided the intent to launch the backup settings and if that
180      * intent resolves to an activity.
181      */
182     @VisibleForTesting
isIntentProvidedByTransport()183     boolean isIntentProvidedByTransport() {
184         Intent intent = getIntentFromBackupTransport();
185         return intent != null && intent.resolveActivity(mContext.getPackageManager()) != null;
186     }
187 
188     /**
189      * Gets an intent to launch the backup settings from the current transport using
190      * {@link com.android.internal.backup.IBackupTransport#dataManagementIntent()} API.
191      *
192      * @return intent provided by transport or null if no intent was provided.
193      */
getIntentFromBackupTransport()194     private Intent getIntentFromBackupTransport() {
195         try {
196             Intent intent =
197                     mBackupManager.getDataManagementIntent(mBackupManager.getCurrentTransport());
198             if (Log.isLoggable(TAG, Log.DEBUG)) {
199                 if (intent != null) {
200                     Log.d(TAG, "Parsed intent from backup transport: " + intent.toString());
201                 } else {
202                     Log.d(TAG, "Received a null intent from backup transport");
203                 }
204             }
205             return intent;
206         } catch (RemoteException e) {
207             Log.e(TAG, "Error getting data management intent", e);
208         }
209         return null;
210     }
211 
212     /** Checks if backup service is enabled for this user. */
isBackupServiceActive()213     public boolean isBackupServiceActive() {
214         boolean backupOkay;
215         try {
216             backupOkay = mBackupManager.isBackupServiceActive(UserHandle.myUserId());
217         } catch (Exception e) {
218             // things go wrong talking to the backup system => ignore and
219             // pass the default 'false' as the "backup is a thing?" state.
220             backupOkay = false;
221         }
222         return backupOkay;
223     }
224 
225     @VisibleForTesting
getLabelFromBackupTransport()226     CharSequence getLabelFromBackupTransport() {
227         try {
228             CharSequence label =
229                     mBackupManager.getDataManagementLabelForUser(
230                             UserHandle.myUserId(), mBackupManager.getCurrentTransport());
231             if (Log.isLoggable(TAG, Log.DEBUG)) {
232                 Log.d(TAG, "Received the backup settings label from backup transport: " + label);
233             }
234             return label;
235         } catch (RemoteException e) {
236             Log.e(TAG, "Error getting data management label", e);
237         }
238         return null;
239     }
240 
241     @VisibleForTesting
getSummaryFromBackupTransport()242     String getSummaryFromBackupTransport() {
243         try {
244             String summary =
245                     mBackupManager.getDestinationString(mBackupManager.getCurrentTransport());
246             if (Log.isLoggable(TAG, Log.DEBUG)) {
247                 Log.d(TAG,
248                         "Received the backup settings summary from backup transport: " + summary);
249             }
250             return summary;
251         } catch (RemoteException e) {
252             Log.e(TAG, "Error getting data management summary", e);
253         }
254         return null;
255     }
256 }
257