1 /*
2  * Copyright (C) 2015 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.storage;
18 
19 import android.app.Activity;
20 import android.app.Fragment;
21 import android.content.BroadcastReceiver;
22 import android.content.Context;
23 import android.content.Intent;
24 import android.content.IntentFilter;
25 import android.os.Bundle;
26 import android.os.Handler;
27 import android.os.storage.StorageManager;
28 import android.os.storage.VolumeInfo;
29 import android.text.TextUtils;
30 import android.view.View;
31 import android.widget.Toast;
32 
33 import androidx.annotation.NonNull;
34 import androidx.annotation.Nullable;
35 import androidx.leanback.app.GuidedStepFragment;
36 import androidx.leanback.widget.GuidanceStylist;
37 import androidx.leanback.widget.GuidedAction;
38 import androidx.localbroadcastmanager.content.LocalBroadcastManager;
39 
40 import com.android.tv.settings.R;
41 import com.android.tv.settings.dialog.ProgressDialogFragment;
42 
43 import java.util.List;
44 
45 public class UnmountActivity extends Activity {
46 
47     private static final String TAG = "UnmountActivity";
48 
49     public static final String EXTRA_VOLUME_DESC = "UnmountActivity.volumeDesc";
50 
51     private String mUnmountVolumeId;
52     private String mUnmountVolumeDesc;
53 
54     private final Handler mHandler = new Handler();
55     private final BroadcastReceiver mUnmountReceiver = new UnmountReceiver();
56 
getIntent(Context context, String volumeId, String volumeDesc)57     public static Intent getIntent(Context context, String volumeId, String volumeDesc) {
58         final Intent i = new Intent(context, UnmountActivity.class);
59         i.putExtra(VolumeInfo.EXTRA_VOLUME_ID, volumeId);
60         i.putExtra(EXTRA_VOLUME_DESC, volumeDesc);
61         return i;
62     }
63 
64     @Override
onCreate(@ullable Bundle savedInstanceState)65     protected void onCreate(@Nullable Bundle savedInstanceState) {
66         super.onCreate(savedInstanceState);
67 
68         mUnmountVolumeId = getIntent().getStringExtra(VolumeInfo.EXTRA_VOLUME_ID);
69         mUnmountVolumeDesc = getIntent().getStringExtra(EXTRA_VOLUME_DESC);
70 
71         LocalBroadcastManager.getInstance(this).registerReceiver(mUnmountReceiver,
72                 new IntentFilter(SettingsStorageService.ACTION_UNMOUNT));
73 
74         if (savedInstanceState == null) {
75             final StorageManager storageManager = getSystemService(StorageManager.class);
76             final VolumeInfo volumeInfo = storageManager.findVolumeById(mUnmountVolumeId);
77 
78             if (volumeInfo == null) {
79                 // Unmounted already, just bail
80                 finish();
81                 return;
82             }
83 
84             if (volumeInfo.getType() == VolumeInfo.TYPE_PRIVATE) {
85                 final Fragment fragment = UnmountPrivateStepFragment.newInstance(mUnmountVolumeId);
86                 getFragmentManager().beginTransaction()
87                         .replace(android.R.id.content, fragment)
88                         .commit();
89             } else {
90                 // Jump straight to unmounting
91                 onRequestUnmount();
92             }
93         }
94     }
95 
96     @Override
onDestroy()97     protected void onDestroy() {
98         super.onDestroy();
99 
100         LocalBroadcastManager.getInstance(this).unregisterReceiver(mUnmountReceiver);
101     }
102 
onRequestUnmount()103     public void onRequestUnmount() {
104         final Fragment fragment = UnmountProgressFragment.newInstance(mUnmountVolumeDesc);
105         getFragmentManager().beginTransaction()
106                 .replace(android.R.id.content, fragment)
107                 .commit();
108         // Post this so that it will presumably run after onResume, if we're calling from onCreate()
109         mHandler.post(new Runnable() {
110             @Override
111             public void run() {
112                 SettingsStorageService.unmount(UnmountActivity.this, mUnmountVolumeId);
113             }
114         });
115     }
116 
117     @Override
onResume()118     protected void onResume() {
119         super.onResume();
120         final VolumeInfo volumeInfo =
121                 getSystemService(StorageManager.class).findVolumeById(mUnmountVolumeId);
122 
123         if (volumeInfo == null) {
124             // Unmounted already, just bail
125             finish();
126         }
127     }
128 
129     private class UnmountReceiver extends BroadcastReceiver {
130 
131         @Override
onReceive(Context context, Intent intent)132         public void onReceive(Context context, Intent intent) {
133             if (TextUtils.equals(intent.getAction(), SettingsStorageService.ACTION_UNMOUNT)
134                     && TextUtils.equals(intent.getStringExtra(VolumeInfo.EXTRA_VOLUME_ID),
135                     mUnmountVolumeId)) {
136                 final Boolean success =
137                         intent.getBooleanExtra(SettingsStorageService.EXTRA_SUCCESS, false);
138                 if (success) {
139                     Toast.makeText(context,
140                             getString(R.string.storage_unmount_success, mUnmountVolumeDesc),
141                             Toast.LENGTH_SHORT).show();
142                 } else {
143                     Toast.makeText(context,
144                             getString(R.string.storage_unmount_failure, mUnmountVolumeDesc),
145                             Toast.LENGTH_SHORT).show();
146                 }
147                 finish();
148             }
149         }
150     }
151 
152     public static class UnmountPrivateStepFragment extends GuidedStepFragment {
153 
154         private static final int ACTION_ID_UNMOUNT = 1;
155 
newInstance(String volumeId)156         public static UnmountPrivateStepFragment newInstance(String volumeId) {
157             final UnmountPrivateStepFragment fragment = new UnmountPrivateStepFragment();
158             final Bundle b = new Bundle(1);
159             b.putString(VolumeInfo.EXTRA_VOLUME_ID, volumeId);
160             fragment.setArguments(b);
161             return fragment;
162         }
163 
164         @Override
165         public @NonNull
onCreateGuidance(Bundle savedInstanceState)166         GuidanceStylist.Guidance onCreateGuidance(Bundle savedInstanceState) {
167             return new GuidanceStylist.Guidance(
168                     getString(R.string.storage_wizard_eject_private_title),
169                     getString(R.string.storage_wizard_eject_private_description), "",
170                     getActivity().getDrawable(R.drawable.ic_storage_132dp));
171         }
172 
173         @Override
onCreateActions(@onNull List<GuidedAction> actions, Bundle savedInstanceState)174         public void onCreateActions(@NonNull List<GuidedAction> actions, Bundle savedInstanceState) {
175             actions.add(new GuidedAction.Builder(getContext())
176                     .clickAction(GuidedAction.ACTION_ID_CANCEL)
177                     .build());
178             actions.add(new GuidedAction.Builder(getContext())
179                     .id(ACTION_ID_UNMOUNT)
180                     .title(getString(R.string.storage_eject))
181                     .build());
182         }
183 
184         @Override
onGuidedActionClicked(GuidedAction action)185         public void onGuidedActionClicked(GuidedAction action) {
186             final long id = action.getId();
187 
188             if (id == GuidedAction.ACTION_ID_CANCEL) {
189                 if (!getFragmentManager().popBackStackImmediate()) {
190                     getActivity().finish();
191                 }
192             } else if (id == ACTION_ID_UNMOUNT) {
193                 ((UnmountActivity) getActivity()).onRequestUnmount();
194             }
195         }
196     }
197 
198     public static class UnmountProgressFragment extends ProgressDialogFragment {
199 
200         private static final String ARG_DESCRIPTION = "description";
201 
newInstance(CharSequence description)202         public static UnmountProgressFragment newInstance(CharSequence description) {
203             final Bundle b = new Bundle(1);
204             b.putCharSequence(ARG_DESCRIPTION, description);
205             final UnmountProgressFragment fragment = new UnmountProgressFragment();
206             fragment.setArguments(b);
207             return fragment;
208         }
209 
210         @Override
onViewCreated(View view, @Nullable Bundle savedInstanceState)211         public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {
212             super.onViewCreated(view, savedInstanceState);
213             final CharSequence description = getArguments().getCharSequence(ARG_DESCRIPTION);
214             setTitle(getActivity().getString(R.string.storage_wizard_eject_progress_title,
215                     description));
216         }
217     }
218 }
219