1 /*
2  * Copyright (C) 2020 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.development.storage;
18 
19 import android.app.ActionBar;
20 import android.app.ListActivity;
21 import android.app.blob.BlobInfo;
22 import android.app.blob.BlobStoreManager;
23 import android.content.Context;
24 import android.content.DialogInterface;
25 import android.content.Intent;
26 import android.os.Bundle;
27 import android.os.UserHandle;
28 import android.util.Log;
29 import android.view.LayoutInflater;
30 import android.view.View;
31 import android.view.ViewGroup;
32 import android.widget.ArrayAdapter;
33 import android.widget.ListView;
34 import android.widget.Toast;
35 
36 import androidx.appcompat.app.AlertDialog;
37 
38 import com.android.internal.util.CollectionUtils;
39 import com.android.settings.R;
40 
41 import java.io.IOException;
42 import java.util.List;
43 
44 public class BlobInfoListView extends ListActivity {
45     private static final String TAG = "BlobInfoListView";
46 
47     private Context mContext;
48     private BlobStoreManager mBlobStoreManager;
49     private BlobListAdapter mAdapter;
50     private LayoutInflater mInflater;
51 
52     @Override
onCreate(Bundle savedInstanceState)53     protected void onCreate(Bundle savedInstanceState) {
54         super.onCreate(savedInstanceState);
55         mContext = this;
56 
57         mBlobStoreManager = (BlobStoreManager) getSystemService(BlobStoreManager.class);
58         mInflater = (LayoutInflater) getSystemService(LayoutInflater.class);
59 
60         mAdapter = new BlobListAdapter(this);
61         setListAdapter(mAdapter);
62 
63         final ActionBar actionBar = getActionBar();
64         if (actionBar != null) {
65             actionBar.setDisplayHomeAsUpEnabled(true);
66         }
67     }
68 
69     @Override
onNavigateUp()70     public boolean onNavigateUp() {
71         finish();
72         return true;
73     }
74 
75     @Override
onResume()76     protected void onResume() {
77         super.onResume();
78         queryBlobsAndUpdateList();
79     }
80 
81     @Override
onActivityResult(int requestCode, int resultCode, Intent data)82     protected void onActivityResult(int requestCode, int resultCode, Intent data) {
83         super.onActivityResult(requestCode, resultCode, data);
84         if (requestCode == SharedDataUtils.LEASE_VIEW_REQUEST_CODE
85                 && resultCode == SharedDataUtils.LEASE_VIEW_RESULT_CODE_FAILURE) {
86             Toast.makeText(this, com.android.settingslib.R.string.shared_data_delete_failure_text,
87                             Toast.LENGTH_LONG)
88                     .show();
89         }
90         // do nothing on LEASE_VIEW_RESULT_CODE_SUCCESS since data is updated in onResume()
91     }
92 
93     @Override
onListItemClick(ListView l, View v, int position, long id)94     protected void onListItemClick(ListView l, View v, int position, long id) {
95         final BlobInfo blob = mAdapter.getItem(position);
96         if (CollectionUtils.isEmpty(blob.getLeases())) {
97             showDeleteBlobDialog(blob);
98         } else {
99             final Intent intent = new Intent(this, LeaseInfoListView.class);
100             intent.putExtra(SharedDataUtils.BLOB_KEY, blob);
101             startActivityForResult(intent, SharedDataUtils.LEASE_VIEW_REQUEST_CODE);
102         }
103     }
104 
showDeleteBlobDialog(BlobInfo blob)105     private void showDeleteBlobDialog(BlobInfo blob) {
106         final AlertDialog dialog = new AlertDialog.Builder(mContext)
107                 .setMessage(com.android.settingslib.R.string.shared_data_no_accessors_dialog_text)
108                 .setPositiveButton(android.R.string.ok, getDialogOnClickListener(blob))
109                 .setNegativeButton(android.R.string.cancel, null)
110                 .create();
111         dialog.show();
112     }
113 
getDialogOnClickListener(BlobInfo blob)114     private DialogInterface.OnClickListener getDialogOnClickListener(BlobInfo blob) {
115         return (dialog, which) -> {
116             try {
117                 mBlobStoreManager.deleteBlob(blob);
118             } catch (IOException e) {
119                 Log.e(TAG, "Unable to delete blob: " + e.getMessage());
120                 Toast.makeText(this,
121                                 com.android.settingslib.R.string.shared_data_delete_failure_text,
122                                 Toast.LENGTH_LONG)
123                         .show();
124             }
125             queryBlobsAndUpdateList();
126         };
127     }
128 
129     private void queryBlobsAndUpdateList() {
130         try {
131             mAdapter.updateList(mBlobStoreManager.queryBlobsForUser(UserHandle.CURRENT));
132         } catch (IOException e) {
133             Log.e(TAG, "Unable to fetch blobs for current user: " + e.getMessage());
134             Toast.makeText(this, com.android.settingslib.R.string.shared_data_query_failure_text,
135                     Toast.LENGTH_LONG).show();
136             finish();
137         }
138     }
139 
140     private class BlobListAdapter extends ArrayAdapter<BlobInfo> {
141         BlobListAdapter(Context context) {
142             super(context, 0);
143         }
144 
145         void updateList(List<BlobInfo> blobs) {
146             clear();
147             if (blobs.isEmpty()) {
148                 finish();
149             } else {
150                 addAll(blobs);
151             }
152         }
153 
154         @Override
155         public View getView(int position, View convertView, ViewGroup parent) {
156             final BlobInfoViewHolder holder = BlobInfoViewHolder.createOrRecycle(
157                     mInflater, convertView);
158             convertView = holder.rootView;
159 
160             final BlobInfo blob = getItem(position);
161             holder.blobLabel.setText(blob.getLabel());
162             holder.blobId.setText(
163                     getString(com.android.settingslib.R.string.blob_id_text, blob.getId()));
164             holder.blobExpiry.setText(formatExpiryTime(blob.getExpiryTimeMs()));
165             holder.blobSize.setText(SharedDataUtils.formatSize(blob.getSizeBytes()));
166             return convertView;
167         }
168 
169         private String formatExpiryTime(long expiryTimeMs) {
170             if (expiryTimeMs == 0) {
171                 return getString(R.string.blob_never_expires_text);
172             }
173             return getString(com.android.settingslib.R.string.blob_expires_text,
174                     SharedDataUtils.formatTime(expiryTimeMs));
175         }
176     }
177 }
178