Loading api/system-current.txt +15 −0 Original line number Diff line number Diff line Loading @@ -29,6 +29,7 @@ package android { field public static final String BIND_CONTENT_SUGGESTIONS_SERVICE = "android.permission.BIND_CONTENT_SUGGESTIONS_SERVICE"; field public static final String BIND_DIRECTORY_SEARCH = "android.permission.BIND_DIRECTORY_SEARCH"; field public static final String BIND_EUICC_SERVICE = "android.permission.BIND_EUICC_SERVICE"; field public static final String BIND_EXTERNAL_STORAGE_SERVICE = "android.permission.BIND_EXTERNAL_STORAGE_SERVICE"; field public static final String BIND_IMS_SERVICE = "android.permission.BIND_IMS_SERVICE"; field public static final String BIND_KEYGUARD_APPWIDGET = "android.permission.BIND_KEYGUARD_APPWIDGET"; field public static final String BIND_NETWORK_RECOMMENDATION_SERVICE = "android.permission.BIND_NETWORK_RECOMMENDATION_SERVICE"; Loading Loading @@ -6767,6 +6768,20 @@ package android.service.sms { } package android.service.storage { public abstract class ExternalStorageService extends android.app.Service { ctor public ExternalStorageService(); method @NonNull public final android.os.IBinder onBind(@NonNull android.content.Intent); method public abstract void onEndSession(@NonNull String) throws java.io.IOException; method public abstract void onStartSession(@NonNull String, int, @NonNull android.os.ParcelFileDescriptor, @NonNull String, @NonNull String) throws java.io.IOException; field public static final int FLAG_SESSION_ATTRIBUTE_INDEXABLE = 2; // 0x2 field public static final int FLAG_SESSION_TYPE_FUSE = 1; // 0x1 field public static final String SERVICE_INTERFACE = "android.service.storage.ExternalStorageService"; } } package android.service.textclassifier { public abstract class TextClassifierService extends android.app.Service { Loading core/java/android/service/storage/ExternalStorageService.java 0 → 100644 +168 −0 Original line number Diff line number Diff line /* * Copyright (C) 2019 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package android.service.storage; import android.annotation.IntDef; import android.annotation.NonNull; import android.annotation.SdkConstant; import android.annotation.SystemApi; import android.app.Service; import android.content.Intent; import android.os.Bundle; import android.os.Handler; import android.os.IBinder; import android.os.Looper; import android.os.ParcelFileDescriptor; import android.os.ParcelableException; import android.os.RemoteCallback; import android.os.RemoteException; import java.io.IOException; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; /** * A service to handle filesystem I/O from other apps. * * <p>To extend this class, you must declare the service in your manifest file with the * {@link android.Manifest.permission#BIND_EXTERNAL_STORAGE_SERVICE} permission, * and include an intent filter with the {@link #SERVICE_INTERFACE} action. * For example:</p> * <pre> * <service android:name=".ExternalStorageServiceImpl" * android:exported="true" * android:priority="100" * android:permission="android.permission.BIND_EXTERNAL_STORAGE_SERVICE"> * <intent-filter> * <action android:name="android.service.storage.ExternalStorageService" /> * </intent-filter> * </service> * </pre> * @hide */ @SystemApi public abstract class ExternalStorageService extends Service { /** * The Intent action that a service must respond to. Add it as an intent filter in the * manifest declaration of the implementing service. */ @SdkConstant(SdkConstant.SdkConstantType.SERVICE_ACTION) public static final String SERVICE_INTERFACE = "android.service.storage.ExternalStorageService"; /** * Whether the session associated with the device file descriptor when calling * {@link #onStartSession} is a FUSE session. */ public static final int FLAG_SESSION_TYPE_FUSE = 1 << 0; /** * Whether the upper file system path specified when calling {@link #onStartSession} * should be indexed. */ public static final int FLAG_SESSION_ATTRIBUTE_INDEXABLE = 1 << 1; /** * {@link Bundle} key for a {@link String} value. * * {@hide} */ public static final String EXTRA_SESSION_ID = "android.service.storage.extra.session_id"; /** * {@link Bundle} key for a {@link ParcelableException} value. * * {@hide} */ public static final String EXTRA_ERROR = "android.service.storage.extra.error"; /** @hide */ @IntDef(flag = true, prefix = {"FLAG_SESSION_"}, value = {FLAG_SESSION_TYPE_FUSE, FLAG_SESSION_ATTRIBUTE_INDEXABLE}) @Retention(RetentionPolicy.SOURCE) public @interface SessionFlag {} private final ExternalStorageServiceWrapper mWrapper = new ExternalStorageServiceWrapper(); private final Handler mHandler = new Handler(Looper.getMainLooper(), null, true); /** * Called when the system starts a session associated with {@code deviceFd} * identified by {@code sessionId} to handle filesystem I/O for other apps. The type of * session and other attributes are passed in {@code flag}. * * <p> I/O is received as requests originating from {@code upperFileSystemPath} on * {@code deviceFd}. Implementors should handle the I/O by responding to these requests * using the data on the {@code lowerFileSystemPath}. * * <p> Additional calls to start a session for the same {@code sessionId} while the session * is still starting or already started should have no effect. */ public abstract void onStartSession(@NonNull String sessionId, @SessionFlag int flag, @NonNull ParcelFileDescriptor deviceFd, @NonNull String upperFileSystemPath, @NonNull String lowerFileSystemPath) throws IOException; /** * Called when the system ends the session identified by {@code sessionId}. Implementors should * stop handling filesystem I/O and clean up resources from the ended session. * * <p> Additional calls to end a session for the same {@code sessionId} while the session * is still ending or has not started should have no effect. */ public abstract void onEndSession(@NonNull String sessionId) throws IOException; @Override @NonNull public final IBinder onBind(@NonNull Intent intent) { return mWrapper; } private class ExternalStorageServiceWrapper extends IExternalStorageService.Stub { @Override public void startSession(String sessionId, @SessionFlag int flag, ParcelFileDescriptor deviceFd, String upperPath, String lowerPath, RemoteCallback callback) throws RemoteException { mHandler.post(() -> { try { onStartSession(sessionId, flag, deviceFd, upperPath, lowerPath); sendResult(sessionId, null /* throwable */, callback); } catch (Throwable t) { sendResult(sessionId, t, callback); } }); } @Override public void endSession(String sessionId, RemoteCallback callback) throws RemoteException { mHandler.post(() -> { try { onEndSession(sessionId); sendResult(sessionId, null /* throwable */, callback); } catch (Throwable t) { sendResult(sessionId, t, callback); } }); } private void sendResult(String sessionId, Throwable throwable, RemoteCallback callback) { Bundle bundle = new Bundle(); bundle.putString(EXTRA_SESSION_ID, sessionId); if (throwable != null) { bundle.putParcelable(EXTRA_ERROR, new ParcelableException(throwable)); } callback.sendResult(bundle); } } } core/java/android/service/storage/IExternalStorageService.aidl 0 → 100644 +30 −0 Original line number Diff line number Diff line /* * Copyright (C) 2019 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package android.service.storage; import android.os.ParcelFileDescriptor; import android.os.RemoteCallback; /** * @hide */ oneway interface IExternalStorageService { void startSession(@utf8InCpp String sessionId, int type, in ParcelFileDescriptor deviceFd, @utf8InCpp String upperPath, @utf8InCpp String lowerPath, in RemoteCallback callback); void endSession(@utf8InCpp String sessionId, in RemoteCallback callback); } No newline at end of file core/res/AndroidManifest.xml +7 −0 Original line number Diff line number Diff line Loading @@ -4524,6 +4524,13 @@ <permission android:name="android.permission.BIND_EXPLICIT_HEALTH_CHECK_SERVICE" android:protectionLevel="signature|privileged" /> <!-- @SystemApi Must be required by an {@link android.service.storage.ExternalStorageService} to ensure that only the system can bind to it. @hide This is not a third-party API (intended for OEMs and system apps). --> <permission android:name="android.permission.BIND_EXTERNAL_STORAGE_SERVICE" android:protectionLevel="signature" /> <!-- @hide Permission that allows configuring appops. <p>Not for use by third-party applications. --> <permission android:name="android.permission.MANAGE_APPOPS" Loading Loading
api/system-current.txt +15 −0 Original line number Diff line number Diff line Loading @@ -29,6 +29,7 @@ package android { field public static final String BIND_CONTENT_SUGGESTIONS_SERVICE = "android.permission.BIND_CONTENT_SUGGESTIONS_SERVICE"; field public static final String BIND_DIRECTORY_SEARCH = "android.permission.BIND_DIRECTORY_SEARCH"; field public static final String BIND_EUICC_SERVICE = "android.permission.BIND_EUICC_SERVICE"; field public static final String BIND_EXTERNAL_STORAGE_SERVICE = "android.permission.BIND_EXTERNAL_STORAGE_SERVICE"; field public static final String BIND_IMS_SERVICE = "android.permission.BIND_IMS_SERVICE"; field public static final String BIND_KEYGUARD_APPWIDGET = "android.permission.BIND_KEYGUARD_APPWIDGET"; field public static final String BIND_NETWORK_RECOMMENDATION_SERVICE = "android.permission.BIND_NETWORK_RECOMMENDATION_SERVICE"; Loading Loading @@ -6767,6 +6768,20 @@ package android.service.sms { } package android.service.storage { public abstract class ExternalStorageService extends android.app.Service { ctor public ExternalStorageService(); method @NonNull public final android.os.IBinder onBind(@NonNull android.content.Intent); method public abstract void onEndSession(@NonNull String) throws java.io.IOException; method public abstract void onStartSession(@NonNull String, int, @NonNull android.os.ParcelFileDescriptor, @NonNull String, @NonNull String) throws java.io.IOException; field public static final int FLAG_SESSION_ATTRIBUTE_INDEXABLE = 2; // 0x2 field public static final int FLAG_SESSION_TYPE_FUSE = 1; // 0x1 field public static final String SERVICE_INTERFACE = "android.service.storage.ExternalStorageService"; } } package android.service.textclassifier { public abstract class TextClassifierService extends android.app.Service { Loading
core/java/android/service/storage/ExternalStorageService.java 0 → 100644 +168 −0 Original line number Diff line number Diff line /* * Copyright (C) 2019 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package android.service.storage; import android.annotation.IntDef; import android.annotation.NonNull; import android.annotation.SdkConstant; import android.annotation.SystemApi; import android.app.Service; import android.content.Intent; import android.os.Bundle; import android.os.Handler; import android.os.IBinder; import android.os.Looper; import android.os.ParcelFileDescriptor; import android.os.ParcelableException; import android.os.RemoteCallback; import android.os.RemoteException; import java.io.IOException; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; /** * A service to handle filesystem I/O from other apps. * * <p>To extend this class, you must declare the service in your manifest file with the * {@link android.Manifest.permission#BIND_EXTERNAL_STORAGE_SERVICE} permission, * and include an intent filter with the {@link #SERVICE_INTERFACE} action. * For example:</p> * <pre> * <service android:name=".ExternalStorageServiceImpl" * android:exported="true" * android:priority="100" * android:permission="android.permission.BIND_EXTERNAL_STORAGE_SERVICE"> * <intent-filter> * <action android:name="android.service.storage.ExternalStorageService" /> * </intent-filter> * </service> * </pre> * @hide */ @SystemApi public abstract class ExternalStorageService extends Service { /** * The Intent action that a service must respond to. Add it as an intent filter in the * manifest declaration of the implementing service. */ @SdkConstant(SdkConstant.SdkConstantType.SERVICE_ACTION) public static final String SERVICE_INTERFACE = "android.service.storage.ExternalStorageService"; /** * Whether the session associated with the device file descriptor when calling * {@link #onStartSession} is a FUSE session. */ public static final int FLAG_SESSION_TYPE_FUSE = 1 << 0; /** * Whether the upper file system path specified when calling {@link #onStartSession} * should be indexed. */ public static final int FLAG_SESSION_ATTRIBUTE_INDEXABLE = 1 << 1; /** * {@link Bundle} key for a {@link String} value. * * {@hide} */ public static final String EXTRA_SESSION_ID = "android.service.storage.extra.session_id"; /** * {@link Bundle} key for a {@link ParcelableException} value. * * {@hide} */ public static final String EXTRA_ERROR = "android.service.storage.extra.error"; /** @hide */ @IntDef(flag = true, prefix = {"FLAG_SESSION_"}, value = {FLAG_SESSION_TYPE_FUSE, FLAG_SESSION_ATTRIBUTE_INDEXABLE}) @Retention(RetentionPolicy.SOURCE) public @interface SessionFlag {} private final ExternalStorageServiceWrapper mWrapper = new ExternalStorageServiceWrapper(); private final Handler mHandler = new Handler(Looper.getMainLooper(), null, true); /** * Called when the system starts a session associated with {@code deviceFd} * identified by {@code sessionId} to handle filesystem I/O for other apps. The type of * session and other attributes are passed in {@code flag}. * * <p> I/O is received as requests originating from {@code upperFileSystemPath} on * {@code deviceFd}. Implementors should handle the I/O by responding to these requests * using the data on the {@code lowerFileSystemPath}. * * <p> Additional calls to start a session for the same {@code sessionId} while the session * is still starting or already started should have no effect. */ public abstract void onStartSession(@NonNull String sessionId, @SessionFlag int flag, @NonNull ParcelFileDescriptor deviceFd, @NonNull String upperFileSystemPath, @NonNull String lowerFileSystemPath) throws IOException; /** * Called when the system ends the session identified by {@code sessionId}. Implementors should * stop handling filesystem I/O and clean up resources from the ended session. * * <p> Additional calls to end a session for the same {@code sessionId} while the session * is still ending or has not started should have no effect. */ public abstract void onEndSession(@NonNull String sessionId) throws IOException; @Override @NonNull public final IBinder onBind(@NonNull Intent intent) { return mWrapper; } private class ExternalStorageServiceWrapper extends IExternalStorageService.Stub { @Override public void startSession(String sessionId, @SessionFlag int flag, ParcelFileDescriptor deviceFd, String upperPath, String lowerPath, RemoteCallback callback) throws RemoteException { mHandler.post(() -> { try { onStartSession(sessionId, flag, deviceFd, upperPath, lowerPath); sendResult(sessionId, null /* throwable */, callback); } catch (Throwable t) { sendResult(sessionId, t, callback); } }); } @Override public void endSession(String sessionId, RemoteCallback callback) throws RemoteException { mHandler.post(() -> { try { onEndSession(sessionId); sendResult(sessionId, null /* throwable */, callback); } catch (Throwable t) { sendResult(sessionId, t, callback); } }); } private void sendResult(String sessionId, Throwable throwable, RemoteCallback callback) { Bundle bundle = new Bundle(); bundle.putString(EXTRA_SESSION_ID, sessionId); if (throwable != null) { bundle.putParcelable(EXTRA_ERROR, new ParcelableException(throwable)); } callback.sendResult(bundle); } } }
core/java/android/service/storage/IExternalStorageService.aidl 0 → 100644 +30 −0 Original line number Diff line number Diff line /* * Copyright (C) 2019 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package android.service.storage; import android.os.ParcelFileDescriptor; import android.os.RemoteCallback; /** * @hide */ oneway interface IExternalStorageService { void startSession(@utf8InCpp String sessionId, int type, in ParcelFileDescriptor deviceFd, @utf8InCpp String upperPath, @utf8InCpp String lowerPath, in RemoteCallback callback); void endSession(@utf8InCpp String sessionId, in RemoteCallback callback); } No newline at end of file
core/res/AndroidManifest.xml +7 −0 Original line number Diff line number Diff line Loading @@ -4524,6 +4524,13 @@ <permission android:name="android.permission.BIND_EXPLICIT_HEALTH_CHECK_SERVICE" android:protectionLevel="signature|privileged" /> <!-- @SystemApi Must be required by an {@link android.service.storage.ExternalStorageService} to ensure that only the system can bind to it. @hide This is not a third-party API (intended for OEMs and system apps). --> <permission android:name="android.permission.BIND_EXTERNAL_STORAGE_SERVICE" android:protectionLevel="signature" /> <!-- @hide Permission that allows configuring appops. <p>Not for use by third-party applications. --> <permission android:name="android.permission.MANAGE_APPOPS" Loading