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 { openFile(String path, String seLinuxContext, String mode)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 */ ShellCallback()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 */ openFile(String path, String seLinuxContext, String mode)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 onOpenFile(String path, String seLinuxContext, String mode)80 public ParcelFileDescriptor onOpenFile(String path, String seLinuxContext, String mode) { 81 return null; 82 } 83 writeToParcel(ShellCallback callback, Parcel out)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 describeContents()92 public int describeContents() { 93 return 0; 94 } 95 writeToParcel(Parcel out, int flags)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 getShellCallbackBinder()105 public IBinder getShellCallbackBinder() { 106 return mShellCallback.asBinder(); 107 } 108 ShellCallback(Parcel in)109 ShellCallback(Parcel in) { 110 mLocal = false; 111 mShellCallback = IShellCallback.Stub.asInterface(in.readStrongBinder()); 112 if (mShellCallback != null) { 113 Binder.allowBlocking(mShellCallback.asBinder()); 114 } 115 } 116 117 public static final @android.annotation.NonNull Parcelable.Creator<ShellCallback> CREATOR 118 = new Parcelable.Creator<ShellCallback>() { 119 public ShellCallback createFromParcel(Parcel in) { 120 return new ShellCallback(in); 121 } 122 public ShellCallback[] newArray(int size) { 123 return new ShellCallback[size]; 124 } 125 }; 126 } 127