Home | History | Annotate | Download | only in os
      1 /*
      2  * Copyright (C) 2016 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.os;
     18 
     19 import android.util.Log;
     20 
     21 import com.android.internal.os.IShellCallback;
     22 
     23 /**
     24  * Special-purpose API for use with {@link IBinder#shellCommand IBinder.shellCommand} for
     25  * performing operations back on the invoking shell.
     26  * @hide
     27  */
     28 public class ShellCallback implements Parcelable {
     29     final static String TAG = "ShellCallback";
     30 
     31     final static boolean DEBUG = false;
     32 
     33     final boolean mLocal;
     34 
     35     IShellCallback mShellCallback;
     36 
     37     class MyShellCallback extends IShellCallback.Stub {
     38         public ParcelFileDescriptor openFile(String path, String seLinuxContext,
     39                 String mode) {
     40             return onOpenFile(path, seLinuxContext, mode);
     41         }
     42     }
     43 
     44     /**
     45      * Create a new ShellCallback to receive requests.
     46      */
     47     public ShellCallback() {
     48         mLocal = true;
     49     }
     50 
     51     /**
     52      * Ask the shell to open a file.  If opening for writing, will truncate the file if it
     53      * already exists and will create the file if it doesn't exist.
     54      * @param path Path of the file to be opened/created.
     55      * @param seLinuxContext Optional SELinux context that must be allowed to have
     56      * access to the file; if null, nothing is required.
     57      * @param mode Mode to open file in: "r" for input/reading an existing file,
     58      * "r+" for reading/writing an existing file, "w" for output/writing a new file (either
     59      * creating or truncating an existing one), "w+" for reading/writing a new file (either
     60      * creating or truncating an existing one).
     61      */
     62     public ParcelFileDescriptor openFile(String path, String seLinuxContext, String mode) {
     63         if (DEBUG) Log.d(TAG, "openFile " + this + " mode=" + mode + ": mLocal=" + mLocal
     64                 + " mShellCallback=" + mShellCallback);
     65 
     66         if (mLocal) {
     67             return onOpenFile(path, seLinuxContext, mode);
     68         }
     69 
     70         if (mShellCallback != null) {
     71             try {
     72                 return mShellCallback.openFile(path, seLinuxContext, mode);
     73             } catch (RemoteException e) {
     74                 Log.w(TAG, "Failure opening " + path, e);
     75             }
     76         }
     77         return null;
     78     }
     79 
     80     public ParcelFileDescriptor onOpenFile(String path, String seLinuxContext, String mode) {
     81         return null;
     82     }
     83 
     84     public static void writeToParcel(ShellCallback callback, Parcel out) {
     85         if (callback == null) {
     86             out.writeStrongBinder(null);
     87         } else {
     88             callback.writeToParcel(out, 0);
     89         }
     90     }
     91 
     92     public int describeContents() {
     93         return 0;
     94     }
     95 
     96     public void writeToParcel(Parcel out, int flags) {
     97         synchronized (this) {
     98             if (mShellCallback == null) {
     99                 mShellCallback = new MyShellCallback();
    100             }
    101             out.writeStrongBinder(mShellCallback.asBinder());
    102         }
    103     }
    104 
    105     ShellCallback(Parcel in) {
    106         mLocal = false;
    107         mShellCallback = IShellCallback.Stub.asInterface(in.readStrongBinder());
    108         if (mShellCallback != null) {
    109             Binder.allowBlocking(mShellCallback.asBinder());
    110         }
    111     }
    112 
    113     public static final @android.annotation.NonNull Parcelable.Creator<ShellCallback> CREATOR
    114             = new Parcelable.Creator<ShellCallback>() {
    115         public ShellCallback createFromParcel(Parcel in) {
    116             return new ShellCallback(in);
    117         }
    118         public ShellCallback[] newArray(int size) {
    119             return new ShellCallback[size];
    120         }
    121     };
    122 }
    123