diff options
| -rw-r--r-- | Android.bp | 1 | ||||
| -rw-r--r-- | core/java/android/os/BinderProxy.java | 128 | ||||
| -rw-r--r-- | core/java/android/os/FileUtils.java | 37 | ||||
| -rw-r--r-- | core/java/android/os/ParcelFileDescriptor.java | 3 | ||||
| -rw-r--r-- | core/jni/android_util_Binder.cpp | 15 | ||||
| -rw-r--r-- | core/res/AndroidManifest.xml | 2 | ||||
| -rw-r--r-- | services/core/java/com/android/server/StorageManagerService.java | 25 | ||||
| -rw-r--r-- | services/core/java/com/android/server/am/ActivityManagerService.java | 15 | ||||
| -rw-r--r-- | services/core/java/com/android/server/storage/AppFuseBridge.java | 22 | ||||
| -rw-r--r-- | telephony/java/android/provider/Telephony.java | 53 | ||||
| -rw-r--r-- | telephony/java/android/telephony/RcsManager.java | 52 | ||||
| -rw-r--r-- | telephony/java/com/android/internal/telephony/IRcs.aidl | 21 | ||||
| -rw-r--r-- | telephony/java/com/android/internal/telephony/TelephonyIntents.java | 14 |
13 files changed, 307 insertions, 81 deletions
diff --git a/Android.bp b/Android.bp index 170e22e1cbde..f49e4e5eb496 100644 --- a/Android.bp +++ b/Android.bp @@ -546,6 +546,7 @@ java_defaults { "telephony/java/com/android/internal/telephony/IOnSubscriptionsChangedListener.aidl", "telephony/java/com/android/internal/telephony/IPhoneStateListener.aidl", "telephony/java/com/android/internal/telephony/IPhoneSubInfo.aidl", + "telephony/java/com/android/internal/telephony/IRcs.aidl", "telephony/java/com/android/internal/telephony/ISms.aidl", "telephony/java/com/android/internal/telephony/ISub.aidl", "telephony/java/com/android/internal/telephony/IAns.aidl", diff --git a/core/java/android/os/BinderProxy.java b/core/java/android/os/BinderProxy.java index e492f88d4329..591370ff728b 100644 --- a/core/java/android/os/BinderProxy.java +++ b/core/java/android/os/BinderProxy.java @@ -225,10 +225,11 @@ public final class BinderProxy implements IBinder { } } - /** - * Dump a histogram to the logcat. Used to diagnose abnormally large proxy maps. - */ - private void dumpProxyInterfaceCounts() { + private InterfaceCount[] getSortedInterfaceCounts(int maxToReturn) { + if (maxToReturn < 0) { + throw new IllegalArgumentException("negative interface count"); + } + Map<String, Integer> counts = new HashMap<>(); for (ArrayList<WeakReference<BinderProxy>> a : mMainIndexValues) { if (a != null) { @@ -258,13 +259,30 @@ public final class BinderProxy implements IBinder { } Map.Entry<String, Integer>[] sorted = counts.entrySet().toArray( new Map.Entry[counts.size()]); + Arrays.sort(sorted, (Map.Entry<String, Integer> a, Map.Entry<String, Integer> b) -> b.getValue().compareTo(a.getValue())); - Log.v(Binder.TAG, "BinderProxy descriptor histogram (top ten):"); - int printLength = Math.min(10, sorted.length); - for (int i = 0; i < printLength; i++) { - Log.v(Binder.TAG, " #" + (i + 1) + ": " + sorted[i].getKey() + " x" - + sorted[i].getValue()); + + int returnCount = Math.min(maxToReturn, sorted.length); + InterfaceCount[] ifaceCounts = new InterfaceCount[returnCount]; + for (int i = 0; i < returnCount; i++) { + ifaceCounts[i] = new InterfaceCount(sorted[i].getKey(), sorted[i].getValue()); + } + return ifaceCounts; + } + + static final int MAX_NUM_INTERFACES_TO_DUMP = 10; + + /** + * Dump a histogram to the logcat. Used to diagnose abnormally large proxy maps. + */ + private void dumpProxyInterfaceCounts() { + final InterfaceCount[] sorted = getSortedInterfaceCounts(MAX_NUM_INTERFACES_TO_DUMP); + + Log.v(Binder.TAG, "BinderProxy descriptor histogram " + + "(top " + Integer.toString(MAX_NUM_INTERFACES_TO_DUMP) + "):"); + for (int i = 0; i < sorted.length; i++) { + Log.v(Binder.TAG, " #" + (i + 1) + ": " + sorted[i]); } } @@ -296,30 +314,57 @@ public final class BinderProxy implements IBinder { new ArrayList[MAIN_INDEX_SIZE]; } - private static ProxyMap sProxyMap = new ProxyMap(); + @GuardedBy("sProxyMap") + private static final ProxyMap sProxyMap = new ProxyMap(); /** - * Dump proxy debug information. - * - * Note: this method is not thread-safe; callers must serialize with other - * accesses to sProxyMap, in particular {@link #getInstance(long, long)}. - * - * @hide - */ - private static void dumpProxyDebugInfo() { + * Simple pair-value class to store number of binder proxy interfaces live in this process. + */ + public static final class InterfaceCount { + private final String mInterfaceName; + private final int mCount; + + InterfaceCount(String interfaceName, int count) { + mInterfaceName = interfaceName; + mCount = count; + } + + @Override + public String toString() { + return mInterfaceName + " x" + Integer.toString(mCount); + } + } + + /** + * Get a sorted array with entries mapping proxy interface names to the number + * of live proxies with those names. + * + * @param num maximum number of proxy interface counts to return. Use + * Integer.MAX_VALUE to retrieve all + * @hide + */ + public static InterfaceCount[] getSortedInterfaceCounts(int num) { + synchronized (sProxyMap) { + return sProxyMap.getSortedInterfaceCounts(num); + } + } + + /** + * Dump proxy debug information. + * + * @hide + */ + public static void dumpProxyDebugInfo() { if (Build.IS_DEBUGGABLE) { - sProxyMap.dumpProxyInterfaceCounts(); - // Note that we don't call dumpPerUidProxyCounts(); this is because this - // method may be called as part of the uid limit being hit, and calling - // back into the UID tracking code would cause us to try to acquire a mutex - // that is held during that callback. + synchronized (sProxyMap) { + sProxyMap.dumpProxyInterfaceCounts(); + sProxyMap.dumpPerUidProxyCounts(); + } } } /** * Return a BinderProxy for IBinder. - * This method is thread-hostile! The (native) caller serializes getInstance() calls using - * gProxyLock. * If we previously returned a BinderProxy bp for the same iBinder, and bp is still * in use, then we return the same bp. * @@ -331,21 +376,23 @@ public final class BinderProxy implements IBinder { */ private static BinderProxy getInstance(long nativeData, long iBinder) { BinderProxy result; - try { - result = sProxyMap.get(iBinder); - if (result != null) { - return result; + synchronized (sProxyMap) { + try { + result = sProxyMap.get(iBinder); + if (result != null) { + return result; + } + result = new BinderProxy(nativeData); + } catch (Throwable e) { + // We're throwing an exception (probably OOME); don't drop nativeData. + NativeAllocationRegistry.applyFreeFunction(NoImagePreloadHolder.sNativeFinalizer, + nativeData); + throw e; } - result = new BinderProxy(nativeData); - } catch (Throwable e) { - // We're throwing an exception (probably OOME); don't drop nativeData. - NativeAllocationRegistry.applyFreeFunction(NoImagePreloadHolder.sNativeFinalizer, - nativeData); - throw e; + NoImagePreloadHolder.sRegistry.registerNativeAllocation(result, nativeData); + // The registry now owns nativeData, even if registration threw an exception. + sProxyMap.set(iBinder, result); } - NoImagePreloadHolder.sRegistry.registerNativeAllocation(result, nativeData); - // The registry now owns nativeData, even if registration threw an exception. - sProxyMap.set(iBinder, result); return result; } @@ -526,12 +573,11 @@ public final class BinderProxy implements IBinder { } } - private static final void sendDeathNotice(DeathRecipient recipient) { + private static void sendDeathNotice(DeathRecipient recipient) { if (false) Log.v("JavaBinder", "sendDeathNotice to " + recipient); try { recipient.binderDied(); - } - catch (RuntimeException exc) { + } catch (RuntimeException exc) { Log.w("BinderNative", "Uncaught exception from death notification", exc); } diff --git a/core/java/android/os/FileUtils.java b/core/java/android/os/FileUtils.java index 88d6e847b644..ddeb8380c331 100644 --- a/core/java/android/os/FileUtils.java +++ b/core/java/android/os/FileUtils.java @@ -16,6 +16,18 @@ package android.os; +import static android.os.ParcelFileDescriptor.MODE_APPEND; +import static android.os.ParcelFileDescriptor.MODE_CREATE; +import static android.os.ParcelFileDescriptor.MODE_READ_ONLY; +import static android.os.ParcelFileDescriptor.MODE_READ_WRITE; +import static android.os.ParcelFileDescriptor.MODE_TRUNCATE; +import static android.os.ParcelFileDescriptor.MODE_WRITE_ONLY; +import static android.system.OsConstants.O_APPEND; +import static android.system.OsConstants.O_CREAT; +import static android.system.OsConstants.O_RDONLY; +import static android.system.OsConstants.O_RDWR; +import static android.system.OsConstants.O_TRUNC; +import static android.system.OsConstants.O_WRONLY; import static android.system.OsConstants.SPLICE_F_MORE; import static android.system.OsConstants.SPLICE_F_MOVE; import static android.system.OsConstants.S_ISFIFO; @@ -1050,6 +1062,30 @@ public class FileUtils { return val * pow; } + /** {@hide} */ + public static int translateModePfdToPosix(int mode) { + int res = 0; + if ((mode & MODE_READ_WRITE) == MODE_READ_WRITE) { + res |= O_RDWR; + } else if ((mode & MODE_WRITE_ONLY) == MODE_WRITE_ONLY) { + res |= O_WRONLY; + } else if ((mode & MODE_READ_ONLY) == MODE_READ_ONLY) { + res |= O_RDONLY; + } else { + throw new IllegalArgumentException("Bad mode: " + mode); + } + if ((mode & MODE_CREATE) == MODE_CREATE) { + res |= O_CREAT; + } + if ((mode & MODE_TRUNCATE) == MODE_TRUNCATE) { + res |= O_TRUNC; + } + if ((mode & MODE_APPEND) == MODE_APPEND) { + res |= O_APPEND; + } + return res; + } + @VisibleForTesting public static class MemoryPipe extends Thread implements AutoCloseable { private final FileDescriptor[] pipe; @@ -1115,3 +1151,4 @@ public class FileUtils { } } } + diff --git a/core/java/android/os/ParcelFileDescriptor.java b/core/java/android/os/ParcelFileDescriptor.java index 7409ca741c52..81fc5c0303d5 100644 --- a/core/java/android/os/ParcelFileDescriptor.java +++ b/core/java/android/os/ParcelFileDescriptor.java @@ -1092,6 +1092,9 @@ public class ParcelFileDescriptor implements Parcelable, Closeable { /** * Internal class representing a remote status read by * {@link ParcelFileDescriptor#readCommStatus(FileDescriptor, byte[])}. + * + * Warning: this must be kept in sync with ParcelFileDescriptorStatus at + * frameworks/native/libs/binder/Parcel.cpp */ private static class Status { /** Special value indicating remote side died. */ diff --git a/core/jni/android_util_Binder.cpp b/core/jni/android_util_Binder.cpp index 9341d9a48913..adff4d644c08 100644 --- a/core/jni/android_util_Binder.cpp +++ b/core/jni/android_util_Binder.cpp @@ -110,7 +110,6 @@ static struct binderproxy_offsets_t jclass mClass; jmethodID mGetInstance; jmethodID mSendDeathNotice; - jmethodID mDumpProxyDebugInfo; // Object state. jfieldID mNativeData; // Field holds native pointer to BinderProxyNativeData. @@ -1038,18 +1037,6 @@ static void android_os_BinderInternal_handleGc(JNIEnv* env, jobject clazz) static void android_os_BinderInternal_proxyLimitcallback(int uid) { JNIEnv *env = AndroidRuntime::getJNIEnv(); - { - // Calls into BinderProxy must be serialized - AutoMutex _l(gProxyLock); - env->CallStaticObjectMethod(gBinderProxyOffsets.mClass, - gBinderProxyOffsets.mDumpProxyDebugInfo); - } - if (env->ExceptionCheck()) { - ScopedLocalRef<jthrowable> excep(env, env->ExceptionOccurred()); - report_exception(env, excep.get(), - "*** Uncaught exception in dumpProxyDebugInfo"); - } - env->CallStaticVoidMethod(gBinderInternalOffsets.mClass, gBinderInternalOffsets.mProxyLimitCallback, uid); @@ -1439,8 +1426,6 @@ static int int_register_android_os_BinderProxy(JNIEnv* env) "(JJ)Landroid/os/BinderProxy;"); gBinderProxyOffsets.mSendDeathNotice = GetStaticMethodIDOrDie(env, clazz, "sendDeathNotice", "(Landroid/os/IBinder$DeathRecipient;)V"); - gBinderProxyOffsets.mDumpProxyDebugInfo = GetStaticMethodIDOrDie(env, clazz, "dumpProxyDebugInfo", - "()V"); gBinderProxyOffsets.mNativeData = GetFieldIDOrDie(env, clazz, "mNativeData", "J"); clazz = FindClassOrDie(env, "java/lang/Class"); diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml index 1f3a8fce8ef1..9ce6044bcf3e 100644 --- a/core/res/AndroidManifest.xml +++ b/core/res/AndroidManifest.xml @@ -398,6 +398,8 @@ <protected-broadcast android:name="android.telecom.action.DEFAULT_DIALER_CHANGED" /> <protected-broadcast android:name="android.provider.action.DEFAULT_SMS_PACKAGE_CHANGED" /> + <protected-broadcast android:name="android.provider.action.SMS_MMS_DB_CREATED" /> + <protected-broadcast android:name="android.provider.action.SMS_MMS_DB_LOST" /> <protected-broadcast android:name="android.intent.action.CONTENT_CHANGED" /> <protected-broadcast android:name="android.provider.Telephony.MMS_DOWNLOADED" /> diff --git a/services/core/java/com/android/server/StorageManagerService.java b/services/core/java/com/android/server/StorageManagerService.java index d11a74fd404c..a3e6ea2518a6 100644 --- a/services/core/java/com/android/server/StorageManagerService.java +++ b/services/core/java/com/android/server/StorageManagerService.java @@ -2602,24 +2602,35 @@ class StorageManagerService extends IStorageManager.Stub class AppFuseMountScope extends AppFuseBridge.MountScope { boolean opened = false; - public AppFuseMountScope(int uid, int pid, int mountId) { - super(uid, pid, mountId); + public AppFuseMountScope(int uid, int mountId) { + super(uid, mountId); } @Override public ParcelFileDescriptor open() throws NativeDaemonConnectorException { try { return new ParcelFileDescriptor( - mVold.mountAppFuse(uid, Process.myPid(), mountId)); + mVold.mountAppFuse(uid, mountId)); } catch (Exception e) { throw new NativeDaemonConnectorException("Failed to mount", e); } } @Override + public ParcelFileDescriptor openFile(int mountId, int fileId, int flags) + throws NativeDaemonConnectorException { + try { + return new ParcelFileDescriptor( + mVold.openAppFuseFile(uid, mountId, fileId, flags)); + } catch (Exception e) { + throw new NativeDaemonConnectorException("Failed to open", e); + } + } + + @Override public void close() throws Exception { if (opened) { - mVold.unmountAppFuse(uid, Process.myPid(), mountId); + mVold.unmountAppFuse(uid, mountId); opened = false; } } @@ -2629,7 +2640,6 @@ class StorageManagerService extends IStorageManager.Stub public @Nullable AppFuseMount mountProxyFileDescriptorBridge() { Slog.v(TAG, "mountProxyFileDescriptorBridge"); final int uid = Binder.getCallingUid(); - final int pid = Binder.getCallingPid(); while (true) { synchronized (mAppFuseLock) { @@ -2643,7 +2653,7 @@ class StorageManagerService extends IStorageManager.Stub final int name = mNextAppFuseName++; try { return new AppFuseMount( - name, mAppFuseBridge.addBridge(new AppFuseMountScope(uid, pid, name))); + name, mAppFuseBridge.addBridge(new AppFuseMountScope(uid, name))); } catch (FuseUnavailableMountException e) { if (newlyCreated) { // If newly created bridge fails, it's a real error. @@ -2664,14 +2674,13 @@ class StorageManagerService extends IStorageManager.Stub public @Nullable ParcelFileDescriptor openProxyFileDescriptor( int mountId, int fileId, int mode) { Slog.v(TAG, "mountProxyFileDescriptor"); - final int pid = Binder.getCallingPid(); try { synchronized (mAppFuseLock) { if (mAppFuseBridge == null) { Slog.e(TAG, "FuseBridge has not been created"); return null; } - return mAppFuseBridge.openFile(pid, mountId, fileId, mode); + return mAppFuseBridge.openFile(mountId, fileId, mode); } } catch (FuseUnavailableMountException | InterruptedException error) { Slog.v(TAG, "The mount point has already been invalid", error); diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java index 7aadcd400f0e..fa9c58e1955c 100644 --- a/services/core/java/com/android/server/am/ActivityManagerService.java +++ b/services/core/java/com/android/server/am/ActivityManagerService.java @@ -318,6 +318,7 @@ import android.net.ProxyInfo; import android.net.Uri; import android.os.BatteryStats; import android.os.Binder; +import android.os.BinderProxy; import android.os.Build; import android.os.Bundle; import android.os.Debug; @@ -15210,6 +15211,7 @@ public class ActivityManagerService extends IActivityManager.Stub public void onLimitReached(int uid) { Slog.wtf(TAG, "Uid " + uid + " sent too many Binders to uid " + Process.myUid()); + BinderProxy.dumpProxyDebugInfo(); if (uid == Process.SYSTEM_UID) { Slog.i(TAG, "Skipping kill (uid is SYSTEM)"); } else { @@ -16061,8 +16063,10 @@ public class ActivityManagerService extends IActivityManager.Stub } } else if ("binder-proxies".equals(cmd)) { if (opti >= args.length) { + dumpBinderProxyInterfaceCounts(pw, + "Top proxy interface names held by SYSTEM"); dumpBinderProxiesCounts(pw, BinderInternal.nGetBinderProxyPerUidCounts(), - "Counts of Binder Proxies held by SYSTEM"); + "Number of proxies per uid held by SYSTEM"); } else { String uid = args[opti]; opti++; @@ -16565,6 +16569,15 @@ public class ActivityManagerService extends IActivityManager.Stub return printed; } + void dumpBinderProxyInterfaceCounts(PrintWriter pw, String header) { + final BinderProxy.InterfaceCount[] proxyCounts = BinderProxy.getSortedInterfaceCounts(50); + + pw.println(header); + for (int i = 0; i < proxyCounts.length; i++) { + pw.println(" #" + (i + 1) + ": " + proxyCounts[i]); + } + } + boolean dumpBinderProxiesCounts(PrintWriter pw, SparseIntArray counts, String header) { if(counts != null) { pw.println(header); diff --git a/services/core/java/com/android/server/storage/AppFuseBridge.java b/services/core/java/com/android/server/storage/AppFuseBridge.java index 6a0b6489f470..9d6a64701e85 100644 --- a/services/core/java/com/android/server/storage/AppFuseBridge.java +++ b/services/core/java/com/android/server/storage/AppFuseBridge.java @@ -16,6 +16,7 @@ package com.android.server.storage; +import android.os.FileUtils; import android.os.ParcelFileDescriptor; import android.system.ErrnoException; import android.system.Os; @@ -25,8 +26,6 @@ import com.android.internal.os.FuseUnavailableMountException; import com.android.internal.util.Preconditions; import com.android.server.NativeDaemonConnectorException; import libcore.io.IoUtils; -import java.io.File; -import java.io.FileNotFoundException; import java.util.concurrent.CountDownLatch; /** @@ -87,7 +86,7 @@ public class AppFuseBridge implements Runnable { } } - public ParcelFileDescriptor openFile(int pid, int mountId, int fileId, int mode) + public ParcelFileDescriptor openFile(int mountId, int fileId, int mode) throws FuseUnavailableMountException, InterruptedException { final MountScope scope; synchronized (this) { @@ -96,17 +95,14 @@ public class AppFuseBridge implements Runnable { throw new FuseUnavailableMountException(mountId); } } - if (scope.pid != pid) { - throw new SecurityException("PID does not match"); - } final boolean result = scope.waitForMount(); if (result == false) { throw new FuseUnavailableMountException(mountId); } try { - return ParcelFileDescriptor.open( - new File(scope.mountPoint, String.valueOf(fileId)), mode); - } catch (FileNotFoundException error) { + int flags = FileUtils.translateModePfdToPosix(mode); + return scope.openFile(mountId, fileId, flags); + } catch (NativeDaemonConnectorException error) { throw new FuseUnavailableMountException(mountId); } } @@ -131,17 +127,13 @@ public class AppFuseBridge implements Runnable { public static abstract class MountScope implements AutoCloseable { public final int uid; - public final int pid; public final int mountId; - public final File mountPoint; private final CountDownLatch mMounted = new CountDownLatch(1); private boolean mMountResult = false; - public MountScope(int uid, int pid, int mountId) { + public MountScope(int uid, int mountId) { this.uid = uid; - this.pid = pid; this.mountId = mountId; - this.mountPoint = new File(String.format(APPFUSE_MOUNT_NAME_TEMPLATE, uid, mountId)); } @GuardedBy("AppFuseBridge.this") @@ -159,6 +151,8 @@ public class AppFuseBridge implements Runnable { } public abstract ParcelFileDescriptor open() throws NativeDaemonConnectorException; + public abstract ParcelFileDescriptor openFile(int mountId, int fileId, int flags) + throws NativeDaemonConnectorException; } private native long native_new(); diff --git a/telephony/java/android/provider/Telephony.java b/telephony/java/android/provider/Telephony.java index 7b798e8f185a..efea81763b9f 100644 --- a/telephony/java/android/provider/Telephony.java +++ b/telephony/java/android/provider/Telephony.java @@ -16,6 +16,7 @@ package android.provider; +import android.annotation.RequiresPermission; import android.annotation.SdkConstant; import android.annotation.SdkConstant.SdkConstantType; import android.annotation.SystemApi; @@ -1181,6 +1182,58 @@ public final class Telephony { "android.provider.action.DEFAULT_SMS_PACKAGE_CHANGED_INTERNAL"; /** + * Broadcast action: When SMS-MMS db is being created. If file-based encryption is + * supported, this broadcast indicates creation of the db in credential-encrypted + * storage. A boolean is specified in {@link #EXTRA_IS_INITIAL_CREATE} to indicate if + * this is the initial create of the db. Requires + * {@link android.Manifest.permission#READ_SMS} to receive. + * + * @see #EXTRA_IS_INITIAL_CREATE + * + * @hide + */ + @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) + public static final String ACTION_SMS_MMS_DB_CREATED = + "android.provider.action.SMS_MMS_DB_CREATED"; + + /** + * Boolean flag passed as an extra with {@link #ACTION_SMS_MMS_DB_CREATED} to indicate + * whether the DB creation is the initial creation on the device, that is it is after a + * factory-data reset or a new device. Any subsequent creations of the DB (which + * happens only in error scenarios) will have this flag set to false. + * + * @see #ACTION_SMS_MMS_DB_CREATED + * + * @hide + */ + public static final String EXTRA_IS_INITIAL_CREATE = + "android.provider.extra.IS_INITIAL_CREATE"; + + /** + * Broadcast intent action indicating that the telephony provider SMS MMS database is + * corrupted. A boolean is specified in {@link #EXTRA_IS_CORRUPTED} to indicate if the + * database is corrupted. Requires the + * {@link android.Manifest.permission#READ_PRIVILEGED_PHONE_STATE permission. + * + * @hide + */ + @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) + @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) + public static final String ACTION_SMS_MMS_DB_LOST = + "android.provider.action.SMS_MMS_DB_LOST"; + + /** + * Boolean flag passed as an extra with {@link #ACTION_SMS_MMS_DB_LOST} to indicate + * whether the DB got corrupted or not. + * + * @see #ACTION_SMS_MMS_DB_LOST + * + * @hide + */ + public static final String EXTRA_IS_CORRUPTED = + "android.provider.extra.IS_CORRUPTED"; + + /** * Read the PDUs out of an {@link #SMS_RECEIVED_ACTION} or a * {@link #DATA_SMS_RECEIVED_ACTION} intent. * diff --git a/telephony/java/android/telephony/RcsManager.java b/telephony/java/android/telephony/RcsManager.java new file mode 100644 index 000000000000..00ce03a1f668 --- /dev/null +++ b/telephony/java/android/telephony/RcsManager.java @@ -0,0 +1,52 @@ +/* + * Copyright (C) 2018 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.telephony; + +import android.os.RemoteException; +import android.os.ServiceManager; + +import com.android.internal.telephony.IRcs; + +/** + * RcsManager is the application interface to RcsProvider and provides access methods to + * RCS related database tables. + * @hide - TODO make this public + */ +public class RcsManager { + private static final String TAG = "RcsManager"; + private static final boolean VDBG = false; + + /** + * Delete the RcsThread identified by the given threadId. + * @param threadId threadId of the thread to be deleted. + */ + public void deleteThread(int threadId) { + if (VDBG) logd("deleteThread: threadId: " + threadId); + try { + IRcs iRcs = IRcs.Stub.asInterface(ServiceManager.getService("ircs")); + if (iRcs != null) { + iRcs.deleteThread(threadId); + } + } catch (RemoteException re) { + + } + } + + private static void logd(String msg) { + Rlog.d(TAG, msg); + } +} diff --git a/telephony/java/com/android/internal/telephony/IRcs.aidl b/telephony/java/com/android/internal/telephony/IRcs.aidl new file mode 100644 index 000000000000..ede8695ef08e --- /dev/null +++ b/telephony/java/com/android/internal/telephony/IRcs.aidl @@ -0,0 +1,21 @@ +/* + * Copyright (C) 2018 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 com.android.internal.telephony; + +interface IRcs { + void deleteThread(int threadId); +}
\ No newline at end of file diff --git a/telephony/java/com/android/internal/telephony/TelephonyIntents.java b/telephony/java/com/android/internal/telephony/TelephonyIntents.java index 5ecb43ebf112..2a648bd8b252 100644 --- a/telephony/java/com/android/internal/telephony/TelephonyIntents.java +++ b/telephony/java/com/android/internal/telephony/TelephonyIntents.java @@ -480,9 +480,9 @@ public class TelephonyIntents { public static final String EXTRA_PCO_VALUE_KEY = "pcoValue"; public static final String EXTRA_DEFAULT_NETWORK_AVAILABLE_KEY = "defaultNetworkAvailable"; - /** + /** * Broadcast action to trigger CI OMA-DM Session. - */ + */ public static final String ACTION_REQUEST_OMADM_CONFIGURATION_UPDATE = "com.android.omadm.service.CONFIGURATION_UPDATE"; @@ -491,4 +491,14 @@ public class TelephonyIntents { */ public static final String ACTION_CARRIER_CERTIFICATE_DOWNLOAD = "com.android.internal.telephony.ACTION_CARRIER_CERTIFICATE_DOWNLOAD"; + + /** + * Broadcast action to indicate an error related to Line1Number has been detected. + * + * Requires the READ_PRIVILEGED_PHONE_STATE permission. + * + * @hide + */ + public static final String ACTION_LINE1_NUMBER_ERROR_DETECTED = + "com.android.internal.telephony.ACTION_LINE1_NUMBER_ERROR_DETECTED"; } |