Home | History | Annotate | Download | only in privacy
      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.tv.settings.device.privacy;
     18 
     19 import com.android.tv.settings.ActionBehavior;
     20 import com.android.tv.settings.ActionKey;
     21 import com.android.tv.settings.R;
     22 import com.android.tv.settings.dialog.old.Action;
     23 import com.android.tv.settings.dialog.old.ActionAdapter;
     24 import com.android.tv.settings.dialog.old.ActionFragment;
     25 import com.android.tv.settings.dialog.old.ContentFragment;
     26 import com.android.tv.settings.dialog.old.DialogActivity;
     27 import com.android.tv.settings.util.IntentUtils;
     28 
     29 import android.app.ActivityManager;
     30 import android.app.AlertDialog;
     31 import android.app.Dialog;
     32 import android.app.backup.IBackupManager;
     33 import android.app.Fragment;
     34 import android.app.admin.DevicePolicyManager;
     35 import android.content.ComponentName;
     36 import android.content.Context;
     37 import android.content.DialogInterface;
     38 import android.content.Intent;
     39 import android.content.res.Resources;
     40 import android.os.Bundle;
     41 import android.os.RemoteException;
     42 import android.os.ServiceManager;
     43 import android.provider.Settings;
     44 
     45 import java.util.ArrayList;
     46 import java.util.Collections;
     47 import java.util.HashMap;
     48 import java.util.Map;
     49 
     50 /**
     51  * Activity that allows enabling and disabling of backup and restore functions.
     52  */
     53 public class PrivacyActivity extends DialogActivity
     54         implements ActionAdapter.Listener, DialogInterface.OnClickListener {
     55 
     56     private static final int DIALOG_ERASE_BACKUP = 2;
     57 
     58     /**
     59      * Support for shutdown-after-reset. If our launch intent has a true value for
     60      * the boolean extra under the following key, then include it in the intent we
     61      * use to trigger a factory reset. This will cause us to shut down instead of
     62      * restart after the reset.
     63      */
     64     private static final String SHUTDOWN_INTENT_EXTRA = "shutdown";
     65 
     66     private IBackupManager mBackupManager;
     67     private ContentFragment mContentFragment;
     68     private ActionFragment mActionFragment;
     69     private Dialog mConfirmDialog;
     70     private int mDialogType;
     71 
     72     @Override
     73     protected void onCreate(Bundle savedInstanceState) {
     74         super.onCreate(savedInstanceState);
     75 
     76         mBackupManager = IBackupManager.Stub.asInterface(
     77                 ServiceManager.getService(Context.BACKUP_SERVICE));
     78 
     79         // TODO implement backup and restore (b/10414565), then:
     80         // NOTE1: Don't disable backups in SetupCompletedFragment under
     81         // SetupWraith.
     82         // NOTE2: Do no call finish() in onFactoryReset() upon CANCEL.
     83         // NOTE3: Set breadcrumb to R.string.device_backup_restore for
     84         // createFactoryResetContentFragment().
     85         // NOTE4: Below call
     86         // createMainMenuContentFragment() and getMainActions()
     87         // instead of
     88         // createFactoryResetContentFragment() and getFactoryResetActions().
     89         // NOTE5: Change the backup_restore preference under res/xml/device to
     90         // device_backup_restore.
     91         mContentFragment = createFactoryResetContentFragment();
     92         mActionFragment = ActionFragment.newInstance(getFactoryResetActions());
     93         setContentAndActionFragments(mContentFragment, mActionFragment);
     94     }
     95 
     96     @Override
     97     public void onStop() {
     98         if (mConfirmDialog != null && mConfirmDialog.isShowing()) {
     99             mConfirmDialog.dismiss();
    100         }
    101         mConfirmDialog = null;
    102         mDialogType = 0;
    103         super.onStop();
    104     }
    105 
    106     @Override
    107     public void onClick(DialogInterface dialog, int which) {
    108         if (which == DialogInterface.BUTTON_POSITIVE) {
    109             if (mDialogType == DIALOG_ERASE_BACKUP) {
    110                 try {
    111                     mBackupManager.setBackupEnabled(false);
    112                 } catch (RemoteException e) {
    113                     // ignore.
    114                 }
    115                 goToMainScreen();
    116             }
    117         }
    118         mDialogType = 0;
    119     }
    120 
    121     @Override
    122     public void onActionClicked(Action action) {
    123         ActionKey<ActionType, ActionBehavior> actionKey = new ActionKey<ActionType, ActionBehavior>(
    124                 ActionType.class, ActionBehavior.class, action.getKey());
    125         ActionType type = actionKey.getType();
    126         ActionBehavior behaviour = actionKey.getBehavior();
    127         switch (actionKey.getType()) {
    128             case BACKUP_DATA:
    129                 onBackupData(behaviour);
    130                 break;
    131             case BACKUP_ACCOUNT:
    132                 onBackupAccount(behaviour);
    133                 break;
    134             case AUTOMATIC_RESTORE:
    135                 onAutomaticRestore(behaviour);
    136                 break;
    137             case FACTORY_RESET:
    138                 onFactoryReset(behaviour);
    139                 break;
    140             case FACTORY_RESET_CONFIRM:
    141                 onFactoryResetConfirm(behaviour);
    142                 break;
    143             default:
    144                 break;
    145         }
    146     }
    147 
    148     private void onFactoryReset(ActionBehavior behaviour) {
    149         switch (behaviour) {
    150             case INIT:
    151                 setContentAndActionFragments(createFactoryResetContentFragment(),
    152                         ActionFragment.newInstance(getFactoryResetActions()));
    153                 break;
    154             case CANCEL:
    155                 // TODO pop from backstack to go back to main menu after backups
    156                 // are implemented (b/10414565).
    157                 finish();
    158                 break;
    159             default:
    160                 break;
    161         }
    162     }
    163 
    164     private void onFactoryResetConfirm(ActionBehavior behaviour) {
    165         switch (behaviour) {
    166             case INIT:
    167                 setContentAndActionFragments(ContentFragment.newInstance(
    168                         ActionType.FACTORY_RESET_CONFIRM.getTitle(getResources()),
    169                         getString(R.string.device_reset),
    170                         getString(R.string.confirm_factory_reset_description),
    171                         R.drawable.ic_settings_backuprestore,
    172                         getResources().getColor(R.color.icon_background)),
    173                         ActionFragment.newInstance(getFactoryResetConfirmActions()));
    174                 break;
    175             case OK:
    176                 if (!ActivityManager.isUserAMonkey()) {
    177                     Intent resetIntent = new Intent("android.intent.action.MASTER_CLEAR");
    178                     if (getIntent().getBooleanExtra(SHUTDOWN_INTENT_EXTRA, false)) {
    179                         resetIntent.putExtra(SHUTDOWN_INTENT_EXTRA, true);
    180                     }
    181                     sendBroadcast(resetIntent);
    182                 }
    183                 break;
    184             case CANCEL:
    185                 getFragmentManager().popBackStack(null, 0);
    186                 getFragmentManager().popBackStack(null, 0);
    187                 break;
    188             default:
    189                 break;
    190         }
    191     }
    192 
    193     private ArrayList<Action> getFactoryResetActions() {
    194         ArrayList<Action> actions = new ArrayList<Action>();
    195         actions.add(new Action.Builder()
    196                 .key(new ActionKey<ActionType, ActionBehavior>(ActionType.FACTORY_RESET_CONFIRM,
    197                         ActionBehavior.INIT).getKey())
    198                 .title(getString(R.string.factory_reset_device))
    199                 .build());
    200         actions.add(new Action.Builder()
    201                 .key(new ActionKey<ActionType, ActionBehavior>(ActionType.FACTORY_RESET,
    202                         ActionBehavior.CANCEL).getKey())
    203                 .title(getString(R.string.settings_cancel))
    204                 .build());
    205         return actions;
    206     }
    207 
    208     private ArrayList<Action> getFactoryResetConfirmActions() {
    209         ArrayList<Action> actions = new ArrayList<Action>();
    210         actions.add(new Action.Builder()
    211                 .key(new ActionKey<ActionType, ActionBehavior>(ActionType.FACTORY_RESET_CONFIRM,
    212                         ActionBehavior.OK).getKey())
    213                 .title(getString(R.string.confirm_factory_reset_device))
    214                 .build());
    215         actions.add(new Action.Builder()
    216                 .key(new ActionKey<ActionType, ActionBehavior>(ActionType.FACTORY_RESET_CONFIRM,
    217                         ActionBehavior.CANCEL).getKey())
    218                 .title(getString(R.string.settings_cancel))
    219                 .build());
    220         return actions;
    221     }
    222 
    223     private void onBackupData(ActionBehavior behaviour) {
    224         try {
    225             boolean isOn = mBackupManager.isBackupEnabled();
    226             switch (behaviour) {
    227                 case INIT:
    228                     ArrayList<Action> actions = new ArrayList<Action>();
    229                     actions.add(ActionBehavior.ON.toAction(new ActionKey<
    230                             ActionType, ActionBehavior>(
    231                             ActionType.BACKUP_DATA, ActionBehavior.ON).getKey(),
    232                             getResources(), isOn));
    233                     actions.add(ActionBehavior.OFF.toAction(new ActionKey<
    234                             ActionType, ActionBehavior>(
    235                             ActionType.BACKUP_DATA, ActionBehavior.OFF).getKey(),
    236                             getResources(), !isOn));
    237                     setContentAndActionFragments(
    238                             createSubMenuContentFragment(ActionType.BACKUP_DATA),
    239                             ActionFragment.newInstance(actions));
    240                     break;
    241                 case ON:
    242                     if (!isOn) {
    243                         try {
    244                             mBackupManager.setBackupEnabled(true);
    245                         } catch (RemoteException e) {
    246                             // ignore.
    247                         }
    248                     }
    249                     goToMainScreen();
    250                     break;
    251                 case OFF:
    252                     if (isOn) {
    253                         mDialogType = DIALOG_ERASE_BACKUP;
    254                         CharSequence msg = getResources()
    255                                 .getText(R.string.backup_erase_dialog_message);
    256                         // TODO: DialogFragment?
    257                         mConfirmDialog = new AlertDialog.Builder(this).setMessage(msg)
    258                                 .setTitle(R.string.backup_erase_dialog_title)
    259                                 .setIconAttribute(android.R.attr.alertDialogIcon)
    260                                 .setPositiveButton(android.R.string.ok, this)
    261                                 .setNegativeButton(android.R.string.cancel, this).show();
    262                     }
    263                     goToMainScreen();
    264                     break;
    265                 default:
    266                     break;
    267             }
    268         } catch (RemoteException e) {
    269             // ignore.
    270         }
    271     }
    272 
    273     private void onBackupAccount(ActionBehavior behaviour) {
    274         try {
    275             String transport = mBackupManager.getCurrentTransport();
    276             Intent configIntent = mBackupManager.getConfigurationIntent(transport);
    277             if (configIntent != null) {
    278                 IntentUtils.startActivity(this, configIntent);
    279             }
    280         } catch (RemoteException e) {
    281             // ignore.
    282         }
    283     }
    284 
    285     private void onAutomaticRestore(ActionBehavior behaviour) {
    286         boolean isOn = isAutoRestoreEnabled();
    287         switch (behaviour) {
    288             case INIT:
    289                 ArrayList<Action> actions = new ArrayList<Action>();
    290                 actions.add(ActionBehavior.ON.toAction(new ActionKey<ActionType, ActionBehavior>(
    291                         ActionType.AUTOMATIC_RESTORE, ActionBehavior.ON).getKey(), getResources(),
    292                         isOn));
    293                 actions.add(ActionBehavior.OFF.toAction(new ActionKey<ActionType, ActionBehavior>(
    294                         ActionType.AUTOMATIC_RESTORE, ActionBehavior.OFF).getKey(), getResources(),
    295                         !isOn));
    296                 setContentAndActionFragments(
    297                         createSubMenuContentFragment(ActionType.AUTOMATIC_RESTORE),
    298                         ActionFragment.newInstance(actions));
    299                 break;
    300             case ON:
    301                 if (!isOn) {
    302                     try {
    303                         mBackupManager.setAutoRestore(true);
    304                     } catch (RemoteException e) {
    305                         // ignore.
    306                     }
    307                 }
    308                 goToMainScreen();
    309                 break;
    310             case OFF:
    311                 if (isOn) {
    312                     try {
    313                         mBackupManager.setAutoRestore(false);
    314                     } catch (RemoteException e) {
    315                         // ignore.
    316                     }
    317                 }
    318                 goToMainScreen();
    319                 break;
    320             default:
    321                 break;
    322         }
    323     }
    324 
    325     private boolean isAutoRestoreEnabled() {
    326         return Settings.Secure.getInt(getContentResolver(), Settings.Secure.BACKUP_AUTO_RESTORE, 1)
    327                 == 1;
    328     }
    329 
    330     private void goToMainScreen() {
    331         updateMainScreen();
    332         getFragmentManager().popBackStack(null, 0);
    333     }
    334 
    335     private ArrayList<Action> getMainActions() {
    336         ArrayList<Action> actions = new ArrayList<Action>();
    337 
    338         try {
    339             boolean isBackupEnabled = mBackupManager.isBackupEnabled();
    340             String transport = mBackupManager.getCurrentTransport();
    341             Intent configIntent = mBackupManager.getConfigurationIntent(transport);
    342             String configSummary = mBackupManager.getDestinationString(transport);
    343 
    344             actions.add(ActionType.BACKUP_DATA.toAction(getResources(),
    345                     mBackupManager.isBackupEnabled() ? getString(R.string.settings_on)
    346                             : getString(R.string.settings_off)));
    347             if (isBackupEnabled && configIntent != null) {
    348                 actions.add(ActionType.BACKUP_ACCOUNT.toAction(
    349                         getResources(), configSummary == null ? getString(
    350                                 R.string.backup_configure_account_default_summary)
    351                                 : configSummary));
    352             }
    353             if (isBackupEnabled) {
    354                 actions.add(ActionType.AUTOMATIC_RESTORE.toAction(
    355                         getResources(), isAutoRestoreEnabled() ? getString(R.string.settings_on)
    356                                 : getString(R.string.settings_off)));
    357             }
    358 
    359         } catch (RemoteException re) {
    360             // no backup manager means no actions.
    361         }
    362 
    363         actions.add(ActionType.FACTORY_RESET.toAction(getResources(), null));
    364 
    365         return actions;
    366     }
    367 
    368     private Fragment createSubMenuContentFragment(ActionType type) {
    369         return ContentFragment.newInstance(type.getTitle(getResources()),
    370                 getString(R.string.device_backup_restore), null,
    371                 R.drawable.ic_settings_backuprestore,
    372                 getResources().getColor(R.color.icon_background));
    373     }
    374 
    375     private ContentFragment createMainMenuContentFragment() {
    376         return ContentFragment.newInstance(getString(R.string.device_backup_restore),
    377                 getString(R.string.header_category_device),
    378                 null, R.drawable.ic_settings_backuprestore,
    379                 getResources().getColor(R.color.icon_background));
    380     }
    381 
    382     private ContentFragment createFactoryResetContentFragment() {
    383         // TODO Set breadcrumb to R.string.device_backup_restore b/10414565
    384         return ContentFragment.newInstance(
    385                 ActionType.FACTORY_RESET.getTitle(getResources()),
    386                 getString(R.string.header_category_device),
    387                 getString(R.string.factory_reset_description),
    388                 R.drawable.ic_settings_backuprestore,
    389                 getResources().getColor(R.color.icon_background));
    390     }
    391 
    392     private void updateMainScreen() {
    393         ((ActionAdapter) mActionFragment.getAdapter()).setActions(getMainActions());
    394     }
    395 }
    396