Home | History | Annotate | Download | only in storage
      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.tv.settings.device.storage;
     18 
     19 import android.app.ActivityManager;
     20 import android.content.BroadcastReceiver;
     21 import android.content.Context;
     22 import android.content.Intent;
     23 import android.content.pm.UserInfo;
     24 import android.os.UserHandle;
     25 import android.os.UserManager;
     26 import android.os.storage.DiskInfo;
     27 import android.os.storage.StorageManager;
     28 import android.os.storage.VolumeInfo;
     29 import android.os.storage.VolumeRecord;
     30 import android.provider.Settings;
     31 import android.text.TextUtils;
     32 import android.util.Log;
     33 import android.widget.Toast;
     34 
     35 import com.android.tv.settings.R;
     36 
     37 import java.util.List;
     38 
     39 /**
     40  * Broadcast receiver invoked when a USB device is connected/disconnected/scanned.
     41  */
     42 public class DiskReceiver extends BroadcastReceiver {
     43     private static final String TAG = "DiskReceiver";
     44 
     45     private StorageManager mStorageManager;
     46 
     47     @Override
     48     public void onReceive(Context context, Intent intent) {
     49         final UserManager userManager =
     50                 (UserManager) context.getSystemService(Context.USER_SERVICE);
     51         final UserInfo userInfo = userManager.getUserInfo(UserHandle.myUserId());
     52 
     53         if (userInfo.isRestricted()
     54                 || ActivityManager.getCurrentUser() != UserHandle.myUserId()) {
     55             Log.d(TAG, "Ignoring storage notification: wrong user");
     56             return;
     57         }
     58 
     59         if (Settings.Secure.getInt(context.getContentResolver(),
     60                 Settings.Secure.USER_SETUP_COMPLETE, 0) == 0) {
     61             Log.d(TAG, "Ignoring storage notification: setup not complete");
     62             return;
     63         }
     64 
     65         mStorageManager = context.getSystemService(StorageManager.class);
     66 
     67         if (TextUtils.equals(intent.getAction(), VolumeInfo.ACTION_VOLUME_STATE_CHANGED)) {
     68             final int state = intent.getIntExtra(VolumeInfo.EXTRA_VOLUME_STATE, -1);
     69             if (state == VolumeInfo.STATE_MOUNTED
     70                     || state == VolumeInfo.STATE_MOUNTED_READ_ONLY) {
     71                 handleMount(context, intent);
     72             } else if (state == VolumeInfo.STATE_UNMOUNTED
     73                     || state == VolumeInfo.STATE_BAD_REMOVAL) {
     74                 handleUnmount(context, intent);
     75             }
     76         } else if (TextUtils.equals(intent.getAction(),
     77                 "com.google.android.tungsten.setupwraith.TV_SETTINGS_POST_SETUP")) {
     78             handleSetupComplete(context);
     79         }
     80     }
     81 
     82     private void handleMount(Context context, Intent intent) {
     83         final String volumeId = intent.getStringExtra(VolumeInfo.EXTRA_VOLUME_ID);
     84 
     85         final List<VolumeInfo> volumeInfos = mStorageManager.getVolumes();
     86         for (final VolumeInfo info : volumeInfos) {
     87             if (!TextUtils.equals(info.getId(), volumeId)) {
     88                 continue;
     89             }
     90             final String uuid = info.getFsUuid();
     91             Log.d(TAG, "Scanning volume: " + info);
     92             if (info.getType() == VolumeInfo.TYPE_PRIVATE
     93                     && !TextUtils.equals(volumeId, VolumeInfo.ID_PRIVATE_INTERNAL)) {
     94                 Toast.makeText(context, R.string.storage_mount_adopted, Toast.LENGTH_SHORT)
     95                     .show();
     96                 return;
     97             }
     98         }
     99     }
    100 
    101     private void handleUnmount(Context context, Intent intent) {
    102         final String fsUuid = intent.getStringExtra(VolumeRecord.EXTRA_FS_UUID);
    103         if (TextUtils.isEmpty(fsUuid)) {
    104             Log.e(TAG, "Missing fsUuid, not launching activity.");
    105             return;
    106         }
    107         VolumeRecord volumeRecord = null;
    108         try {
    109             volumeRecord = mStorageManager.findRecordByUuid(fsUuid);
    110         } catch (Exception e) {
    111             Log.e(TAG, "Error finding volume record", e);
    112         }
    113         if (volumeRecord == null) {
    114             return;
    115         }
    116         Log.d(TAG, "Found ejected volume: " + volumeRecord + " for FSUUID: " + fsUuid);
    117         if (volumeRecord.getType() == VolumeInfo.TYPE_PRIVATE) {
    118             final Intent i = NewStorageActivity.getMissingStorageLaunchIntent(context, fsUuid);
    119             setPopupLaunchFlags(i);
    120             context.startActivity(i);
    121         }
    122     }
    123 
    124     private void handleSetupComplete(Context context) {
    125         Log.d(TAG, "Scanning for storage post-setup");
    126 
    127         final List<DiskInfo> diskInfos = mStorageManager.getDisks();
    128         for (DiskInfo diskInfo : diskInfos) {
    129             Log.d(TAG, "Scanning disk: " + diskInfo);
    130             if (diskInfo.size <= 0) {
    131                 Log.d(TAG, "Disk ID " + diskInfo.id + " has no media");
    132                 continue;
    133             }
    134             if (diskInfo.volumeCount != 0) {
    135                 Log.d(TAG, "Disk ID " + diskInfo.id + " has usable volumes, deferring");
    136                 continue;
    137             }
    138             // No usable volumes, prompt the user to erase the disk
    139             final Intent i =
    140                     NewStorageActivity.getNewStorageLaunchIntent(context, null, diskInfo.id);
    141             setPopupLaunchFlags(i);
    142             context.startActivity(i);
    143             return;
    144         }
    145 
    146         final List<VolumeInfo> volumeInfos = mStorageManager.getVolumes();
    147         for (final VolumeInfo info : volumeInfos) {
    148             final String uuid = info.getFsUuid();
    149             Log.d(TAG, "Scanning volume: " + info);
    150             if (info.getType() != VolumeInfo.TYPE_PUBLIC || TextUtils.isEmpty(uuid)) {
    151                 continue;
    152             }
    153             final VolumeRecord record = mStorageManager.findRecordByUuid(uuid);
    154             if (record.isInited() || record.isSnoozed()) {
    155                 continue;
    156             }
    157             final DiskInfo disk = info.getDisk();
    158             if (disk.isAdoptable()) {
    159                 final Intent i = NewStorageActivity.getNewStorageLaunchIntent(context,
    160                         info.getId(), disk.getId());
    161                 setPopupLaunchFlags(i);
    162                 context.startActivity(i);
    163                 return;
    164             }
    165         }
    166     }
    167 
    168     private void setPopupLaunchFlags(Intent intent) {
    169         intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
    170     }
    171 }
    172