Home | History | Annotate | Download | only in mtp
      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 android.mtp;
     18 
     19 import com.android.internal.util.Preconditions;
     20 
     21 import android.content.Context;
     22 import android.content.SharedPreferences;
     23 import android.util.ByteStringUtils;
     24 
     25 import java.io.FileDescriptor;
     26 import java.util.Random;
     27 
     28 /**
     29  * Java wrapper for MTP/PTP support as USB responder.
     30  * {@hide}
     31  */
     32 public class MtpServer implements Runnable {
     33 
     34     private long mNativeContext; // accessed by native methods
     35     private final MtpDatabase mDatabase;
     36     private final Runnable mOnTerminate;
     37     private final Context mContext;
     38 
     39 // It requires "exactly 32 characters, including any leading 0s" in MTP spec
     40 // (5.1.1.14 Serial Number)
     41     private static final int sID_LEN_BYTES = 16;
     42     private static final int sID_LEN_STR = (sID_LEN_BYTES * 2);
     43 
     44     static {
     45         System.loadLibrary("media_jni");
     46     }
     47 
     48     public MtpServer(
     49             MtpDatabase database,
     50             FileDescriptor controlFd,
     51             boolean usePtp,
     52             Runnable onTerminate,
     53             String deviceInfoManufacturer,
     54             String deviceInfoModel,
     55             String deviceInfoDeviceVersion) {
     56         mDatabase = Preconditions.checkNotNull(database);
     57         mOnTerminate = Preconditions.checkNotNull(onTerminate);
     58         mContext = mDatabase.getContext();
     59 
     60         final String strID_PREFS_NAME = "mtp-cfg";
     61         final String strID_PREFS_KEY = "mtp-id";
     62         String strRandomId = null;
     63         String deviceInfoSerialNumber;
     64 
     65         SharedPreferences sharedPref =
     66                 mContext.getSharedPreferences(strID_PREFS_NAME, Context.MODE_PRIVATE);
     67         if (sharedPref.contains(strID_PREFS_KEY)) {
     68             strRandomId = sharedPref.getString(strID_PREFS_KEY, null);
     69 
     70             // Check for format consistence (regenerate upon corruption)
     71             if (strRandomId.length() != sID_LEN_STR) {
     72                 strRandomId = null;
     73             } else {
     74                 // Only accept hex digit
     75                 for (int ii = 0; ii < strRandomId.length(); ii++)
     76                     if (Character.digit(strRandomId.charAt(ii), 16) == -1) {
     77                         strRandomId = null;
     78                         break;
     79                     }
     80             }
     81         }
     82 
     83         if (strRandomId == null) {
     84             strRandomId = getRandId();
     85             sharedPref.edit().putString(strID_PREFS_KEY, strRandomId).apply();
     86         }
     87 
     88         deviceInfoSerialNumber = strRandomId;
     89 
     90         native_setup(
     91                 database,
     92                 controlFd,
     93                 usePtp,
     94                 deviceInfoManufacturer,
     95                 deviceInfoModel,
     96                 deviceInfoDeviceVersion,
     97                 deviceInfoSerialNumber);
     98         database.setServer(this);
     99     }
    100 
    101     private String getRandId() {
    102         Random randomVal = new Random();
    103         byte[] randomBytes = new byte[sID_LEN_BYTES];
    104 
    105         randomVal.nextBytes(randomBytes);
    106         return ByteStringUtils.toHexString(randomBytes);
    107     }
    108 
    109     public void start() {
    110         Thread thread = new Thread(this, "MtpServer");
    111         thread.start();
    112     }
    113 
    114     @Override
    115     public void run() {
    116         native_run();
    117         native_cleanup();
    118         mDatabase.close();
    119         mOnTerminate.run();
    120     }
    121 
    122     public void sendObjectAdded(int handle) {
    123         native_send_object_added(handle);
    124     }
    125 
    126     public void sendObjectRemoved(int handle) {
    127         native_send_object_removed(handle);
    128     }
    129 
    130     public void sendObjectInfoChanged(int handle) {
    131         native_send_object_info_changed(handle);
    132     }
    133 
    134     public void sendDevicePropertyChanged(int property) {
    135         native_send_device_property_changed(property);
    136     }
    137 
    138     public void addStorage(MtpStorage storage) {
    139         native_add_storage(storage);
    140     }
    141 
    142     public void removeStorage(MtpStorage storage) {
    143         native_remove_storage(storage.getStorageId());
    144     }
    145 
    146     public static void configure(boolean usePtp) {
    147         native_configure(usePtp);
    148     }
    149 
    150     public static native final void native_configure(boolean usePtp);
    151     private native final void native_setup(
    152             MtpDatabase database,
    153             FileDescriptor controlFd,
    154             boolean usePtp,
    155             String deviceInfoManufacturer,
    156             String deviceInfoModel,
    157             String deviceInfoDeviceVersion,
    158             String deviceInfoSerialNumber);
    159     private native final void native_run();
    160     private native final void native_cleanup();
    161     private native final void native_send_object_added(int handle);
    162     private native final void native_send_object_removed(int handle);
    163     private native final void native_send_object_info_changed(int handle);
    164     private native final void native_send_device_property_changed(int property);
    165     private native final void native_add_storage(MtpStorage storage);
    166     private native final void native_remove_storage(int storageId);
    167 }
    168