Home | History | Annotate | Download | only in media
      1 /*
      2  * Copyright (C) 2010 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.providers.media;
     18 
     19 import android.app.KeyguardManager;
     20 import android.app.Service;
     21 import android.content.BroadcastReceiver;
     22 import android.content.Context;
     23 import android.content.Intent;
     24 import android.content.IntentFilter;
     25 import android.hardware.usb.UsbManager;
     26 import android.mtp.MtpDatabase;
     27 import android.mtp.MtpServer;
     28 import android.mtp.MtpStorage;
     29 import android.os.Environment;
     30 import android.os.Handler;
     31 import android.os.IBinder;
     32 import android.os.storage.StorageEventListener;
     33 import android.os.storage.StorageManager;
     34 import android.os.storage.StorageVolume;
     35 import android.provider.Settings;
     36 import android.util.Log;
     37 
     38 import java.util.HashMap;
     39 
     40 public class MtpService extends Service {
     41     private static final String TAG = "MtpService";
     42 
     43     private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
     44         @Override
     45         public void onReceive(Context context, Intent intent) {
     46             final String action = intent.getAction();
     47             if (Intent.ACTION_USER_PRESENT.equals(action)) {
     48                 synchronized (mBinder) {
     49                     // Unhide the storage units when the user has unlocked the lockscreen
     50                     if (mMtpDisabled) {
     51                         for (MtpStorage storage : mStorageMap.values()) {
     52                             addStorageLocked(storage);
     53                         }
     54                         mMtpDisabled = false;
     55                     }
     56                 }
     57             }
     58         }
     59     };
     60 
     61     private final StorageEventListener mStorageEventListener = new StorageEventListener() {
     62         public void onStorageStateChanged(String path, String oldState, String newState) {
     63             synchronized (mBinder) {
     64                 Log.d(TAG, "onStorageStateChanged " + path + " " + oldState + " -> " + newState);
     65                 if (Environment.MEDIA_MOUNTED.equals(newState)) {
     66                     volumeMountedLocked(path);
     67                 } else if (Environment.MEDIA_MOUNTED.equals(oldState)) {
     68                     MtpStorage storage = mStorageMap.remove(path);
     69                     if (storage != null) {
     70                         removeStorageLocked(storage);
     71                     }
     72                 }
     73             }
     74         }
     75     };
     76 
     77     private MtpDatabase mDatabase;
     78     private MtpServer mServer;
     79     private StorageManager mStorageManager;
     80     private boolean mMtpDisabled; // true if MTP is disabled due to secure keyguard
     81     private final HashMap<String, MtpStorage> mStorageMap = new HashMap<String, MtpStorage>();
     82     private StorageVolume[] mVolumes;
     83 
     84     @Override
     85     public void onCreate() {
     86         // lock MTP if the keyguard is locked and secure
     87         KeyguardManager keyguardManager =
     88                 (KeyguardManager)getSystemService(Context.KEYGUARD_SERVICE);
     89         mMtpDisabled = keyguardManager.isKeyguardLocked() && keyguardManager.isKeyguardSecure();
     90         registerReceiver(mReceiver, new IntentFilter(Intent.ACTION_USER_PRESENT));
     91 
     92         mStorageManager = (StorageManager)getSystemService(Context.STORAGE_SERVICE);
     93         synchronized (mBinder) {
     94             mStorageManager.registerListener(mStorageEventListener);
     95             StorageVolume[] volumes = mStorageManager.getVolumeList();
     96             mVolumes = volumes;
     97             for (int i = 0; i < volumes.length; i++) {
     98                 String path = volumes[i].getPath();
     99                 String state = mStorageManager.getVolumeState(path);
    100                 if (Environment.MEDIA_MOUNTED.equals(state)) {
    101                    volumeMountedLocked(path);
    102                 }
    103             }
    104         }
    105     }
    106 
    107     @Override
    108     public int onStartCommand(Intent intent, int flags, int startId) {
    109         synchronized (mBinder) {
    110             if (mServer == null) {
    111                 Log.d(TAG, "starting MTP server");
    112                 mDatabase = new MtpDatabase(this, MediaProvider.EXTERNAL_VOLUME,
    113                         mVolumes[0].getPath());
    114                 boolean usePtp = (intent == null ? false
    115                         : intent.getBooleanExtra(UsbManager.USB_FUNCTION_PTP, false));
    116                 mServer = new MtpServer(mDatabase, usePtp);
    117                 if (!mMtpDisabled) {
    118                     for (MtpStorage storage : mStorageMap.values()) {
    119                         addStorageLocked(storage);
    120                     }
    121                 }
    122                 mServer.start();
    123             }
    124         }
    125 
    126         return START_STICKY;
    127     }
    128 
    129     @Override
    130     public void onDestroy()
    131     {
    132         unregisterReceiver(mReceiver);
    133         mStorageManager.unregisterListener(mStorageEventListener);
    134     }
    135 
    136     private final IMtpService.Stub mBinder =
    137             new IMtpService.Stub() {
    138         public void sendObjectAdded(int objectHandle) {
    139             synchronized (mBinder) {
    140                 if (mServer != null) {
    141                     mServer.sendObjectAdded(objectHandle);
    142                 }
    143             }
    144         }
    145 
    146         public void sendObjectRemoved(int objectHandle) {
    147             synchronized (mBinder) {
    148                 if (mServer != null) {
    149                     mServer.sendObjectRemoved(objectHandle);
    150                 }
    151             }
    152         }
    153     };
    154 
    155     @Override
    156     public IBinder onBind(Intent intent)
    157     {
    158         return mBinder;
    159     }
    160 
    161     private void volumeMountedLocked(String path) {
    162         for (int i = 0; i < mVolumes.length; i++) {
    163             StorageVolume volume = mVolumes[i];
    164             if (volume.getPath().equals(path)) {
    165                 int storageId = MtpStorage.getStorageId(i);
    166                 long reserveSpace = volume.getMtpReserveSpace() * 1024 * 1024;
    167 
    168                 MtpStorage storage = new MtpStorage(volume);
    169                 mStorageMap.put(path, storage);
    170                 if (!mMtpDisabled) {
    171                     addStorageLocked(storage);
    172                 }
    173                 break;
    174             }
    175         }
    176     }
    177 
    178     private void addStorageLocked(MtpStorage storage) {
    179         Log.d(TAG, "addStorageLocked " + storage.getStorageId() + " " + storage.getPath());
    180         if (mDatabase != null) {
    181             mDatabase.addStorage(storage);
    182         }
    183         if (mServer != null) {
    184             mServer.addStorage(storage);
    185         }
    186     }
    187 
    188     private void removeStorageLocked(MtpStorage storage) {
    189         Log.d(TAG, "removeStorageLocked " + storage.getStorageId() + " " + storage.getPath());
    190         if (mDatabase != null) {
    191             mDatabase.removeStorage(storage);
    192         }
    193         if (mServer != null) {
    194             mServer.removeStorage(storage);
    195         }
    196     }
    197 }
    198 
    199