summaryrefslogtreecommitdiff
path: root/core/java
diff options
context:
space:
mode:
Diffstat (limited to 'core/java')
-rw-r--r--core/java/android/app/Activity.java46
-rw-r--r--core/java/android/app/ContextImpl.java12
-rw-r--r--core/java/android/app/EventLogTags.logtags36
-rw-r--r--core/java/android/app/INotificationManager.aidl3
-rw-r--r--core/java/android/app/SystemServiceRegistry.java9
-rw-r--r--core/java/android/app/admin/DevicePolicyManager.java5
-rw-r--r--core/java/android/app/backup/BackupManager.java25
-rw-r--r--core/java/android/app/backup/IBackupManager.aidl6
-rw-r--r--core/java/android/app/timedetector/ITimeDetectorService.aidl2
-rw-r--r--core/java/android/app/timedetector/ManualTimeSuggestion.aidl (renamed from core/java/android/service/euicc/EuiccProfileInfo.aidl)7
-rw-r--r--core/java/android/app/timedetector/ManualTimeSuggestion.java127
-rw-r--r--core/java/android/app/timedetector/PhoneTimeSuggestion.java23
-rw-r--r--core/java/android/app/timedetector/TimeDetector.java37
-rw-r--r--core/java/android/app/timezonedetector/ITimeZoneDetectorService.aidl36
-rw-r--r--core/java/android/app/timezonedetector/PhoneTimeZoneSuggestion.aidl (renamed from core/java/android/service/euicc/GetEuiccProfileInfoListResult.aidl)6
-rw-r--r--core/java/android/app/timezonedetector/PhoneTimeZoneSuggestion.java341
-rw-r--r--core/java/android/app/timezonedetector/TimeZoneDetector.java59
-rw-r--r--core/java/android/content/Context.java62
-rw-r--r--core/java/android/content/ContextWrapper.java10
-rw-r--r--core/java/android/net/IpConfiguration.java10
-rw-r--r--core/java/android/net/LinkProperties.java6
-rw-r--r--core/java/android/os/Binder.java13
-rwxr-xr-xcore/java/android/os/Build.java4
-rw-r--r--core/java/android/os/FileObserver.java2
-rw-r--r--core/java/android/os/ResultReceiver.aidl18
-rw-r--r--core/java/android/os/UserManager.java5
-rw-r--r--core/java/android/os/incremental/IIncrementalManager.aidl (renamed from core/java/android/os/incremental/IIncrementalService.aidl)24
-rw-r--r--core/java/android/os/incremental/IncrementalDataLoaderParams.java84
-rw-r--r--core/java/android/os/incremental/IncrementalDataLoaderParamsParcel.aidl2
-rw-r--r--core/java/android/os/incremental/IncrementalManager.java327
-rw-r--r--core/java/android/os/incremental/IncrementalStorage.java346
-rw-r--r--core/java/android/provider/Settings.java110
-rw-r--r--core/java/android/provider/Telephony.java4856
-rw-r--r--core/java/android/service/autofill/SaveInfo.java20
-rw-r--r--core/java/android/service/carrier/CarrierIdentifier.aidl19
-rw-r--r--core/java/android/service/carrier/CarrierIdentifier.java255
-rw-r--r--core/java/android/service/carrier/CarrierService.java160
-rw-r--r--core/java/android/service/carrier/ICarrierService.aidl33
-rw-r--r--core/java/android/service/euicc/DownloadSubscriptionResult.aidl19
-rw-r--r--core/java/android/service/euicc/DownloadSubscriptionResult.java99
-rw-r--r--core/java/android/service/euicc/EuiccProfileInfo.java455
-rw-r--r--core/java/android/service/euicc/EuiccService.java838
-rw-r--r--core/java/android/service/euicc/GetDefaultDownloadableSubscriptionListResult.aidl19
-rw-r--r--core/java/android/service/euicc/GetDefaultDownloadableSubscriptionListResult.java118
-rw-r--r--core/java/android/service/euicc/GetDownloadableSubscriptionMetadataResult.aidl19
-rw-r--r--core/java/android/service/euicc/GetDownloadableSubscriptionMetadataResult.java114
-rw-r--r--core/java/android/service/euicc/GetEuiccProfileInfoListResult.java126
-rw-r--r--core/java/android/service/euicc/IDeleteSubscriptionCallback.aidl23
-rw-r--r--core/java/android/service/euicc/IDownloadSubscriptionCallback.aidl24
-rw-r--r--core/java/android/service/euicc/IEraseSubscriptionsCallback.aidl23
-rw-r--r--core/java/android/service/euicc/IEuiccService.aidl59
-rw-r--r--core/java/android/service/euicc/IGetDefaultDownloadableSubscriptionListCallback.aidl25
-rw-r--r--core/java/android/service/euicc/IGetDownloadableSubscriptionMetadataCallback.aidl25
-rw-r--r--core/java/android/service/euicc/IGetEidCallback.aidl23
-rw-r--r--core/java/android/service/euicc/IGetEuiccInfoCallback.aidl25
-rw-r--r--core/java/android/service/euicc/IGetEuiccProfileInfoListCallback.aidl25
-rw-r--r--core/java/android/service/euicc/IGetOtaStatusCallback.aidl22
-rw-r--r--core/java/android/service/euicc/IOtaStatusChangedCallback.aidl22
-rw-r--r--core/java/android/service/euicc/IRetainSubscriptionsForFactoryResetCallback.aidl23
-rw-r--r--core/java/android/service/euicc/ISwitchToSubscriptionCallback.aidl23
-rw-r--r--core/java/android/service/euicc/IUpdateSubscriptionNicknameCallback.aidl23
-rw-r--r--core/java/android/util/FeatureFlagUtils.java2
-rw-r--r--core/java/android/view/SurfaceControl.java15
-rw-r--r--core/java/android/view/WindowlessViewRoot.java16
-rw-r--r--core/java/android/view/WindowlessWindowManager.java33
-rw-r--r--core/java/android/view/accessibility/AccessibilityEvent.java60
-rw-r--r--core/java/android/view/accessibility/AccessibilityNodeInfo.java161
-rw-r--r--core/java/android/view/accessibility/AccessibilityRecord.java25
-rw-r--r--core/java/android/view/accessibility/AccessibilityWindowInfo.java23
-rw-r--r--core/java/com/android/internal/content/NativeLibraryHelper.java19
-rw-r--r--core/java/com/android/internal/os/BatteryStatsImpl.java20
-rw-r--r--core/java/com/android/internal/os/ZygoteInit.java28
-rw-r--r--core/java/com/android/internal/util/BitUtils.java6
73 files changed, 6829 insertions, 2897 deletions
diff --git a/core/java/android/app/Activity.java b/core/java/android/app/Activity.java
index f54e841fd2a0..6bea68b446a4 100644
--- a/core/java/android/app/Activity.java
+++ b/core/java/android/app/Activity.java
@@ -769,17 +769,6 @@ public class Activity extends ContextThemeWrapper
private static final String KEYBOARD_SHORTCUTS_RECEIVER_PKG_NAME = "com.android.systemui";
- private static final int LOG_AM_ON_CREATE_CALLED = 30057;
- private static final int LOG_AM_ON_START_CALLED = 30059;
- private static final int LOG_AM_ON_RESUME_CALLED = 30022;
- private static final int LOG_AM_ON_PAUSE_CALLED = 30021;
- private static final int LOG_AM_ON_STOP_CALLED = 30049;
- private static final int LOG_AM_ON_RESTART_CALLED = 30058;
- private static final int LOG_AM_ON_DESTROY_CALLED = 30060;
- private static final int LOG_AM_ON_ACTIVITY_RESULT_CALLED = 30062;
- private static final int LOG_AM_ON_TOP_RESUMED_GAINED_CALLED = 30064;
- private static final int LOG_AM_ON_TOP_RESUMED_LOST_CALLED = 30065;
-
private static class ManagedDialog {
Dialog mDialog;
Bundle mArgs;
@@ -1863,8 +1852,13 @@ public class Activity extends ContextThemeWrapper
final void performTopResumedActivityChanged(boolean isTopResumedActivity, String reason) {
onTopResumedActivityChanged(isTopResumedActivity);
- writeEventLog(isTopResumedActivity
- ? LOG_AM_ON_TOP_RESUMED_GAINED_CALLED : LOG_AM_ON_TOP_RESUMED_LOST_CALLED, reason);
+ if (isTopResumedActivity) {
+ EventLogTags.writeWmOnTopResumedGainedCalled(mIdent, getComponentName().getClassName(),
+ reason);
+ } else {
+ EventLogTags.writeWmOnTopResumedLostCalled(mIdent, getComponentName().getClassName(),
+ reason);
+ }
}
void setVoiceInteractor(IVoiceInteractor voiceInteractor) {
@@ -7898,7 +7892,8 @@ public class Activity extends ContextThemeWrapper
} else {
onCreate(icicle);
}
- writeEventLog(LOG_AM_ON_CREATE_CALLED, "performCreate");
+ EventLogTags.writeWmOnCreateCalled(mIdent, getComponentName().getClassName(),
+ "performCreate");
mActivityTransitionState.readState(icicle);
mVisibleFromClient = !mWindow.getWindowStyle().getBoolean(
@@ -7920,7 +7915,7 @@ public class Activity extends ContextThemeWrapper
mCalled = false;
mFragments.execPendingActions();
mInstrumentation.callActivityOnStart(this);
- writeEventLog(LOG_AM_ON_START_CALLED, reason);
+ EventLogTags.writeWmOnStartCalled(mIdent, getComponentName().getClassName(), reason);
if (!mCalled) {
throw new SuperNotCalledException(
@@ -7998,7 +7993,7 @@ public class Activity extends ContextThemeWrapper
mCalled = false;
mInstrumentation.callActivityOnRestart(this);
- writeEventLog(LOG_AM_ON_RESTART_CALLED, reason);
+ EventLogTags.writeWmOnRestartCalled(mIdent, getComponentName().getClassName(), reason);
if (!mCalled) {
throw new SuperNotCalledException(
"Activity " + mComponent.toShortString() +
@@ -8031,7 +8026,7 @@ public class Activity extends ContextThemeWrapper
mCalled = false;
// mResumed is set by the instrumentation
mInstrumentation.callActivityOnResume(this);
- writeEventLog(LOG_AM_ON_RESUME_CALLED, reason);
+ EventLogTags.writeWmOnResumeCalled(mIdent, getComponentName().getClassName(), reason);
if (!mCalled) {
throw new SuperNotCalledException(
"Activity " + mComponent.toShortString() +
@@ -8070,7 +8065,8 @@ public class Activity extends ContextThemeWrapper
mFragments.dispatchPause();
mCalled = false;
onPause();
- writeEventLog(LOG_AM_ON_PAUSE_CALLED, "performPause");
+ EventLogTags.writeWmOnPausedCalled(mIdent, getComponentName().getClassName(),
+ "performPause");
mResumed = false;
if (!mCalled && getApplicationInfo().targetSdkVersion
>= android.os.Build.VERSION_CODES.GINGERBREAD) {
@@ -8110,7 +8106,7 @@ public class Activity extends ContextThemeWrapper
mCalled = false;
mInstrumentation.callActivityOnStop(this);
- writeEventLog(LOG_AM_ON_STOP_CALLED, reason);
+ EventLogTags.writeWmOnStopCalled(mIdent, getComponentName().getClassName(), reason);
if (!mCalled) {
throw new SuperNotCalledException(
"Activity " + mComponent.toShortString() +
@@ -8140,7 +8136,8 @@ public class Activity extends ContextThemeWrapper
mWindow.destroy();
mFragments.dispatchDestroy();
onDestroy();
- writeEventLog(LOG_AM_ON_DESTROY_CALLED, "performDestroy");
+ EventLogTags.writeWmOnDestroyCalled(mIdent, getComponentName().getClassName(),
+ "performDestroy");
mFragments.doLoaderDestroy();
if (mVoiceInteractor != null) {
mVoiceInteractor.detachActivity();
@@ -8233,7 +8230,9 @@ public class Activity extends ContextThemeWrapper
frag.onActivityResult(requestCode, resultCode, data);
}
}
- writeEventLog(LOG_AM_ON_ACTIVITY_RESULT_CALLED, reason);
+
+ EventLogTags.writeWmOnActivityResultCalled(mIdent, getComponentName().getClassName(),
+ reason);
}
/**
@@ -8660,11 +8659,6 @@ public class Activity extends ContextThemeWrapper
}
}
- /** Log a lifecycle event for current user id and component class. */
- private void writeEventLog(int event, String reason) {
- EventLog.writeEvent(event, mIdent, getComponentName().getClassName(), reason);
- }
-
class HostCallbacks extends FragmentHostCallback<Activity> {
public HostCallbacks() {
super(Activity.this /*activity*/);
diff --git a/core/java/android/app/ContextImpl.java b/core/java/android/app/ContextImpl.java
index 1c8f4948eb85..46f88d5c81e4 100644
--- a/core/java/android/app/ContextImpl.java
+++ b/core/java/android/app/ContextImpl.java
@@ -1362,6 +1362,18 @@ class ContextImpl extends Context {
}
@Override
+ public void sendOrderedBroadcast(Intent intent, String receiverPermission, String receiverAppOp,
+ Bundle options, BroadcastReceiver resultReceiver, Handler scheduler, int initialCode,
+ String initialData, @Nullable Bundle initialExtras) {
+ int intAppOp = AppOpsManager.OP_NONE;
+ if (!TextUtils.isEmpty(receiverAppOp)) {
+ intAppOp = AppOpsManager.strOpToOp(receiverAppOp);
+ }
+ sendOrderedBroadcastAsUser(intent, getUser(), receiverPermission, intAppOp, options,
+ resultReceiver, scheduler, initialCode, initialData, initialExtras);
+ }
+
+ @Override
@Deprecated
public void sendStickyBroadcast(Intent intent) {
warnIfCallingFromSystemProcess();
diff --git a/core/java/android/app/EventLogTags.logtags b/core/java/android/app/EventLogTags.logtags
new file mode 100644
index 000000000000..6296a689b6dd
--- /dev/null
+++ b/core/java/android/app/EventLogTags.logtags
@@ -0,0 +1,36 @@
+# See system/core/logcat/event.logtags for a description of the format of this file.
+
+option java_package android.app
+
+# Do not change these names without updating the checkin_events setting in
+# google3/googledata/wireless/android/provisioning/gservices.config !!
+#
+# The activity's onPause has been called.
+30021 wm_on_paused_called (Token|1|5),(Component Name|3),(Reason|3)
+# The activity's onResume has been called.
+30022 wm_on_resume_called (Token|1|5),(Component Name|3),(Reason|3)
+
+# Attempting to stop an activity
+30048 wm_stop_activity (User|1|5),(Token|1|5),(Component Name|3)
+# The activity's onStop has been called.
+30049 wm_on_stop_called (Token|1|5),(Component Name|3),(Reason|3)
+
+# The activity's onCreate has been called.
+30057 wm_on_create_called (Token|1|5),(Component Name|3),(Reason|3)
+# The activity's onRestart has been called.
+30058 wm_on_restart_called (Token|1|5),(Component Name|3),(Reason|3)
+# The activity's onStart has been called.
+30059 wm_on_start_called (Token|1|5),(Component Name|3),(Reason|3)
+# The activity's onDestroy has been called.
+30060 wm_on_destroy_called (Token|1|5),(Component Name|3),(Reason|3)
+# The activity's onActivityResult has been called.
+30062 wm_on_activity_result_called (Token|1|5),(Component Name|3),(Reason|3)
+
+# The activity's onTopResumedActivityChanged(true) has been called.
+30064 wm_on_top_resumed_gained_called (Token|1|5),(Component Name|3),(Reason|3)
+# The activity's onTopResumedActivityChanged(false) has been called.
+30065 wm_on_top_resumed_lost_called (Token|1|5),(Component Name|3),(Reason|3)
+
+# An activity been add into stopping list
+30066 wm_add_to_stopping (User|1|5),(Token|1|5),(Component Name|3),(Reason|3)
+
diff --git a/core/java/android/app/INotificationManager.aidl b/core/java/android/app/INotificationManager.aidl
index 9aca22360fd8..0957dba4eac1 100644
--- a/core/java/android/app/INotificationManager.aidl
+++ b/core/java/android/app/INotificationManager.aidl
@@ -21,6 +21,7 @@ import android.app.ITransientNotification;
import android.app.Notification;
import android.app.NotificationChannel;
import android.app.NotificationChannelGroup;
+import android.app.NotificationHistory;
import android.app.NotificationManager;
import android.content.ComponentName;
import android.content.Intent;
@@ -119,6 +120,8 @@ interface INotificationManager
@UnsupportedAppUsage
StatusBarNotification[] getHistoricalNotifications(String callingPkg, int count);
+ NotificationHistory getNotificationHistory(String callingPkg);
+
void registerListener(in INotificationListener listener, in ComponentName component, int userid);
void unregisterListener(in INotificationListener listener, int userid);
diff --git a/core/java/android/app/SystemServiceRegistry.java b/core/java/android/app/SystemServiceRegistry.java
index d9b3d3bf57e8..1829f74700fd 100644
--- a/core/java/android/app/SystemServiceRegistry.java
+++ b/core/java/android/app/SystemServiceRegistry.java
@@ -34,6 +34,7 @@ import android.app.role.RoleManager;
import android.app.slice.SliceManager;
import android.app.timedetector.TimeDetector;
import android.app.timezone.RulesManager;
+import android.app.timezonedetector.TimeZoneDetector;
import android.app.trust.TrustManager;
import android.app.usage.IStorageStatsManager;
import android.app.usage.IUsageStatsManager;
@@ -1125,6 +1126,14 @@ public final class SystemServiceRegistry {
return new TimeDetector();
}});
+ registerService(Context.TIME_ZONE_DETECTOR_SERVICE, TimeZoneDetector.class,
+ new CachedServiceFetcher<TimeZoneDetector>() {
+ @Override
+ public TimeZoneDetector createService(ContextImpl ctx)
+ throws ServiceNotFoundException {
+ return new TimeZoneDetector();
+ }});
+
registerService(Context.PERMISSION_SERVICE, PermissionManager.class,
new CachedServiceFetcher<PermissionManager>() {
@Override
diff --git a/core/java/android/app/admin/DevicePolicyManager.java b/core/java/android/app/admin/DevicePolicyManager.java
index 73980a50e567..47fd87d446ff 100644
--- a/core/java/android/app/admin/DevicePolicyManager.java
+++ b/core/java/android/app/admin/DevicePolicyManager.java
@@ -6363,6 +6363,9 @@ public class DevicePolicyManager {
/**
* Sets the device owner information to be shown on the lock screen.
* <p>
+ * Device owner information set using this method overrides any owner information manually set
+ * by the user and prevents the user from further changing it.
+ * <p>
* If the device owner information is {@code null} or empty then the device owner info is
* cleared and the user owner info is shown on the lock screen if it is set.
* <p>
@@ -6372,6 +6375,8 @@ public class DevicePolicyManager {
* If the device owner information needs to be localized, it is the responsibility of the
* {@link DeviceAdminReceiver} to listen to the {@link Intent#ACTION_LOCALE_CHANGED} broadcast
* and set a new version of this string accordingly.
+ * <p>
+ * May be called by the device owner or the profile owner of an organization-owned device.
*
* @param admin The name of the admin component to check.
* @param info Device owner information which will be displayed instead of the user owner info.
diff --git a/core/java/android/app/backup/BackupManager.java b/core/java/android/app/backup/BackupManager.java
index 25caaaa6e5ad..93d1e7166708 100644
--- a/core/java/android/app/backup/BackupManager.java
+++ b/core/java/android/app/backup/BackupManager.java
@@ -34,6 +34,8 @@ import android.os.UserHandle;
import android.util.Log;
import android.util.Pair;
+import java.util.List;
+
/**
* The interface through which an application interacts with the Android backup service to
* request backup and restore operations.
@@ -948,6 +950,29 @@ public class BackupManager {
return null;
}
+ /**
+ * Excludes keys from KV restore for a given package. The corresponding data will be excluded
+ * from the data set available the backup agent during restore. However, final list of keys
+ * that have been excluded will be passed to the agent to make it aware of the exclusions.
+ *
+ * @param packageName The name of the package for which to exclude keys.
+ * @param keys The list of keys to exclude.
+ *
+ * @hide
+ */
+ @SystemApi
+ @RequiresPermission(android.Manifest.permission.BACKUP)
+ public void excludeKeysFromRestore(@NonNull String packageName, @NonNull List<String> keys) {
+ checkServiceBinder();
+ if (sService != null) {
+ try {
+ sService.excludeKeysFromRestore(packageName, keys);
+ } catch (RemoteException e) {
+ Log.e(TAG, "excludeKeysFromRestore() couldn't connect");
+ }
+ }
+ }
+
/*
* We wrap incoming binder calls with a private class implementation that
* redirects them into main-thread actions. This serializes the backup
diff --git a/core/java/android/app/backup/IBackupManager.aidl b/core/java/android/app/backup/IBackupManager.aidl
index 2dfaad759d3f..099272d8e3ec 100644
--- a/core/java/android/app/backup/IBackupManager.aidl
+++ b/core/java/android/app/backup/IBackupManager.aidl
@@ -710,4 +710,10 @@ interface IBackupManager {
*/
void setAncestralSerialNumber(in long ancestralSerialNumber);
+ /**
+ * Excludes keys from KV restore for a given package. The corresponding data will be excluded
+ * from the data set available the backup agent during restore. However, final list of keys
+ * that have been excluded will be passed to the agent to make it aware of the exclusions.
+ */
+ void excludeKeysFromRestore(String packageName, in List<String> keys);
}
diff --git a/core/java/android/app/timedetector/ITimeDetectorService.aidl b/core/java/android/app/timedetector/ITimeDetectorService.aidl
index ddc4932d6fec..9877fc741b7b 100644
--- a/core/java/android/app/timedetector/ITimeDetectorService.aidl
+++ b/core/java/android/app/timedetector/ITimeDetectorService.aidl
@@ -16,6 +16,7 @@
package android.app.timedetector;
+import android.app.timedetector.ManualTimeSuggestion;
import android.app.timedetector.PhoneTimeSuggestion;
/**
@@ -33,4 +34,5 @@ import android.app.timedetector.PhoneTimeSuggestion;
*/
interface ITimeDetectorService {
void suggestPhoneTime(in PhoneTimeSuggestion timeSuggestion);
+ void suggestManualTime(in ManualTimeSuggestion timeSuggestion);
}
diff --git a/core/java/android/service/euicc/EuiccProfileInfo.aidl b/core/java/android/app/timedetector/ManualTimeSuggestion.aidl
index 321021b5273c..213940493114 100644
--- a/core/java/android/service/euicc/EuiccProfileInfo.aidl
+++ b/core/java/android/app/timedetector/ManualTimeSuggestion.aidl
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2018 The Android Open Source Project
+ * 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.
@@ -13,6 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package android.service.euicc;
-parcelable EuiccProfileInfo;
+package android.app.timedetector;
+
+parcelable ManualTimeSuggestion;
diff --git a/core/java/android/app/timedetector/ManualTimeSuggestion.java b/core/java/android/app/timedetector/ManualTimeSuggestion.java
new file mode 100644
index 000000000000..e7d619a27607
--- /dev/null
+++ b/core/java/android/app/timedetector/ManualTimeSuggestion.java
@@ -0,0 +1,127 @@
+/*
+ * 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.app.timedetector;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.os.Parcel;
+import android.os.Parcelable;
+import android.util.TimestampedValue;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+import java.util.Objects;
+
+/**
+ * A time signal from a manual (user provided) source. The value consists of the number of
+ * milliseconds elapsed since 1/1/1970 00:00:00 UTC and the time according to the elapsed realtime
+ * clock when that number was established. The elapsed realtime clock is considered accurate but
+ * volatile, so time signals must not be persisted across device resets.
+ *
+ * @hide
+ */
+public final class ManualTimeSuggestion implements Parcelable {
+
+ public static final @NonNull Creator<ManualTimeSuggestion> CREATOR =
+ new Creator<ManualTimeSuggestion>() {
+ public ManualTimeSuggestion createFromParcel(Parcel in) {
+ return ManualTimeSuggestion.createFromParcel(in);
+ }
+
+ public ManualTimeSuggestion[] newArray(int size) {
+ return new ManualTimeSuggestion[size];
+ }
+ };
+
+ @NonNull
+ private final TimestampedValue<Long> mUtcTime;
+ @Nullable
+ private ArrayList<String> mDebugInfo;
+
+ public ManualTimeSuggestion(@NonNull TimestampedValue<Long> utcTime) {
+ mUtcTime = Objects.requireNonNull(utcTime);
+ }
+
+ private static ManualTimeSuggestion createFromParcel(Parcel in) {
+ TimestampedValue<Long> utcTime = in.readParcelable(null /* classLoader */);
+ ManualTimeSuggestion suggestion = new ManualTimeSuggestion(utcTime);
+ @SuppressWarnings("unchecked")
+ ArrayList<String> debugInfo = (ArrayList<String>) in.readArrayList(null /* classLoader */);
+ suggestion.mDebugInfo = debugInfo;
+ return suggestion;
+ }
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ @Override
+ public void writeToParcel(@NonNull Parcel dest, int flags) {
+ dest.writeParcelable(mUtcTime, 0);
+ dest.writeList(mDebugInfo);
+ }
+
+ @NonNull
+ public TimestampedValue<Long> getUtcTime() {
+ return mUtcTime;
+ }
+
+ @NonNull
+ public List<String> getDebugInfo() {
+ return Collections.unmodifiableList(mDebugInfo);
+ }
+
+ /**
+ * Associates information with the instance that can be useful for debugging / logging. The
+ * information is present in {@link #toString()} but is not considered for
+ * {@link #equals(Object)} and {@link #hashCode()}.
+ */
+ public void addDebugInfo(String... debugInfos) {
+ if (mDebugInfo == null) {
+ mDebugInfo = new ArrayList<>();
+ }
+ mDebugInfo.addAll(Arrays.asList(debugInfos));
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) {
+ return true;
+ }
+ if (o == null || getClass() != o.getClass()) {
+ return false;
+ }
+ ManualTimeSuggestion that = (ManualTimeSuggestion) o;
+ return Objects.equals(mUtcTime, that.mUtcTime);
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(mUtcTime);
+ }
+
+ @Override
+ public String toString() {
+ return "ManualTimeSuggestion{"
+ + "mUtcTime=" + mUtcTime
+ + ", mDebugInfo=" + mDebugInfo
+ + '}';
+ }
+}
diff --git a/core/java/android/app/timedetector/PhoneTimeSuggestion.java b/core/java/android/app/timedetector/PhoneTimeSuggestion.java
index 475a4aafd929..233dbbc42f50 100644
--- a/core/java/android/app/timedetector/PhoneTimeSuggestion.java
+++ b/core/java/android/app/timedetector/PhoneTimeSuggestion.java
@@ -29,7 +29,9 @@ import java.util.List;
import java.util.Objects;
/**
- * A time signal from a telephony source. The value consists of the number of milliseconds elapsed
+ * A time signal from a telephony source. The value can be {@code null} to indicate that the
+ * telephony source has entered an "un-opinionated" state and any previously sent suggestions are
+ * being withdrawn. When not {@code null}, the value consists of the number of milliseconds elapsed
* since 1/1/1970 00:00:00 UTC and the time according to the elapsed realtime clock when that number
* was established. The elapsed realtime clock is considered accurate but volatile, so time signals
* must not be persisted across device resets.
@@ -50,20 +52,17 @@ public final class PhoneTimeSuggestion implements Parcelable {
};
private final int mPhoneId;
- @NonNull
- private final TimestampedValue<Long> mUtcTime;
- @Nullable
- private ArrayList<String> mDebugInfo;
+ @Nullable private TimestampedValue<Long> mUtcTime;
+ @Nullable private ArrayList<String> mDebugInfo;
- public PhoneTimeSuggestion(int phoneId, @NonNull TimestampedValue<Long> utcTime) {
+ public PhoneTimeSuggestion(int phoneId) {
mPhoneId = phoneId;
- mUtcTime = Objects.requireNonNull(utcTime);
}
private static PhoneTimeSuggestion createFromParcel(Parcel in) {
int phoneId = in.readInt();
- TimestampedValue<Long> utcTime = in.readParcelable(null /* classLoader */);
- PhoneTimeSuggestion suggestion = new PhoneTimeSuggestion(phoneId, utcTime);
+ PhoneTimeSuggestion suggestion = new PhoneTimeSuggestion(phoneId);
+ suggestion.setUtcTime(in.readParcelable(null /* classLoader */));
@SuppressWarnings("unchecked")
ArrayList<String> debugInfo = (ArrayList<String>) in.readArrayList(null /* classLoader */);
suggestion.mDebugInfo = debugInfo;
@@ -86,7 +85,11 @@ public final class PhoneTimeSuggestion implements Parcelable {
return mPhoneId;
}
- @NonNull
+ public void setUtcTime(@Nullable TimestampedValue<Long> utcTime) {
+ mUtcTime = utcTime;
+ }
+
+ @Nullable
public TimestampedValue<Long> getUtcTime() {
return mUtcTime;
}
diff --git a/core/java/android/app/timedetector/TimeDetector.java b/core/java/android/app/timedetector/TimeDetector.java
index 334e9582a145..48d5cd2d65a5 100644
--- a/core/java/android/app/timedetector/TimeDetector.java
+++ b/core/java/android/app/timedetector/TimeDetector.java
@@ -17,19 +17,22 @@
package android.app.timedetector;
import android.annotation.NonNull;
+import android.annotation.RequiresPermission;
import android.annotation.SystemService;
import android.content.Context;
import android.os.RemoteException;
import android.os.ServiceManager;
import android.os.ServiceManager.ServiceNotFoundException;
+import android.os.SystemClock;
import android.util.Log;
+import android.util.TimestampedValue;
/**
* The interface through which system components can send signals to the TimeDetectorService.
* @hide
*/
@SystemService(Context.TIME_DETECTOR_SERVICE)
-public final class TimeDetector {
+public class TimeDetector {
private static final String TAG = "timedetector.TimeDetector";
private static final boolean DEBUG = false;
@@ -41,10 +44,11 @@ public final class TimeDetector {
}
/**
- * Suggests the current time to the detector. The detector may ignore the signal if better
- * signals are available such as those that come from more reliable sources or were
- * determined more recently.
+ * Suggests the current phone-signal derived time to the detector. The detector may ignore the
+ * signal if better signals are available such as those that come from more reliable sources or
+ * were determined more recently.
*/
+ @RequiresPermission(android.Manifest.permission.SET_TIME)
public void suggestPhoneTime(@NonNull PhoneTimeSuggestion timeSuggestion) {
if (DEBUG) {
Log.d(TAG, "suggestPhoneTime called: " + timeSuggestion);
@@ -56,4 +60,29 @@ public final class TimeDetector {
}
}
+ /**
+ * Suggests the user's manually entered current time to the detector.
+ */
+ @RequiresPermission(android.Manifest.permission.SET_TIME)
+ public void suggestManualTime(@NonNull ManualTimeSuggestion timeSuggestion) {
+ if (DEBUG) {
+ Log.d(TAG, "suggestManualTime called: " + timeSuggestion);
+ }
+ try {
+ mITimeDetectorService.suggestManualTime(timeSuggestion);
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+
+ /**
+ * A shared utility method to create a {@link ManualTimeSuggestion}.
+ */
+ public static ManualTimeSuggestion createManualTimeSuggestion(long when, String why) {
+ TimestampedValue<Long> utcTime =
+ new TimestampedValue<>(SystemClock.elapsedRealtime(), when);
+ ManualTimeSuggestion manualTimeSuggestion = new ManualTimeSuggestion(utcTime);
+ manualTimeSuggestion.addDebugInfo(why);
+ return manualTimeSuggestion;
+ }
}
diff --git a/core/java/android/app/timezonedetector/ITimeZoneDetectorService.aidl b/core/java/android/app/timezonedetector/ITimeZoneDetectorService.aidl
new file mode 100644
index 000000000000..260c7df72fba
--- /dev/null
+++ b/core/java/android/app/timezonedetector/ITimeZoneDetectorService.aidl
@@ -0,0 +1,36 @@
+/*
+ * 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.app.timezonedetector;
+
+import android.app.timezonedetector.PhoneTimeZoneSuggestion;
+
+/**
+ * System private API to communicate with time zone detector service.
+ *
+ * <p>Used to provide information to the Time Zone Detector Service from other parts of the Android
+ * system that have access to time zone-related signals, e.g. telephony.
+ *
+ * <p>Use the {@link android.app.timezonedetector.TimeZoneDetector} class rather than going through
+ * this Binder interface directly. See {@link android.app.timezonedetector.TimeZoneDetectorService}
+ * for more complete documentation.
+ *
+ *
+ * {@hide}
+ */
+interface ITimeZoneDetectorService {
+ void suggestPhoneTimeZone(in PhoneTimeZoneSuggestion timeZoneSuggestion);
+}
diff --git a/core/java/android/service/euicc/GetEuiccProfileInfoListResult.aidl b/core/java/android/app/timezonedetector/PhoneTimeZoneSuggestion.aidl
index 6003b79462da..3ad903bb5949 100644
--- a/core/java/android/service/euicc/GetEuiccProfileInfoListResult.aidl
+++ b/core/java/android/app/timezonedetector/PhoneTimeZoneSuggestion.aidl
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2017 The Android Open Source Project
+ * 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.
@@ -14,6 +14,6 @@
* limitations under the License.
*/
-package android.service.euicc;
+package android.app.timezonedetector;
-parcelable GetEuiccProfileInfoListResult;
+parcelable PhoneTimeZoneSuggestion;
diff --git a/core/java/android/app/timezonedetector/PhoneTimeZoneSuggestion.java b/core/java/android/app/timezonedetector/PhoneTimeZoneSuggestion.java
new file mode 100644
index 000000000000..e8162488394c
--- /dev/null
+++ b/core/java/android/app/timezonedetector/PhoneTimeZoneSuggestion.java
@@ -0,0 +1,341 @@
+/*
+ * Copyright 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.app.timezonedetector;
+
+import android.annotation.IntDef;
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.os.Parcel;
+import android.os.Parcelable;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.Objects;
+
+/**
+ * A suggested time zone from a Phone-based signal, e.g. from MCC and NITZ information.
+ *
+ * @hide
+ */
+public final class PhoneTimeZoneSuggestion implements Parcelable {
+
+ @NonNull
+ public static final Creator<PhoneTimeZoneSuggestion> CREATOR =
+ new Creator<PhoneTimeZoneSuggestion>() {
+ public PhoneTimeZoneSuggestion createFromParcel(Parcel in) {
+ return PhoneTimeZoneSuggestion.createFromParcel(in);
+ }
+
+ public PhoneTimeZoneSuggestion[] newArray(int size) {
+ return new PhoneTimeZoneSuggestion[size];
+ }
+ };
+
+ /**
+ * Creates an empty time zone suggestion, i.e. one that will cancel previous suggestions with
+ * the same {@code phoneId}.
+ */
+ @NonNull
+ public static PhoneTimeZoneSuggestion createEmptySuggestion(
+ int phoneId, @NonNull String debugInfo) {
+ return new Builder(phoneId).addDebugInfo(debugInfo).build();
+ }
+
+ @IntDef({ MATCH_TYPE_NA, MATCH_TYPE_NETWORK_COUNTRY_ONLY, MATCH_TYPE_NETWORK_COUNTRY_AND_OFFSET,
+ MATCH_TYPE_EMULATOR_ZONE_ID, MATCH_TYPE_TEST_NETWORK_OFFSET_ONLY })
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface MatchType {}
+
+ /** Used when match type is not applicable. */
+ public static final int MATCH_TYPE_NA = 0;
+
+ /**
+ * Only the network country is known.
+ */
+ public static final int MATCH_TYPE_NETWORK_COUNTRY_ONLY = 2;
+
+ /**
+ * Both the network county and offset were known.
+ */
+ public static final int MATCH_TYPE_NETWORK_COUNTRY_AND_OFFSET = 3;
+
+ /**
+ * The device is running in an emulator and an NITZ signal was simulated containing an
+ * Android extension with an explicit Olson ID.
+ */
+ public static final int MATCH_TYPE_EMULATOR_ZONE_ID = 4;
+
+ /**
+ * The phone is most likely running in a test network not associated with a country (this is
+ * distinct from the country just not being known yet).
+ * Historically, Android has just picked an arbitrary time zone with the correct offset when
+ * on a test network.
+ */
+ public static final int MATCH_TYPE_TEST_NETWORK_OFFSET_ONLY = 5;
+
+ @IntDef({ QUALITY_NA, QUALITY_SINGLE_ZONE, QUALITY_MULTIPLE_ZONES_WITH_SAME_OFFSET,
+ QUALITY_MULTIPLE_ZONES_WITH_DIFFERENT_OFFSETS })
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface Quality {}
+
+ /** Used when quality is not applicable. */
+ public static final int QUALITY_NA = 0;
+
+ /** There is only one answer */
+ public static final int QUALITY_SINGLE_ZONE = 1;
+
+ /**
+ * There are multiple answers, but they all shared the same offset / DST state at the time
+ * the suggestion was created. i.e. it might be the wrong zone but the user won't notice
+ * immediately if it is wrong.
+ */
+ public static final int QUALITY_MULTIPLE_ZONES_WITH_SAME_OFFSET = 2;
+
+ /**
+ * There are multiple answers with different offsets. The one given is just one possible.
+ */
+ public static final int QUALITY_MULTIPLE_ZONES_WITH_DIFFERENT_OFFSETS = 3;
+
+ /**
+ * The ID of the phone this suggestion is associated with. For multiple-sim devices this
+ * helps to establish origin so filtering / stickiness can be implemented.
+ */
+ private final int mPhoneId;
+
+ /**
+ * The suggestion. {@code null} means there is no current suggestion and any previous suggestion
+ * should be forgotten.
+ */
+ private final String mZoneId;
+
+ /**
+ * The type of "match" used to establish the time zone.
+ */
+ @MatchType
+ private final int mMatchType;
+
+ /**
+ * A measure of the quality of the time zone suggestion, i.e. how confident one could be in
+ * it.
+ */
+ @Quality
+ private final int mQuality;
+
+ /**
+ * Free-form debug information about how the signal was derived. Used for debug only,
+ * intentionally not used in equals(), etc.
+ */
+ private List<String> mDebugInfo;
+
+ private PhoneTimeZoneSuggestion(Builder builder) {
+ mPhoneId = builder.mPhoneId;
+ mZoneId = builder.mZoneId;
+ mMatchType = builder.mMatchType;
+ mQuality = builder.mQuality;
+ mDebugInfo = builder.mDebugInfo != null ? new ArrayList<>(builder.mDebugInfo) : null;
+ }
+
+ @SuppressWarnings("unchecked")
+ private static PhoneTimeZoneSuggestion createFromParcel(Parcel in) {
+ // Use the Builder so we get validation during build().
+ int phoneId = in.readInt();
+ PhoneTimeZoneSuggestion suggestion = new Builder(phoneId)
+ .setZoneId(in.readString())
+ .setMatchType(in.readInt())
+ .setQuality(in.readInt())
+ .build();
+ List<String> debugInfo = in.readArrayList(PhoneTimeZoneSuggestion.class.getClassLoader());
+ if (debugInfo != null) {
+ suggestion.addDebugInfo(debugInfo);
+ }
+ return suggestion;
+ }
+
+ @Override
+ public void writeToParcel(@NonNull Parcel dest, int flags) {
+ dest.writeInt(mPhoneId);
+ dest.writeString(mZoneId);
+ dest.writeInt(mMatchType);
+ dest.writeInt(mQuality);
+ dest.writeList(mDebugInfo);
+ }
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ public int getPhoneId() {
+ return mPhoneId;
+ }
+
+ @Nullable
+ public String getZoneId() {
+ return mZoneId;
+ }
+
+ @MatchType
+ public int getMatchType() {
+ return mMatchType;
+ }
+
+ @Quality
+ public int getQuality() {
+ return mQuality;
+ }
+
+ @NonNull
+ public List<String> getDebugInfo() {
+ return mDebugInfo == null
+ ? Collections.emptyList() : Collections.unmodifiableList(mDebugInfo);
+ }
+
+ /**
+ * Associates information with the instance that can be useful for debugging / logging. The
+ * information is present in {@link #toString()} but is not considered for
+ * {@link #equals(Object)} and {@link #hashCode()}.
+ */
+ public void addDebugInfo(@NonNull String debugInfo) {
+ if (mDebugInfo == null) {
+ mDebugInfo = new ArrayList<>();
+ }
+ mDebugInfo.add(debugInfo);
+ }
+
+ /**
+ * Associates information with the instance that can be useful for debugging / logging. The
+ * information is present in {@link #toString()} but is not considered for
+ * {@link #equals(Object)} and {@link #hashCode()}.
+ */
+ public void addDebugInfo(@NonNull List<String> debugInfo) {
+ if (mDebugInfo == null) {
+ mDebugInfo = new ArrayList<>(debugInfo.size());
+ }
+ mDebugInfo.addAll(debugInfo);
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) {
+ return true;
+ }
+ if (o == null || getClass() != o.getClass()) {
+ return false;
+ }
+ PhoneTimeZoneSuggestion that = (PhoneTimeZoneSuggestion) o;
+ return mPhoneId == that.mPhoneId
+ && mMatchType == that.mMatchType
+ && mQuality == that.mQuality
+ && Objects.equals(mZoneId, that.mZoneId);
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(mPhoneId, mZoneId, mMatchType, mQuality);
+ }
+
+ @Override
+ public String toString() {
+ return "PhoneTimeZoneSuggestion{"
+ + "mPhoneId=" + mPhoneId
+ + ", mZoneId='" + mZoneId + '\''
+ + ", mMatchType=" + mMatchType
+ + ", mQuality=" + mQuality
+ + ", mDebugInfo=" + mDebugInfo
+ + '}';
+ }
+
+ /**
+ * Builds {@link PhoneTimeZoneSuggestion} instances.
+ *
+ * @hide
+ */
+ public static class Builder {
+ private final int mPhoneId;
+ private String mZoneId;
+ @MatchType private int mMatchType;
+ @Quality private int mQuality;
+ private List<String> mDebugInfo;
+
+ public Builder(int phoneId) {
+ mPhoneId = phoneId;
+ }
+
+ /** Returns the builder for call chaining. */
+ public Builder setZoneId(String zoneId) {
+ mZoneId = zoneId;
+ return this;
+ }
+
+ /** Returns the builder for call chaining. */
+ public Builder setMatchType(@MatchType int matchType) {
+ mMatchType = matchType;
+ return this;
+ }
+
+ /** Returns the builder for call chaining. */
+ public Builder setQuality(@Quality int quality) {
+ mQuality = quality;
+ return this;
+ }
+
+ /** Returns the builder for call chaining. */
+ public Builder addDebugInfo(@NonNull String debugInfo) {
+ if (mDebugInfo == null) {
+ mDebugInfo = new ArrayList<>();
+ }
+ mDebugInfo.add(debugInfo);
+ return this;
+ }
+
+ /**
+ * Performs basic structural validation of this instance. e.g. Are all the fields populated
+ * that must be? Are the enum ints set to valid values?
+ */
+ void validate() {
+ int quality = mQuality;
+ int matchType = mMatchType;
+ if (mZoneId == null) {
+ if (quality != QUALITY_NA || matchType != MATCH_TYPE_NA) {
+ throw new RuntimeException("Invalid quality or match type for null zone ID."
+ + " quality=" + quality + ", matchType=" + matchType);
+ }
+ } else {
+ boolean qualityValid = (quality == QUALITY_SINGLE_ZONE
+ || quality == QUALITY_MULTIPLE_ZONES_WITH_SAME_OFFSET
+ || quality == QUALITY_MULTIPLE_ZONES_WITH_DIFFERENT_OFFSETS);
+ boolean matchTypeValid = (matchType == MATCH_TYPE_NETWORK_COUNTRY_ONLY
+ || matchType == MATCH_TYPE_NETWORK_COUNTRY_AND_OFFSET
+ || matchType == MATCH_TYPE_EMULATOR_ZONE_ID
+ || matchType == MATCH_TYPE_TEST_NETWORK_OFFSET_ONLY);
+ if (!qualityValid || !matchTypeValid) {
+ throw new RuntimeException("Invalid quality or match type with zone ID."
+ + " quality=" + quality + ", matchType=" + matchType);
+ }
+ }
+ }
+
+ /** Returns the {@link PhoneTimeZoneSuggestion}. */
+ public PhoneTimeZoneSuggestion build() {
+ validate();
+ return new PhoneTimeZoneSuggestion(this);
+ }
+ }
+}
diff --git a/core/java/android/app/timezonedetector/TimeZoneDetector.java b/core/java/android/app/timezonedetector/TimeZoneDetector.java
new file mode 100644
index 000000000000..909cbc2ccdf7
--- /dev/null
+++ b/core/java/android/app/timezonedetector/TimeZoneDetector.java
@@ -0,0 +1,59 @@
+/*
+ * 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.app.timezonedetector;
+
+import android.annotation.NonNull;
+import android.annotation.SystemService;
+import android.content.Context;
+import android.os.RemoteException;
+import android.os.ServiceManager;
+import android.os.ServiceManager.ServiceNotFoundException;
+import android.util.Log;
+
+/**
+ * The interface through which system components can send signals to the TimeZoneDetectorService.
+ * @hide
+ */
+@SystemService(Context.TIME_ZONE_DETECTOR_SERVICE)
+public final class TimeZoneDetector {
+ private static final String TAG = "timezonedetector.TimeZoneDetector";
+ private static final boolean DEBUG = false;
+
+ private final ITimeZoneDetectorService mITimeZoneDetectorService;
+
+ public TimeZoneDetector() throws ServiceNotFoundException {
+ mITimeZoneDetectorService = ITimeZoneDetectorService.Stub.asInterface(
+ ServiceManager.getServiceOrThrow(Context.TIME_ZONE_DETECTOR_SERVICE));
+ }
+
+ /**
+ * Suggests the current time zone to the detector. The detector may ignore the signal if better
+ * signals are available such as those that come from more reliable sources or were
+ * determined more recently.
+ */
+ public void suggestPhoneTimeZone(@NonNull PhoneTimeZoneSuggestion timeZoneSuggestion) {
+ if (DEBUG) {
+ Log.d(TAG, "suggestPhoneTimeZone called: " + timeZoneSuggestion);
+ }
+ try {
+ mITimeZoneDetectorService.suggestPhoneTimeZone(timeZoneSuggestion);
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+
+}
diff --git a/core/java/android/content/Context.java b/core/java/android/content/Context.java
index 4a0fc6689fa7..341b5206ba90 100644
--- a/core/java/android/content/Context.java
+++ b/core/java/android/content/Context.java
@@ -2484,6 +2484,48 @@ public abstract class Context {
}
/**
+ * Version of
+ * {@link #sendOrderedBroadcast(Intent, String, BroadcastReceiver, Handler, int, String,
+ * Bundle)} that allows you to specify the App Op to enforce restrictions on which receivers
+ * the broadcast will be sent to as well as supply an optional sending options
+ *
+ * <p>See {@link BroadcastReceiver} for more information on Intent broadcasts.
+ *
+ * @param intent The Intent to broadcast; all receivers matching this
+ * Intent will receive the broadcast.
+ * @param receiverPermission String naming a permissions that
+ * a receiver must hold in order to receive your broadcast.
+ * If null, no permission is required.
+ * @param receiverAppOp The app op associated with the broadcast. If null, no appOp is
+ * required. If both receiverAppOp and receiverPermission are non-null,
+ * a receiver must have both of them to
+ * receive the broadcast
+ * @param options (optional) Additional sending options, generated from a
+ * {@link android.app.BroadcastOptions}.
+ * @param resultReceiver Your own BroadcastReceiver to treat as the final
+ * receiver of the broadcast.
+ * @param scheduler A custom Handler with which to schedule the
+ * resultReceiver callback; if null it will be
+ * scheduled in the Context's main thread.
+ * @param initialCode An initial value for the result code. Often
+ * Activity.RESULT_OK.
+ * @param initialData An initial value for the result data. Often
+ * null.
+ * @param initialExtras An initial value for the result extras. Often
+ * null.
+ *
+ * @see #sendOrderedBroadcast(Intent, String, BroadcastReceiver, Handler, int, String, Bundle)
+ * @see android.app.BroadcastOptions
+ */
+ public void sendOrderedBroadcast(@RequiresPermission @NonNull Intent intent,
+ @Nullable String receiverPermission, @Nullable String receiverAppOp,
+ @Nullable Bundle options, @Nullable BroadcastReceiver resultReceiver,
+ @Nullable Handler scheduler, int initialCode, @Nullable String initialData,
+ @Nullable Bundle initialExtras) {
+ throw new RuntimeException("Not implemented. Must override in a subclass.");
+ }
+
+ /**
* <p>Perform a {@link #sendBroadcast(Intent)} that is "sticky," meaning the
* Intent you are sending stays around after the broadcast is complete,
* so that others can quickly retrieve that data through the return
@@ -3383,7 +3425,9 @@ public abstract class Context {
CROSS_PROFILE_APPS_SERVICE,
//@hide: SYSTEM_UPDATE_SERVICE,
//@hide: TIME_DETECTOR_SERVICE,
+ //@hide: TIME_ZONE_DETECTOR_SERVICE,
PERMISSION_SERVICE,
+ INCREMENTAL_SERVICE,
})
@Retention(RetentionPolicy.SOURCE)
public @interface ServiceName {}
@@ -4835,7 +4879,7 @@ public abstract class Context {
/**
* Use with {@link #getSystemService(String)} to retrieve an
- * {@link android.app.timedetector.ITimeDetectorService}.
+ * {@link android.app.timedetector.TimeDetector}.
* @hide
*
* @see #getSystemService(String)
@@ -4843,6 +4887,15 @@ public abstract class Context {
public static final String TIME_DETECTOR_SERVICE = "time_detector";
/**
+ * Use with {@link #getSystemService(String)} to retrieve an
+ * {@link android.app.timezonedetector.TimeZoneDetector}.
+ * @hide
+ *
+ * @see #getSystemService(String)
+ */
+ public static final String TIME_ZONE_DETECTOR_SERVICE = "time_zone_detector";
+
+ /**
* Binder service name for {@link AppBindingService}.
* @hide
*/
@@ -4917,6 +4970,13 @@ public abstract class Context {
public static final String APP_INTEGRITY_SERVICE = "app_integrity";
/**
+ * Use with {@link #getSystemService(String)} to retrieve an
+ * {@link android.os.incremental.IncrementalManager}.
+ * @hide
+ */
+ public static final String INCREMENTAL_SERVICE = "incremental";
+
+ /**
* Determine whether the given permission is allowed for a particular
* process and user ID running in the system.
*
diff --git a/core/java/android/content/ContextWrapper.java b/core/java/android/content/ContextWrapper.java
index e44d6ae40356..d6442e28439f 100644
--- a/core/java/android/content/ContextWrapper.java
+++ b/core/java/android/content/ContextWrapper.java
@@ -590,6 +590,16 @@ public class ContextWrapper extends Context {
}
@Override
+ public void sendOrderedBroadcast(@RequiresPermission @NonNull Intent intent,
+ @Nullable String receiverPermission, @Nullable String receiverAppOp,
+ @Nullable Bundle options, @Nullable BroadcastReceiver resultReceiver,
+ @Nullable Handler scheduler, int initialCode, @Nullable String initialData,
+ @Nullable Bundle initialExtras) {
+ mBase.sendOrderedBroadcast(intent, receiverPermission, receiverAppOp, options,
+ resultReceiver, scheduler, initialCode, initialData, initialExtras);
+ }
+
+ @Override
@Deprecated
public void sendStickyBroadcast(Intent intent) {
mBase.sendStickyBroadcast(intent);
diff --git a/core/java/android/net/IpConfiguration.java b/core/java/android/net/IpConfiguration.java
index 143467b15fe8..dddb64d8cece 100644
--- a/core/java/android/net/IpConfiguration.java
+++ b/core/java/android/net/IpConfiguration.java
@@ -191,18 +191,12 @@ public final class IpConfiguration implements Parcelable {
83 * httpProxy.hashCode();
}
- /**
- * Implement the Parcelable interface
- * @hide
- */
+ /** Implement the Parcelable interface */
public int describeContents() {
return 0;
}
- /**
- * Implement the Parcelable interface
- * @hide
- */
+ /** Implement the Parcelable interface */
public void writeToParcel(@NonNull Parcel dest, int flags) {
dest.writeString(ipAssignment.name());
dest.writeString(proxySettings.name());
diff --git a/core/java/android/net/LinkProperties.java b/core/java/android/net/LinkProperties.java
index 0706e755d133..8e1834113486 100644
--- a/core/java/android/net/LinkProperties.java
+++ b/core/java/android/net/LinkProperties.java
@@ -762,10 +762,7 @@ public final class LinkProperties implements Parcelable {
* Returns the NAT64 prefix in use on this link, if any.
*
* @return the NAT64 prefix or {@code null}.
- * @hide
*/
- @SystemApi
- @TestApi
public @Nullable IpPrefix getNat64Prefix() {
return mNat64Prefix;
}
@@ -777,10 +774,7 @@ public final class LinkProperties implements Parcelable {
* 128-bit IPv6 address) are supported or {@code null} for no prefix.
*
* @param prefix the NAT64 prefix.
- * @hide
*/
- @SystemApi
- @TestApi
public void setNat64Prefix(@Nullable IpPrefix prefix) {
if (prefix != null && prefix.getPrefixLength() != 96) {
throw new IllegalArgumentException("Only 96-bit prefixes are supported: " + prefix);
diff --git a/core/java/android/os/Binder.java b/core/java/android/os/Binder.java
index ec3919997603..15ff69e7fd2a 100644
--- a/core/java/android/os/Binder.java
+++ b/core/java/android/os/Binder.java
@@ -505,6 +505,19 @@ public class Binder implements IBinder {
public static final native void restoreCallingWorkSource(long token);
/**
+ * Mark as being built with VINTF-level stability promise. This API should
+ * only ever be invoked by the build system. It means that the interface
+ * represented by this binder is guaranteed to be kept stable for several
+ * years, and the build system also keeps snapshots of these APIs and
+ * invokes the AIDL compiler to make sure that these snapshots are
+ * backwards compatible. Instead of using this API, use an @VintfStability
+ * interface.
+ *
+ * @hide
+ */
+ public final native void markVintfStability();
+
+ /**
* Flush any Binder commands pending in the current thread to the kernel
* driver. This can be
* useful to call before performing an operation that may block for a long
diff --git a/core/java/android/os/Build.java b/core/java/android/os/Build.java
index 89ccef64d4cd..6eaea99d5c49 100755
--- a/core/java/android/os/Build.java
+++ b/core/java/android/os/Build.java
@@ -1084,7 +1084,7 @@ public class Build {
return result == 0;
}
- final String system = SystemProperties.get("ro.build.fingerprint");
+ final String system = SystemProperties.get("ro.system.build.fingerprint");
final String vendor = SystemProperties.get("ro.vendor.build.fingerprint");
final String bootimage = SystemProperties.get("ro.bootimage.build.fingerprint");
final String requiredBootloader = SystemProperties.get("ro.build.expect.bootloader");
@@ -1094,7 +1094,7 @@ public class Build {
TelephonyProperties.baseband_version(), "");
if (TextUtils.isEmpty(system)) {
- Slog.e(TAG, "Required ro.build.fingerprint is empty!");
+ Slog.e(TAG, "Required ro.system.build.fingerprint is empty!");
return false;
}
diff --git a/core/java/android/os/FileObserver.java b/core/java/android/os/FileObserver.java
index 4d9ebc2b5923..5b715c0dcb3c 100644
--- a/core/java/android/os/FileObserver.java
+++ b/core/java/android/os/FileObserver.java
@@ -32,7 +32,7 @@ import java.util.List;
/**
* Monitors files (using <a href="http://en.wikipedia.org/wiki/Inotify">inotify</a>)
- * to fire an event after files are accessed or changed by by any process on
+ * to fire an event after files are accessed or changed by any process on
* the device (including this one). FileObserver is an abstract class;
* subclasses must implement the event handler {@link #onEvent(int, String)}.
*
diff --git a/core/java/android/os/ResultReceiver.aidl b/core/java/android/os/ResultReceiver.aidl
index 28ce6d5f15b0..9fd5bc970496 100644
--- a/core/java/android/os/ResultReceiver.aidl
+++ b/core/java/android/os/ResultReceiver.aidl
@@ -2,19 +2,19 @@
**
** Copyright 2007, 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
+** 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
+** 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
+** 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.os;
-parcelable ResultReceiver;
+@JavaOnlyStableParcelable parcelable ResultReceiver;
diff --git a/core/java/android/os/UserManager.java b/core/java/android/os/UserManager.java
index ce91c50ca696..74340f0d4710 100644
--- a/core/java/android/os/UserManager.java
+++ b/core/java/android/os/UserManager.java
@@ -46,6 +46,7 @@ import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Rect;
import android.graphics.drawable.Drawable;
+import android.location.LocationManager;
import android.provider.Settings;
import android.telephony.TelephonyManager;
import android.view.WindowManager.LayoutParams;
@@ -486,13 +487,13 @@ public class UserManager {
*
* <p>This user restriction is different from {@link #DISALLOW_SHARE_LOCATION},
* as the device owner or profile owner can still enable or disable location mode via
- * {@link DevicePolicyManager#setSecureSetting} when this restriction is on.
+ * {@link DevicePolicyManager#setLocationEnabled} when this restriction is on.
*
* <p>The default value is <code>false</code>.
*
* <p>Key for user restrictions.
* <p>Type: Boolean
- * @see android.location.LocationManager#isProviderEnabled(String)
+ * @see LocationManager#isLocationEnabled()
* @see DevicePolicyManager#addUserRestriction(ComponentName, String)
* @see DevicePolicyManager#clearUserRestriction(ComponentName, String)
* @see #getUserRestrictions()
diff --git a/core/java/android/os/incremental/IIncrementalService.aidl b/core/java/android/os/incremental/IIncrementalManager.aidl
index 1c832ca9e6db..d6446d485af5 100644
--- a/core/java/android/os/incremental/IIncrementalService.aidl
+++ b/core/java/android/os/incremental/IIncrementalManager.aidl
@@ -19,7 +19,7 @@ package android.os.incremental;
import android.os.incremental.IncrementalDataLoaderParamsParcel;
/** @hide */
-interface IIncrementalService {
+interface IIncrementalManager {
/**
* A set of flags for the |createMode| parameters when creating a new Incremental storage.
*/
@@ -53,6 +53,12 @@ interface IIncrementalService {
int makeDirectory(int storageId, in @utf8InCpp String pathUnderStorage);
/**
+ * Recursively creates a directory under a storage. The target directory is specified by its relative path under the storage.
+ * All the parent directories of the target directory will be created if they do not exist already.
+ */
+ int makeDirectories(int storageId, in @utf8InCpp String pathUnderStorage);
+
+ /**
* Creates a file under a storage, specifying its name, size and metadata.
*/
int makeFile(int storageId, in @utf8InCpp String pathUnderStorage, long size, in byte[] metadata);
@@ -64,10 +70,12 @@ interface IIncrementalService {
int makeFileFromRange(int storageId, in @utf8InCpp String targetPathUnderStorage, in @utf8InCpp String sourcePathUnderStorage, long start, long end);
/**
- * Creates a hard link between two files in a storage.
- * Both source and destination are specified by relative paths under storage.
+ * Creates a hard link between two files in two storage instances.
+ * Source and dest specified by parent storage IDs and their relative paths under the storage.
+ * The source and dest storage instances should be in the same fs mount.
+ * Note: destStorageId can be the same as sourceStorageId.
*/
- int makeLink(int storageId, in @utf8InCpp String sourcePathUnderStorage, in @utf8InCpp String destPathUnderStorage);
+ int makeLink(int sourceStorageId, in @utf8InCpp String sourcePathUnderStorage, int destStorageId, in @utf8InCpp String destPathUnderStorage);
/**
* Deletes a hard link in a storage, specified by the relative path of the link target under storage.
@@ -85,12 +93,12 @@ interface IIncrementalService {
byte[] getFileMetadata(int storageId, in @utf8InCpp String pathUnderStorage);
/**
- * Returns the list of file paths under a storage.
+ * Starts loading data for a storage.
*/
- @utf8InCpp String[] getFileList(int storageId);
+ boolean startLoading(int storageId);
/**
- * Starts loading data for a storage.
+ * Deletes a storage given its ID. Deletes its bind mounts and unmount it. Stop its data loader.
*/
- boolean startLoading(int storageId);
+ void deleteStorage(int storageId);
}
diff --git a/core/java/android/os/incremental/IncrementalDataLoaderParams.java b/core/java/android/os/incremental/IncrementalDataLoaderParams.java
new file mode 100644
index 000000000000..701f1cc8de02
--- /dev/null
+++ b/core/java/android/os/incremental/IncrementalDataLoaderParams.java
@@ -0,0 +1,84 @@
+/*
+ * 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.os.incremental;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.os.ParcelFileDescriptor;
+
+import java.util.Arrays;
+import java.util.Map;
+import java.util.stream.Collectors;
+
+/**
+ * This class represents the parameters used to configure an Incremental Data Loader.
+ * Hide for now.
+ * @hide
+ */
+public class IncrementalDataLoaderParams {
+ @NonNull private final IncrementalDataLoaderParamsParcel mData;
+
+ public IncrementalDataLoaderParams(@NonNull String url, @NonNull String packageName,
+ @Nullable Map<String, ParcelFileDescriptor> namedFds) {
+ IncrementalDataLoaderParamsParcel data = new IncrementalDataLoaderParamsParcel();
+ data.staticArgs = url;
+ data.packageName = packageName;
+ if (namedFds == null || namedFds.isEmpty()) {
+ data.dynamicArgs = new NamedParcelFileDescriptor[0];
+ } else {
+ data.dynamicArgs = new NamedParcelFileDescriptor[namedFds.size()];
+ int i = 0;
+ for (Map.Entry<String, ParcelFileDescriptor> namedFd : namedFds.entrySet()) {
+ data.dynamicArgs[i] = new NamedParcelFileDescriptor();
+ data.dynamicArgs[i].name = namedFd.getKey();
+ data.dynamicArgs[i].fd = namedFd.getValue();
+ i += 1;
+ }
+ }
+ mData = data;
+ }
+
+ public IncrementalDataLoaderParams(@NonNull IncrementalDataLoaderParamsParcel data) {
+ mData = data;
+ }
+
+ /**
+ * @return static server's URL
+ */
+ public final @NonNull String getStaticArgs() {
+ return mData.staticArgs;
+ }
+
+ /**
+ * @return data loader's package name
+ */
+ public final @NonNull String getPackageName() {
+ return mData.packageName;
+ }
+
+ public final @NonNull IncrementalDataLoaderParamsParcel getData() {
+ return mData;
+ }
+
+ /**
+ * @return data loader's dynamic arguments such as file descriptors
+ */
+ public final @NonNull Map<String, ParcelFileDescriptor> getDynamicArgs() {
+ return Arrays.stream(mData.dynamicArgs).collect(
+ Collectors.toMap(p->p.name, p->p.fd));
+ }
+}
diff --git a/core/java/android/os/incremental/IncrementalDataLoaderParamsParcel.aidl b/core/java/android/os/incremental/IncrementalDataLoaderParamsParcel.aidl
index 50c28f0a4c17..cd988dcace5b 100644
--- a/core/java/android/os/incremental/IncrementalDataLoaderParamsParcel.aidl
+++ b/core/java/android/os/incremental/IncrementalDataLoaderParamsParcel.aidl
@@ -23,7 +23,7 @@ import android.os.incremental.NamedParcelFileDescriptor;
* @hide
*/
parcelable IncrementalDataLoaderParamsParcel {
- @utf8InCpp String staticUri;
@utf8InCpp String packageName;
+ @utf8InCpp String staticArgs;
NamedParcelFileDescriptor[] dynamicArgs;
}
diff --git a/core/java/android/os/incremental/IncrementalManager.java b/core/java/android/os/incremental/IncrementalManager.java
new file mode 100644
index 000000000000..5aabf86e17e6
--- /dev/null
+++ b/core/java/android/os/incremental/IncrementalManager.java
@@ -0,0 +1,327 @@
+/*
+ * 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.os.incremental;
+
+import android.annotation.IntDef;
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.annotation.SystemService;
+import android.content.Context;
+import android.os.RemoteException;
+import android.system.ErrnoException;
+import android.system.Os;
+import android.util.SparseArray;
+
+import com.android.internal.annotations.GuardedBy;
+
+import java.io.File;
+import java.io.IOException;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+
+/**
+ * Provides operations to open or create an IncrementalStorage, using IIncrementalManager service.
+ * Example Usage:
+ *
+ * <blockquote><pre>
+ * IncrementalManager manager = (IncrementalManager) getSystemService(Context.INCREMENTAL_MANAGER);
+ * IncrementalStorage storage = manager.openStorage("/path/to/incremental/dir");
+ * </pre></blockquote>
+ *
+ * @hide
+ */
+@SystemService(Context.INCREMENTAL_SERVICE)
+public class IncrementalManager {
+ private static final String TAG = "IncrementalManager";
+ private final IIncrementalManager mService;
+ @GuardedBy("mStorages")
+ private final SparseArray<IncrementalStorage> mStorages = new SparseArray<>();
+
+ public static final int CREATE_MODE_TEMPORARY_BIND =
+ IIncrementalManager.CREATE_MODE_TEMPORARY_BIND;
+ public static final int CREATE_MODE_PERMANENT_BIND =
+ IIncrementalManager.CREATE_MODE_PERMANENT_BIND;
+ public static final int CREATE_MODE_CREATE =
+ IIncrementalManager.CREATE_MODE_CREATE;
+ public static final int CREATE_MODE_OPEN_EXISTING =
+ IIncrementalManager.CREATE_MODE_OPEN_EXISTING;
+
+ @Retention(RetentionPolicy.SOURCE)
+ @IntDef(prefix = {"CREATE_MODE_"}, value = {
+ CREATE_MODE_TEMPORARY_BIND,
+ CREATE_MODE_PERMANENT_BIND,
+ CREATE_MODE_CREATE,
+ CREATE_MODE_OPEN_EXISTING,
+ })
+ public @interface CreateMode {
+ }
+
+ public IncrementalManager(@NonNull IIncrementalManager is) {
+ mService = is;
+ }
+
+ /**
+ * Returns a storage object given a storage ID.
+ *
+ * @param storageId The storage ID to identify the storage object.
+ * @return IncrementalStorage object corresponding to storage ID.
+ */
+ @Nullable
+ public IncrementalStorage getStorage(int storageId) {
+ synchronized (mStorages) {
+ return mStorages.get(storageId);
+ }
+ }
+
+ /**
+ * Opens or create an Incremental File System mounted directory and returns an
+ * IncrementalStorage object.
+ *
+ * @param path Absolute path to mount Incremental File System on.
+ * @param params IncrementalDataLoaderParams object to configure data loading.
+ * @param createMode Mode for opening an old Incremental File System mount or
+ * creating a new mount.
+ * @param autoStartDataLoader Set true to immediately start data loader after creating storage.
+ * @return IncrementalStorage object corresponding to the mounted directory.
+ */
+ @Nullable
+ public IncrementalStorage createStorage(@NonNull String path,
+ @NonNull IncrementalDataLoaderParams params, @CreateMode int createMode,
+ boolean autoStartDataLoader) {
+ try {
+ final int id = mService.createStorage(path, params.getData(), createMode);
+ if (id < 0) {
+ return null;
+ }
+ final IncrementalStorage storage = new IncrementalStorage(mService, id);
+ synchronized (mStorages) {
+ mStorages.put(id, storage);
+ }
+ if (autoStartDataLoader) {
+ storage.startLoading();
+ }
+ return storage;
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+
+ /**
+ * Opens an existing Incremental File System mounted directory and returns an
+ * IncrementalStorage object.
+ *
+ * @param path Absolute target path that Incremental File System has been mounted on.
+ * @return IncrementalStorage object corresponding to the mounted directory.
+ */
+ @Nullable
+ public IncrementalStorage openStorage(@NonNull String path) {
+ try {
+ final int id = mService.openStorage(path);
+ if (id < 0) {
+ return null;
+ }
+ final IncrementalStorage storage = new IncrementalStorage(mService, id);
+ synchronized (mStorages) {
+ mStorages.put(id, storage);
+ }
+ return storage;
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+
+ /**
+ * Opens or creates an IncrementalStorage that is linked to another IncrementalStorage.
+ *
+ * @return IncrementalStorage object corresponding to the linked storage.
+ */
+ @Nullable
+ public IncrementalStorage createStorage(@NonNull String path,
+ @NonNull IncrementalStorage linkedStorage, @CreateMode int createMode) {
+ try {
+ final int id = mService.createLinkedStorage(path, linkedStorage.getId(), createMode);
+ if (id < 0) {
+ return null;
+ }
+ final IncrementalStorage storage = new IncrementalStorage(mService, id);
+ synchronized (mStorages) {
+ mStorages.put(id, storage);
+ }
+ return storage;
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+
+ /**
+ * Iterates through path parents to find the base dir of an Incremental Storage.
+ *
+ * @param file Target file to search storage for.
+ * @return Absolute path which is a bind-mount point of Incremental File System.
+ */
+ private Path getStoragePathForFile(File file) {
+ File currentPath = new File(file.getParent());
+ while (currentPath.getParent() != null) {
+ IncrementalStorage storage = openStorage(currentPath.getAbsolutePath());
+ if (storage != null) {
+ return currentPath.toPath();
+ }
+ currentPath = new File(currentPath.getParent());
+ }
+ return null;
+ }
+
+ /**
+ * Renames an Incremental path to a new path. If source path is a file, make a link from the old
+ * Incremental file to the new one. If source path is a dir, unbind old dir from Incremental
+ * Storage and bind the new one.
+ * <ol>
+ * <li> For renaming a dir, dest dir will be created if not exists, and does not need to
+ * be on the same Incremental storage as the source. </li>
+ * <li> For renaming a file, dest file must be on the same Incremental storage as source.
+ * </li>
+ * </ol>
+ *
+ * @param sourcePath Absolute path to the source. Should be the same type as the destPath
+ * (file or dir). Expected to already exist and is an Incremental path.
+ * @param destPath Absolute path to the destination.
+ * @throws IllegalArgumentException when 1) source does not exist,
+ * or 2) source and dest type mismatch (one is file and the other is dir),
+ * or 3) source path is not on Incremental File System,
+ * @throws IOException when 1) cannot find the root path of the Incremental storage of source,
+ * or 2) cannot retrieve the Incremental storage instance of the source,
+ * or 3) renaming a file, but dest is not on the same Incremental Storage,
+ * or 4) renaming a dir, dest dir does not exist but fails to be created.
+ *
+ * TODO(b/136132412): add unit tests
+ */
+ public void rename(@NonNull String sourcePath, @NonNull String destPath) throws IOException {
+ final File source = new File(sourcePath);
+ final File dest = new File(destPath);
+ if (!source.exists()) {
+ throw new IllegalArgumentException("Path not exist: " + sourcePath);
+ }
+ if (dest.exists()) {
+ throw new IllegalArgumentException("Target path already exists: " + destPath);
+ }
+ if (source.isDirectory() && dest.exists() && dest.isFile()) {
+ throw new IllegalArgumentException(
+ "Trying to rename a dir but destination is a file: " + destPath);
+ }
+ if (source.isFile() && dest.exists() && dest.isDirectory()) {
+ throw new IllegalArgumentException(
+ "Trying to rename a file but destination is a dir: " + destPath);
+ }
+ if (!isIncrementalPath(sourcePath)) {
+ throw new IllegalArgumentException("Not an Incremental path: " + sourcePath);
+ }
+
+ Path storagePath = Paths.get(sourcePath);
+ if (source.isFile()) {
+ storagePath = getStoragePathForFile(source);
+ }
+ if (storagePath == null || storagePath.toAbsolutePath() == null) {
+ throw new IOException("Invalid source storage path for: " + sourcePath);
+ }
+ final IncrementalStorage storage = openStorage(storagePath.toAbsolutePath().toString());
+ if (storage == null) {
+ throw new IOException("Failed to retrieve storage from Incremental Service.");
+ }
+ if (source.isFile()) {
+ renameFile(storage, storagePath, source, dest);
+ } else {
+ renameDir(storage, storagePath, source, dest);
+ }
+ }
+
+ private void renameFile(IncrementalStorage storage, Path storagePath,
+ File source, File dest) throws IOException {
+ Path sourcePath = source.toPath();
+ Path destPath = dest.toPath();
+ if (!sourcePath.startsWith(storagePath)) {
+ throw new IOException("Path: " + source.getAbsolutePath() + " is not on storage at: "
+ + storagePath.toString());
+ }
+ if (!destPath.startsWith(storagePath)) {
+ throw new IOException("Path: " + dest.getAbsolutePath() + " is not on storage at: "
+ + storagePath.toString());
+ }
+ final Path sourceRelativePath = storagePath.relativize(sourcePath);
+ final Path destRelativePath = storagePath.relativize(destPath);
+ storage.moveFile(sourceRelativePath.toString(), destRelativePath.toString());
+
+ }
+
+ private void renameDir(IncrementalStorage storage, Path storagePath,
+ File source, File dest) throws IOException {
+ Path destPath = dest.toPath();
+ boolean usedMkdir = false;
+ try {
+ Os.mkdir(dest.getAbsolutePath(), 0755);
+ usedMkdir = true;
+ } catch (ErrnoException e) {
+ // Traditional mkdir fails but maybe we can create it on Incremental File System if
+ // the dest path is on the same Incremental storage as the source.
+ if (destPath.startsWith(storagePath)) {
+ storage.makeDirectories(storagePath.relativize(destPath).toString());
+ } else {
+ throw new IOException("Failed to create directory: " + dest.getAbsolutePath(), e);
+ }
+ }
+ try {
+ storage.moveDir(source.getAbsolutePath(), dest.getAbsolutePath());
+ } catch (Exception ex) {
+ if (usedMkdir) {
+ try {
+ Os.remove(dest.getAbsolutePath());
+ } catch (ErrnoException ignored) {
+ }
+ }
+ throw new IOException(
+ "Failed to move " + source.getAbsolutePath() + " to " + dest.getAbsolutePath());
+ }
+ }
+
+ /**
+ * Closes a storage specified by the absolute path. If the path is not Incremental, do nothing.
+ * Unbinds the target dir and deletes the corresponding storage instance.
+ */
+ public void closeStorage(@NonNull String path) {
+ try {
+ final int id = mService.openStorage(path);
+ if (id < 0) {
+ return;
+ }
+ mService.deleteStorage(id);
+ synchronized (mStorages) {
+ mStorages.remove(id);
+ }
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+
+ /**
+ * Checks if path is mounted on Incremental File System.
+ */
+ public static boolean isIncrementalPath(@NonNull String path) {
+ // TODO(b/136132412): implement native method
+ return false;
+ }
+}
diff --git a/core/java/android/os/incremental/IncrementalStorage.java b/core/java/android/os/incremental/IncrementalStorage.java
new file mode 100644
index 000000000000..2bf89ed7f7e8
--- /dev/null
+++ b/core/java/android/os/incremental/IncrementalStorage.java
@@ -0,0 +1,346 @@
+/*
+ * 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.os.incremental;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.os.RemoteException;
+
+import java.io.File;
+import java.io.IOException;
+
+/**
+ * Provides operations on an Incremental File System directory, using IncrementalService. Example
+ * usage:
+ *
+ * <blockquote><pre>
+ * IncrementalManager manager = (IncrementalManager) getSystemService(Context.INCREMENTAL_MANAGER);
+ * IncrementalStorage storage = manager.openStorage("/path/to/incremental/dir");
+ * storage.makeDirectory("subdir");
+ * </pre></blockquote>
+ *
+ * @hide
+ */
+public final class IncrementalStorage {
+ private static final String TAG = "IncrementalStorage";
+ private final int mId;
+ private final IIncrementalManager mService;
+
+
+ public IncrementalStorage(@NonNull IIncrementalManager is, int id) {
+ mService = is;
+ mId = id;
+ }
+
+ public int getId() {
+ return mId;
+ }
+
+ /**
+ * Temporarily bind-mounts the current storage directory to a target directory. The bind-mount
+ * will NOT be preserved between device reboots.
+ *
+ * @param targetPath Absolute path to the target directory.
+ */
+ public void bind(@NonNull String targetPath) throws IOException {
+ bind("", targetPath);
+ }
+
+ /**
+ * Temporarily bind-mounts a subdir under the current storage directory to a target directory.
+ * The bind-mount will NOT be preserved between device reboots.
+ *
+ * @param sourcePathUnderStorage Source path as a relative path under current storage
+ * directory.
+ * @param targetPath Absolute path to the target directory.
+ */
+ public void bind(@NonNull String sourcePathUnderStorage, @NonNull String targetPath)
+ throws IOException {
+ try {
+ int res = mService.makeBindMount(mId, sourcePathUnderStorage, targetPath,
+ IIncrementalManager.BIND_TEMPORARY);
+ if (res < 0) {
+ throw new IOException("bind() failed with errno " + -res);
+ }
+ } catch (RemoteException e) {
+ e.rethrowFromSystemServer();
+ }
+ }
+
+
+ /**
+ * Permanently bind-mounts the current storage directory to a target directory. The bind-mount
+ * WILL be preserved between device reboots.
+ *
+ * @param targetPath Absolute path to the target directory.
+ */
+ public void bindPermanent(@NonNull String targetPath) throws IOException {
+ bindPermanent("", targetPath);
+ }
+
+ /**
+ * Permanently bind-mounts a subdir under the current storage directory to a target directory.
+ * The bind-mount WILL be preserved between device reboots.
+ *
+ * @param sourcePathUnderStorage Relative path under the current storage directory.
+ * @param targetPath Absolute path to the target directory.
+ */
+ public void bindPermanent(@NonNull String sourcePathUnderStorage, @NonNull String targetPath)
+ throws IOException {
+ try {
+ int res = mService.makeBindMount(mId, sourcePathUnderStorage, targetPath,
+ IIncrementalManager.BIND_PERMANENT);
+ if (res < 0) {
+ throw new IOException("bind() permanent failed with errno " + -res);
+ }
+ } catch (RemoteException e) {
+ e.rethrowFromSystemServer();
+ }
+ }
+
+ /**
+ * Unbinds a bind mount.
+ *
+ * @param targetPath Absolute path to the target directory.
+ */
+ public void unBind(@NonNull String targetPath) throws IOException {
+ try {
+ int res = mService.deleteBindMount(mId, targetPath);
+ if (res < 0) {
+ throw new IOException("unbind() failed with errno " + -res);
+ }
+ } catch (RemoteException e) {
+ e.rethrowFromSystemServer();
+ }
+ }
+
+ /**
+ * Creates a sub-directory under the current storage directory.
+ *
+ * @param pathUnderStorage Relative path of the sub-directory, e.g., "subdir"
+ */
+ public void makeDirectory(@NonNull String pathUnderStorage) throws IOException {
+ try {
+ int res = mService.makeDirectory(mId, pathUnderStorage);
+ if (res < 0) {
+ throw new IOException("makeDirectory() failed with errno " + -res);
+ }
+ } catch (RemoteException e) {
+ e.rethrowFromSystemServer();
+ }
+ }
+
+ /**
+ * Creates a sub-directory under the current storage directory. If its parent dirs do not exist,
+ * create the parent dirs as well.
+ *
+ * @param pathUnderStorage Relative path of the sub-directory, e.g., "subdir/subsubdir"
+ */
+ public void makeDirectories(@NonNull String pathUnderStorage) throws IOException {
+ try {
+ int res = mService.makeDirectories(mId, pathUnderStorage);
+ if (res < 0) {
+ throw new IOException("makeDirectory() failed with errno " + -res);
+ }
+ } catch (RemoteException e) {
+ e.rethrowFromSystemServer();
+ }
+ }
+
+ /**
+ * Creates a file under the current storage directory.
+ *
+ * @param pathUnderStorage Relative path of the new file.
+ * @param size Size of the new file in bytes.
+ * @param metadata Metadata bytes.
+ */
+ public void makeFile(@NonNull String pathUnderStorage, long size,
+ @Nullable byte[] metadata) throws IOException {
+ try {
+ int res = mService.makeFile(mId, pathUnderStorage, size, metadata);
+ if (res < 0) {
+ throw new IOException("makeFile() failed with errno " + -res);
+ }
+ } catch (RemoteException e) {
+ e.rethrowFromSystemServer();
+ }
+ }
+
+ /**
+ * Creates a file in Incremental storage. The content of the file is mapped from a range inside
+ * a source file in the same storage.
+ *
+ * @param destRelativePath Target relative path under storage.
+ * @param sourceRelativePath Source relative path under storage.
+ * @param rangeStart Starting offset (in bytes) in the source file.
+ * @param rangeEnd Ending offset (in bytes) in the source file.
+ */
+ public void makeFileFromRange(@NonNull String destRelativePath,
+ @NonNull String sourceRelativePath, long rangeStart, long rangeEnd) throws IOException {
+ try {
+ int res = mService.makeFileFromRange(mId, destRelativePath, sourceRelativePath,
+ rangeStart, rangeEnd);
+ if (res < 0) {
+ throw new IOException("makeFileFromRange() failed, errno " + -res);
+ }
+ } catch (RemoteException e) {
+ e.rethrowFromSystemServer();
+ }
+ }
+
+ /**
+ * Creates a hard-link between two paths, which can be under different storages but in the same
+ * Incremental File System.
+ *
+ * @param sourcePathUnderStorage The relative path of the source.
+ * @param destStorage The target storage of the link target.
+ * @param destPathUnderStorage The relative path of the target.
+ */
+ public void makeLink(@NonNull String sourcePathUnderStorage, IncrementalStorage destStorage,
+ @NonNull String destPathUnderStorage) throws IOException {
+ try {
+ int res = mService.makeLink(mId, sourcePathUnderStorage, destStorage.getId(),
+ destPathUnderStorage);
+ if (res < 0) {
+ throw new IOException("makeLink() failed with errno " + -res);
+ }
+ } catch (RemoteException e) {
+ e.rethrowFromSystemServer();
+ }
+ }
+
+ /**
+ * Deletes a hard-link under the current storage directory.
+ *
+ * @param pathUnderStorage The relative path of the target.
+ */
+ public void unlink(@NonNull String pathUnderStorage) throws IOException {
+ try {
+ int res = mService.unlink(mId, pathUnderStorage);
+ if (res < 0) {
+ throw new IOException("unlink() failed with errno " + -res);
+ }
+ } catch (RemoteException e) {
+ e.rethrowFromSystemServer();
+ }
+ }
+
+ /**
+ * Rename an old file name to a new file name under the current storage directory.
+ *
+ * @param sourcePathUnderStorage Old file path as a relative path to the storage directory.
+ * @param destPathUnderStorage New file path as a relative path to the storage directory.
+ */
+ public void moveFile(@NonNull String sourcePathUnderStorage,
+ @NonNull String destPathUnderStorage) throws IOException {
+ try {
+ int res = mService.makeLink(mId, sourcePathUnderStorage, mId, destPathUnderStorage);
+ if (res < 0) {
+ throw new IOException("moveFile() failed at makeLink(), errno " + -res);
+ }
+ } catch (RemoteException e) {
+ e.rethrowFromSystemServer();
+ }
+ try {
+ mService.unlink(mId, sourcePathUnderStorage);
+ } catch (RemoteException ignored) {
+ }
+ }
+
+ /**
+ * Move a directory, which is bind-mounted to a given storage, to a new location. The bind mount
+ * will be persistent between reboots.
+ *
+ * @param sourcePath The old path of the directory as an absolute path.
+ * @param destPath The new path of the directory as an absolute path, expected to already
+ * exist.
+ */
+ public void moveDir(@NonNull String sourcePath, @NonNull String destPath) throws IOException {
+ if (!new File(destPath).exists()) {
+ throw new IOException("moveDir() requires that destination dir already exists.");
+ }
+ try {
+ int res = mService.makeBindMount(mId, "", destPath, IIncrementalManager.BIND_PERMANENT);
+ if (res < 0) {
+ throw new IOException("moveDir() failed at making bind mount, errno " + -res);
+ }
+ } catch (RemoteException e) {
+ e.rethrowFromSystemServer();
+ }
+ try {
+ mService.deleteBindMount(mId, sourcePath);
+ } catch (RemoteException ignored) {
+ }
+ }
+
+ /**
+ * Checks whether a file under the current storage directory is fully loaded.
+ *
+ * @param pathUnderStorage The relative path of the file.
+ * @return True if the file is fully loaded.
+ */
+ public boolean isFileFullyLoaded(@NonNull String pathUnderStorage) {
+ return isFileRangeLoaded(pathUnderStorage, 0, -1);
+ }
+
+ /**
+ * Checks whether a range in a file if loaded.
+ *
+ * @param pathUnderStorage The relative path of the file.
+ * @param start The starting offset of the range.
+ * @param end The ending offset of the range.
+ * @return True if the file is fully loaded.
+ */
+ public boolean isFileRangeLoaded(@NonNull String pathUnderStorage, long start, long end) {
+ try {
+ return mService.isFileRangeLoaded(mId, pathUnderStorage, start, end);
+ } catch (RemoteException e) {
+ e.rethrowFromSystemServer();
+ return false;
+ }
+ }
+
+ /**
+ * Returns the metadata object of an IncFs File.
+ *
+ * @param pathUnderStorage The relative path of the file.
+ * @return Byte array that contains metadata bytes.
+ */
+ @Nullable
+ public byte[] getFileMetadata(@NonNull String pathUnderStorage) {
+ try {
+ return mService.getFileMetadata(mId, pathUnderStorage);
+ } catch (RemoteException e) {
+ e.rethrowFromSystemServer();
+ return null;
+ }
+ }
+
+ /**
+ * Informs the data loader service associated with the current storage to start data loader
+ *
+ * @return True if data loader is successfully started.
+ */
+ public boolean startLoading() {
+ try {
+ return mService.startLoading(mId);
+ } catch (RemoteException e) {
+ e.rethrowFromSystemServer();
+ return false;
+ }
+ }
+}
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index cc4ed4b221e0..f627daa74da4 100644
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -89,7 +89,6 @@ import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
-import java.util.Locale;
import java.util.Map;
import java.util.Set;
@@ -8168,6 +8167,15 @@ public final class Settings {
public static final String NOTIFICATION_BADGING = "notification_badging";
/**
+ * When enabled the system will maintain a rolling history of received notifications. When
+ * disabled the history will be disabled and deleted.
+ *
+ * The value 1 - enable, 0 - disable
+ * @hide
+ */
+ public static final String NOTIFICATION_HISTORY_ENABLED = "notification_history_enabled";
+
+ /**
* Whether notifications are dismissed by a right-to-left swipe (instead of a left-to-right
* swipe).
*
@@ -10637,6 +10645,7 @@ public final class Settings {
/** {@hide} */
public static final String
BLUETOOTH_HEARING_AID_PRIORITY_PREFIX = "bluetooth_hearing_aid_priority_";
+
/**
* Enable/disable radio bug detection
*
@@ -11454,105 +11463,6 @@ public final class Settings {
"adb_allowed_connection_time";
/**
- * Get the key that retrieves a bluetooth headset's priority.
- * @hide
- */
- public static final String getBluetoothHeadsetPriorityKey(String address) {
- return BLUETOOTH_HEADSET_PRIORITY_PREFIX + address.toUpperCase(Locale.ROOT);
- }
-
- /**
- * Get the key that retrieves a bluetooth a2dp sink's priority.
- * @hide
- */
- public static final String getBluetoothA2dpSinkPriorityKey(String address) {
- return BLUETOOTH_A2DP_SINK_PRIORITY_PREFIX + address.toUpperCase(Locale.ROOT);
- }
-
- /**
- * Get the key that retrieves a bluetooth a2dp src's priority.
- * @hide
- */
- public static final String getBluetoothA2dpSrcPriorityKey(String address) {
- return BLUETOOTH_A2DP_SRC_PRIORITY_PREFIX + address.toUpperCase(Locale.ROOT);
- }
-
- /**
- * Get the key that retrieves a bluetooth a2dp device's ability to support optional codecs.
- * @hide
- */
- public static final String getBluetoothA2dpSupportsOptionalCodecsKey(String address) {
- return BLUETOOTH_A2DP_SUPPORTS_OPTIONAL_CODECS_PREFIX +
- address.toUpperCase(Locale.ROOT);
- }
-
- /**
- * Get the key that retrieves whether a bluetooth a2dp device should have optional codecs
- * enabled.
- * @hide
- */
- public static final String getBluetoothA2dpOptionalCodecsEnabledKey(String address) {
- return BLUETOOTH_A2DP_OPTIONAL_CODECS_ENABLED_PREFIX +
- address.toUpperCase(Locale.ROOT);
- }
-
- /**
- * Get the key that retrieves a bluetooth Input Device's priority.
- * @hide
- */
- public static final String getBluetoothHidHostPriorityKey(String address) {
- return BLUETOOTH_INPUT_DEVICE_PRIORITY_PREFIX + address.toUpperCase(Locale.ROOT);
- }
-
- /**
- * Get the key that retrieves a bluetooth pan client priority.
- * @hide
- */
- public static final String getBluetoothPanPriorityKey(String address) {
- return BLUETOOTH_PAN_PRIORITY_PREFIX + address.toUpperCase(Locale.ROOT);
- }
-
- /**
- * Get the key that retrieves a bluetooth hearing aid priority.
- * @hide
- */
- public static final String getBluetoothHearingAidPriorityKey(String address) {
- return BLUETOOTH_HEARING_AID_PRIORITY_PREFIX + address.toUpperCase(Locale.ROOT);
- }
-
- /**
- * Get the key that retrieves a bluetooth map priority.
- * @hide
- */
- public static final String getBluetoothMapPriorityKey(String address) {
- return BLUETOOTH_MAP_PRIORITY_PREFIX + address.toUpperCase(Locale.ROOT);
- }
-
- /**
- * Get the key that retrieves a bluetooth map client priority.
- * @hide
- */
- public static final String getBluetoothMapClientPriorityKey(String address) {
- return BLUETOOTH_MAP_CLIENT_PRIORITY_PREFIX + address.toUpperCase(Locale.ROOT);
- }
-
- /**
- * Get the key that retrieves a bluetooth pbap client priority.
- * @hide
- */
- public static final String getBluetoothPbapClientPriorityKey(String address) {
- return BLUETOOTH_PBAP_CLIENT_PRIORITY_PREFIX + address.toUpperCase(Locale.ROOT);
- }
-
- /**
- * Get the key that retrieves a bluetooth sap priority.
- * @hide
- */
- public static final String getBluetoothSapPriorityKey(String address) {
- return BLUETOOTH_SAP_PRIORITY_PREFIX + address.toUpperCase(Locale.ROOT);
- }
-
- /**
* Scaling factor for normal window animations. Setting to 0 will
* disable window animations.
*/
diff --git a/core/java/android/provider/Telephony.java b/core/java/android/provider/Telephony.java
new file mode 100644
index 000000000000..add03160bbe9
--- /dev/null
+++ b/core/java/android/provider/Telephony.java
@@ -0,0 +1,4856 @@
+/*
+ * Copyright (C) 2006 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.provider;
+
+import android.Manifest;
+import android.annotation.IntDef;
+import android.annotation.NonNull;
+import android.annotation.RequiresPermission;
+import android.annotation.SdkConstant;
+import android.annotation.SdkConstant.SdkConstantType;
+import android.annotation.SystemApi;
+import android.annotation.TestApi;
+import android.annotation.UnsupportedAppUsage;
+import android.content.ComponentName;
+import android.content.ContentResolver;
+import android.content.ContentValues;
+import android.content.Context;
+import android.content.Intent;
+import android.database.ContentObserver;
+import android.database.Cursor;
+import android.database.sqlite.SqliteWrapper;
+import android.net.Uri;
+import android.os.Build;
+import android.os.Parcel;
+import android.telephony.Rlog;
+import android.telephony.ServiceState;
+import android.telephony.SmsMessage;
+import android.telephony.SubscriptionManager;
+import android.telephony.TelephonyManager;
+import android.text.TextUtils;
+import android.util.Patterns;
+
+import com.android.internal.telephony.PhoneConstants;
+import com.android.internal.telephony.SmsApplication;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.util.HashSet;
+import java.util.Set;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+/**
+ * The Telephony provider contains data related to phone operation, specifically SMS and MMS
+ * messages, access to the APN list, including the MMSC to use, and the service state.
+ *
+ * <p class="note"><strong>Note:</strong> These APIs are not available on all Android-powered
+ * devices. If your app depends on telephony features such as for managing SMS messages, include
+ * a <a href="{@docRoot}guide/topics/manifest/uses-feature-element.html">{@code <uses-feature>}
+ * </a> element in your manifest that declares the {@code "android.hardware.telephony"} hardware
+ * feature. Alternatively, you can check for telephony availability at runtime using either
+ * {@link android.content.pm.PackageManager#hasSystemFeature
+ * hasSystemFeature(PackageManager.FEATURE_TELEPHONY)} or {@link
+ * android.telephony.TelephonyManager#getPhoneType}.</p>
+ *
+ * <h3>Creating an SMS app</h3>
+ *
+ * <p>Only the default SMS app (selected by the user in system settings) is able to write to the
+ * SMS Provider (the tables defined within the {@code Telephony} class) and only the default SMS
+ * app receives the {@link android.provider.Telephony.Sms.Intents#SMS_DELIVER_ACTION} broadcast
+ * when the user receives an SMS or the {@link
+ * android.provider.Telephony.Sms.Intents#WAP_PUSH_DELIVER_ACTION} broadcast when the user
+ * receives an MMS.</p>
+ *
+ * <p>Any app that wants to behave as the user's default SMS app must handle the following intents:
+ * <ul>
+ * <li>In a broadcast receiver, include an intent filter for {@link Sms.Intents#SMS_DELIVER_ACTION}
+ * (<code>"android.provider.Telephony.SMS_DELIVER"</code>). The broadcast receiver must also
+ * require the {@link android.Manifest.permission#BROADCAST_SMS} permission.
+ * <p>This allows your app to directly receive incoming SMS messages.</p></li>
+ * <li>In a broadcast receiver, include an intent filter for {@link
+ * Sms.Intents#WAP_PUSH_DELIVER_ACTION}} ({@code "android.provider.Telephony.WAP_PUSH_DELIVER"})
+ * with the MIME type <code>"application/vnd.wap.mms-message"</code>.
+ * The broadcast receiver must also require the {@link
+ * android.Manifest.permission#BROADCAST_WAP_PUSH} permission.
+ * <p>This allows your app to directly receive incoming MMS messages.</p></li>
+ * <li>In your activity that delivers new messages, include an intent filter for
+ * {@link android.content.Intent#ACTION_SENDTO} (<code>"android.intent.action.SENDTO"
+ * </code>) with schemas, <code>sms:</code>, <code>smsto:</code>, <code>mms:</code>, and
+ * <code>mmsto:</code>.
+ * <p>This allows your app to receive intents from other apps that want to deliver a
+ * message.</p></li>
+ * <li>In a service, include an intent filter for {@link
+ * android.telephony.TelephonyManager#ACTION_RESPOND_VIA_MESSAGE}
+ * (<code>"android.intent.action.RESPOND_VIA_MESSAGE"</code>) with schemas,
+ * <code>sms:</code>, <code>smsto:</code>, <code>mms:</code>, and <code>mmsto:</code>.
+ * This service must also require the {@link
+ * android.Manifest.permission#SEND_RESPOND_VIA_MESSAGE} permission.
+ * <p>This allows users to respond to incoming phone calls with an immediate text message
+ * using your app.</p></li>
+ * </ul>
+ *
+ * <p>Other apps that are not selected as the default SMS app can only <em>read</em> the SMS
+ * Provider, but may also be notified when a new SMS arrives by listening for the {@link
+ * Sms.Intents#SMS_RECEIVED_ACTION}
+ * broadcast, which is a non-abortable broadcast that may be delivered to multiple apps. This
+ * broadcast is intended for apps that&mdash;while not selected as the default SMS app&mdash;need to
+ * read special incoming messages such as to perform phone number verification.</p>
+ *
+ * <p>For more information about building SMS apps, read the blog post, <a
+ * href="http://android-developers.blogspot.com/2013/10/getting-your-sms-apps-ready-for-kitkat.html"
+ * >Getting Your SMS Apps Ready for KitKat</a>.</p>
+ *
+ */
+public final class Telephony {
+ private static final String TAG = "Telephony";
+
+ /**
+ * Not instantiable.
+ * @hide
+ */
+ private Telephony() {
+ }
+
+ /**
+ * Base columns for tables that contain text-based SMSs.
+ */
+ public interface TextBasedSmsColumns {
+
+ /** Message type: all messages. */
+ public static final int MESSAGE_TYPE_ALL = 0;
+
+ /** Message type: inbox. */
+ public static final int MESSAGE_TYPE_INBOX = 1;
+
+ /** Message type: sent messages. */
+ public static final int MESSAGE_TYPE_SENT = 2;
+
+ /** Message type: drafts. */
+ public static final int MESSAGE_TYPE_DRAFT = 3;
+
+ /** Message type: outbox. */
+ public static final int MESSAGE_TYPE_OUTBOX = 4;
+
+ /** Message type: failed outgoing message. */
+ public static final int MESSAGE_TYPE_FAILED = 5;
+
+ /** Message type: queued to send later. */
+ public static final int MESSAGE_TYPE_QUEUED = 6;
+
+ /**
+ * The type of message.
+ * <P>Type: INTEGER</P>
+ */
+ public static final String TYPE = "type";
+
+ /**
+ * The thread ID of the message.
+ * <P>Type: INTEGER</P>
+ */
+ public static final String THREAD_ID = "thread_id";
+
+ /**
+ * The address of the other party.
+ * <P>Type: TEXT</P>
+ */
+ public static final String ADDRESS = "address";
+
+ /**
+ * The date the message was received.
+ * <P>Type: INTEGER (long)</P>
+ */
+ public static final String DATE = "date";
+
+ /**
+ * The date the message was sent.
+ * <P>Type: INTEGER (long)</P>
+ */
+ public static final String DATE_SENT = "date_sent";
+
+ /**
+ * Has the message been read?
+ * <P>Type: INTEGER (boolean)</P>
+ */
+ public static final String READ = "read";
+
+ /**
+ * Has the message been seen by the user? The "seen" flag determines
+ * whether we need to show a notification.
+ * <P>Type: INTEGER (boolean)</P>
+ */
+ public static final String SEEN = "seen";
+
+ /**
+ * {@code TP-Status} value for the message, or -1 if no status has been received.
+ * <P>Type: INTEGER</P>
+ */
+ public static final String STATUS = "status";
+
+ /** TP-Status: no status received. */
+ public static final int STATUS_NONE = -1;
+ /** TP-Status: complete. */
+ public static final int STATUS_COMPLETE = 0;
+ /** TP-Status: pending. */
+ public static final int STATUS_PENDING = 32;
+ /** TP-Status: failed. */
+ public static final int STATUS_FAILED = 64;
+
+ /**
+ * The subject of the message, if present.
+ * <P>Type: TEXT</P>
+ */
+ public static final String SUBJECT = "subject";
+
+ /**
+ * The body of the message.
+ * <P>Type: TEXT</P>
+ */
+ public static final String BODY = "body";
+
+ /**
+ * The ID of the sender of the conversation, if present.
+ * <P>Type: INTEGER (reference to item in {@code content://contacts/people})</P>
+ */
+ public static final String PERSON = "person";
+
+ /**
+ * The protocol identifier code.
+ * <P>Type: INTEGER</P>
+ */
+ public static final String PROTOCOL = "protocol";
+
+ /**
+ * Is the {@code TP-Reply-Path} flag set?
+ * <P>Type: BOOLEAN</P>
+ */
+ public static final String REPLY_PATH_PRESENT = "reply_path_present";
+
+ /**
+ * The service center (SC) through which to send the message, if present.
+ * <P>Type: TEXT</P>
+ */
+ public static final String SERVICE_CENTER = "service_center";
+
+ /**
+ * Is the message locked?
+ * <P>Type: INTEGER (boolean)</P>
+ */
+ public static final String LOCKED = "locked";
+
+ /**
+ * The subscription to which the message belongs to. Its value will be
+ * < 0 if the sub id cannot be determined.
+ * <p>Type: INTEGER (long) </p>
+ */
+ public static final String SUBSCRIPTION_ID = "sub_id";
+
+ /**
+ * The MTU size of the mobile interface to which the APN connected
+ * @hide
+ */
+ public static final String MTU = "mtu";
+
+ /**
+ * Error code associated with sending or receiving this message
+ * <P>Type: INTEGER</P>
+ */
+ public static final String ERROR_CODE = "error_code";
+
+ /**
+ * The identity of the sender of a sent message. It is
+ * usually the package name of the app which sends the message.
+ * <p class="note"><strong>Note:</strong>
+ * This column is read-only. It is set by the provider and can not be changed by apps.
+ * <p>Type: TEXT</p>
+ */
+ public static final String CREATOR = "creator";
+ }
+
+ /**
+ * Columns in sms_changes table.
+ * @hide
+ */
+ public interface TextBasedSmsChangesColumns {
+ /**
+ * The {@code content://} style URL for this table.
+ * @hide
+ */
+ public static final Uri CONTENT_URI = Uri.parse("content://sms-changes");
+
+ /**
+ * Primary key.
+ * <P>Type: INTEGER (long)</P>
+ * @hide
+ */
+ public static final String ID = "_id";
+
+ /**
+ * Triggers on sms table create a row in this table for each update/delete.
+ * This column is the "_id" of the row from sms table that was updated/deleted.
+ * <P>Type: INTEGER (long)</P>
+ * @hide
+ */
+ public static final String ORIG_ROW_ID = "orig_rowid";
+
+ /**
+ * Triggers on sms table create a row in this table for each update/delete.
+ * This column is the "sub_id" of the row from sms table that was updated/deleted.
+ * @hide
+ * <P>Type: INTEGER (long)</P>
+ */
+ public static final String SUB_ID = "sub_id";
+
+ /**
+ * The type of operation that created this row.
+ * {@link #TYPE_UPDATE} = update op
+ * {@link #TYPE_DELETE} = delete op
+ * @hide
+ * <P>Type: INTEGER (long)</P>
+ */
+ public static final String TYPE = "type";
+
+ /**
+ * One of the possible values for the above column "type". Indicates it is an update op.
+ * @hide
+ */
+ public static final int TYPE_UPDATE = 0;
+
+ /**
+ * One of the possible values for the above column "type". Indicates it is a delete op.
+ * @hide
+ */
+ public static final int TYPE_DELETE = 1;
+
+ /**
+ * This column contains a non-null value only if the operation on sms table is an update op
+ * and the column "read" is changed by the update op.
+ * <P>Type: INTEGER (boolean)</P>
+ * @hide
+ */
+ public static final String NEW_READ_STATUS = "new_read_status";
+ }
+
+ /**
+ * Contains all text-based SMS messages.
+ */
+ public static final class Sms implements BaseColumns, TextBasedSmsColumns {
+
+ /**
+ * Not instantiable.
+ * @hide
+ */
+ private Sms() {
+ }
+
+ /**
+ * Used to determine the currently configured default SMS package.
+ * @param context context of the requesting application
+ * @return package name for the default SMS package or null
+ */
+ public static String getDefaultSmsPackage(Context context) {
+ ComponentName component = SmsApplication.getDefaultSmsApplication(context, false);
+ if (component != null) {
+ return component.getPackageName();
+ }
+ return null;
+ }
+
+ /**
+ * Return cursor for table query.
+ * @hide
+ */
+ public static Cursor query(ContentResolver cr, String[] projection) {
+ return cr.query(CONTENT_URI, projection, null, null, DEFAULT_SORT_ORDER);
+ }
+
+ /**
+ * Return cursor for table query.
+ * @hide
+ */
+ @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
+ public static Cursor query(ContentResolver cr, String[] projection,
+ String where, String orderBy) {
+ return cr.query(CONTENT_URI, projection, where,
+ null, orderBy == null ? DEFAULT_SORT_ORDER : orderBy);
+ }
+
+ /**
+ * The {@code content://} style URL for this table.
+ */
+ public static final Uri CONTENT_URI = Uri.parse("content://sms");
+
+ /**
+ * The default sort order for this table.
+ */
+ public static final String DEFAULT_SORT_ORDER = "date DESC";
+
+ /**
+ * Add an SMS to the given URI.
+ *
+ * @param resolver the content resolver to use
+ * @param uri the URI to add the message to
+ * @param address the address of the sender
+ * @param body the body of the message
+ * @param subject the pseudo-subject of the message
+ * @param date the timestamp for the message
+ * @param read true if the message has been read, false if not
+ * @param deliveryReport true if a delivery report was requested, false if not
+ * @return the URI for the new message
+ * @hide
+ */
+ @UnsupportedAppUsage
+ public static Uri addMessageToUri(ContentResolver resolver,
+ Uri uri, String address, String body, String subject,
+ Long date, boolean read, boolean deliveryReport) {
+ return addMessageToUri(SubscriptionManager.getDefaultSmsSubscriptionId(),
+ resolver, uri, address, body, subject, date, read, deliveryReport, -1L);
+ }
+
+ /**
+ * Add an SMS to the given URI.
+ *
+ * @param resolver the content resolver to use
+ * @param uri the URI to add the message to
+ * @param address the address of the sender
+ * @param body the body of the message
+ * @param subject the psuedo-subject of the message
+ * @param date the timestamp for the message
+ * @param read true if the message has been read, false if not
+ * @param deliveryReport true if a delivery report was requested, false if not
+ * @param subId the subscription which the message belongs to
+ * @return the URI for the new message
+ * @hide
+ */
+ @UnsupportedAppUsage
+ public static Uri addMessageToUri(int subId, ContentResolver resolver,
+ Uri uri, String address, String body, String subject,
+ Long date, boolean read, boolean deliveryReport) {
+ return addMessageToUri(subId, resolver, uri, address, body, subject,
+ date, read, deliveryReport, -1L);
+ }
+
+ /**
+ * Add an SMS to the given URI with the specified thread ID.
+ *
+ * @param resolver the content resolver to use
+ * @param uri the URI to add the message to
+ * @param address the address of the sender
+ * @param body the body of the message
+ * @param subject the pseudo-subject of the message
+ * @param date the timestamp for the message
+ * @param read true if the message has been read, false if not
+ * @param deliveryReport true if a delivery report was requested, false if not
+ * @param threadId the thread_id of the message
+ * @return the URI for the new message
+ * @hide
+ */
+ @UnsupportedAppUsage
+ public static Uri addMessageToUri(ContentResolver resolver,
+ Uri uri, String address, String body, String subject,
+ Long date, boolean read, boolean deliveryReport, long threadId) {
+ return addMessageToUri(SubscriptionManager.getDefaultSmsSubscriptionId(),
+ resolver, uri, address, body, subject,
+ date, read, deliveryReport, threadId);
+ }
+
+ /**
+ * Add an SMS to the given URI with thread_id specified.
+ *
+ * @param resolver the content resolver to use
+ * @param uri the URI to add the message to
+ * @param address the address of the sender
+ * @param body the body of the message
+ * @param subject the psuedo-subject of the message
+ * @param date the timestamp for the message
+ * @param read true if the message has been read, false if not
+ * @param deliveryReport true if a delivery report was requested, false if not
+ * @param threadId the thread_id of the message
+ * @param subId the subscription which the message belongs to
+ * @return the URI for the new message
+ * @hide
+ */
+ @UnsupportedAppUsage
+ public static Uri addMessageToUri(int subId, ContentResolver resolver,
+ Uri uri, String address, String body, String subject,
+ Long date, boolean read, boolean deliveryReport, long threadId) {
+ ContentValues values = new ContentValues(8);
+ Rlog.v(TAG,"Telephony addMessageToUri sub id: " + subId);
+
+ values.put(SUBSCRIPTION_ID, subId);
+ values.put(ADDRESS, address);
+ if (date != null) {
+ values.put(DATE, date);
+ }
+ values.put(READ, read ? Integer.valueOf(1) : Integer.valueOf(0));
+ values.put(SUBJECT, subject);
+ values.put(BODY, body);
+ if (deliveryReport) {
+ values.put(STATUS, STATUS_PENDING);
+ }
+ if (threadId != -1L) {
+ values.put(THREAD_ID, threadId);
+ }
+ return resolver.insert(uri, values);
+ }
+
+ /**
+ * Move a message to the given folder.
+ *
+ * @param context the context to use
+ * @param uri the message to move
+ * @param folder the folder to move to
+ * @return true if the operation succeeded
+ * @hide
+ */
+ @UnsupportedAppUsage
+ public static boolean moveMessageToFolder(Context context,
+ Uri uri, int folder, int error) {
+ if (uri == null) {
+ return false;
+ }
+
+ boolean markAsUnread = false;
+ boolean markAsRead = false;
+ switch(folder) {
+ case MESSAGE_TYPE_INBOX:
+ case MESSAGE_TYPE_DRAFT:
+ break;
+ case MESSAGE_TYPE_OUTBOX:
+ case MESSAGE_TYPE_SENT:
+ markAsRead = true;
+ break;
+ case MESSAGE_TYPE_FAILED:
+ case MESSAGE_TYPE_QUEUED:
+ markAsUnread = true;
+ break;
+ default:
+ return false;
+ }
+
+ ContentValues values = new ContentValues(3);
+
+ values.put(TYPE, folder);
+ if (markAsUnread) {
+ values.put(READ, 0);
+ } else if (markAsRead) {
+ values.put(READ, 1);
+ }
+ values.put(ERROR_CODE, error);
+
+ return 1 == SqliteWrapper.update(context, context.getContentResolver(),
+ uri, values, null, null);
+ }
+
+ /**
+ * Returns true iff the folder (message type) identifies an
+ * outgoing message.
+ * @hide
+ */
+ @UnsupportedAppUsage
+ public static boolean isOutgoingFolder(int messageType) {
+ return (messageType == MESSAGE_TYPE_FAILED)
+ || (messageType == MESSAGE_TYPE_OUTBOX)
+ || (messageType == MESSAGE_TYPE_SENT)
+ || (messageType == MESSAGE_TYPE_QUEUED);
+ }
+
+ /**
+ * Contains all text-based SMS messages in the SMS app inbox.
+ */
+ public static final class Inbox implements BaseColumns, TextBasedSmsColumns {
+
+ /**
+ * Not instantiable.
+ * @hide
+ */
+ private Inbox() {
+ }
+
+ /**
+ * The {@code content://} style URL for this table.
+ */
+ public static final Uri CONTENT_URI = Uri.parse("content://sms/inbox");
+
+ /**
+ * The default sort order for this table.
+ */
+ public static final String DEFAULT_SORT_ORDER = "date DESC";
+
+ /**
+ * Add an SMS to the Draft box.
+ *
+ * @param resolver the content resolver to use
+ * @param address the address of the sender
+ * @param body the body of the message
+ * @param subject the pseudo-subject of the message
+ * @param date the timestamp for the message
+ * @param read true if the message has been read, false if not
+ * @return the URI for the new message
+ * @hide
+ */
+ @UnsupportedAppUsage
+ public static Uri addMessage(ContentResolver resolver,
+ String address, String body, String subject, Long date,
+ boolean read) {
+ return addMessageToUri(SubscriptionManager.getDefaultSmsSubscriptionId(),
+ resolver, CONTENT_URI, address, body, subject, date, read, false);
+ }
+
+ /**
+ * Add an SMS to the Draft box.
+ *
+ * @param resolver the content resolver to use
+ * @param address the address of the sender
+ * @param body the body of the message
+ * @param subject the psuedo-subject of the message
+ * @param date the timestamp for the message
+ * @param read true if the message has been read, false if not
+ * @param subId the subscription which the message belongs to
+ * @return the URI for the new message
+ * @hide
+ */
+ @UnsupportedAppUsage
+ public static Uri addMessage(int subId, ContentResolver resolver,
+ String address, String body, String subject, Long date, boolean read) {
+ return addMessageToUri(subId, resolver, CONTENT_URI, address, body,
+ subject, date, read, false);
+ }
+ }
+
+ /**
+ * Contains all sent text-based SMS messages in the SMS app.
+ */
+ public static final class Sent implements BaseColumns, TextBasedSmsColumns {
+
+ /**
+ * Not instantiable.
+ * @hide
+ */
+ private Sent() {
+ }
+
+ /**
+ * The {@code content://} style URL for this table.
+ */
+ public static final Uri CONTENT_URI = Uri.parse("content://sms/sent");
+
+ /**
+ * The default sort order for this table.
+ */
+ public static final String DEFAULT_SORT_ORDER = "date DESC";
+
+ /**
+ * Add an SMS to the Draft box.
+ *
+ * @param resolver the content resolver to use
+ * @param address the address of the sender
+ * @param body the body of the message
+ * @param subject the pseudo-subject of the message
+ * @param date the timestamp for the message
+ * @return the URI for the new message
+ * @hide
+ */
+ @UnsupportedAppUsage
+ public static Uri addMessage(ContentResolver resolver,
+ String address, String body, String subject, Long date) {
+ return addMessageToUri(SubscriptionManager.getDefaultSmsSubscriptionId(),
+ resolver, CONTENT_URI, address, body, subject, date, true, false);
+ }
+
+ /**
+ * Add an SMS to the Draft box.
+ *
+ * @param resolver the content resolver to use
+ * @param address the address of the sender
+ * @param body the body of the message
+ * @param subject the psuedo-subject of the message
+ * @param date the timestamp for the message
+ * @param subId the subscription which the message belongs to
+ * @return the URI for the new message
+ * @hide
+ */
+ @UnsupportedAppUsage
+ public static Uri addMessage(int subId, ContentResolver resolver,
+ String address, String body, String subject, Long date) {
+ return addMessageToUri(subId, resolver, CONTENT_URI, address, body,
+ subject, date, true, false);
+ }
+ }
+
+ /**
+ * Contains all draft text-based SMS messages in the SMS app.
+ */
+ public static final class Draft implements BaseColumns, TextBasedSmsColumns {
+
+ /**
+ * Not instantiable.
+ * @hide
+ */
+ private Draft() {
+ }
+
+ /**
+ * The {@code content://} style URL for this table.
+ */
+ public static final Uri CONTENT_URI = Uri.parse("content://sms/draft");
+
+ /**
+ * @hide
+ */
+ @UnsupportedAppUsage
+ public static Uri addMessage(ContentResolver resolver,
+ String address, String body, String subject, Long date) {
+ return addMessageToUri(SubscriptionManager.getDefaultSmsSubscriptionId(),
+ resolver, CONTENT_URI, address, body, subject, date, true, false);
+ }
+
+ /**
+ * Add an SMS to the Draft box.
+ *
+ * @param resolver the content resolver to use
+ * @param address the address of the sender
+ * @param body the body of the message
+ * @param subject the psuedo-subject of the message
+ * @param date the timestamp for the message
+ * @param subId the subscription which the message belongs to
+ * @return the URI for the new message
+ * @hide
+ */
+ @UnsupportedAppUsage
+ public static Uri addMessage(int subId, ContentResolver resolver,
+ String address, String body, String subject, Long date) {
+ return addMessageToUri(subId, resolver, CONTENT_URI, address, body,
+ subject, date, true, false);
+ }
+
+ /**
+ * The default sort order for this table.
+ */
+ public static final String DEFAULT_SORT_ORDER = "date DESC";
+ }
+
+ /**
+ * Contains all pending outgoing text-based SMS messages.
+ */
+ public static final class Outbox implements BaseColumns, TextBasedSmsColumns {
+
+ /**
+ * Not instantiable.
+ * @hide
+ */
+ private Outbox() {
+ }
+
+ /**
+ * The {@code content://} style URL for this table.
+ */
+ public static final Uri CONTENT_URI = Uri.parse("content://sms/outbox");
+
+ /**
+ * The default sort order for this table.
+ */
+ public static final String DEFAULT_SORT_ORDER = "date DESC";
+
+ /**
+ * Add an SMS to the outbox.
+ *
+ * @param resolver the content resolver to use
+ * @param address the address of the sender
+ * @param body the body of the message
+ * @param subject the pseudo-subject of the message
+ * @param date the timestamp for the message
+ * @param deliveryReport whether a delivery report was requested for the message
+ * @return the URI for the new message
+ * @hide
+ */
+ @UnsupportedAppUsage
+ public static Uri addMessage(ContentResolver resolver,
+ String address, String body, String subject, Long date,
+ boolean deliveryReport, long threadId) {
+ return addMessageToUri(SubscriptionManager.getDefaultSmsSubscriptionId(),
+ resolver, CONTENT_URI, address, body, subject, date,
+ true, deliveryReport, threadId);
+ }
+
+ /**
+ * Add an SMS to the Out box.
+ *
+ * @param resolver the content resolver to use
+ * @param address the address of the sender
+ * @param body the body of the message
+ * @param subject the psuedo-subject of the message
+ * @param date the timestamp for the message
+ * @param deliveryReport whether a delivery report was requested for the message
+ * @param subId the subscription which the message belongs to
+ * @return the URI for the new message
+ * @hide
+ */
+ public static Uri addMessage(int subId, ContentResolver resolver,
+ String address, String body, String subject, Long date,
+ boolean deliveryReport, long threadId) {
+ return addMessageToUri(subId, resolver, CONTENT_URI, address, body,
+ subject, date, true, deliveryReport, threadId);
+ }
+ }
+
+ /**
+ * Contains a view of SMS conversations (also referred to as threads). This is similar to
+ * {@link Threads}, but only includes SMS messages and columns relevant to SMS
+ * conversations.
+ * <p>
+ * Note that this view ignores any information about MMS messages, it is a
+ * view of conversations as if MMS messages did not exist at all. This means that all
+ * relevant information, such as snippets and message count, will ignore any MMS messages
+ * that might be in the same thread through other views and present only data based on the
+ * SMS messages in that thread.
+ */
+ public static final class Conversations
+ implements BaseColumns, TextBasedSmsColumns {
+
+ /**
+ * Not instantiable.
+ * @hide
+ */
+ private Conversations() {
+ }
+
+ /**
+ * The {@code content://} style URL for this table.
+ */
+ public static final Uri CONTENT_URI = Uri.parse("content://sms/conversations");
+
+ /**
+ * The default sort order for this table.
+ */
+ public static final String DEFAULT_SORT_ORDER = "date DESC";
+
+ /**
+ * The first 45 characters of the body of the most recent message.
+ * <P>Type: TEXT</P>
+ */
+ public static final String SNIPPET = "snippet";
+
+ /**
+ * The number of messages in the conversation.
+ * <P>Type: INTEGER</P>
+ */
+ public static final String MESSAGE_COUNT = "msg_count";
+ }
+
+ /**
+ * Contains constants for SMS related Intents that are broadcast.
+ */
+ public static final class Intents {
+
+ /**
+ * Not instantiable.
+ * @hide
+ */
+ private Intents() {
+ }
+
+ /**
+ * Set by BroadcastReceiver to indicate that the message was handled
+ * successfully.
+ */
+ public static final int RESULT_SMS_HANDLED = 1;
+
+ /**
+ * Set by BroadcastReceiver to indicate a generic error while
+ * processing the message.
+ */
+ public static final int RESULT_SMS_GENERIC_ERROR = 2;
+
+ /**
+ * Set as a "result" extra in the {@link #SMS_REJECTED_ACTION} intent to indicate
+ * insufficient memory to store the message.
+ */
+ public static final int RESULT_SMS_OUT_OF_MEMORY = 3;
+
+ /**
+ * Set as a "result" extra in the {@link #SMS_REJECTED_ACTION} intent to indicate that
+ * the message, while possibly valid, is of a format or encoding that is not supported.
+ */
+ public static final int RESULT_SMS_UNSUPPORTED = 4;
+
+ /**
+ * Set as a "result" extra in the {@link #SMS_REJECTED_ACTION} intent to indicate a
+ * duplicate incoming message.
+ */
+ public static final int RESULT_SMS_DUPLICATED = 5;
+
+ /**
+ * Set as a "result" extra in the {@link #SMS_REJECTED_ACTION} intent to indicate a
+ * dispatch failure.
+ */
+ public static final int RESULT_SMS_DISPATCH_FAILURE = 6;
+
+ /**
+ * Set as a "result" extra in the {@link #SMS_REJECTED_ACTION} intent to indicate a null
+ * PDU was received.
+ */
+ public static final int RESULT_SMS_NULL_PDU = 7;
+
+ /**
+ * Set as a "result" extra in the {@link #SMS_REJECTED_ACTION} intent to indicate a null
+ * message was encountered.
+ */
+ public static final int RESULT_SMS_NULL_MESSAGE = 8;
+
+ /**
+ * Set as a "result" extra in the {@link #SMS_REJECTED_ACTION} intent to indicate an sms
+ * was received while the phone was in encrypted state.
+ */
+ public static final int RESULT_SMS_RECEIVED_WHILE_ENCRYPTED = 9;
+
+ /**
+ * Set as a "result" extra in the {@link #SMS_REJECTED_ACTION} intent to indicate a
+ * telephony database error.
+ */
+ public static final int RESULT_SMS_DATABASE_ERROR = 10;
+
+ /**
+ * Set as a "result" extra in the {@link #SMS_REJECTED_ACTION} intent to indicate an
+ * invalid uri.
+ */
+ public static final int RESULT_SMS_INVALID_URI = 11;
+
+ /**
+ * Activity action: Ask the user to change the default
+ * SMS application. This will show a dialog that asks the
+ * user whether they want to replace the current default
+ * SMS application with the one specified in
+ * {@link #EXTRA_PACKAGE_NAME}.
+ * <p>
+ * This is no longer supported since Q, please use
+ * {@link android.app.role.RoleManager#createRequestRoleIntent(String)} with
+ * {@link android.app.role.RoleManager#ROLE_SMS} instead.
+ */
+ @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
+ public static final String ACTION_CHANGE_DEFAULT =
+ "android.provider.Telephony.ACTION_CHANGE_DEFAULT";
+
+ /**
+ * The PackageName string passed in as an
+ * extra for {@link #ACTION_CHANGE_DEFAULT}
+ *
+ * @see #ACTION_CHANGE_DEFAULT
+ * <p>
+ * This is no longer supported since Q, please use
+ * {@link android.app.role.RoleManager#createRequestRoleIntent(String)} with
+ * {@link android.app.role.RoleManager#ROLE_SMS} instead.
+ */
+ public static final String EXTRA_PACKAGE_NAME = "package";
+
+ /**
+ * Broadcast Action: A new text-based SMS message has been received
+ * by the device. This intent will only be delivered to the default
+ * sms app. That app is responsible for writing the message and notifying
+ * the user. The intent will have the following extra values:</p>
+ *
+ * <ul>
+ * <li><em>"pdus"</em> - An Object[] of byte[]s containing the PDUs
+ * that make up the message.</li>
+ * <li><em>"format"</em> - A String describing the format of the PDUs. It can
+ * be either "3gpp" or "3gpp2".</li>
+ * <li><em>"subscription"</em> - An optional long value of the subscription id which
+ * received the message.</li>
+ * <li><em>"slot"</em> - An optional int value of the SIM slot containing the
+ * subscription.</li>
+ * <li><em>"phone"</em> - An optional int value of the phone id associated with the
+ * subscription.</li>
+ * <li><em>"errorCode"</em> - An optional int error code associated with receiving
+ * the message.</li>
+ * </ul>
+ *
+ * <p>The extra values can be extracted using
+ * {@link #getMessagesFromIntent(Intent)}.</p>
+ *
+ * <p>If a BroadcastReceiver encounters an error while processing
+ * this intent it should set the result code appropriately.</p>
+ *
+ * <p class="note"><strong>Note:</strong>
+ * The broadcast receiver that filters for this intent must declare
+ * {@link android.Manifest.permission#BROADCAST_SMS} as a required permission in
+ * the <a href="{@docRoot}guide/topics/manifest/receiver-element.html">{@code
+ * <receiver>}</a> tag.
+ *
+ * <p>Requires {@link android.Manifest.permission#RECEIVE_SMS} to receive.</p>
+ */
+ @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
+ public static final String SMS_DELIVER_ACTION =
+ "android.provider.Telephony.SMS_DELIVER";
+
+ /**
+ * Broadcast Action: A new text-based SMS message has been received
+ * by the device. This intent will be delivered to all registered
+ * receivers as a notification. These apps are not expected to write the
+ * message or notify the user. The intent will have the following extra
+ * values:</p>
+ *
+ * <ul>
+ * <li><em>"pdus"</em> - An Object[] of byte[]s containing the PDUs
+ * that make up the message.</li>
+ * </ul>
+ *
+ * <p>The extra values can be extracted using
+ * {@link #getMessagesFromIntent(Intent)}.</p>
+ *
+ * <p>If a BroadcastReceiver encounters an error while processing
+ * this intent it should set the result code appropriately.</p>
+ *
+ * <p>Requires {@link android.Manifest.permission#RECEIVE_SMS} to receive.</p>
+ */
+ @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
+ public static final String SMS_RECEIVED_ACTION =
+ "android.provider.Telephony.SMS_RECEIVED";
+
+ /**
+ * Broadcast Action: A new data based SMS message has been received
+ * by the device. This intent will be delivered to all registered
+ * receivers as a notification. The intent will have the following extra
+ * values:</p>
+ *
+ * <ul>
+ * <li><em>"pdus"</em> - An Object[] of byte[]s containing the PDUs
+ * that make up the message.</li>
+ * </ul>
+ *
+ * <p>The extra values can be extracted using
+ * {@link #getMessagesFromIntent(Intent)}.</p>
+ *
+ * <p>If a BroadcastReceiver encounters an error while processing
+ * this intent it should set the result code appropriately.</p>
+ *
+ * <p>Requires {@link android.Manifest.permission#RECEIVE_SMS} to receive.</p>
+ */
+ @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
+ public static final String DATA_SMS_RECEIVED_ACTION =
+ "android.intent.action.DATA_SMS_RECEIVED";
+
+ /**
+ * Broadcast Action: A new WAP PUSH message has been received by the
+ * device. This intent will only be delivered to the default
+ * sms app. That app is responsible for writing the message and notifying
+ * the user. The intent will have the following extra values:</p>
+ *
+ * <ul>
+ * <li><em>"transactionId"</em> - (Integer) The WAP transaction ID</li>
+ * <li><em>"pduType"</em> - (Integer) The WAP PDU type</li>
+ * <li><em>"header"</em> - (byte[]) The header of the message</li>
+ * <li><em>"data"</em> - (byte[]) The data payload of the message</li>
+ * <li><em>"contentTypeParameters" </em>
+ * -(HashMap&lt;String,String&gt;) Any parameters associated with the content type
+ * (decoded from the WSP Content-Type header)</li>
+ * <li><em>"subscription"</em> - An optional long value of the subscription id which
+ * received the message.</li>
+ * <li><em>"slot"</em> - An optional int value of the SIM slot containing the
+ * subscription.</li>
+ * <li><em>"phone"</em> - An optional int value of the phone id associated with the
+ * subscription.</li>
+ * </ul>
+ *
+ * <p>If a BroadcastReceiver encounters an error while processing
+ * this intent it should set the result code appropriately.</p>
+ *
+ * <p>The contentTypeParameters extra value is map of content parameters keyed by
+ * their names.</p>
+ *
+ * <p>If any unassigned well-known parameters are encountered, the key of the map will
+ * be 'unassigned/0x...', where '...' is the hex value of the unassigned parameter. If
+ * a parameter has No-Value the value in the map will be null.</p>
+ *
+ * <p>Requires {@link android.Manifest.permission#RECEIVE_MMS} or
+ * {@link android.Manifest.permission#RECEIVE_WAP_PUSH} (depending on WAP PUSH type) to
+ * receive.</p>
+ *
+ * <p class="note"><strong>Note:</strong>
+ * The broadcast receiver that filters for this intent must declare
+ * {@link android.Manifest.permission#BROADCAST_WAP_PUSH} as a required permission in
+ * the <a href="{@docRoot}guide/topics/manifest/receiver-element.html">{@code
+ * <receiver>}</a> tag.
+ */
+ @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
+ public static final String WAP_PUSH_DELIVER_ACTION =
+ "android.provider.Telephony.WAP_PUSH_DELIVER";
+
+ /**
+ * Broadcast Action: A new WAP PUSH message has been received by the
+ * device. This intent will be delivered to all registered
+ * receivers as a notification. These apps are not expected to write the
+ * message or notify the user. The intent will have the following extra
+ * values:</p>
+ *
+ * <ul>
+ * <li><em>"transactionId"</em> - (Integer) The WAP transaction ID</li>
+ * <li><em>"pduType"</em> - (Integer) The WAP PDU type</li>
+ * <li><em>"header"</em> - (byte[]) The header of the message</li>
+ * <li><em>"data"</em> - (byte[]) The data payload of the message</li>
+ * <li><em>"contentTypeParameters"</em>
+ * - (HashMap&lt;String,String&gt;) Any parameters associated with the content type
+ * (decoded from the WSP Content-Type header)</li>
+ * </ul>
+ *
+ * <p>If a BroadcastReceiver encounters an error while processing
+ * this intent it should set the result code appropriately.</p>
+ *
+ * <p>The contentTypeParameters extra value is map of content parameters keyed by
+ * their names.</p>
+ *
+ * <p>If any unassigned well-known parameters are encountered, the key of the map will
+ * be 'unassigned/0x...', where '...' is the hex value of the unassigned parameter. If
+ * a parameter has No-Value the value in the map will be null.</p>
+ *
+ * <p>Requires {@link android.Manifest.permission#RECEIVE_MMS} or
+ * {@link android.Manifest.permission#RECEIVE_WAP_PUSH} (depending on WAP PUSH type) to
+ * receive.</p>
+ */
+ @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
+ public static final String WAP_PUSH_RECEIVED_ACTION =
+ "android.provider.Telephony.WAP_PUSH_RECEIVED";
+
+ /**
+ * Broadcast Action: A new Cell Broadcast message has been received
+ * by the device. The intent will have the following extra
+ * values:</p>
+ *
+ * <ul>
+ * <li><em>"message"</em> - An SmsCbMessage object containing the broadcast message
+ * data. This is not an emergency alert, so ETWS and CMAS data will be null.</li>
+ * </ul>
+ *
+ * <p>The extra values can be extracted using
+ * {@link #getMessagesFromIntent(Intent)}.</p>
+ *
+ * <p>If a BroadcastReceiver encounters an error while processing
+ * this intent it should set the result code appropriately.</p>
+ *
+ * <p>Requires {@link android.Manifest.permission#RECEIVE_SMS} to receive.</p>
+ */
+ @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
+ public static final String SMS_CB_RECEIVED_ACTION =
+ "android.provider.Telephony.SMS_CB_RECEIVED";
+
+ /**
+ * Action: A SMS based carrier provision intent. Used to identify default
+ * carrier provisioning app on the device.
+ * @hide
+ */
+ @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
+ @TestApi
+ public static final String SMS_CARRIER_PROVISION_ACTION =
+ "android.provider.Telephony.SMS_CARRIER_PROVISION";
+
+ /**
+ * Broadcast Action: A new Emergency Broadcast message has been received
+ * by the device. The intent will have the following extra
+ * values:</p>
+ *
+ * <ul>
+ * <li><em>"message"</em> - An {@link android.telephony.SmsCbMessage} object
+ * containing the broadcast message data, including ETWS or CMAS warning notification
+ * info if present.</li>
+ * </ul>
+ *
+ * <p>The extra values can be extracted using
+ * {@link #getMessagesFromIntent(Intent)}.</p>
+ *
+ * <p>If a BroadcastReceiver encounters an error while processing
+ * this intent it should set the result code appropriately.</p>
+ *
+ * <p>Requires {@link android.Manifest.permission#RECEIVE_EMERGENCY_BROADCAST} to
+ * receive.</p>
+ * @hide
+ */
+ @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
+ @SystemApi
+ public static final String ACTION_SMS_EMERGENCY_CB_RECEIVED =
+ "android.provider.action.SMS_EMERGENCY_CB_RECEIVED";
+
+ /**
+ * Broadcast Action: A new CDMA SMS has been received containing Service Category
+ * Program Data (updates the list of enabled broadcast channels). The intent will
+ * have the following extra values:</p>
+ *
+ * <ul>
+ * <li><em>"operations"</em> - An array of CdmaSmsCbProgramData objects containing
+ * the service category operations (add/delete/clear) to perform.</li>
+ * </ul>
+ *
+ * <p>The extra values can be extracted using
+ * {@link #getMessagesFromIntent(Intent)}.</p>
+ *
+ * <p>If a BroadcastReceiver encounters an error while processing
+ * this intent it should set the result code appropriately.</p>
+ *
+ * <p>Requires {@link android.Manifest.permission#RECEIVE_SMS} to receive.</p>
+ */
+ @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
+ public static final String SMS_SERVICE_CATEGORY_PROGRAM_DATA_RECEIVED_ACTION =
+ "android.provider.Telephony.SMS_SERVICE_CATEGORY_PROGRAM_DATA_RECEIVED";
+
+ /**
+ * Broadcast Action: The SIM storage for SMS messages is full. If
+ * space is not freed, messages targeted for the SIM (class 2) may
+ * not be saved.
+ *
+ * <p>Requires {@link android.Manifest.permission#RECEIVE_SMS} to receive.</p>
+ */
+ @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
+ public static final String SIM_FULL_ACTION =
+ "android.provider.Telephony.SIM_FULL";
+
+ /**
+ * Broadcast Action: An incoming SMS has been rejected by the
+ * telephony framework. This intent is sent in lieu of any
+ * of the RECEIVED_ACTION intents. The intent will have the
+ * following extra value:</p>
+ *
+ * <ul>
+ * <li><em>"result"</em> - An int result code, e.g. {@link #RESULT_SMS_OUT_OF_MEMORY}
+ * indicating the error returned to the network.</li>
+ * </ul>
+ *
+ * <p>Requires {@link android.Manifest.permission#RECEIVE_SMS} to receive.</p>
+ */
+ @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
+ public static final String SMS_REJECTED_ACTION =
+ "android.provider.Telephony.SMS_REJECTED";
+
+ /**
+ * Broadcast Action: An incoming MMS has been downloaded. The intent is sent to all
+ * users, except for secondary users where SMS has been disabled and to managed
+ * profiles.
+ * @hide
+ */
+ @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
+ public static final String MMS_DOWNLOADED_ACTION =
+ "android.provider.Telephony.MMS_DOWNLOADED";
+
+ /**
+ * Broadcast Action: A debug code has been entered in the dialer. This intent is
+ * broadcast by the system and OEM telephony apps may need to receive these broadcasts.
+ * These "secret codes" are used to activate developer menus by dialing certain codes.
+ * And they are of the form {@code *#*#<code>#*#*}. The intent will have the data
+ * URI: {@code android_secret_code://<code>}. It is possible that a manifest
+ * receiver would be woken up even if it is not currently running.
+ *
+ * <p>Requires {@code android.Manifest.permission#CONTROL_INCALL_EXPERIENCE} to
+ * send and receive.</p>
+ * @deprecated it is no longer supported, use {@link
+ * TelephonyManager#ACTION_SECRET_CODE} instead
+ */
+ @Deprecated
+ @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
+ public static final String SECRET_CODE_ACTION =
+ "android.provider.Telephony.SECRET_CODE";
+
+ /**
+ * Broadcast action: When the default SMS package changes,
+ * the previous default SMS package and the new default SMS
+ * package are sent this broadcast to notify them of the change.
+ * A boolean is specified in {@link #EXTRA_IS_DEFAULT_SMS_APP} to
+ * indicate whether the package is the new default SMS package.
+ */
+ @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
+ public static final String ACTION_DEFAULT_SMS_PACKAGE_CHANGED =
+ "android.provider.action.DEFAULT_SMS_PACKAGE_CHANGED";
+
+ /**
+ * The IsDefaultSmsApp boolean passed as an
+ * extra for {@link #ACTION_DEFAULT_SMS_PACKAGE_CHANGED} to indicate whether the
+ * SMS app is becoming the default SMS app or is no longer the default.
+ *
+ * @see #ACTION_DEFAULT_SMS_PACKAGE_CHANGED
+ */
+ public static final String EXTRA_IS_DEFAULT_SMS_APP =
+ "android.provider.extra.IS_DEFAULT_SMS_APP";
+
+ /**
+ * Broadcast action: When a change is made to the SmsProvider or
+ * MmsProvider by a process other than the default SMS application,
+ * this intent is broadcast to the default SMS application so it can
+ * re-sync or update the change. The uri that was used to call the provider
+ * can be retrieved from the intent with getData(). The actual affected uris
+ * (which would depend on the selection specified) are not included.
+ */
+ @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
+ public static final String ACTION_EXTERNAL_PROVIDER_CHANGE =
+ "android.provider.action.EXTERNAL_PROVIDER_CHANGE";
+
+ /**
+ * Same as {@link #ACTION_DEFAULT_SMS_PACKAGE_CHANGED} but it's implicit (e.g. sent to
+ * all apps) and requires
+ * {@link android.Manifest.permission#MONITOR_DEFAULT_SMS_PACKAGE} to receive.
+ *
+ * @hide
+ */
+ @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
+ public static final String ACTION_DEFAULT_SMS_PACKAGE_CHANGED_INTERNAL =
+ "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.
+ *
+ * @param intent the intent to read from
+ * @return an array of SmsMessages for the PDUs
+ */
+ public static SmsMessage[] getMessagesFromIntent(Intent intent) {
+ Object[] messages;
+ try {
+ messages = (Object[]) intent.getSerializableExtra("pdus");
+ }
+ catch (ClassCastException e) {
+ Rlog.e(TAG, "getMessagesFromIntent: " + e);
+ return null;
+ }
+
+ if (messages == null) {
+ Rlog.e(TAG, "pdus does not exist in the intent");
+ return null;
+ }
+
+ String format = intent.getStringExtra("format");
+ int subId = intent.getIntExtra(PhoneConstants.SUBSCRIPTION_KEY,
+ SubscriptionManager.getDefaultSmsSubscriptionId());
+
+ Rlog.v(TAG, " getMessagesFromIntent sub_id : " + subId);
+
+ int pduCount = messages.length;
+ SmsMessage[] msgs = new SmsMessage[pduCount];
+
+ for (int i = 0; i < pduCount; i++) {
+ byte[] pdu = (byte[]) messages[i];
+ msgs[i] = SmsMessage.createFromPdu(pdu, format);
+ if (msgs[i] != null) msgs[i].setSubId(subId);
+ }
+ return msgs;
+ }
+ }
+ }
+
+ /**
+ * Base column for the table that contain Carrier Public key.
+ * @hide
+ */
+ @SystemApi
+ public interface CarrierColumns extends BaseColumns {
+
+ /**
+ * Mobile Country Code (MCC).
+ * <P> Type: TEXT </P>
+ */
+ public static final String MCC = "mcc";
+
+ /**
+ * Mobile Network Code (MNC).
+ * <P> Type: TEXT </P>
+ */
+ public static final String MNC = "mnc";
+
+ /**
+ * KeyType whether the key is being used for WLAN or ePDG.
+ * <P> Type: INTEGER </P>
+ */
+ public static final String KEY_TYPE = "key_type";
+
+ /**
+ * MVNO type:
+ * {@code SPN (Service Provider Name), IMSI, GID (Group Identifier Level 1)}.
+ * <P> Type: TEXT </P>
+ */
+ public static final String MVNO_TYPE = "mvno_type";
+
+ /**
+ * MVNO data.
+ * Use the following examples.
+ * <ul>
+ * <li>SPN: A MOBILE, BEN NL, ...</li>
+ * <li>IMSI: 302720x94, 2060188, ...</li>
+ * <li>GID: 4E, 33, ...</li>
+ * </ul>
+ * <P> Type: TEXT </P>
+ */
+ public static final String MVNO_MATCH_DATA = "mvno_match_data";
+
+ /**
+ * The carrier public key that is used for the IMSI encryption.
+ * <P> Type: TEXT </P>
+ */
+ public static final String PUBLIC_KEY = "public_key";
+
+ /**
+ * The key identifier Attribute value pair that helps a server locate
+ * the private key to decrypt the permanent identity.
+ * <P> Type: TEXT </P>
+ */
+ public static final String KEY_IDENTIFIER = "key_identifier";
+
+ /**
+ * Date-Time in UTC when the key will expire.
+ * <P> Type: INTEGER (long) </P>
+ */
+ public static final String EXPIRATION_TIME = "expiration_time";
+
+ /**
+ * Timestamp when this table was last modified, in milliseconds since
+ * January 1, 1970 00:00:00.0 UTC.
+ * <P> Type: INTEGER (long) </P>
+ */
+ public static final String LAST_MODIFIED = "last_modified";
+
+ /**
+ * The {@code content://} style URL for this table.
+ */
+ @NonNull
+ public static final Uri CONTENT_URI = Uri.parse("content://carrier_information/carrier");
+ }
+
+ /**
+ * Base columns for tables that contain MMSs.
+ */
+ public interface BaseMmsColumns extends BaseColumns {
+
+ /** Message box: all messages. */
+ public static final int MESSAGE_BOX_ALL = 0;
+ /** Message box: inbox. */
+ public static final int MESSAGE_BOX_INBOX = 1;
+ /** Message box: sent messages. */
+ public static final int MESSAGE_BOX_SENT = 2;
+ /** Message box: drafts. */
+ public static final int MESSAGE_BOX_DRAFTS = 3;
+ /** Message box: outbox. */
+ public static final int MESSAGE_BOX_OUTBOX = 4;
+ /** Message box: failed. */
+ public static final int MESSAGE_BOX_FAILED = 5;
+
+ /**
+ * The thread ID of the message.
+ * <P>Type: INTEGER (long)</P>
+ */
+ public static final String THREAD_ID = "thread_id";
+
+ /**
+ * The date the message was received.
+ * <P>Type: INTEGER (long)</P>
+ */
+ public static final String DATE = "date";
+
+ /**
+ * The date the message was sent.
+ * <P>Type: INTEGER (long)</P>
+ */
+ public static final String DATE_SENT = "date_sent";
+
+ /**
+ * The box which the message belongs to, e.g. {@link #MESSAGE_BOX_INBOX}.
+ * <P>Type: INTEGER</P>
+ */
+ public static final String MESSAGE_BOX = "msg_box";
+
+ /**
+ * Has the message been read?
+ * <P>Type: INTEGER (boolean)</P>
+ */
+ public static final String READ = "read";
+
+ /**
+ * Has the message been seen by the user? The "seen" flag determines
+ * whether we need to show a new message notification.
+ * <P>Type: INTEGER (boolean)</P>
+ */
+ public static final String SEEN = "seen";
+
+ /**
+ * Does the message have only a text part (can also have a subject) with
+ * no picture, slideshow, sound, etc. parts?
+ * <P>Type: INTEGER (boolean)</P>
+ */
+ public static final String TEXT_ONLY = "text_only";
+
+ /**
+ * The {@code Message-ID} of the message.
+ * <P>Type: TEXT</P>
+ */
+ public static final String MESSAGE_ID = "m_id";
+
+ /**
+ * The subject of the message, if present.
+ * <P>Type: TEXT</P>
+ */
+ public static final String SUBJECT = "sub";
+
+ /**
+ * The character set of the subject, if present.
+ * <P>Type: INTEGER</P>
+ */
+ public static final String SUBJECT_CHARSET = "sub_cs";
+
+ /**
+ * The {@code Content-Type} of the message.
+ * <P>Type: TEXT</P>
+ */
+ public static final String CONTENT_TYPE = "ct_t";
+
+ /**
+ * The {@code Content-Location} of the message.
+ * <P>Type: TEXT</P>
+ */
+ public static final String CONTENT_LOCATION = "ct_l";
+
+ /**
+ * The expiry time of the message.
+ * <P>Type: INTEGER (long)</P>
+ */
+ public static final String EXPIRY = "exp";
+
+ /**
+ * The class of the message.
+ * <P>Type: TEXT</P>
+ */
+ public static final String MESSAGE_CLASS = "m_cls";
+
+ /**
+ * The type of the message defined by MMS spec.
+ * <P>Type: INTEGER</P>
+ */
+ public static final String MESSAGE_TYPE = "m_type";
+
+ /**
+ * The version of the specification that this message conforms to.
+ * <P>Type: INTEGER</P>
+ */
+ public static final String MMS_VERSION = "v";
+
+ /**
+ * The size of the message.
+ * <P>Type: INTEGER</P>
+ */
+ public static final String MESSAGE_SIZE = "m_size";
+
+ /**
+ * The priority of the message.
+ * <P>Type: INTEGER</P>
+ */
+ public static final String PRIORITY = "pri";
+
+ /**
+ * The {@code read-report} of the message.
+ * <P>Type: INTEGER (boolean)</P>
+ */
+ public static final String READ_REPORT = "rr";
+
+ /**
+ * Is read report allowed?
+ * <P>Type: INTEGER (boolean)</P>
+ */
+ public static final String REPORT_ALLOWED = "rpt_a";
+
+ /**
+ * The {@code response-status} of the message.
+ * <P>Type: INTEGER</P>
+ */
+ public static final String RESPONSE_STATUS = "resp_st";
+
+ /**
+ * The {@code status} of the message.
+ * <P>Type: INTEGER</P>
+ */
+ public static final String STATUS = "st";
+
+ /**
+ * The {@code transaction-id} of the message.
+ * <P>Type: TEXT</P>
+ */
+ public static final String TRANSACTION_ID = "tr_id";
+
+ /**
+ * The {@code retrieve-status} of the message.
+ * <P>Type: INTEGER</P>
+ */
+ public static final String RETRIEVE_STATUS = "retr_st";
+
+ /**
+ * The {@code retrieve-text} of the message.
+ * <P>Type: TEXT</P>
+ */
+ public static final String RETRIEVE_TEXT = "retr_txt";
+
+ /**
+ * The character set of the retrieve-text.
+ * <P>Type: INTEGER</P>
+ */
+ public static final String RETRIEVE_TEXT_CHARSET = "retr_txt_cs";
+
+ /**
+ * The {@code read-status} of the message.
+ * <P>Type: INTEGER</P>
+ */
+ public static final String READ_STATUS = "read_status";
+
+ /**
+ * The {@code content-class} of the message.
+ * <P>Type: INTEGER</P>
+ */
+ public static final String CONTENT_CLASS = "ct_cls";
+
+ /**
+ * The {@code delivery-report} of the message.
+ * <P>Type: INTEGER</P>
+ */
+ public static final String DELIVERY_REPORT = "d_rpt";
+
+ /**
+ * The {@code delivery-time-token} of the message.
+ * <P>Type: INTEGER</P>
+ * @deprecated this column is no longer supported.
+ * @hide
+ */
+ @Deprecated
+ public static final String DELIVERY_TIME_TOKEN = "d_tm_tok";
+
+ /**
+ * The {@code delivery-time} of the message.
+ * <P>Type: INTEGER</P>
+ */
+ public static final String DELIVERY_TIME = "d_tm";
+
+ /**
+ * The {@code response-text} of the message.
+ * <P>Type: TEXT</P>
+ */
+ public static final String RESPONSE_TEXT = "resp_txt";
+
+ /**
+ * The {@code sender-visibility} of the message.
+ * <P>Type: TEXT</P>
+ * @deprecated this column is no longer supported.
+ * @hide
+ */
+ @Deprecated
+ public static final String SENDER_VISIBILITY = "s_vis";
+
+ /**
+ * The {@code reply-charging} of the message.
+ * <P>Type: INTEGER</P>
+ * @deprecated this column is no longer supported.
+ * @hide
+ */
+ @Deprecated
+ public static final String REPLY_CHARGING = "r_chg";
+
+ /**
+ * The {@code reply-charging-deadline-token} of the message.
+ * <P>Type: INTEGER</P>
+ * @deprecated this column is no longer supported.
+ * @hide
+ */
+ @Deprecated
+ public static final String REPLY_CHARGING_DEADLINE_TOKEN = "r_chg_dl_tok";
+
+ /**
+ * The {@code reply-charging-deadline} of the message.
+ * <P>Type: INTEGER</P>
+ * @deprecated this column is no longer supported.
+ * @hide
+ */
+ @Deprecated
+ public static final String REPLY_CHARGING_DEADLINE = "r_chg_dl";
+
+ /**
+ * The {@code reply-charging-id} of the message.
+ * <P>Type: TEXT</P>
+ * @deprecated this column is no longer supported.
+ * @hide
+ */
+ @Deprecated
+ public static final String REPLY_CHARGING_ID = "r_chg_id";
+
+ /**
+ * The {@code reply-charging-size} of the message.
+ * <P>Type: INTEGER</P>
+ * @deprecated this column is no longer supported.
+ * @hide
+ */
+ @Deprecated
+ public static final String REPLY_CHARGING_SIZE = "r_chg_sz";
+
+ /**
+ * The {@code previously-sent-by} of the message.
+ * <P>Type: TEXT</P>
+ * @deprecated this column is no longer supported.
+ * @hide
+ */
+ @Deprecated
+ public static final String PREVIOUSLY_SENT_BY = "p_s_by";
+
+ /**
+ * The {@code previously-sent-date} of the message.
+ * <P>Type: INTEGER</P>
+ * @deprecated this column is no longer supported.
+ * @hide
+ */
+ @Deprecated
+ public static final String PREVIOUSLY_SENT_DATE = "p_s_d";
+
+ /**
+ * The {@code store} of the message.
+ * <P>Type: TEXT</P>
+ * @deprecated this column is no longer supported.
+ * @hide
+ */
+ @Deprecated
+ public static final String STORE = "store";
+
+ /**
+ * The {@code mm-state} of the message.
+ * <P>Type: INTEGER</P>
+ * @deprecated this column is no longer supported.
+ * @hide
+ */
+ @Deprecated
+ public static final String MM_STATE = "mm_st";
+
+ /**
+ * The {@code mm-flags-token} of the message.
+ * <P>Type: INTEGER</P>
+ * @deprecated this column is no longer supported.
+ * @hide
+ */
+ @Deprecated
+ public static final String MM_FLAGS_TOKEN = "mm_flg_tok";
+
+ /**
+ * The {@code mm-flags} of the message.
+ * <P>Type: TEXT</P>
+ * @deprecated this column is no longer supported.
+ * @hide
+ */
+ @Deprecated
+ public static final String MM_FLAGS = "mm_flg";
+
+ /**
+ * The {@code store-status} of the message.
+ * <P>Type: TEXT</P>
+ * @deprecated this column is no longer supported.
+ * @hide
+ */
+ @Deprecated
+ public static final String STORE_STATUS = "store_st";
+
+ /**
+ * The {@code store-status-text} of the message.
+ * <P>Type: TEXT</P>
+ * @deprecated this column is no longer supported.
+ * @hide
+ */
+ @Deprecated
+ public static final String STORE_STATUS_TEXT = "store_st_txt";
+
+ /**
+ * The {@code stored} of the message.
+ * <P>Type: TEXT</P>
+ * @deprecated this column is no longer supported.
+ * @hide
+ */
+ @Deprecated
+ public static final String STORED = "stored";
+
+ /**
+ * The {@code totals} of the message.
+ * <P>Type: TEXT</P>
+ * @deprecated this column is no longer supported.
+ * @hide
+ */
+ @Deprecated
+ public static final String TOTALS = "totals";
+
+ /**
+ * The {@code mbox-totals} of the message.
+ * <P>Type: TEXT</P>
+ * @deprecated this column is no longer supported.
+ * @hide
+ */
+ @Deprecated
+ public static final String MBOX_TOTALS = "mb_t";
+
+ /**
+ * The {@code mbox-totals-token} of the message.
+ * <P>Type: INTEGER</P>
+ * @deprecated this column is no longer supported.
+ * @hide
+ */
+ @Deprecated
+ public static final String MBOX_TOTALS_TOKEN = "mb_t_tok";
+
+ /**
+ * The {@code quotas} of the message.
+ * <P>Type: TEXT</P>
+ * @deprecated this column is no longer supported.
+ * @hide
+ */
+ @Deprecated
+ public static final String QUOTAS = "qt";
+
+ /**
+ * The {@code mbox-quotas} of the message.
+ * <P>Type: TEXT</P>
+ * @deprecated this column is no longer supported.
+ * @hide
+ */
+ @Deprecated
+ public static final String MBOX_QUOTAS = "mb_qt";
+
+ /**
+ * The {@code mbox-quotas-token} of the message.
+ * <P>Type: INTEGER</P>
+ * @deprecated this column is no longer supported.
+ * @hide
+ */
+ @Deprecated
+ public static final String MBOX_QUOTAS_TOKEN = "mb_qt_tok";
+
+ /**
+ * The {@code message-count} of the message.
+ * <P>Type: INTEGER</P>
+ * @deprecated this column is no longer supported.
+ * @hide
+ */
+ @Deprecated
+ public static final String MESSAGE_COUNT = "m_cnt";
+
+ /**
+ * The {@code start} of the message.
+ * <P>Type: INTEGER</P>
+ * @deprecated this column is no longer supported.
+ * @hide
+ */
+ @Deprecated
+ public static final String START = "start";
+
+ /**
+ * The {@code distribution-indicator} of the message.
+ * <P>Type: TEXT</P>
+ * @deprecated this column is no longer supported.
+ * @hide
+ */
+ @Deprecated
+ public static final String DISTRIBUTION_INDICATOR = "d_ind";
+
+ /**
+ * The {@code element-descriptor} of the message.
+ * <P>Type: TEXT</P>
+ * @deprecated this column is no longer supported.
+ * @hide
+ */
+ @Deprecated
+ public static final String ELEMENT_DESCRIPTOR = "e_des";
+
+ /**
+ * The {@code limit} of the message.
+ * <P>Type: INTEGER</P>
+ * @deprecated this column is no longer supported.
+ * @hide
+ */
+ @Deprecated
+ public static final String LIMIT = "limit";
+
+ /**
+ * The {@code recommended-retrieval-mode} of the message.
+ * <P>Type: INTEGER</P>
+ * @deprecated this column is no longer supported.
+ * @hide
+ */
+ @Deprecated
+ public static final String RECOMMENDED_RETRIEVAL_MODE = "r_r_mod";
+
+ /**
+ * The {@code recommended-retrieval-mode-text} of the message.
+ * <P>Type: TEXT</P>
+ * @deprecated this column is no longer supported.
+ * @hide
+ */
+ @Deprecated
+ public static final String RECOMMENDED_RETRIEVAL_MODE_TEXT = "r_r_mod_txt";
+
+ /**
+ * The {@code status-text} of the message.
+ * <P>Type: TEXT</P>
+ * @deprecated this column is no longer supported.
+ * @hide
+ */
+ @Deprecated
+ public static final String STATUS_TEXT = "st_txt";
+
+ /**
+ * The {@code applic-id} of the message.
+ * <P>Type: TEXT</P>
+ * @deprecated this column is no longer supported.
+ * @hide
+ */
+ @Deprecated
+ public static final String APPLIC_ID = "apl_id";
+
+ /**
+ * The {@code reply-applic-id} of the message.
+ * <P>Type: TEXT</P>
+ * @deprecated this column is no longer supported.
+ * @hide
+ */
+ @Deprecated
+ public static final String REPLY_APPLIC_ID = "r_apl_id";
+
+ /**
+ * The {@code aux-applic-id} of the message.
+ * <P>Type: TEXT</P>
+ * @deprecated this column is no longer supported.
+ * @hide
+ */
+ @Deprecated
+ public static final String AUX_APPLIC_ID = "aux_apl_id";
+
+ /**
+ * The {@code drm-content} of the message.
+ * <P>Type: TEXT</P>
+ * @deprecated this column is no longer supported.
+ * @hide
+ */
+ @Deprecated
+ public static final String DRM_CONTENT = "drm_c";
+
+ /**
+ * The {@code adaptation-allowed} of the message.
+ * <P>Type: TEXT</P>
+ * @deprecated this column is no longer supported.
+ * @hide
+ */
+ @Deprecated
+ public static final String ADAPTATION_ALLOWED = "adp_a";
+
+ /**
+ * The {@code replace-id} of the message.
+ * <P>Type: TEXT</P>
+ * @deprecated this column is no longer supported.
+ * @hide
+ */
+ @Deprecated
+ public static final String REPLACE_ID = "repl_id";
+
+ /**
+ * The {@code cancel-id} of the message.
+ * <P>Type: TEXT</P>
+ * @deprecated this column is no longer supported.
+ * @hide
+ */
+ @Deprecated
+ public static final String CANCEL_ID = "cl_id";
+
+ /**
+ * The {@code cancel-status} of the message.
+ * <P>Type: INTEGER</P>
+ * @deprecated this column is no longer supported.
+ * @hide
+ */
+ @Deprecated
+ public static final String CANCEL_STATUS = "cl_st";
+
+ /**
+ * Is the message locked?
+ * <P>Type: INTEGER (boolean)</P>
+ */
+ public static final String LOCKED = "locked";
+
+ /**
+ * The subscription to which the message belongs to. Its value will be
+ * < 0 if the sub id cannot be determined.
+ * <p>Type: INTEGER (long)</p>
+ */
+ public static final String SUBSCRIPTION_ID = "sub_id";
+
+ /**
+ * The identity of the sender of a sent message. It is
+ * usually the package name of the app which sends the message.
+ * <p class="note"><strong>Note:</strong>
+ * This column is read-only. It is set by the provider and can not be changed by apps.
+ * <p>Type: TEXT</p>
+ */
+ public static final String CREATOR = "creator";
+ }
+
+ /**
+ * Columns for the "canonical_addresses" table used by MMS and SMS.
+ */
+ public interface CanonicalAddressesColumns extends BaseColumns {
+ /**
+ * An address used in MMS or SMS. Email addresses are
+ * converted to lower case and are compared by string
+ * equality. Other addresses are compared using
+ * PHONE_NUMBERS_EQUAL.
+ * <P>Type: TEXT</P>
+ */
+ public static final String ADDRESS = "address";
+ }
+
+ /**
+ * Columns for the "threads" table used by MMS and SMS.
+ */
+ public interface ThreadsColumns extends BaseColumns {
+
+ /**
+ * The date at which the thread was created.
+ * <P>Type: INTEGER (long)</P>
+ */
+ public static final String DATE = "date";
+
+ /**
+ * A string encoding of the recipient IDs of the recipients of
+ * the message, in numerical order and separated by spaces.
+ * <P>Type: TEXT</P>
+ */
+ public static final String RECIPIENT_IDS = "recipient_ids";
+
+ /**
+ * The message count of the thread.
+ * <P>Type: INTEGER</P>
+ */
+ public static final String MESSAGE_COUNT = "message_count";
+
+ /**
+ * Indicates whether all messages of the thread have been read.
+ * <P>Type: INTEGER</P>
+ */
+ public static final String READ = "read";
+
+ /**
+ * The snippet of the latest message in the thread.
+ * <P>Type: TEXT</P>
+ */
+ public static final String SNIPPET = "snippet";
+
+ /**
+ * The charset of the snippet.
+ * <P>Type: INTEGER</P>
+ */
+ public static final String SNIPPET_CHARSET = "snippet_cs";
+
+ /**
+ * Type of the thread, either {@link Threads#COMMON_THREAD} or
+ * {@link Threads#BROADCAST_THREAD}.
+ * <P>Type: INTEGER</P>
+ */
+ public static final String TYPE = "type";
+
+ /**
+ * Indicates whether there is a transmission error in the thread.
+ * <P>Type: INTEGER</P>
+ */
+ public static final String ERROR = "error";
+
+ /**
+ * Indicates whether this thread contains any attachments.
+ * <P>Type: INTEGER</P>
+ */
+ public static final String HAS_ATTACHMENT = "has_attachment";
+
+ /**
+ * If the thread is archived
+ * <P>Type: INTEGER (boolean)</P>
+ */
+ public static final String ARCHIVED = "archived";
+ }
+
+ /**
+ * Helper functions for the "threads" table used by MMS and SMS.
+ *
+ * Thread IDs are determined by the participants in a conversation and can be used to match
+ * both SMS and MMS messages.
+ *
+ * To avoid issues where applications might cache a thread ID, the thread ID of a deleted thread
+ * must not be reused to point at a new thread.
+ */
+ public static final class Threads implements ThreadsColumns {
+
+ @UnsupportedAppUsage
+ private static final String[] ID_PROJECTION = { BaseColumns._ID };
+
+ /**
+ * Private {@code content://} style URL for this table. Used by
+ * {@link #getOrCreateThreadId(android.content.Context, java.util.Set)}.
+ */
+ @UnsupportedAppUsage
+ private static final Uri THREAD_ID_CONTENT_URI = Uri.parse(
+ "content://mms-sms/threadID");
+
+ /**
+ * The {@code content://} style URL for this table, by conversation.
+ */
+ public static final Uri CONTENT_URI = Uri.withAppendedPath(
+ MmsSms.CONTENT_URI, "conversations");
+
+ /**
+ * The {@code content://} style URL for this table, for obsolete threads.
+ */
+ public static final Uri OBSOLETE_THREADS_URI = Uri.withAppendedPath(
+ CONTENT_URI, "obsolete");
+
+ /** Thread type: common thread. */
+ public static final int COMMON_THREAD = 0;
+
+ /** Thread type: broadcast thread. */
+ public static final int BROADCAST_THREAD = 1;
+
+ /**
+ * Not instantiable.
+ * @hide
+ */
+ private Threads() {
+ }
+
+ /**
+ * This is a single-recipient version of {@code getOrCreateThreadId}.
+ * It's convenient for use with SMS messages.
+ * @param context the context object to use.
+ * @param recipient the recipient to send to.
+ */
+ public static long getOrCreateThreadId(Context context, String recipient) {
+ Set<String> recipients = new HashSet<String>();
+
+ recipients.add(recipient);
+ return getOrCreateThreadId(context, recipients);
+ }
+
+ /**
+ * Given a set of recipients return its thread ID.
+ * <p>
+ * If a thread exists containing the provided participants, return its thread ID. Otherwise,
+ * this will create a new thread containing the provided participants and return its ID.
+ */
+ public static long getOrCreateThreadId(
+ Context context, Set<String> recipients) {
+ Uri.Builder uriBuilder = THREAD_ID_CONTENT_URI.buildUpon();
+
+ for (String recipient : recipients) {
+ if (Mms.isEmailAddress(recipient)) {
+ recipient = Mms.extractAddrSpec(recipient);
+ }
+
+ uriBuilder.appendQueryParameter("recipient", recipient);
+ }
+
+ Uri uri = uriBuilder.build();
+ //if (DEBUG) Rlog.v(TAG, "getOrCreateThreadId uri: " + uri);
+
+ Cursor cursor = SqliteWrapper.query(context, context.getContentResolver(),
+ uri, ID_PROJECTION, null, null, null);
+ if (cursor != null) {
+ try {
+ if (cursor.moveToFirst()) {
+ return cursor.getLong(0);
+ } else {
+ Rlog.e(TAG, "getOrCreateThreadId returned no rows!");
+ }
+ } finally {
+ cursor.close();
+ }
+ }
+
+ Rlog.e(TAG, "getOrCreateThreadId failed with " + recipients.size() + " recipients");
+ throw new IllegalArgumentException("Unable to find or allocate a thread ID.");
+ }
+ }
+
+ /**
+ * Columns for the "rcs_*" tables used by {@link android.telephony.ims.RcsMessageStore} classes.
+ *
+ * @hide - not meant for public use
+ */
+ public interface RcsColumns {
+ // TODO(sahinc): Turn this to true once the schema finalizes, so that people can update
+ // their messaging databases. NOTE: move the switch/case update in MmsSmsDatabaseHelper to
+ // the latest version of the database before turning this flag to true.
+ boolean IS_RCS_TABLE_SCHEMA_CODE_COMPLETE = false;
+
+ /**
+ * The authority for the content provider
+ */
+ String AUTHORITY = "rcs";
+
+ /**
+ * The URI to start building upon to use {@link com.android.providers.telephony.RcsProvider}
+ */
+ Uri CONTENT_AND_AUTHORITY = Uri.parse("content://" + AUTHORITY);
+
+ /**
+ * The value to be used whenever a transaction that expects an integer to be returned
+ * failed.
+ */
+ int TRANSACTION_FAILED = Integer.MIN_VALUE;
+
+ /**
+ * The value that denotes a timestamp was not set before (e.g. a message that is not
+ * delivered yet will not have a DELIVERED_TIMESTAMP)
+ */
+ long TIMESTAMP_NOT_SET = 0;
+
+ /**
+ * The table that {@link android.telephony.ims.RcsThread} gets persisted to
+ */
+ interface RcsThreadColumns {
+ /**
+ * The path that should be used for referring to
+ * {@link android.telephony.ims.RcsThread}s in
+ * {@link com.android.providers.telephony.RcsProvider} URIs.
+ */
+ String RCS_THREAD_URI_PART = "thread";
+
+ /**
+ * The URI to query or modify {@link android.telephony.ims.RcsThread} via the content
+ * provider.
+ */
+ Uri RCS_THREAD_URI = Uri.withAppendedPath(CONTENT_AND_AUTHORITY, RCS_THREAD_URI_PART);
+
+ /**
+ * The unique identifier of an {@link android.telephony.ims.RcsThread}
+ */
+ String RCS_THREAD_ID_COLUMN = "rcs_thread_id";
+ }
+
+ /**
+ * The table that {@link android.telephony.ims.Rcs1To1Thread} gets persisted to
+ */
+ interface Rcs1To1ThreadColumns extends RcsThreadColumns {
+ /**
+ * The path that should be used for referring to
+ * {@link android.telephony.ims.Rcs1To1Thread}s in
+ * {@link com.android.providers.telephony.RcsProvider} URIs.
+ */
+ String RCS_1_TO_1_THREAD_URI_PART = "p2p_thread";
+
+ /**
+ * The URI to query or modify {@link android.telephony.ims.Rcs1To1Thread}s via the
+ * content provider. Can also insert to this URI to create a new 1-to-1 thread. When
+ * performing an insert, ensure that the provided content values contain the other
+ * participant's ID under the key
+ * {@link RcsParticipantColumns.RCS_PARTICIPANT_ID_COLUMN}
+ */
+ Uri RCS_1_TO_1_THREAD_URI = Uri.withAppendedPath(CONTENT_AND_AUTHORITY,
+ RCS_1_TO_1_THREAD_URI_PART);
+
+ /**
+ * The SMS/MMS thread to fallback to in case of an RCS outage
+ */
+ String FALLBACK_THREAD_ID_COLUMN = "rcs_fallback_thread_id";
+ }
+
+ /**
+ * The table that {@link android.telephony.ims.RcsGroupThread} gets persisted to
+ */
+ interface RcsGroupThreadColumns extends RcsThreadColumns {
+ /**
+ * The path that should be used for referring to
+ * {@link android.telephony.ims.RcsGroupThread}s in
+ * {@link com.android.providers.telephony.RcsProvider} URIs.
+ */
+ String RCS_GROUP_THREAD_URI_PART = "group_thread";
+
+ /**
+ * The URI to query or modify {@link android.telephony.ims.RcsGroupThread}s via the
+ * content provider
+ */
+ Uri RCS_GROUP_THREAD_URI = Uri.withAppendedPath(CONTENT_AND_AUTHORITY,
+ RCS_GROUP_THREAD_URI_PART);
+
+ /**
+ * The owner/admin of the {@link android.telephony.ims.RcsGroupThread}
+ */
+ String OWNER_PARTICIPANT_COLUMN = "owner_participant";
+
+ /**
+ * The user visible name of the group
+ */
+ String GROUP_NAME_COLUMN = "group_name";
+
+ /**
+ * The user visible icon of the group
+ */
+ String GROUP_ICON_COLUMN = "group_icon";
+
+ /**
+ * The RCS conference URI for this group
+ */
+ String CONFERENCE_URI_COLUMN = "conference_uri";
+ }
+
+ /**
+ * The view that enables polling from all types of RCS threads at once
+ */
+ interface RcsUnifiedThreadColumns extends RcsThreadColumns, Rcs1To1ThreadColumns,
+ RcsGroupThreadColumns {
+ /**
+ * The type of this {@link android.telephony.ims.RcsThread}
+ */
+ String THREAD_TYPE_COLUMN = "thread_type";
+
+ /**
+ * Integer returned as a result from a database query that denotes the thread is 1 to 1
+ */
+ int THREAD_TYPE_1_TO_1 = 0;
+
+ /**
+ * Integer returned as a result from a database query that denotes the thread is 1 to 1
+ */
+ int THREAD_TYPE_GROUP = 1;
+ }
+
+ /**
+ * The table that {@link android.telephony.ims.RcsParticipant} gets persisted to
+ */
+ interface RcsParticipantColumns {
+ /**
+ * The path that should be used for referring to
+ * {@link android.telephony.ims.RcsParticipant}s in
+ * {@link com.android.providers.telephony.RcsProvider} URIs.
+ */
+ String RCS_PARTICIPANT_URI_PART = "participant";
+
+ /**
+ * The URI to query or modify {@link android.telephony.ims.RcsParticipant}s via the
+ * content provider
+ */
+ Uri RCS_PARTICIPANT_URI = Uri.withAppendedPath(CONTENT_AND_AUTHORITY,
+ RCS_PARTICIPANT_URI_PART);
+
+ /**
+ * The unique identifier of the entry in the database
+ */
+ String RCS_PARTICIPANT_ID_COLUMN = "rcs_participant_id";
+
+ /**
+ * A foreign key on canonical_address table, also used by SMS/MMS
+ */
+ String CANONICAL_ADDRESS_ID_COLUMN = "canonical_address_id";
+
+ /**
+ * The user visible RCS alias for this participant.
+ */
+ String RCS_ALIAS_COLUMN = "rcs_alias";
+ }
+
+ /**
+ * Additional constants to enable access to {@link android.telephony.ims.RcsParticipant}
+ * related data
+ */
+ interface RcsParticipantHelpers extends RcsParticipantColumns {
+ /**
+ * The view that unifies "rcs_participant" and "canonical_addresses" tables for easy
+ * access to participant address.
+ */
+ String RCS_PARTICIPANT_WITH_ADDRESS_VIEW = "rcs_participant_with_address_view";
+
+ /**
+ * The view that unifies "rcs_participant", "canonical_addresses" and
+ * "rcs_thread_participant" junction table to get full information on participants that
+ * contribute to threads.
+ */
+ String RCS_PARTICIPANT_WITH_THREAD_VIEW = "rcs_participant_with_thread_view";
+ }
+
+ /**
+ * The table that {@link android.telephony.ims.RcsMessage} gets persisted to
+ */
+ interface RcsMessageColumns {
+ /**
+ * Denotes the type of this message (i.e.
+ * {@link android.telephony.ims.RcsIncomingMessage} or
+ * {@link android.telephony.ims.RcsOutgoingMessage}
+ */
+ String MESSAGE_TYPE_COLUMN = "rcs_message_type";
+
+ /**
+ * The unique identifier for the message in the database - i.e. the primary key.
+ */
+ String MESSAGE_ID_COLUMN = "rcs_message_row_id";
+
+ /**
+ * The globally unique RCS identifier for the message. Please see 4.4.5.2 - GSMA
+ * RCC.53 (RCS Device API 1.6 Specification)
+ */
+ String GLOBAL_ID_COLUMN = "rcs_message_global_id";
+
+ /**
+ * The subscription where this message was sent from/to.
+ */
+ String SUB_ID_COLUMN = "sub_id";
+
+ /**
+ * The sending status of the message.
+ * @see android.telephony.ims.RcsMessage.RcsMessageStatus
+ */
+ String STATUS_COLUMN = "status";
+
+ /**
+ * The creation timestamp of the message.
+ */
+ String ORIGINATION_TIMESTAMP_COLUMN = "origination_timestamp";
+
+ /**
+ * The text content of the message.
+ */
+ String MESSAGE_TEXT_COLUMN = "rcs_text";
+
+ /**
+ * The latitude content of the message, if it contains a location.
+ */
+ String LATITUDE_COLUMN = "latitude";
+
+ /**
+ * The longitude content of the message, if it contains a location.
+ */
+ String LONGITUDE_COLUMN = "longitude";
+ }
+
+ /**
+ * The table that additional information of {@link android.telephony.ims.RcsIncomingMessage}
+ * gets persisted to.
+ */
+ interface RcsIncomingMessageColumns extends RcsMessageColumns {
+ /**
+ The path that should be used for referring to
+ * {@link android.telephony.ims.RcsIncomingMessage}s in
+ * {@link com.android.providers.telephony.RcsProvider} URIs.
+ */
+ String INCOMING_MESSAGE_URI_PART = "incoming_message";
+
+ /**
+ * The URI to query incoming messages through
+ * {@link com.android.providers.telephony.RcsProvider}
+ */
+ Uri INCOMING_MESSAGE_URI = Uri.withAppendedPath(CONTENT_AND_AUTHORITY,
+ INCOMING_MESSAGE_URI_PART);
+
+ /**
+ * The ID of the {@link android.telephony.ims.RcsParticipant} that sent this message
+ */
+ String SENDER_PARTICIPANT_ID_COLUMN = "sender_participant";
+
+ /**
+ * The timestamp of arrival for this message.
+ */
+ String ARRIVAL_TIMESTAMP_COLUMN = "arrival_timestamp";
+
+ /**
+ * The time when the recipient has read this message.
+ */
+ String SEEN_TIMESTAMP_COLUMN = "seen_timestamp";
+ }
+
+ /**
+ * The table that additional information of {@link android.telephony.ims.RcsOutgoingMessage}
+ * gets persisted to.
+ */
+ interface RcsOutgoingMessageColumns extends RcsMessageColumns {
+ /**
+ * The path that should be used for referring to
+ * {@link android.telephony.ims.RcsOutgoingMessage}s in
+ * {@link com.android.providers.telephony.RcsProvider} URIs.
+ */
+ String OUTGOING_MESSAGE_URI_PART = "outgoing_message";
+
+ /**
+ * The URI to query or modify {@link android.telephony.ims.RcsOutgoingMessage}s via the
+ * content provider
+ */
+ Uri OUTGOING_MESSAGE_URI = Uri.withAppendedPath(CONTENT_AND_AUTHORITY,
+ OUTGOING_MESSAGE_URI_PART);
+ }
+
+ /**
+ * The delivery information of an {@link android.telephony.ims.RcsOutgoingMessage}
+ */
+ interface RcsMessageDeliveryColumns extends RcsOutgoingMessageColumns {
+ /**
+ * The path that should be used for referring to
+ * {@link android.telephony.ims.RcsOutgoingMessageDelivery}s in
+ * {@link com.android.providers.telephony.RcsProvider} URIs.
+ */
+ String DELIVERY_URI_PART = "delivery";
+
+ /**
+ * The timestamp of delivery of this message.
+ */
+ String DELIVERED_TIMESTAMP_COLUMN = "delivered_timestamp";
+
+ /**
+ * The time when the recipient has read this message.
+ */
+ String SEEN_TIMESTAMP_COLUMN = "seen_timestamp";
+ }
+
+ /**
+ * The views that allow querying {@link android.telephony.ims.RcsIncomingMessage} and
+ * {@link android.telephony.ims.RcsOutgoingMessage} at the same time.
+ */
+ interface RcsUnifiedMessageColumns extends RcsIncomingMessageColumns,
+ RcsOutgoingMessageColumns {
+ /**
+ * The path that is used to query all {@link android.telephony.ims.RcsMessage} in
+ * {@link com.android.providers.telephony.RcsProvider} URIs.
+ */
+ String UNIFIED_MESSAGE_URI_PART = "message";
+
+ /**
+ * The URI to query all types of {@link android.telephony.ims.RcsMessage}s
+ */
+ Uri UNIFIED_MESSAGE_URI = Uri.withAppendedPath(CONTENT_AND_AUTHORITY,
+ UNIFIED_MESSAGE_URI_PART);
+
+ /**
+ * The name of the view that unites rcs_message and rcs_incoming_message tables.
+ */
+ String UNIFIED_INCOMING_MESSAGE_VIEW = "unified_incoming_message_view";
+
+ /**
+ * The name of the view that unites rcs_message and rcs_outgoing_message tables.
+ */
+ String UNIFIED_OUTGOING_MESSAGE_VIEW = "unified_outgoing_message_view";
+
+ /**
+ * The column that shows from which table the message entry came from.
+ */
+ String MESSAGE_TYPE_COLUMN = "message_type";
+
+ /**
+ * Integer returned as a result from a database query that denotes that the message is
+ * an incoming message
+ */
+ int MESSAGE_TYPE_INCOMING = 1;
+
+ /**
+ * Integer returned as a result from a database query that denotes that the message is
+ * an outgoing message
+ */
+ int MESSAGE_TYPE_OUTGOING = 0;
+ }
+
+ /**
+ * The table that {@link android.telephony.ims.RcsFileTransferPart} gets persisted to.
+ */
+ interface RcsFileTransferColumns {
+ /**
+ * The path that should be used for referring to
+ * {@link android.telephony.ims.RcsFileTransferPart}s in
+ * {@link com.android.providers.telephony.RcsProvider} URIs.
+ */
+ String FILE_TRANSFER_URI_PART = "file_transfer";
+
+ /**
+ * The URI to query or modify {@link android.telephony.ims.RcsFileTransferPart}s via the
+ * content provider
+ */
+ Uri FILE_TRANSFER_URI = Uri.withAppendedPath(CONTENT_AND_AUTHORITY,
+ FILE_TRANSFER_URI_PART);
+
+ /**
+ * The globally unique file transfer ID for this RCS file transfer.
+ */
+ String FILE_TRANSFER_ID_COLUMN = "rcs_file_transfer_id";
+
+ /**
+ * The RCS session ID for this file transfer. The ID is implementation dependent but
+ * should be unique.
+ */
+ String SESSION_ID_COLUMN = "session_id";
+
+ /**
+ * The URI that points to the content of this file transfer
+ */
+ String CONTENT_URI_COLUMN = "content_uri";
+
+ /**
+ * The file type of this file transfer in bytes. The validity of types is not enforced
+ * in {@link android.telephony.ims.RcsMessageStore} APIs.
+ */
+ String CONTENT_TYPE_COLUMN = "content_type";
+
+ /**
+ * The size of the file transfer in bytes.
+ */
+ String FILE_SIZE_COLUMN = "file_size";
+
+ /**
+ * Number of bytes that was successfully transmitted for this file transfer
+ */
+ String SUCCESSFULLY_TRANSFERRED_BYTES = "transfer_offset";
+
+ /**
+ * The status of this file transfer
+ * @see android.telephony.ims.RcsFileTransferPart.RcsFileTransferStatus
+ */
+ String TRANSFER_STATUS_COLUMN = "transfer_status";
+
+ /**
+ * The on-screen width of the file transfer, if it contains multi-media
+ */
+ String WIDTH_COLUMN = "width";
+
+ /**
+ * The on-screen height of the file transfer, if it contains multi-media
+ */
+ String HEIGHT_COLUMN = "height";
+
+ /**
+ * The duration of the content in milliseconds if this file transfer contains
+ * multi-media
+ */
+ String DURATION_MILLIS_COLUMN = "duration";
+
+ /**
+ * The URI to the preview of the content of this file transfer
+ */
+ String PREVIEW_URI_COLUMN = "preview_uri";
+
+ /**
+ * The type of the preview of the content of this file transfer. The validity of types
+ * is not enforced in {@link android.telephony.ims.RcsMessageStore} APIs.
+ */
+ String PREVIEW_TYPE_COLUMN = "preview_type";
+ }
+
+ /**
+ * The table that holds the information for
+ * {@link android.telephony.ims.RcsGroupThreadEvent} and its subclasses.
+ */
+ interface RcsThreadEventColumns {
+ /**
+ * The string used in the {@link com.android.providers.telephony.RcsProvider} URI to
+ * refer to participant joined events (example URI:
+ * {@code content://rcs/group_thread/3/participant_joined_event})
+ */
+ String PARTICIPANT_JOINED_URI_PART = "participant_joined_event";
+
+ /**
+ * The string used in the {@link com.android.providers.telephony.RcsProvider} URI to
+ * refer to participant left events. (example URI:
+ * {@code content://rcs/group_thread/3/participant_left_event/4})
+ */
+ String PARTICIPANT_LEFT_URI_PART = "participant_left_event";
+
+ /**
+ * The string used in the {@link com.android.providers.telephony.RcsProvider} URI to
+ * refer to name changed events. (example URI:
+ * {@code content://rcs/group_thread/3/name_changed_event})
+ */
+ String NAME_CHANGED_URI_PART = "name_changed_event";
+
+ /**
+ * The string used in the {@link com.android.providers.telephony.RcsProvider} URI to
+ * refer to icon changed events. (example URI:
+ * {@code content://rcs/group_thread/3/icon_changed_event})
+ */
+ String ICON_CHANGED_URI_PART = "icon_changed_event";
+
+ /**
+ * The unique ID of this event in the database, i.e. the primary key
+ */
+ String EVENT_ID_COLUMN = "event_id";
+
+ /**
+ * The type of this event
+ *
+ * @see RcsEventTypes
+ */
+ String EVENT_TYPE_COLUMN = "event_type";
+
+ /**
+ * The timestamp in milliseconds of when this event happened
+ */
+ String TIMESTAMP_COLUMN = "origination_timestamp";
+
+ /**
+ * The participant that generated this event
+ */
+ String SOURCE_PARTICIPANT_ID_COLUMN = "source_participant";
+
+ /**
+ * The receiving participant of this event if this was an
+ * {@link android.telephony.ims.RcsGroupThreadParticipantJoinedEvent} or
+ * {@link android.telephony.ims.RcsGroupThreadParticipantLeftEvent}
+ */
+ String DESTINATION_PARTICIPANT_ID_COLUMN = "destination_participant";
+
+ /**
+ * The URI for the new icon of the group thread if this was an
+ * {@link android.telephony.ims.RcsGroupThreadIconChangedEvent}
+ */
+ String NEW_ICON_URI_COLUMN = "new_icon_uri";
+
+ /**
+ * The URI for the new name of the group thread if this was an
+ * {@link android.telephony.ims.RcsGroupThreadNameChangedEvent}
+ */
+ String NEW_NAME_COLUMN = "new_name";
+ }
+
+ /**
+ * The table that {@link android.telephony.ims.RcsParticipantAliasChangedEvent} gets
+ * persisted to
+ */
+ interface RcsParticipantEventColumns {
+ /**
+ * The path that should be used for referring to
+ * {@link android.telephony.ims.RcsParticipantAliasChangedEvent}s in
+ * {@link com.android.providers.telephony.RcsProvider} URIs.
+ */
+ String ALIAS_CHANGE_EVENT_URI_PART = "alias_change_event";
+
+ /**
+ * The new alias of the participant
+ */
+ String NEW_ALIAS_COLUMN = "new_alias";
+ }
+
+ /**
+ * These values are used in {@link com.android.providers.telephony.RcsProvider} to determine
+ * what kind of event is present in the storage.
+ */
+ interface RcsEventTypes {
+ /**
+ * Integer constant that is stored in the
+ * {@link com.android.providers.telephony.RcsProvider} database that denotes the event
+ * is of type {@link android.telephony.ims.RcsParticipantAliasChangedEvent}
+ */
+ int PARTICIPANT_ALIAS_CHANGED_EVENT_TYPE = 1;
+
+ /**
+ * Integer constant that is stored in the
+ * {@link com.android.providers.telephony.RcsProvider} database that denotes the event
+ * is of type {@link android.telephony.ims.RcsGroupThreadParticipantJoinedEvent}
+ */
+ int PARTICIPANT_JOINED_EVENT_TYPE = 2;
+
+ /**
+ * Integer constant that is stored in the
+ * {@link com.android.providers.telephony.RcsProvider} database that denotes the event
+ * is of type {@link android.telephony.ims.RcsGroupThreadParticipantLeftEvent}
+ */
+ int PARTICIPANT_LEFT_EVENT_TYPE = 4;
+
+ /**
+ * Integer constant that is stored in the
+ * {@link com.android.providers.telephony.RcsProvider} database that denotes the event
+ * is of type {@link android.telephony.ims.RcsGroupThreadIconChangedEvent}
+ */
+ int ICON_CHANGED_EVENT_TYPE = 8;
+
+ /**
+ * Integer constant that is stored in the
+ * {@link com.android.providers.telephony.RcsProvider} database that denotes the event
+ * is of type {@link android.telephony.ims.RcsGroupThreadNameChangedEvent}
+ */
+ int NAME_CHANGED_EVENT_TYPE = 16;
+ }
+
+ /**
+ * The view that allows unified querying across all events
+ */
+ interface RcsUnifiedEventHelper extends RcsParticipantEventColumns, RcsThreadEventColumns {
+ /**
+ * The path that should be used for referring to
+ * {@link android.telephony.ims.RcsEvent}s in
+ * {@link com.android.providers.telephony.RcsProvider} URIs.
+ */
+ String RCS_EVENT_QUERY_URI_PATH = "event";
+
+ /**
+ * The URI to query {@link android.telephony.ims.RcsEvent}s via the content provider.
+ */
+ Uri RCS_EVENT_QUERY_URI = Uri.withAppendedPath(CONTENT_AND_AUTHORITY,
+ RCS_EVENT_QUERY_URI_PATH);
+ }
+
+ /**
+ * Allows RCS specific canonical address handling.
+ */
+ interface RcsCanonicalAddressHelper {
+ /**
+ * Returns the canonical address ID for a canonical address, if now row exists, this
+ * will add a row and return its ID. This helper works against the same table used by
+ * the SMS and MMS threads, but is accessible only by the phone process for use by RCS
+ * message storage.
+ *
+ * @throws IllegalArgumentException if unable to retrieve or create the canonical
+ * address entry.
+ */
+ static long getOrCreateCanonicalAddressId(
+ ContentResolver contentResolver, String canonicalAddress) {
+
+ Uri.Builder uriBuilder = CONTENT_AND_AUTHORITY.buildUpon();
+ uriBuilder.appendPath("canonical-address");
+ uriBuilder.appendQueryParameter("address", canonicalAddress);
+ Uri uri = uriBuilder.build();
+
+ try (Cursor cursor = contentResolver.query(uri, null, null, null)) {
+ if (cursor != null && cursor.moveToFirst()) {
+ return cursor.getLong(cursor.getColumnIndex(CanonicalAddressesColumns._ID));
+ } else {
+ Rlog.e(TAG, "getOrCreateCanonicalAddressId returned no rows");
+ }
+ }
+
+ Rlog.e(TAG, "getOrCreateCanonicalAddressId failed");
+ throw new IllegalArgumentException(
+ "Unable to find or allocate a canonical address ID");
+ }
+ }
+ }
+
+ /**
+ * Contains all MMS messages.
+ */
+ public static final class Mms implements BaseMmsColumns {
+
+ /**
+ * Not instantiable.
+ * @hide
+ */
+ private Mms() {
+ }
+
+ /**
+ * The {@code content://} URI for this table.
+ */
+ public static final Uri CONTENT_URI = Uri.parse("content://mms");
+
+ /**
+ * Content URI for getting MMS report requests.
+ */
+ public static final Uri REPORT_REQUEST_URI = Uri.withAppendedPath(
+ CONTENT_URI, "report-request");
+
+ /**
+ * Content URI for getting MMS report status.
+ */
+ public static final Uri REPORT_STATUS_URI = Uri.withAppendedPath(
+ CONTENT_URI, "report-status");
+
+ /**
+ * The default sort order for this table.
+ */
+ public static final String DEFAULT_SORT_ORDER = "date DESC";
+
+ /**
+ * Regex pattern for names and email addresses.
+ * <ul>
+ * <li><em>mailbox</em> = {@code name-addr}</li>
+ * <li><em>name-addr</em> = {@code [display-name] angle-addr}</li>
+ * <li><em>angle-addr</em> = {@code [CFWS] "<" addr-spec ">" [CFWS]}</li>
+ * </ul>
+ * @hide
+ */
+ @UnsupportedAppUsage
+ public static final Pattern NAME_ADDR_EMAIL_PATTERN =
+ Pattern.compile("\\s*(\"[^\"]*\"|[^<>\"]+)\\s*<([^<>]+)>\\s*");
+
+ /**
+ * Helper method to query this table.
+ * @hide
+ */
+ public static Cursor query(
+ ContentResolver cr, String[] projection) {
+ return cr.query(CONTENT_URI, projection, null, null, DEFAULT_SORT_ORDER);
+ }
+
+ /**
+ * Helper method to query this table.
+ * @hide
+ */
+ public static Cursor query(
+ ContentResolver cr, String[] projection,
+ String where, String orderBy) {
+ return cr.query(CONTENT_URI, projection,
+ where, null, orderBy == null ? DEFAULT_SORT_ORDER : orderBy);
+ }
+
+ /**
+ * Helper method to extract email address from address string.
+ * @hide
+ */
+ @UnsupportedAppUsage
+ public static String extractAddrSpec(String address) {
+ Matcher match = NAME_ADDR_EMAIL_PATTERN.matcher(address);
+
+ if (match.matches()) {
+ return match.group(2);
+ }
+ return address;
+ }
+
+ /**
+ * Is the specified address an email address?
+ *
+ * @param address the input address to test
+ * @return true if address is an email address; false otherwise.
+ * @hide
+ */
+ @UnsupportedAppUsage
+ public static boolean isEmailAddress(String address) {
+ if (TextUtils.isEmpty(address)) {
+ return false;
+ }
+
+ String s = extractAddrSpec(address);
+ Matcher match = Patterns.EMAIL_ADDRESS.matcher(s);
+ return match.matches();
+ }
+
+ /**
+ * Is the specified number a phone number?
+ *
+ * @param number the input number to test
+ * @return true if number is a phone number; false otherwise.
+ * @hide
+ */
+ @UnsupportedAppUsage
+ public static boolean isPhoneNumber(String number) {
+ if (TextUtils.isEmpty(number)) {
+ return false;
+ }
+
+ Matcher match = Patterns.PHONE.matcher(number);
+ return match.matches();
+ }
+
+ /**
+ * Contains all MMS messages in the MMS app inbox.
+ */
+ public static final class Inbox implements BaseMmsColumns {
+
+ /**
+ * Not instantiable.
+ * @hide
+ */
+ private Inbox() {
+ }
+
+ /**
+ * The {@code content://} style URL for this table.
+ */
+ public static final Uri
+ CONTENT_URI = Uri.parse("content://mms/inbox");
+
+ /**
+ * The default sort order for this table.
+ */
+ public static final String DEFAULT_SORT_ORDER = "date DESC";
+ }
+
+ /**
+ * Contains all MMS messages in the MMS app sent folder.
+ */
+ public static final class Sent implements BaseMmsColumns {
+
+ /**
+ * Not instantiable.
+ * @hide
+ */
+ private Sent() {
+ }
+
+ /**
+ * The {@code content://} style URL for this table.
+ */
+ public static final Uri
+ CONTENT_URI = Uri.parse("content://mms/sent");
+
+ /**
+ * The default sort order for this table.
+ */
+ public static final String DEFAULT_SORT_ORDER = "date DESC";
+ }
+
+ /**
+ * Contains all MMS messages in the MMS app drafts folder.
+ */
+ public static final class Draft implements BaseMmsColumns {
+
+ /**
+ * Not instantiable.
+ * @hide
+ */
+ private Draft() {
+ }
+
+ /**
+ * The {@code content://} style URL for this table.
+ */
+ public static final Uri
+ CONTENT_URI = Uri.parse("content://mms/drafts");
+
+ /**
+ * The default sort order for this table.
+ */
+ public static final String DEFAULT_SORT_ORDER = "date DESC";
+ }
+
+ /**
+ * Contains all MMS messages in the MMS app outbox.
+ */
+ public static final class Outbox implements BaseMmsColumns {
+
+ /**
+ * Not instantiable.
+ * @hide
+ */
+ private Outbox() {
+ }
+
+ /**
+ * The {@code content://} style URL for this table.
+ */
+ public static final Uri
+ CONTENT_URI = Uri.parse("content://mms/outbox");
+
+ /**
+ * The default sort order for this table.
+ */
+ public static final String DEFAULT_SORT_ORDER = "date DESC";
+ }
+
+ /**
+ * Contains address information for an MMS message.
+ */
+ public static final class Addr implements BaseColumns {
+
+ /**
+ * Not instantiable.
+ * @hide
+ */
+ private Addr() {
+ }
+
+ /**
+ * The ID of MM which this address entry belongs to.
+ * <P>Type: INTEGER (long)</P>
+ */
+ public static final String MSG_ID = "msg_id";
+
+ /**
+ * The ID of contact entry in Phone Book.
+ * <P>Type: INTEGER (long)</P>
+ */
+ public static final String CONTACT_ID = "contact_id";
+
+ /**
+ * The address text.
+ * <P>Type: TEXT</P>
+ */
+ public static final String ADDRESS = "address";
+
+ /**
+ * Type of address: must be one of {@code PduHeaders.BCC},
+ * {@code PduHeaders.CC}, {@code PduHeaders.FROM}, {@code PduHeaders.TO}.
+ * <P>Type: INTEGER</P>
+ */
+ public static final String TYPE = "type";
+
+ /**
+ * Character set of this entry (MMS charset value).
+ * <P>Type: INTEGER</P>
+ */
+ public static final String CHARSET = "charset";
+
+ /**
+ * Generates a Addr {@link Uri} for message, used to perform Addr table operation
+ * for mms.
+ *
+ * @param messageId the messageId used to generate Addr {@link Uri} dynamically
+ * @return the addrUri used to perform Addr table operation for mms
+ */
+ @NonNull
+ public static Uri getAddrUriForMessage(@NonNull String messageId) {
+ Uri addrUri = Mms.CONTENT_URI.buildUpon()
+ .appendPath(String.valueOf(messageId)).appendPath("addr").build();
+ return addrUri;
+ }
+ }
+
+ /**
+ * Contains message parts.
+ *
+ * To avoid issues where applications might cache a part ID, the ID of a deleted part must
+ * not be reused to point at a new part.
+ */
+ public static final class Part implements BaseColumns {
+
+ /**
+ * Not instantiable.
+ * @hide
+ */
+ private Part() {
+ }
+
+ /**
+ * The name of part table.
+ */
+ private static final String TABLE_PART = "part";
+
+ /**
+ * The {@code content://} style URL for this table. Can be appended with a part ID to
+ * address individual parts.
+ */
+ @NonNull
+ public static final Uri CONTENT_URI = Uri.withAppendedPath(Mms.CONTENT_URI, TABLE_PART);
+
+ /**
+ * The identifier of the message which this part belongs to.
+ * <P>Type: INTEGER</P>
+ */
+ public static final String MSG_ID = "mid";
+
+ /**
+ * The order of the part.
+ * <P>Type: INTEGER</P>
+ */
+ public static final String SEQ = "seq";
+
+ /**
+ * The content type of the part.
+ * <P>Type: TEXT</P>
+ */
+ public static final String CONTENT_TYPE = "ct";
+
+ /**
+ * The name of the part.
+ * <P>Type: TEXT</P>
+ */
+ public static final String NAME = "name";
+
+ /**
+ * The charset of the part.
+ * <P>Type: TEXT</P>
+ */
+ public static final String CHARSET = "chset";
+
+ /**
+ * The file name of the part.
+ * <P>Type: TEXT</P>
+ */
+ public static final String FILENAME = "fn";
+
+ /**
+ * The content disposition of the part.
+ * <P>Type: TEXT</P>
+ */
+ public static final String CONTENT_DISPOSITION = "cd";
+
+ /**
+ * The content ID of the part.
+ * <P>Type: INTEGER</P>
+ */
+ public static final String CONTENT_ID = "cid";
+
+ /**
+ * The content location of the part.
+ * <P>Type: INTEGER</P>
+ */
+ public static final String CONTENT_LOCATION = "cl";
+
+ /**
+ * The start of content-type of the message.
+ * <P>Type: INTEGER</P>
+ */
+ public static final String CT_START = "ctt_s";
+
+ /**
+ * The type of content-type of the message.
+ * <P>Type: TEXT</P>
+ */
+ public static final String CT_TYPE = "ctt_t";
+
+ /**
+ * The location (on filesystem) of the binary data of the part.
+ * <P>Type: INTEGER</P>
+ */
+ public static final String _DATA = "_data";
+
+ /**
+ * The message text.
+ * <P>Type: TEXT</P>
+ */
+ public static final String TEXT = "text";
+
+ /**
+ * Generates a Part {@link Uri} for message, used to perform Part table operation
+ * for mms.
+ *
+ * @param messageId the messageId used to generate Part {@link Uri} dynamically
+ * @return the partUri used to perform Part table operation for mms
+ */
+ @NonNull
+ public static Uri getPartUriForMessage(@NonNull String messageId) {
+ Uri partUri = Mms.CONTENT_URI.buildUpon()
+ .appendPath(String.valueOf(messageId)).appendPath(
+ TABLE_PART).build();
+ return partUri;
+ }
+ }
+
+ /**
+ * Message send rate table.
+ */
+ public static final class Rate {
+
+ /**
+ * Not instantiable.
+ * @hide
+ */
+ private Rate() {
+ }
+
+ /**
+ * The {@code content://} style URL for this table.
+ */
+ public static final Uri CONTENT_URI = Uri.withAppendedPath(
+ Mms.CONTENT_URI, "rate");
+
+ /**
+ * When a message was successfully sent.
+ * <P>Type: INTEGER (long)</P>
+ */
+ public static final String SENT_TIME = "sent_time";
+ }
+
+ /**
+ * Intents class.
+ */
+ public static final class Intents {
+
+ /**
+ * Not instantiable.
+ * @hide
+ */
+ private Intents() {
+ }
+
+ /**
+ * Indicates that the contents of specified URIs were changed.
+ * The application which is showing or caching these contents
+ * should be updated.
+ */
+ @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
+ public static final String CONTENT_CHANGED_ACTION
+ = "android.intent.action.CONTENT_CHANGED";
+
+ /**
+ * An extra field which stores the URI of deleted contents.
+ */
+ public static final String DELETED_CONTENTS = "deleted_contents";
+ }
+ }
+
+ /**
+ * Contains all MMS and SMS messages.
+ */
+ public static final class MmsSms implements BaseColumns {
+
+ /**
+ * Not instantiable.
+ * @hide
+ */
+ private MmsSms() {
+ }
+
+ /**
+ * The column to distinguish SMS and MMS messages in query results.
+ */
+ public static final String TYPE_DISCRIMINATOR_COLUMN =
+ "transport_type";
+
+ /**
+ * The {@code content://} style URL for this table.
+ */
+ public static final Uri CONTENT_URI = Uri.parse("content://mms-sms/");
+
+ /**
+ * The {@code content://} style URL for this table, by conversation.
+ */
+ public static final Uri CONTENT_CONVERSATIONS_URI = Uri.parse(
+ "content://mms-sms/conversations");
+
+ /**
+ * The {@code content://} style URL for this table, by phone number.
+ */
+ public static final Uri CONTENT_FILTER_BYPHONE_URI = Uri.parse(
+ "content://mms-sms/messages/byphone");
+
+ /**
+ * The {@code content://} style URL for undelivered messages in this table.
+ */
+ public static final Uri CONTENT_UNDELIVERED_URI = Uri.parse(
+ "content://mms-sms/undelivered");
+
+ /**
+ * The {@code content://} style URL for draft messages in this table.
+ */
+ public static final Uri CONTENT_DRAFT_URI = Uri.parse(
+ "content://mms-sms/draft");
+
+ /**
+ * The {@code content://} style URL for locked messages in this table.
+ * <P>This {@link Uri} is used to check at most one locked message found in the union of MMS
+ * and SMS messages. Also this will return only _id column in response.</P>
+ */
+ public static final Uri CONTENT_LOCKED_URI = Uri.parse(
+ "content://mms-sms/locked");
+
+ /**
+ * Pass in a query parameter called "pattern" which is the text to search for.
+ * The sort order is fixed to be: {@code thread_id ASC, date DESC}.
+ */
+ public static final Uri SEARCH_URI = Uri.parse(
+ "content://mms-sms/search");
+
+ // Constants for message protocol types.
+
+ /** SMS protocol type. */
+ public static final int SMS_PROTO = 0;
+
+ /** MMS protocol type. */
+ public static final int MMS_PROTO = 1;
+
+ // Constants for error types of pending messages.
+
+ /** Error type: no error. */
+ public static final int NO_ERROR = 0;
+
+ /** Error type: generic transient error. */
+ public static final int ERR_TYPE_GENERIC = 1;
+
+ /** Error type: SMS protocol transient error. */
+ public static final int ERR_TYPE_SMS_PROTO_TRANSIENT = 2;
+
+ /** Error type: MMS protocol transient error. */
+ public static final int ERR_TYPE_MMS_PROTO_TRANSIENT = 3;
+
+ /** Error type: transport failure. */
+ public static final int ERR_TYPE_TRANSPORT_FAILURE = 4;
+
+ /** Error type: permanent error (along with all higher error values). */
+ public static final int ERR_TYPE_GENERIC_PERMANENT = 10;
+
+ /** Error type: SMS protocol permanent error. */
+ public static final int ERR_TYPE_SMS_PROTO_PERMANENT = 11;
+
+ /** Error type: MMS protocol permanent error. */
+ public static final int ERR_TYPE_MMS_PROTO_PERMANENT = 12;
+
+ /**
+ * Contains pending messages info.
+ */
+ public static final class PendingMessages implements BaseColumns {
+
+ /**
+ * Not instantiable.
+ * @hide
+ */
+ private PendingMessages() {
+ }
+
+ public static final Uri CONTENT_URI = Uri.withAppendedPath(
+ MmsSms.CONTENT_URI, "pending");
+
+ /**
+ * The type of transport protocol (MMS or SMS).
+ * <P>Type: INTEGER</P>
+ */
+ public static final String PROTO_TYPE = "proto_type";
+
+ /**
+ * The ID of the message to be sent or downloaded.
+ * <P>Type: INTEGER (long)</P>
+ */
+ public static final String MSG_ID = "msg_id";
+
+ /**
+ * The type of the message to be sent or downloaded.
+ * This field is only valid for MM. For SM, its value is always set to 0.
+ * <P>Type: INTEGER</P>
+ */
+ public static final String MSG_TYPE = "msg_type";
+
+ /**
+ * The type of the error code.
+ * <P>Type: INTEGER</P>
+ */
+ public static final String ERROR_TYPE = "err_type";
+
+ /**
+ * The error code of sending/retrieving process.
+ * <P>Type: INTEGER</P>
+ */
+ public static final String ERROR_CODE = "err_code";
+
+ /**
+ * How many times we tried to send or download the message.
+ * <P>Type: INTEGER</P>
+ */
+ public static final String RETRY_INDEX = "retry_index";
+
+ /**
+ * The time to do next retry.
+ * <P>Type: INTEGER (long)</P>
+ */
+ public static final String DUE_TIME = "due_time";
+
+ /**
+ * The time we last tried to send or download the message.
+ * <P>Type: INTEGER (long)</P>
+ */
+ public static final String LAST_TRY = "last_try";
+
+ /**
+ * The subscription to which the message belongs to. Its value will be
+ * < 0 if the sub id cannot be determined.
+ * <p>Type: INTEGER (long) </p>
+ */
+ public static final String SUBSCRIPTION_ID = "pending_sub_id";
+ }
+
+ /**
+ * Words table used by provider for full-text searches.
+ * @hide
+ */
+ public static final class WordsTable {
+
+ /**
+ * Not instantiable.
+ * @hide
+ */
+ private WordsTable() {}
+
+ /**
+ * Primary key.
+ * <P>Type: INTEGER (long)</P>
+ */
+ public static final String ID = "_id";
+
+ /**
+ * Source row ID.
+ * <P>Type: INTEGER (long)</P>
+ */
+ public static final String SOURCE_ROW_ID = "source_id";
+
+ /**
+ * Table ID (either 1 or 2).
+ * <P>Type: INTEGER</P>
+ */
+ public static final String TABLE_ID = "table_to_use";
+
+ /**
+ * The words to index.
+ * <P>Type: TEXT</P>
+ */
+ public static final String INDEXED_TEXT = "index_text";
+ }
+ }
+
+ /**
+ * Carriers class contains information about APNs, including MMSC information.
+ */
+ public static final class Carriers implements BaseColumns {
+
+ /**
+ * Not instantiable.
+ * @hide
+ */
+ private Carriers() {}
+
+ /**
+ * The {@code content://} style URL for this table.
+ * For MSIM, this will return APNs for the default subscription
+ * {@link SubscriptionManager#getDefaultSubscriptionId()}. To specify subId for MSIM,
+ * use {@link Uri#withAppendedPath(Uri, String)} to append with subscription id.
+ */
+ @NonNull
+ public static final Uri CONTENT_URI = Uri.parse("content://telephony/carriers");
+
+ /**
+ * The {@code content://} style URL for this table. Used for APN query based on current
+ * subscription. Instead of specifying carrier matching information in the selection,
+ * this API will return all matching APNs from current subscription carrier and queries
+ * will be applied on top of that. If there is no match for MVNO (Mobile Virtual Network
+ * Operator) APNs, return APNs from its MNO (based on mccmnc) instead. For MSIM, this will
+ * return APNs for the default subscription
+ * {@link SubscriptionManager#getDefaultSubscriptionId()}. To specify subId for MSIM,
+ * use {@link Uri#withAppendedPath(Uri, String)} to append with subscription id.
+ */
+ @NonNull
+ public static final Uri SIM_APN_URI = Uri.parse(
+ "content://telephony/carriers/sim_apn_list");
+
+ /**
+ * The {@code content://} style URL to be called from DevicePolicyManagerService,
+ * can manage DPC-owned APNs.
+ * @hide
+ */
+ public static final Uri DPC_URI = Uri.parse("content://telephony/carriers/dpc");
+
+ /**
+ * The {@code content://} style URL to be called from Telephony to query APNs.
+ * When DPC-owned APNs are enforced, only DPC-owned APNs are returned, otherwise only
+ * non-DPC-owned APNs are returned. For MSIM, this will return APNs for the default
+ * subscription {@link SubscriptionManager#getDefaultSubscriptionId()}. To specify subId
+ * for MSIM, use {@link Uri#withAppendedPath(Uri, String)} to append with subscription id.
+ * @hide
+ */
+ public static final Uri FILTERED_URI = Uri.parse("content://telephony/carriers/filtered");
+
+ /**
+ * The {@code content://} style URL to be called from DevicePolicyManagerService
+ * or Telephony to manage whether DPC-owned APNs are enforced.
+ * @hide
+ */
+ public static final Uri ENFORCE_MANAGED_URI = Uri.parse(
+ "content://telephony/carriers/enforce_managed");
+
+ /**
+ * The column name for ENFORCE_MANAGED_URI, indicates whether DPC-owned APNs are enforced.
+ * @hide
+ */
+ public static final String ENFORCE_KEY = "enforced";
+
+ /**
+ * The default sort order for this table.
+ */
+ public static final String DEFAULT_SORT_ORDER = "name ASC";
+
+ /**
+ * Entry name.
+ * <P>Type: TEXT</P>
+ */
+ public static final String NAME = "name";
+
+ /**
+ * APN name.
+ * <P>Type: TEXT</P>
+ */
+ public static final String APN = "apn";
+
+ /**
+ * Proxy address.
+ * <P>Type: TEXT</P>
+ */
+ public static final String PROXY = "proxy";
+
+ /**
+ * Proxy port.
+ * <P>Type: TEXT</P>
+ */
+ public static final String PORT = "port";
+
+ /**
+ * MMS proxy address.
+ * <P>Type: TEXT</P>
+ */
+ public static final String MMSPROXY = "mmsproxy";
+
+ /**
+ * MMS proxy port.
+ * <P>Type: TEXT</P>
+ */
+ public static final String MMSPORT = "mmsport";
+
+ /**
+ * Server address.
+ * <P>Type: TEXT</P>
+ */
+ public static final String SERVER = "server";
+
+ /**
+ * APN username.
+ * <P>Type: TEXT</P>
+ */
+ public static final String USER = "user";
+
+ /**
+ * APN password.
+ * <P>Type: TEXT</P>
+ */
+ public static final String PASSWORD = "password";
+
+ /**
+ * MMSC URL.
+ * <P>Type: TEXT</P>
+ */
+ public static final String MMSC = "mmsc";
+
+ /**
+ * Mobile Country Code (MCC).
+ * <P>Type: TEXT</P>
+ * @deprecated Use {@link #SIM_APN_URI} to query APN instead, this API will return
+ * matching APNs based on current subscription carrier, thus no need to specify MCC and
+ * other carrier matching information. In the future, Android will not support MCC for
+ * APN query.
+ */
+ public static final String MCC = "mcc";
+
+ /**
+ * Mobile Network Code (MNC).
+ * <P>Type: TEXT</P>
+ * @deprecated Use {@link #SIM_APN_URI} to query APN instead, this API will return
+ * matching APNs based on current subscription carrier, thus no need to specify MNC and
+ * other carrier matching information. In the future, Android will not support MNC for
+ * APN query.
+ */
+ public static final String MNC = "mnc";
+
+ /**
+ * Numeric operator ID (as String). Usually {@code MCC + MNC}.
+ * <P>Type: TEXT</P>
+ * @deprecated Use {@link #SIM_APN_URI} to query APN instead, this API will return
+ * matching APNs based on current subscription carrier, thus no need to specify Numeric
+ * and other carrier matching information. In the future, Android will not support Numeric
+ * for APN query.
+ */
+ public static final String NUMERIC = "numeric";
+
+ /**
+ * Authentication type.
+ * <P>Type: INTEGER</P>
+ */
+ public static final String AUTH_TYPE = "authtype";
+
+ /**
+ * Comma-delimited list of APN types.
+ * <P>Type: TEXT</P>
+ */
+ public static final String TYPE = "type";
+
+ /**
+ * The protocol to use to connect to this APN.
+ *
+ * One of the {@code PDP_type} values in TS 27.007 section 10.1.1.
+ * For example: {@code IP}, {@code IPV6}, {@code IPV4V6}, or {@code PPP}.
+ * <P>Type: TEXT</P>
+ */
+ public static final String PROTOCOL = "protocol";
+
+ /**
+ * The protocol to use to connect to this APN when roaming.
+ * The syntax is the same as protocol.
+ * <P>Type: TEXT</P>
+ */
+ public static final String ROAMING_PROTOCOL = "roaming_protocol";
+
+ /**
+ * Is this the current APN?
+ * <P>Type: INTEGER (boolean)</P>
+ */
+ public static final String CURRENT = "current";
+
+ /**
+ * Is this APN enabled?
+ * <P>Type: INTEGER (boolean)</P>
+ */
+ public static final String CARRIER_ENABLED = "carrier_enabled";
+
+ /**
+ * Radio Access Technology info.
+ * To check what values are allowed, refer to {@link android.telephony.ServiceState}.
+ * This should be spread to other technologies,
+ * but is currently only used for LTE (14) and eHRPD (13).
+ * <P>Type: INTEGER</P>
+ * @deprecated this column is no longer supported, use {@link #NETWORK_TYPE_BITMASK} instead
+ */
+ @Deprecated
+ public static final String BEARER = "bearer";
+
+ /**
+ * Radio Access Technology bitmask.
+ * To check what values can be contained, refer to {@link android.telephony.ServiceState}.
+ * 0 indicates all techs otherwise first bit refers to RAT/bearer 1, second bit refers to
+ * RAT/bearer 2 and so on.
+ * Bitmask for a radio tech R is (1 << (R - 1))
+ * <P>Type: INTEGER</P>
+ * @hide
+ * @deprecated this column is no longer supported, use {@link #NETWORK_TYPE_BITMASK} instead
+ */
+ @Deprecated
+ public static final String BEARER_BITMASK = "bearer_bitmask";
+
+ /**
+ * Radio technology (network type) bitmask.
+ * To check what values can be contained, refer to the NETWORK_TYPE_ constants in
+ * {@link android.telephony.TelephonyManager}.
+ * Bitmask for a radio tech R is (1 << (R - 1))
+ * <P>Type: INTEGER</P>
+ */
+ public static final String NETWORK_TYPE_BITMASK = "network_type_bitmask";
+
+ /**
+ * MVNO type:
+ * {@code SPN (Service Provider Name), IMSI, GID (Group Identifier Level 1)}.
+ * <P>Type: TEXT</P>
+ * @deprecated Use {@link #SIM_APN_URI} to query APN instead, this API will return
+ * matching APNs based on current subscription carrier, thus no need to specify MVNO_TYPE
+ * and other carrier matching information. In the future, Android will not support MVNO_TYPE
+ * for APN query.
+ */
+ public static final String MVNO_TYPE = "mvno_type";
+
+ /**
+ * MVNO data.
+ * Use the following examples.
+ * <ul>
+ * <li>SPN: A MOBILE, BEN NL, ...</li>
+ * <li>IMSI: 302720x94, 2060188, ...</li>
+ * <li>GID: 4E, 33, ...</li>
+ * </ul>
+ * <P>Type: TEXT</P>
+ * @deprecated Use {@link #SIM_APN_URI} to query APN instead, this API will return
+ * matching APNs based on current subscription carrier, thus no need to specify
+ * MVNO_MATCH_DATA and other carrier matching information. In the future, Android will not
+ * support MVNO_MATCH_DATA for APN query.
+ */
+ public static final String MVNO_MATCH_DATA = "mvno_match_data";
+
+ /**
+ * The subscription to which the APN belongs to
+ * <p>Type: INTEGER (long) </p>
+ */
+ public static final String SUBSCRIPTION_ID = "sub_id";
+
+ /**
+ * The profile_id to which the APN saved in modem.
+ * <p>Type: INTEGER</p>
+ *@hide
+ */
+ public static final String PROFILE_ID = "profile_id";
+
+ /**
+ * If set to {@code true}, then the APN setting will persist to the modem.
+ * <p>Type: INTEGER (boolean)</p>
+ *@hide
+ */
+ @SystemApi
+ public static final String MODEM_PERSIST = "modem_cognitive";
+
+ /**
+ * The max number of connections of this APN.
+ * <p>Type: INTEGER</p>
+ *@hide
+ */
+ @SystemApi
+ public static final String MAX_CONNECTIONS = "max_conns";
+
+ /**
+ * The wait time for retrying the APN, in milliseconds.
+ * <p>Type: INTEGER</p>
+ *@hide
+ */
+ @SystemApi
+ public static final String WAIT_TIME_RETRY = "wait_time";
+
+ /**
+ * The max number of seconds this APN will support its maximum number of connections
+ * as defined in {@link #MAX_CONNECTIONS}.
+ * <p>Type: INTEGER</p>
+ *@hide
+ */
+ @SystemApi
+ public static final String TIME_LIMIT_FOR_MAX_CONNECTIONS = "max_conns_time";
+
+ /**
+ * The MTU (maximum transmit unit) size of the mobile interface to which the APN is
+ * connected, in bytes.
+ * <p>Type: INTEGER </p>
+ * @hide
+ */
+ @SystemApi
+ public static final String MTU = "mtu";
+
+ /**
+ * APN edit status. APN could be added/edited/deleted by a user or carrier.
+ * see all possible returned APN edit status.
+ * <ul>
+ * <li>{@link #UNEDITED}</li>
+ * <li>{@link #USER_EDITED}</li>
+ * <li>{@link #USER_DELETED}</li>
+ * <li>{@link #CARRIER_EDITED}</li>
+ * <li>{@link #CARRIER_DELETED}</li>
+ * </ul>
+ * <p>Type: INTEGER </p>
+ * @hide
+ */
+ @SystemApi
+ public static final String EDITED_STATUS = "edited";
+
+ /**
+ * {@code true} if this APN visible to the user, {@code false} otherwise.
+ * <p>Type: INTEGER (boolean)</p>
+ * @hide
+ */
+ @SystemApi
+ public static final String USER_VISIBLE = "user_visible";
+
+ /**
+ * {@code true} if the user allowed to edit this APN, {@code false} otherwise.
+ * <p>Type: INTEGER (boolean)</p>
+ * @hide
+ */
+ @SystemApi
+ public static final String USER_EDITABLE = "user_editable";
+
+ /**
+ * {@link #EDITED_STATUS APN edit status} indicates that this APN has not been edited or
+ * fails to edit.
+ * <p>Type: INTEGER </p>
+ * @hide
+ */
+ @SystemApi
+ public static final @EditStatus int UNEDITED = 0;
+
+ /**
+ * {@link #EDITED_STATUS APN edit status} indicates that this APN has been edited by users.
+ * <p>Type: INTEGER </p>
+ * @hide
+ */
+ @SystemApi
+ public static final @EditStatus int USER_EDITED = 1;
+
+ /**
+ * {@link #EDITED_STATUS APN edit status} indicates that this APN has been deleted by users.
+ * <p>Type: INTEGER </p>
+ * @hide
+ */
+ @SystemApi
+ public static final @EditStatus int USER_DELETED = 2;
+
+ /**
+ * {@link #EDITED_STATUS APN edit status} is an intermediate value used to indicate that an
+ * entry deleted by the user is still present in the new APN database and therefore must
+ * remain tagged as user deleted rather than completely removed from the database.
+ * @hide
+ */
+ public static final int USER_DELETED_BUT_PRESENT_IN_XML = 3;
+
+ /**
+ * {@link #EDITED_STATUS APN edit status} indicates that this APN has been edited by
+ * carriers.
+ * <p>Type: INTEGER </p>
+ * @hide
+ */
+ @SystemApi
+ public static final @EditStatus int CARRIER_EDITED = 4;
+
+ /**
+ * {@link #EDITED_STATUS APN edit status} indicates that this APN has been deleted by
+ * carriers. CARRIER_DELETED values are currently not used as there is no use case.
+ * If they are used, delete() will have to change accordingly. Currently it is hardcoded to
+ * USER_DELETED.
+ * <p>Type: INTEGER </p>
+ * @hide
+ */
+ public static final @EditStatus int CARRIER_DELETED = 5;
+
+ /**
+ * {@link #EDITED_STATUS APN edit status} is an intermediate value used to indicate that an
+ * entry deleted by the carrier is still present in the new APN database and therefore must
+ * remain tagged as user deleted rather than completely removed from the database.
+ * @hide
+ */
+ public static final int CARRIER_DELETED_BUT_PRESENT_IN_XML = 6;
+
+ /**
+ * The owner of the APN.
+ * <p>Type: INTEGER</p>
+ * @hide
+ */
+ public static final String OWNED_BY = "owned_by";
+
+ /**
+ * Possible value for the OWNED_BY field.
+ * APN is owned by DPC.
+ * @hide
+ */
+ public static final int OWNED_BY_DPC = 0;
+
+ /**
+ * Possible value for the OWNED_BY field.
+ * APN is owned by other sources.
+ * @hide
+ */
+ public static final int OWNED_BY_OTHERS = 1;
+
+ /**
+ * The APN set id. When the user manually selects an APN or the framework sets an APN as
+ * preferred, all APNs with the same set id as the selected APN should be prioritized over
+ * APNs in other sets.
+ * <p>Type: INTEGER</p>
+ * @hide
+ */
+ @SystemApi
+ public static final String APN_SET_ID = "apn_set_id";
+
+ /**
+ * Possible value for the {@link #APN_SET_ID} field. By default APNs will not belong to a
+ * set. If the user manually selects an APN without apn set id, there is no need to
+ * prioritize any specific APN set ids.
+ * <p>Type: INTEGER</p>
+ * @hide
+ */
+ @SystemApi
+ public static final int NO_APN_SET_ID = 0;
+
+ /**
+ * A unique carrier id associated with this APN
+ * {@see TelephonyManager#getSimCarrierId()}
+ * <p>Type: STRING</p>
+ */
+ public static final String CARRIER_ID = "carrier_id";
+
+ /**
+ * The skip 464xlat flag. Flag works as follows.
+ * {@link #SKIP_464XLAT_DEFAULT}: the APN will skip only APN is IMS and no internet.
+ * {@link #SKIP_464XLAT_DISABLE}: the APN will NOT skip 464xlat
+ * {@link #SKIP_464XLAT_ENABLE}: the APN will skip 464xlat
+ * <p>Type: INTEGER</p>
+ *
+ * @hide
+ */
+ public static final String SKIP_464XLAT = "skip_464xlat";
+
+ /**
+ * Possible value for the {@link #SKIP_464XLAT} field.
+ * <p>Type: INTEGER</p>
+ *
+ * @hide
+ */
+ public static final int SKIP_464XLAT_DEFAULT = -1;
+
+ /**
+ * Possible value for the {@link #SKIP_464XLAT} field.
+ * <p>Type: INTEGER</p>
+ *
+ * @hide
+ */
+ public static final int SKIP_464XLAT_DISABLE = 0;
+
+ /**
+ * Possible value for the {@link #SKIP_464XLAT} field.
+ * <p>Type: INTEGER</p>
+ *
+ * @hide
+ */
+ public static final int SKIP_464XLAT_ENABLE = 1;
+
+
+ /** @hide */
+ @IntDef({
+ UNEDITED,
+ USER_EDITED,
+ USER_DELETED,
+ CARRIER_DELETED,
+ CARRIER_EDITED,
+ })
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface EditStatus {}
+
+ /** @hide */
+ @IntDef({
+ SKIP_464XLAT_DEFAULT,
+ SKIP_464XLAT_DISABLE,
+ SKIP_464XLAT_ENABLE,
+ })
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface Skip464XlatStatus {}
+
+ }
+
+ /**
+ * Contains received cell broadcast messages. More details are available in 3GPP TS 23.041.
+ * @hide
+ */
+ @SystemApi
+ @TestApi
+ public static final class CellBroadcasts implements BaseColumns {
+
+ /**
+ * Not instantiable.
+ * @hide
+ */
+ private CellBroadcasts() {}
+
+ /**
+ * The {@code content://} URI for this table.
+ * Only privileged framework components running on phone or network stack uid can
+ * query or modify this table.
+ */
+ @NonNull
+ public static final Uri CONTENT_URI = Uri.parse("content://cellbroadcasts");
+
+ /**
+ * The {@code content://} URI for query cellbroadcast message history.
+ * query results include following entries
+ * <ul>
+ * <li>{@link #_ID}</li>
+ * <li>{@link #SLOT_INDEX}</li>
+ * <li>{@link #GEOGRAPHICAL_SCOPE}</li>
+ * <li>{@link #PLMN}</li>
+ * <li>{@link #LAC}</li>
+ * <li>{@link #CID}</li>
+ * <li>{@link #SERIAL_NUMBER}</li>
+ * <li>{@link #SERVICE_CATEGORY}</li>
+ * <li>{@link #LANGUAGE_CODE}</li>
+ * <li>{@link #MESSAGE_BODY}</li>
+ * <li>{@link #DELIVERY_TIME}</li>
+ * <li>{@link #MESSAGE_READ}</li>
+ * <li>{@link #MESSAGE_FORMAT}</li>
+ * <li>{@link #MESSAGE_PRIORITY}</li>
+ * <li>{@link #ETWS_WARNING_TYPE}</li>
+ * <li>{@link #CMAS_MESSAGE_CLASS}</li>
+ * <li>{@link #CMAS_CATEGORY}</li>
+ * <li>{@link #CMAS_RESPONSE_TYPE}</li>
+ * <li>{@link #CMAS_SEVERITY}</li>
+ * <li>{@link #CMAS_URGENCY}</li>
+ * <li>{@link #CMAS_CERTAINTY}</li>
+ * </ul>
+ */
+ @RequiresPermission(Manifest.permission.READ_CELL_BROADCASTS)
+ @NonNull
+ public static final Uri MESSAGE_HISTORY_URI = Uri.parse("content://cellbroadcasts/history");
+
+ /**
+ * The subscription which received this cell broadcast message.
+ * <P>Type: INTEGER</P>
+ */
+ public static final String SUB_ID = "sub_id";
+
+ /**
+ * The slot which received this cell broadcast message.
+ * <P>Type: INTEGER</P>
+ */
+ public static final String SLOT_INDEX = "slot_index";
+
+ /**
+ * Message geographical scope. Valid values are:
+ * <ul>
+ * <li>{@link android.telephony.SmsCbMessage#GEOGRAPHICAL_SCOPE_CELL_WIDE}. meaning the
+ * message is for the radio service cell</li>
+ * <li>{@link android.telephony.SmsCbMessage#GEOGRAPHICAL_SCOPE_CELL_WIDE_IMMEDIATE},
+ * meaning the message is for the radio service cell and immediately displayed</li>
+ * <li>{@link android.telephony.SmsCbMessage#GEOGRAPHICAL_SCOPE_PLMN_WIDE}, meaning the
+ * message is for the PLMN (i.e. MCC/MNC)</li>
+ * <li>{@link android.telephony.SmsCbMessage#GEOGRAPHICAL_SCOPE_LOCATION_AREA_WIDE},
+ * meaning the message is for the location area (in GSM) or service area (in UMTS)</li>
+ * </ul>
+ *
+ * <p>A message meant for a particular scope is automatically dismissed when the device
+ * exits that scope.</p>
+ * <P>Type: INTEGER</P>
+ */
+ public static final String GEOGRAPHICAL_SCOPE = "geo_scope";
+
+ /**
+ * Message serial number.
+ * <p>
+ * A 16-bit integer which identifies a particular CBS (cell
+ * broadcast short message service) message. The core network is responsible for
+ * allocating this value, and the value may be managed cyclically (3GPP TS 23.041 section
+ * 9.2.1) once the serial message has been incremented a sufficient number of times.
+ * </p>
+ * <P>Type: INTEGER</P>
+ */
+ public static final String SERIAL_NUMBER = "serial_number";
+
+ /**
+ * PLMN (i.e. MCC/MNC) of broadcast sender. {@code SERIAL_NUMBER + PLMN + LAC + CID}
+ * uniquely identifies a broadcast for duplicate detection purposes.
+ * <P>Type: TEXT</P>
+ */
+ public static final String PLMN = "plmn";
+
+ /**
+ * Location area code (LAC).
+ * <p>Code representing location area (GSM) or service area (UMTS) of broadcast sender.
+ * Unused for CDMA. Only included if Geographical Scope of message is not PLMN wide (01).
+ * This value is sent by the network based on the cell tower.
+ * <P>Type: INTEGER</P>
+ */
+ public static final String LAC = "lac";
+
+ /**
+ * Cell ID of message sender (GSM/UMTS). Unused for CDMA. Only included when the
+ * Geographical Scope of message is cell wide (00 or 11).
+ * <P>Type: INTEGER</P>
+ */
+ public static final String CID = "cid";
+
+ /**
+ * Message code. <em>OBSOLETE: merged into SERIAL_NUMBER.</em>
+ * <P>Type: INTEGER</P>
+ * @hide
+ */
+ public static final String V1_MESSAGE_CODE = "message_code";
+
+ /**
+ * Message identifier. <em>OBSOLETE: renamed to SERVICE_CATEGORY.</em>
+ * <P>Type: INTEGER</P>
+ * @hide
+ */
+ public static final String V1_MESSAGE_IDENTIFIER = "message_id";
+
+ /**
+ * Service category which represents the general topic of the message.
+ * <p>
+ * For GSM/UMTS: message identifier (see 3GPP TS 23.041 section 9.4.1.2.2)
+ * For CDMA: a 16-bit CDMA service category (see 3GPP2 C.R1001-D section 9.3)
+ * </p>
+ * <P>Type: INTEGER</P>
+ */
+ public static final String SERVICE_CATEGORY = "service_category";
+
+ /**
+ * Message language code. (See 3GPP TS 23.041 section 9.4.1.2.3 for details).
+ * <P>Type: TEXT</P>
+ */
+ public static final String LANGUAGE_CODE = "language";
+
+ /**
+ * Message body.
+ * <P>Type: TEXT</P>
+ */
+ public static final String MESSAGE_BODY = "body";
+
+ /**
+ * Message delivery time.
+ * <p>This value is a system timestamp using {@link System#currentTimeMillis}</p>
+ * <P>Type: INTEGER (long)</P>
+ */
+ public static final String DELIVERY_TIME = "date";
+
+ /**
+ * Has the message been viewed?
+ * <P>Type: INTEGER (boolean)</P>
+ */
+ public static final String MESSAGE_READ = "read";
+
+ /**
+ * Message format ({@link android.telephony.SmsCbMessage#MESSAGE_FORMAT_3GPP} or
+ * {@link android.telephony.SmsCbMessage#MESSAGE_FORMAT_3GPP2}).
+ * <P>Type: INTEGER</P>
+ */
+ public static final String MESSAGE_FORMAT = "format";
+
+ /**
+ * Message priority.
+ * <p>This includes
+ * <ul>
+ * <li>{@link android.telephony.SmsCbMessage#MESSAGE_PRIORITY_NORMAL}</li>
+ * <li>{@link android.telephony.SmsCbMessage#MESSAGE_PRIORITY_INTERACTIVE}</li>
+ * <li>{@link android.telephony.SmsCbMessage#MESSAGE_PRIORITY_URGENT}</li>
+ * <li>{@link android.telephony.SmsCbMessage#MESSAGE_PRIORITY_EMERGENCY}</li>
+ * </p>
+ * </ul>
+ * <P>Type: INTEGER</P>
+ */
+ public static final String MESSAGE_PRIORITY = "priority";
+
+ /**
+ * ETWS (Earthquake and Tsunami Warning System) warning type (ETWS alerts only).
+ * <p>See {@link android.telephony.SmsCbEtwsInfo}</p>
+ * <P>Type: INTEGER</P>
+ */
+ public static final String ETWS_WARNING_TYPE = "etws_warning_type";
+
+ /**
+ * CMAS (Commercial Mobile Alert System) message class (CMAS alerts only).
+ * <p>See {@link android.telephony.SmsCbCmasInfo}</p>
+ * <P>Type: INTEGER</P>
+ */
+ public static final String CMAS_MESSAGE_CLASS = "cmas_message_class";
+
+ /**
+ * CMAS category (CMAS alerts only).
+ * <P>Type: INTEGER</P>
+ */
+ public static final String CMAS_CATEGORY = "cmas_category";
+
+ /**
+ * CMAS response type (CMAS alerts only).
+ * <P>Type: INTEGER</P>
+ */
+ public static final String CMAS_RESPONSE_TYPE = "cmas_response_type";
+
+ /**
+ * CMAS severity (CMAS alerts only).
+ * <P>Type: INTEGER</P>
+ */
+ public static final String CMAS_SEVERITY = "cmas_severity";
+
+ /**
+ * CMAS urgency (CMAS alerts only).
+ * <P>Type: INTEGER</P>
+ */
+ public static final String CMAS_URGENCY = "cmas_urgency";
+
+ /**
+ * CMAS certainty (CMAS alerts only).
+ * <P>Type: INTEGER</P>
+ */
+ public static final String CMAS_CERTAINTY = "cmas_certainty";
+
+ /** The default sort order for this table. */
+ public static final String DEFAULT_SORT_ORDER = DELIVERY_TIME + " DESC";
+
+ /**
+ * The timestamp in millisecond of when the device received the message.
+ * <P>Type: BIGINT</P>
+ */
+ public static final String RECEIVED_TIME = "received_time";
+
+ /**
+ * Indicates that whether the message has been broadcasted to the application.
+ * <P>Type: BOOLEAN</P>
+ */
+ public static final String MESSAGE_BROADCASTED = "message_broadcasted";
+
+ /**
+ * The Warning Area Coordinates Elements. This element is used for geo-fencing purpose.
+ *
+ * The geometry and its coordinates are separated vertical bar, the first item is the
+ * geometry type and the remaining items are the parameter of this geometry.
+ *
+ * Only circle and polygon are supported. The coordinates are represented in Horizontal
+ * coordinates format.
+ *
+ * Coordinate encoding:
+ * "latitude, longitude"
+ * where -90.00000 <= latitude <= 90.00000 and -180.00000 <= longitude <= 180.00000
+ *
+ * Polygon encoding:
+ * "polygon|lat1,lng1|lat2,lng2|...|latn,lngn"
+ * lat1,lng1 ... latn,lngn are the vertices coordinate of the polygon.
+ *
+ * Circle encoding:
+ * "circle|lat,lng|radius".
+ * lat,lng is the center of the circle. The unit of circle's radius is meter.
+ *
+ * Example:
+ * "circle|0,0|100" mean a circle which center located at (0,0) and its radius is 100 meter.
+ * "polygon|0,1.5|0,1|1,1|1,0" mean a polygon has vertices (0,1.5),(0,1),(1,1),(1,0).
+ *
+ * There could be more than one geometry store in this field, they are separated by a
+ * semicolon.
+ *
+ * Example:
+ * "circle|0,0|100;polygon|0,0|0,1.5|1,1|1,0;circle|100.123,100|200.123"
+ *
+ * <P>Type: TEXT</P>
+ */
+ public static final String GEOMETRIES = "geometries";
+
+ /**
+ * Geo-Fencing Maximum Wait Time in second. The range of the time is [0, 255]. A device
+ * shall allow to determine its position meeting operator policy. If the device is unable to
+ * determine its position meeting operator policy within the GeoFencing Maximum Wait Time,
+ * it shall present the alert to the user and discontinue further positioning determination
+ * for the alert.
+ *
+ * <P>Type: INTEGER</P>
+ */
+ public static final String MAXIMUM_WAIT_TIME = "maximum_wait_time";
+
+ /**
+ * Query columns for instantiating com.android.cellbroadcastreceiver.CellBroadcastMessage.
+ * @hide
+ */
+ @NonNull
+ public static final String[] QUERY_COLUMNS = {
+ _ID,
+ GEOGRAPHICAL_SCOPE,
+ PLMN,
+ LAC,
+ CID,
+ SERIAL_NUMBER,
+ SERVICE_CATEGORY,
+ LANGUAGE_CODE,
+ MESSAGE_BODY,
+ DELIVERY_TIME,
+ MESSAGE_READ,
+ MESSAGE_FORMAT,
+ MESSAGE_PRIORITY,
+ ETWS_WARNING_TYPE,
+ CMAS_MESSAGE_CLASS,
+ CMAS_CATEGORY,
+ CMAS_RESPONSE_TYPE,
+ CMAS_SEVERITY,
+ CMAS_URGENCY,
+ CMAS_CERTAINTY
+ };
+
+ /**
+ * Query columns for instantiating {@link android.telephony.SmsCbMessage} objects.
+ * @hide
+ */
+ public static final String[] QUERY_COLUMNS_FWK = {
+ _ID,
+ SLOT_INDEX,
+ SUB_ID,
+ GEOGRAPHICAL_SCOPE,
+ PLMN,
+ LAC,
+ CID,
+ SERIAL_NUMBER,
+ SERVICE_CATEGORY,
+ LANGUAGE_CODE,
+ MESSAGE_BODY,
+ MESSAGE_FORMAT,
+ MESSAGE_PRIORITY,
+ ETWS_WARNING_TYPE,
+ CMAS_MESSAGE_CLASS,
+ CMAS_CATEGORY,
+ CMAS_RESPONSE_TYPE,
+ CMAS_SEVERITY,
+ CMAS_URGENCY,
+ CMAS_CERTAINTY,
+ RECEIVED_TIME,
+ MESSAGE_BROADCASTED,
+ GEOMETRIES,
+ MAXIMUM_WAIT_TIME
+ };
+ }
+
+ /**
+ * Constants for interfacing with the ServiceStateProvider and the different fields of the
+ * {@link ServiceState} class accessible through the provider.
+ */
+ public static final class ServiceStateTable {
+
+ /**
+ * Not instantiable.
+ * @hide
+ */
+ private ServiceStateTable() {}
+
+ /**
+ * The authority string for the ServiceStateProvider
+ */
+ public static final String AUTHORITY = "service-state";
+
+ /**
+ * The {@code content://} style URL for the ServiceStateProvider
+ */
+ public static final Uri CONTENT_URI = Uri.parse("content://service-state/");
+
+ /**
+ * Generates a content {@link Uri} used to receive updates on a specific field in the
+ * ServiceState provider.
+ * <p>
+ * Use this {@link Uri} with a {@link ContentObserver} to be notified of changes to the
+ * {@link ServiceState} while your app is running.
+ * You can also use a {@link android.app.job.JobService} to
+ * ensure your app is notified of changes to the {@link Uri} even when it is not running.
+ * Note, however, that using a {@link android.app.job.JobService}
+ * does not guarantee timely delivery of
+ * updates to the {@link Uri}.
+ *
+ * @param subscriptionId the subscriptionId to receive updates on
+ * @param field the ServiceState field to receive updates on
+ * @return the Uri used to observe {@link ServiceState} changes
+ */
+ public static Uri getUriForSubscriptionIdAndField(int subscriptionId, String field) {
+ return CONTENT_URI.buildUpon().appendEncodedPath(String.valueOf(subscriptionId))
+ .appendEncodedPath(field).build();
+ }
+
+ /**
+ * Generates a content {@link Uri} used to receive updates on every field in the
+ * ServiceState provider.
+ * <p>
+ * Use this {@link Uri} with a {@link ContentObserver} to be notified of changes to the
+ * {@link ServiceState} while your app is running. You can also use a
+ * {@link android.app.job.JobService} to
+ * ensure your app is notified of changes to the {@link Uri} even when it is not running.
+ * Note, however, that using a {@link android.app.job.JobService}
+ * does not guarantee timely delivery of
+ * updates to the {@link Uri}.
+ *
+ * @param subscriptionId the subscriptionId to receive updates on
+ * @return the Uri used to observe {@link ServiceState} changes
+ */
+ public static Uri getUriForSubscriptionId(int subscriptionId) {
+ return CONTENT_URI.buildUpon().appendEncodedPath(String.valueOf(subscriptionId)).build();
+ }
+
+ /**
+ * Used to insert a ServiceState into the ServiceStateProvider as a ContentValues instance.
+ *
+ * @param state the ServiceState to convert into ContentValues
+ * @return the convertedContentValues instance
+ * @hide
+ */
+ public static ContentValues getContentValuesForServiceState(ServiceState state) {
+ ContentValues values = new ContentValues();
+ final Parcel p = Parcel.obtain();
+ state.writeToParcel(p, 0);
+ // Turn the parcel to byte array. Safe to do this because the content values were never
+ // written into a persistent storage. ServiceStateProvider keeps values in the memory.
+ values.put(SERVICE_STATE, p.marshall());
+ return values;
+ }
+
+ /**
+ * The current service state.
+ *
+ * This is the entire {@link ServiceState} object in byte array.
+ *
+ * @hide
+ */
+ public static final String SERVICE_STATE = "service_state";
+
+ /**
+ * An integer value indicating the current voice service state.
+ * <p>
+ * Valid values: {@link ServiceState#STATE_IN_SERVICE},
+ * {@link ServiceState#STATE_OUT_OF_SERVICE}, {@link ServiceState#STATE_EMERGENCY_ONLY},
+ * {@link ServiceState#STATE_POWER_OFF}.
+ * <p>
+ * This is the same as {@link ServiceState#getState()}.
+ */
+ public static final String VOICE_REG_STATE = "voice_reg_state";
+
+ /**
+ * An integer value indicating the current data service state.
+ * <p>
+ * Valid values: {@link ServiceState#STATE_IN_SERVICE},
+ * {@link ServiceState#STATE_OUT_OF_SERVICE}, {@link ServiceState#STATE_EMERGENCY_ONLY},
+ * {@link ServiceState#STATE_POWER_OFF}.
+ * <p>
+ * This is the same as {@link ServiceState#getDataRegState()}.
+ * @hide
+ */
+ public static final String DATA_REG_STATE = "data_reg_state";
+
+ /**
+ * An integer value indicating the current voice roaming type.
+ * <p>
+ * This is the same as {@link ServiceState#getVoiceRoamingType()}.
+ * @hide
+ */
+ public static final String VOICE_ROAMING_TYPE = "voice_roaming_type";
+
+ /**
+ * An integer value indicating the current data roaming type.
+ * <p>
+ * This is the same as {@link ServiceState#getDataRoamingType()}.
+ * @hide
+ */
+ public static final String DATA_ROAMING_TYPE = "data_roaming_type";
+
+ /**
+ * The current registered voice network operator name in long alphanumeric format.
+ * <p>
+ * This is the same as {@link ServiceState#getVoiceOperatorAlphaLong()}.
+ * @hide
+ */
+ public static final String VOICE_OPERATOR_ALPHA_LONG = "voice_operator_alpha_long";
+
+ /**
+ * The current registered operator name in short alphanumeric format.
+ * <p>
+ * In GSM/UMTS, short format can be up to 8 characters long. The current registered voice
+ * network operator name in long alphanumeric format.
+ * <p>
+ * This is the same as {@link ServiceState#getVoiceOperatorAlphaShort()}.
+ * @hide
+ */
+ public static final String VOICE_OPERATOR_ALPHA_SHORT = "voice_operator_alpha_short";
+
+
+ /**
+ * The current registered operator numeric id.
+ * <p>
+ * In GSM/UMTS, numeric format is 3 digit country code plus 2 or 3 digit
+ * network code.
+ * <p>
+ * This is the same as {@link ServiceState#getOperatorNumeric()}.
+ */
+ public static final String VOICE_OPERATOR_NUMERIC = "voice_operator_numeric";
+
+ /**
+ * The current registered data network operator name in long alphanumeric format.
+ * <p>
+ * This is the same as {@link ServiceState#getDataOperatorAlphaLong()}.
+ * @hide
+ */
+ public static final String DATA_OPERATOR_ALPHA_LONG = "data_operator_alpha_long";
+
+ /**
+ * The current registered data network operator name in short alphanumeric format.
+ * <p>
+ * This is the same as {@link ServiceState#getDataOperatorAlphaShort()}.
+ * @hide
+ */
+ public static final String DATA_OPERATOR_ALPHA_SHORT = "data_operator_alpha_short";
+
+ /**
+ * The current registered data network operator numeric id.
+ * <p>
+ * This is the same as {@link ServiceState#getDataOperatorNumeric()}.
+ * @hide
+ */
+ public static final String DATA_OPERATOR_NUMERIC = "data_operator_numeric";
+
+ /**
+ * The current network selection mode.
+ * <p>
+ * This is the same as {@link ServiceState#getIsManualSelection()}.
+ */
+ public static final String IS_MANUAL_NETWORK_SELECTION = "is_manual_network_selection";
+
+ /**
+ * This is the same as {@link ServiceState#getRilVoiceRadioTechnology()}.
+ * @hide
+ */
+ public static final String RIL_VOICE_RADIO_TECHNOLOGY = "ril_voice_radio_technology";
+
+ /**
+ * This is the same as {@link ServiceState#getRilDataRadioTechnology()}.
+ * @hide
+ */
+ public static final String RIL_DATA_RADIO_TECHNOLOGY = "ril_data_radio_technology";
+
+ /**
+ * This is the same as {@link ServiceState#getCssIndicator()}.
+ * @hide
+ */
+ public static final String CSS_INDICATOR = "css_indicator";
+
+ /**
+ * This is the same as {@link ServiceState#getCdmaNetworkId()}.
+ * @hide
+ */
+ public static final String NETWORK_ID = "network_id";
+
+ /**
+ * This is the same as {@link ServiceState#getCdmaSystemId()}.
+ * @hide
+ */
+ public static final String SYSTEM_ID = "system_id";
+
+ /**
+ * This is the same as {@link ServiceState#getCdmaRoamingIndicator()}.
+ * @hide
+ */
+ public static final String CDMA_ROAMING_INDICATOR = "cdma_roaming_indicator";
+
+ /**
+ * This is the same as {@link ServiceState#getCdmaDefaultRoamingIndicator()}.
+ * @hide
+ */
+ public static final String CDMA_DEFAULT_ROAMING_INDICATOR =
+ "cdma_default_roaming_indicator";
+
+ /**
+ * This is the same as {@link ServiceState#getCdmaEriIconIndex()}.
+ * @hide
+ */
+ public static final String CDMA_ERI_ICON_INDEX = "cdma_eri_icon_index";
+
+ /**
+ * This is the same as {@link ServiceState#getCdmaEriIconMode()}.
+ * @hide
+ */
+ public static final String CDMA_ERI_ICON_MODE = "cdma_eri_icon_mode";
+
+ /**
+ * This is the same as {@link ServiceState#isEmergencyOnly()}.
+ * @hide
+ */
+ public static final String IS_EMERGENCY_ONLY = "is_emergency_only";
+
+ /**
+ * This is the same as {@link ServiceState#getDataRoamingFromRegistration()}.
+ * @hide
+ */
+ public static final String IS_DATA_ROAMING_FROM_REGISTRATION =
+ "is_data_roaming_from_registration";
+
+ /**
+ * This is the same as {@link ServiceState#isUsingCarrierAggregation()}.
+ * @hide
+ */
+ public static final String IS_USING_CARRIER_AGGREGATION = "is_using_carrier_aggregation";
+
+ /**
+ * The current registered raw data network operator name in long alphanumeric format.
+ * <p>
+ * This is the same as {@link ServiceState#getOperatorAlphaLongRaw()}.
+ * @hide
+ */
+ public static final String OPERATOR_ALPHA_LONG_RAW = "operator_alpha_long_raw";
+
+ /**
+ * The current registered raw data network operator name in short alphanumeric format.
+ * <p>
+ * This is the same as {@link ServiceState#getOperatorAlphaShortRaw()}.
+ * @hide
+ */
+ public static final String OPERATOR_ALPHA_SHORT_RAW = "operator_alpha_short_raw";
+ }
+
+ /**
+ * Contains carrier identification information for the current subscriptions.
+ */
+ public static final class CarrierId implements BaseColumns {
+ /**
+ * Not instantiable.
+ * @hide
+ */
+ private CarrierId() {}
+
+ /**
+ * The {@code content://} style URI for this provider.
+ */
+ public static final Uri CONTENT_URI = Uri.parse("content://carrier_id");
+
+ /**
+ * The authority string for the CarrierId Provider
+ * @hide
+ */
+ public static final String AUTHORITY = "carrier_id";
+
+
+ /**
+ * Generates a content {@link Uri} used to receive updates on carrier identity change
+ * on the given subscriptionId
+ * <p>
+ * Use this {@link Uri} with a {@link ContentObserver} to be notified of changes to the
+ * carrier identity {@link TelephonyManager#getSimCarrierId()}
+ * while your app is running. You can also use a {@link android.app.job.JobService}
+ * to ensure your app
+ * is notified of changes to the {@link Uri} even when it is not running.
+ * Note, however, that using a {@link android.app.job.JobService} does not guarantee
+ * timely delivery of updates to the {@link Uri}.
+ *
+ * @param subscriptionId the subscriptionId to receive updates on
+ * @return the Uri used to observe carrier identity changes
+ */
+ public static Uri getUriForSubscriptionId(int subscriptionId) {
+ return CONTENT_URI.buildUpon().appendEncodedPath(
+ String.valueOf(subscriptionId)).build();
+ }
+
+ /**
+ * Generates a content {@link Uri} used to receive updates on specific carrier identity
+ * change on the given subscriptionId returned by
+ * {@link TelephonyManager#getSimSpecificCarrierId()}.
+ * @see TelephonyManager#ACTION_SUBSCRIPTION_SPECIFIC_CARRIER_IDENTITY_CHANGED
+ * <p>
+ * Use this {@link Uri} with a {@link ContentObserver} to be notified of changes to the
+ * specific carrier identity {@link TelephonyManager#getSimSpecificCarrierId()}
+ * while your app is running. You can also use a {@link android.app.job.JobService}
+ * to ensure your app
+ * is notified of changes to the {@link Uri} even when it is not running.
+ * Note, however, that using a {@link android.app.job.JobService} does not guarantee timely
+ * delivery of updates to the {@link Uri}.
+ *
+ * @param subscriptionId the subscriptionId to receive updates on
+ * @return the Uri used to observe specific carrier identity changes
+ */
+ @NonNull
+ public static Uri getSpecificCarrierIdUriForSubscriptionId(int subscriptionId) {
+ return Uri.withAppendedPath(Uri.withAppendedPath(CONTENT_URI, "specific"),
+ String.valueOf(subscriptionId));
+ }
+
+ /**
+ * A user facing carrier name.
+ * @see TelephonyManager#getSimCarrierIdName()
+ * <P>Type: TEXT </P>
+ */
+ public static final String CARRIER_NAME = "carrier_name";
+
+ /**
+ * A unique carrier id
+ * @see TelephonyManager#getSimCarrierId()
+ * <P>Type: INTEGER </P>
+ */
+ public static final String CARRIER_ID = "carrier_id";
+
+ /**
+ * A fine-grained carrier id.
+ * The specific carrier ID would be used for configuration purposes, but apps wishing to
+ * know about the carrier itself should use the regular carrier ID returned by
+ * {@link TelephonyManager#getSimCarrierId()}.
+ *
+ * @see TelephonyManager#getSimSpecificCarrierId()
+ * This is not a database column, only used to notify content observers for
+ * {@link #getSpecificCarrierIdUriForSubscriptionId(int)}
+ */
+ public static final String SPECIFIC_CARRIER_ID = "specific_carrier_id";
+
+ /**
+ * A user facing carrier name for specific carrier id {@link #SPECIFIC_CARRIER_ID}.
+ * @see TelephonyManager#getSimSpecificCarrierIdName()
+ * This is not a database column, only used to notify content observers for
+ * {@link #getSpecificCarrierIdUriForSubscriptionId(int)}
+ */
+ public static final String SPECIFIC_CARRIER_ID_NAME = "specific_carrier_id_name";
+
+ /**
+ * A unique parent carrier id. The parent-child
+ * relationship can be used to further differentiate a single carrier by different networks,
+ * by prepaid v.s. postpaid. It's an optional field.
+ * A carrier id with a valid parent_carrier_id is considered fine-grained specific carrier
+ * ID, will not be returned as {@link #CARRIER_ID} but {@link #SPECIFIC_CARRIER_ID}.
+ * <P>Type: INTEGER </P>
+ * @hide
+ */
+ public static final String PARENT_CARRIER_ID = "parent_carrier_id";
+
+ /**
+ * Contains mappings between matching rules with carrier id for all carriers.
+ * @hide
+ */
+ @SystemApi
+ public static final class All implements BaseColumns {
+
+ /**
+ * Not instantiable.
+ * @hide
+ */
+ private All() {
+ }
+
+ /**
+ * Numeric operator ID (as String). {@code MCC + MNC}
+ * <P>Type: TEXT </P>
+ */
+ public static final String MCCMNC = "mccmnc";
+
+ /**
+ * Group id level 1 (as String).
+ * <P>Type: TEXT </P>
+ */
+ public static final String GID1 = "gid1";
+
+ /**
+ * Group id level 2 (as String).
+ * <P>Type: TEXT </P>
+ */
+ public static final String GID2 = "gid2";
+
+ /**
+ * Public Land Mobile Network name.
+ * <P>Type: TEXT </P>
+ */
+ public static final String PLMN = "plmn";
+
+ /**
+ * Prefix xpattern of IMSI (International Mobile Subscriber Identity).
+ * <P>Type: TEXT </P>
+ */
+ public static final String IMSI_PREFIX_XPATTERN = "imsi_prefix_xpattern";
+
+ /**
+ * Service Provider Name.
+ * <P>Type: TEXT </P>
+ */
+ public static final String SPN = "spn";
+
+ /**
+ * Prefer APN name.
+ * <P>Type: TEXT </P>
+ */
+ public static final String APN = "apn";
+
+ /**
+ * Prefix of Integrated Circuit Card Identifier.
+ * <P>Type: TEXT </P>
+ */
+ public static final String ICCID_PREFIX = "iccid_prefix";
+
+ /**
+ * Certificate for carrier privilege access rules.
+ * <P>Type: TEXT in hex string </P>
+ */
+ public static final String PRIVILEGE_ACCESS_RULE = "privilege_access_rule";
+
+ /**
+ * The {@code content://} URI for this table.
+ */
+ @NonNull
+ public static final Uri CONTENT_URI = Uri.parse("content://carrier_id/all");
+ }
+ }
+}
diff --git a/core/java/android/service/autofill/SaveInfo.java b/core/java/android/service/autofill/SaveInfo.java
index 48ba4295f3c8..4df43628b5d3 100644
--- a/core/java/android/service/autofill/SaveInfo.java
+++ b/core/java/android/service/autofill/SaveInfo.java
@@ -216,10 +216,21 @@ public final class SaveInfo implements Parcelable {
*/
public static final int NEGATIVE_BUTTON_STYLE_REJECT = 1;
+ /**
+ * Style for the negative button of the save UI to never do the
+ * save operation. This means that the user does not need to save
+ * any data on this activity or application. Once the user tapping
+ * the negative button, the service should never trigger the save
+ * UI again. In addition to this, must consider providing restore
+ * options for the user.
+ */
+ public static final int NEGATIVE_BUTTON_STYLE_NEVER = 2;
+
/** @hide */
@IntDef(prefix = { "NEGATIVE_BUTTON_STYLE_" }, value = {
NEGATIVE_BUTTON_STYLE_CANCEL,
- NEGATIVE_BUTTON_STYLE_REJECT
+ NEGATIVE_BUTTON_STYLE_REJECT,
+ NEGATIVE_BUTTON_STYLE_NEVER
})
@Retention(RetentionPolicy.SOURCE)
@interface NegativeButtonStyle{}
@@ -571,6 +582,7 @@ public final class SaveInfo implements Parcelable {
*
* @see #NEGATIVE_BUTTON_STYLE_CANCEL
* @see #NEGATIVE_BUTTON_STYLE_REJECT
+ * @see #NEGATIVE_BUTTON_STYLE_NEVER
*
* @throws IllegalArgumentException If the style is invalid
*/
@@ -578,11 +590,7 @@ public final class SaveInfo implements Parcelable {
@Nullable IntentSender listener) {
throwIfDestroyed();
Preconditions.checkArgumentInRange(style, NEGATIVE_BUTTON_STYLE_CANCEL,
- NEGATIVE_BUTTON_STYLE_REJECT, "style");
- if (style != NEGATIVE_BUTTON_STYLE_CANCEL
- && style != NEGATIVE_BUTTON_STYLE_REJECT) {
- throw new IllegalArgumentException("Invalid style: " + style);
- }
+ NEGATIVE_BUTTON_STYLE_NEVER, "style");
mNegativeButtonStyle = style;
mNegativeActionListener = listener;
return this;
diff --git a/core/java/android/service/carrier/CarrierIdentifier.aidl b/core/java/android/service/carrier/CarrierIdentifier.aidl
deleted file mode 100644
index 48b13983050d..000000000000
--- a/core/java/android/service/carrier/CarrierIdentifier.aidl
+++ /dev/null
@@ -1,19 +0,0 @@
-/**
- * Copyright (c) 2015, 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.carrier;
-
-parcelable CarrierIdentifier;
diff --git a/core/java/android/service/carrier/CarrierIdentifier.java b/core/java/android/service/carrier/CarrierIdentifier.java
deleted file mode 100644
index af5bf7475f95..000000000000
--- a/core/java/android/service/carrier/CarrierIdentifier.java
+++ /dev/null
@@ -1,255 +0,0 @@
-/**
- * Copyright (c) 2015, 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.carrier;
-
-import android.annotation.NonNull;
-import android.annotation.Nullable;
-import android.os.Parcel;
-import android.os.Parcelable;
-import android.telephony.Rlog;
-import android.telephony.TelephonyManager;
-
-import com.android.internal.telephony.uicc.IccUtils;
-
-import java.util.Objects;
-
-/**
- * Used to pass info to CarrierConfigService implementations so they can decide what values to
- * return. Instead of passing mcc, mnc, gid1, gid2, spn, imsi to locate carrier information,
- * CarrierIdentifier also include carrier id {@link TelephonyManager#getSimCarrierId()},
- * a platform-wide unique identifier for each carrier. CarrierConfigService can directly use
- * carrier id as the key to look up the carrier info.
- */
-public class CarrierIdentifier implements Parcelable {
-
- /** Used to create a {@link CarrierIdentifier} from a {@link Parcel}. */
- public static final @android.annotation.NonNull Creator<CarrierIdentifier> CREATOR = new Creator<CarrierIdentifier>() {
- @Override
- public CarrierIdentifier createFromParcel(Parcel parcel) {
- return new CarrierIdentifier(parcel);
- }
-
- @Override
- public CarrierIdentifier[] newArray(int i) {
- return new CarrierIdentifier[i];
- }
- };
-
- private String mMcc;
- private String mMnc;
- private @Nullable String mSpn;
- private @Nullable String mImsi;
- private @Nullable String mGid1;
- private @Nullable String mGid2;
- private int mCarrierId = TelephonyManager.UNKNOWN_CARRIER_ID;
- private int mSpecificCarrierId = TelephonyManager.UNKNOWN_CARRIER_ID;
-
- public CarrierIdentifier(String mcc, String mnc, @Nullable String spn, @Nullable String imsi,
- @Nullable String gid1, @Nullable String gid2) {
- this(mcc, mnc, spn, imsi, gid1, gid2, TelephonyManager.UNKNOWN_CARRIER_ID,
- TelephonyManager.UNKNOWN_CARRIER_ID);
- }
-
- /**
- * @param mcc mobile country code
- * @param mnc mobile network code
- * @param spn service provider name
- * @param imsi International Mobile Subscriber Identity {@link TelephonyManager#getSubscriberId()}
- * @param gid1 group id level 1 {@link TelephonyManager#getGroupIdLevel1()}
- * @param gid2 group id level 2
- * @param carrierid carrier unique identifier {@link TelephonyManager#getSimCarrierId()}, used
- * to uniquely identify the carrier and look up the carrier configurations.
- * @param specificCarrierId specific carrier identifier
- * {@link TelephonyManager#getSimSpecificCarrierId()}
- */
- public CarrierIdentifier(@NonNull String mcc, @NonNull String mnc, @Nullable String spn,
- @Nullable String imsi, @Nullable String gid1, @Nullable String gid2,
- int carrierid, int specificCarrierId) {
- mMcc = mcc;
- mMnc = mnc;
- mSpn = spn;
- mImsi = imsi;
- mGid1 = gid1;
- mGid2 = gid2;
- mCarrierId = carrierid;
- mSpecificCarrierId = specificCarrierId;
- }
-
- /**
- * Creates a carrier identifier instance.
- *
- * @param mccMnc A 3-byte array as defined by 3GPP TS 24.008.
- * @param gid1 The group identifier level 1.
- * @param gid2 The group identifier level 2.
- * @throws IllegalArgumentException If the length of {@code mccMnc} is not 3.
- */
- public CarrierIdentifier(byte[] mccMnc, @Nullable String gid1, @Nullable String gid2) {
- if (mccMnc.length != 3) {
- throw new IllegalArgumentException(
- "MCC & MNC must be set by a 3-byte array: byte[" + mccMnc.length + "]");
- }
- String hex = IccUtils.bytesToHexString(mccMnc);
- mMcc = new String(new char[] {hex.charAt(1), hex.charAt(0), hex.charAt(3)});
- if (hex.charAt(2) == 'F') {
- mMnc = new String(new char[] {hex.charAt(5), hex.charAt(4)});
- } else {
- mMnc = new String(new char[] {hex.charAt(5), hex.charAt(4), hex.charAt(2)});
- }
- mGid1 = gid1;
- mGid2 = gid2;
- mSpn = null;
- mImsi = null;
- }
-
- /** @hide */
- public CarrierIdentifier(Parcel parcel) {
- readFromParcel(parcel);
- }
-
- /** Get the mobile country code. */
- public String getMcc() {
- return mMcc;
- }
-
- /** Get the mobile network code. */
- public String getMnc() {
- return mMnc;
- }
-
- /** Get the service provider name. */
- @Nullable
- public String getSpn() {
- return mSpn;
- }
-
- /** Get the international mobile subscriber identity. */
- @Nullable
- public String getImsi() {
- return mImsi;
- }
-
- /** Get the group identifier level 1. */
- @Nullable
- public String getGid1() {
- return mGid1;
- }
-
- /** Get the group identifier level 2. */
- @Nullable
- public String getGid2() {
- return mGid2;
- }
-
- /**
- * Returns the carrier id.
- * @see TelephonyManager#getSimCarrierId()
- */
- public int getCarrierId() {
- return mCarrierId;
- }
-
- /**
- * A specific carrier ID returns the fine-grained carrier ID of the current subscription.
- * It can represent the fact that a carrier may be in effect an aggregation of other carriers
- * (ie in an MVNO type scenario) where each of these specific carriers which are used to make
- * up the actual carrier service may have different carrier configurations.
- * A specific carrier ID could also be used, for example, in a scenario where a carrier requires
- * different carrier configuration for different service offering such as a prepaid plan.
- *
- * @see TelephonyManager#getSimSpecificCarrierId()
- */
- public int getSpecificCarrierId() {
- return mSpecificCarrierId;
- }
-
- @Override
- public boolean equals(Object obj) {
- if (this == obj) {
- return true;
- }
- if (obj == null || getClass() != obj.getClass()) {
- return false;
- }
-
- CarrierIdentifier that = (CarrierIdentifier) obj;
- return Objects.equals(mMcc, that.mMcc)
- && Objects.equals(mMnc, that.mMnc)
- && Objects.equals(mSpn, that.mSpn)
- && Objects.equals(mImsi, that.mImsi)
- && Objects.equals(mGid1, that.mGid1)
- && Objects.equals(mGid2, that.mGid2)
- && Objects.equals(mCarrierId, that.mCarrierId)
- && Objects.equals(mSpecificCarrierId, that.mSpecificCarrierId);
- }
-
- @Override
- public int hashCode(){
- return Objects.hash(mMcc, mMnc, mSpn, mImsi, mGid1, mGid2, mCarrierId, mSpecificCarrierId);
- }
-
- @Override
- public int describeContents() {
- return 0;
- }
-
- @Override
- public void writeToParcel(Parcel out, int flags) {
- out.writeString(mMcc);
- out.writeString(mMnc);
- out.writeString(mSpn);
- out.writeString(mImsi);
- out.writeString(mGid1);
- out.writeString(mGid2);
- out.writeInt(mCarrierId);
- out.writeInt(mSpecificCarrierId);
- }
-
- @Override
- public String toString() {
- return "CarrierIdentifier{"
- + "mcc=" + mMcc
- + ",mnc=" + mMnc
- + ",spn=" + mSpn
- + ",imsi=" + Rlog.pii(false, mImsi)
- + ",gid1=" + mGid1
- + ",gid2=" + mGid2
- + ",carrierid=" + mCarrierId
- + ",specificCarrierId=" + mSpecificCarrierId
- + "}";
- }
-
- /** @hide */
- public void readFromParcel(Parcel in) {
- mMcc = in.readString();
- mMnc = in.readString();
- mSpn = in.readString();
- mImsi = in.readString();
- mGid1 = in.readString();
- mGid2 = in.readString();
- mCarrierId = in.readInt();
- mSpecificCarrierId = in.readInt();
- }
-
- /** @hide */
- public interface MatchType {
- int ALL = 0;
- int SPN = 1;
- int IMSI_PREFIX = 2;
- int GID1 = 3;
- int GID2 = 4;
- }
-}
diff --git a/core/java/android/service/carrier/CarrierService.java b/core/java/android/service/carrier/CarrierService.java
deleted file mode 100644
index eefc1b70bac9..000000000000
--- a/core/java/android/service/carrier/CarrierService.java
+++ /dev/null
@@ -1,160 +0,0 @@
-/*
- * Copyright (C) 2015 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.carrier;
-
-import android.annotation.CallSuper;
-import android.app.Service;
-import android.content.Context;
-import android.content.Intent;
-import android.os.Bundle;
-import android.os.IBinder;
-import android.os.PersistableBundle;
-import android.os.ResultReceiver;
-import android.telephony.TelephonyRegistryManager;
-import android.util.Log;
-
-/**
- * A service that exposes carrier-specific functionality to the system.
- * <p>
- * To extend this class, you must declare the service in your manifest file to require the
- * {@link android.Manifest.permission#BIND_CARRIER_SERVICES} permission and include an intent
- * filter with the {@link #CARRIER_SERVICE_INTERFACE}. If the service should have a long-lived
- * binding, set <code>android.service.carrier.LONG_LIVED_BINDING</code> to <code>true</code> in the
- * service's metadata. For example:
- * </p>
- *
- * <pre>{@code
- * <service android:name=".MyCarrierService"
- * android:label="@string/service_name"
- * android:permission="android.permission.BIND_CARRIER_SERVICES">
- * <intent-filter>
- * <action android:name="android.service.carrier.CarrierService" />
- * </intent-filter>
- * <meta-data android:name="android.service.carrier.LONG_LIVED_BINDING"
- * android:value="true" />
- * </service>
- * }</pre>
- */
-public abstract class CarrierService extends Service {
-
- private static final String LOG_TAG = "CarrierService";
-
- public static final String CARRIER_SERVICE_INTERFACE = "android.service.carrier.CarrierService";
-
- private final ICarrierService.Stub mStubWrapper;
-
- public CarrierService() {
- mStubWrapper = new ICarrierServiceWrapper();
- }
-
- /**
- * Override this method to set carrier configuration.
- * <p>
- * This method will be called by telephony services to get carrier-specific configuration
- * values. The returned config will be saved by the system until,
- * <ol>
- * <li>The carrier app package is updated, or</li>
- * <li>The carrier app requests a reload with
- * {@link android.telephony.CarrierConfigManager#notifyConfigChangedForSubId
- * notifyConfigChangedForSubId}.</li>
- * </ol>
- * This method can be called after a SIM card loads, which may be before or after boot.
- * </p>
- * <p>
- * This method should not block for a long time. If expensive operations (e.g. network access)
- * are required, this method can schedule the work and return null. Then, use
- * {@link android.telephony.CarrierConfigManager#notifyConfigChangedForSubId
- * notifyConfigChangedForSubId} to trigger a reload when the config is ready.
- * </p>
- * <p>
- * Implementations should use the keys defined in {@link android.telephony.CarrierConfigManager
- * CarrierConfigManager}. Any configuration values not set in the returned {@link
- * PersistableBundle} may be overridden by the system's default configuration service.
- * </p>
- *
- * @param id contains details about the current carrier that can be used do decide what
- * configuration values to return. Instead of using details like MCCMNC to decide
- * current carrier, it also contains subscription carrier id
- * {@link android.telephony.TelephonyManager#getSimCarrierId()}, a platform-wide
- * unique identifier for each carrier, CarrierConfigService can directly use carrier
- * id as the key to look up the carrier info.
- * @return a {@link PersistableBundle} object containing the configuration or null if default
- * values should be used.
- */
- public abstract PersistableBundle onLoadConfig(CarrierIdentifier id);
-
- /**
- * Informs the system of an intentional upcoming carrier network change by
- * a carrier app. This call is optional and is only used to allow the
- * system to provide alternative UI while telephony is performing an action
- * that may result in intentional, temporary network lack of connectivity.
- * <p>
- * Based on the active parameter passed in, this method will either show or
- * hide the alternative UI. There is no timeout associated with showing
- * this UX, so a carrier app must be sure to call with active set to false
- * sometime after calling with it set to true.
- * <p>
- * Requires Permission: calling app has carrier privileges.
- *
- * @param active Whether the carrier network change is or shortly will be
- * active. Set this value to true to begin showing
- * alternative UI and false to stop.
- * @see android.telephony.TelephonyManager#hasCarrierPrivileges
- */
- public final void notifyCarrierNetworkChange(boolean active) {
- TelephonyRegistryManager telephonyRegistryMgr =
- (TelephonyRegistryManager) this.getSystemService(
- Context.TELEPHONY_REGISTRY_SERVICE);
- if (telephonyRegistryMgr != null) {
- telephonyRegistryMgr.notifyCarrierNetworkChange(active);
- }
- }
-
- /**
- * If overriding this method, call through to the super method for any unknown actions.
- * {@inheritDoc}
- */
- @Override
- @CallSuper
- public IBinder onBind(Intent intent) {
- return mStubWrapper;
- }
-
- /**
- * A wrapper around ICarrierService that forwards calls to implementations of
- * {@link CarrierService}.
- * @hide
- */
- public class ICarrierServiceWrapper extends ICarrierService.Stub {
- /** @hide */
- public static final int RESULT_OK = 0;
- /** @hide */
- public static final int RESULT_ERROR = 1;
- /** @hide */
- public static final String KEY_CONFIG_BUNDLE = "config_bundle";
-
- @Override
- public void getCarrierConfig(CarrierIdentifier id, ResultReceiver result) {
- try {
- Bundle data = new Bundle();
- data.putParcelable(KEY_CONFIG_BUNDLE, CarrierService.this.onLoadConfig(id));
- result.send(RESULT_OK, data);
- } catch (Exception e) {
- Log.e(LOG_TAG, "Error in onLoadConfig: " + e.getMessage(), e);
- result.send(RESULT_ERROR, null);
- }
- }
- }
-}
diff --git a/core/java/android/service/carrier/ICarrierService.aidl b/core/java/android/service/carrier/ICarrierService.aidl
deleted file mode 100644
index ac6f9614d8f5..000000000000
--- a/core/java/android/service/carrier/ICarrierService.aidl
+++ /dev/null
@@ -1,33 +0,0 @@
-/**
- * Copyright (c) 2015, 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.carrier;
-
-import android.os.PersistableBundle;
-import android.os.ResultReceiver;
-import android.service.carrier.CarrierIdentifier;
-
-/**
- * Service used to expose carrier-specific functionality to the system.
- *
- * @see android.service.carrier.CarrierService
- * @hide
- */
-interface ICarrierService {
-
- /** @see android.service.carrier.CarrierService#onLoadConfig */
- oneway void getCarrierConfig(in CarrierIdentifier id, in ResultReceiver result);
-}
diff --git a/core/java/android/service/euicc/DownloadSubscriptionResult.aidl b/core/java/android/service/euicc/DownloadSubscriptionResult.aidl
deleted file mode 100644
index b625fd6d3cb4..000000000000
--- a/core/java/android/service/euicc/DownloadSubscriptionResult.aidl
+++ /dev/null
@@ -1,19 +0,0 @@
-/*
- * 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.service.euicc;
-
-parcelable DownloadSubscriptionResult;
diff --git a/core/java/android/service/euicc/DownloadSubscriptionResult.java b/core/java/android/service/euicc/DownloadSubscriptionResult.java
deleted file mode 100644
index 3b1a2c9def4f..000000000000
--- a/core/java/android/service/euicc/DownloadSubscriptionResult.java
+++ /dev/null
@@ -1,99 +0,0 @@
-/*
- * 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.service.euicc;
-
-import android.annotation.SystemApi;
-import android.os.Parcel;
-import android.os.Parcelable;
-import android.service.euicc.EuiccService.ResolvableError;
-import android.service.euicc.EuiccService.Result;
-
-/**
- * Result of a {@link EuiccService#onDownloadSubscription} operation.
- * @hide
- */
-@SystemApi
-public final class DownloadSubscriptionResult implements Parcelable {
-
- public static final @android.annotation.NonNull Creator<DownloadSubscriptionResult> CREATOR =
- new Creator<DownloadSubscriptionResult>() {
- @Override
- public DownloadSubscriptionResult createFromParcel(Parcel in) {
- return new DownloadSubscriptionResult(in);
- }
-
- @Override
- public DownloadSubscriptionResult[] newArray(int size) {
- return new DownloadSubscriptionResult[size];
- }
- };
-
- private final @Result int mResult;
- private final @ResolvableError int mResolvableErrors;
- private final int mCardId;
-
- public DownloadSubscriptionResult(@Result int result, @ResolvableError int resolvableErrors,
- int cardId) {
- this.mResult = result;
- this.mResolvableErrors = resolvableErrors;
- this.mCardId = cardId;
- }
-
- /** Gets the result of the operation. */
- public @Result int getResult() {
- return mResult;
- }
-
- /**
- * Gets the bit map of resolvable errors.
- *
- * <p>The value is passed from EuiccService. The values can be
- *
- * <ul>
- * <li>{@link EuiccService#RESOLVABLE_ERROR_CONFIRMATION_CODE}
- * <li>{@link EuiccService#RESOLVABLE_ERROR_POLICY_RULES}
- * </ul>
- */
- public @ResolvableError int getResolvableErrors() {
- return mResolvableErrors;
- }
-
- /**
- * Gets the card Id. This is used when resolving resolvable errors. The value is passed from
- * EuiccService.
- */
- public int getCardId() {
- return mCardId;
- }
-
- @Override
- public void writeToParcel(Parcel dest, int flags) {
- dest.writeInt(mResult);
- dest.writeInt(mResolvableErrors);
- dest.writeInt(mCardId);
- }
-
- @Override
- public int describeContents() {
- return 0;
- }
-
- private DownloadSubscriptionResult(Parcel in) {
- this.mResult = in.readInt();
- this.mResolvableErrors = in.readInt();
- this.mCardId = in.readInt();
- }
-}
diff --git a/core/java/android/service/euicc/EuiccProfileInfo.java b/core/java/android/service/euicc/EuiccProfileInfo.java
deleted file mode 100644
index 6c357ccdd03d..000000000000
--- a/core/java/android/service/euicc/EuiccProfileInfo.java
+++ /dev/null
@@ -1,455 +0,0 @@
-/*
- * Copyright (C) 2017 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.euicc;
-
-import android.annotation.IntDef;
-import android.annotation.NonNull;
-import android.annotation.Nullable;
-import android.annotation.SystemApi;
-import android.annotation.UnsupportedAppUsage;
-import android.os.Parcel;
-import android.os.Parcelable;
-import android.service.carrier.CarrierIdentifier;
-import android.telephony.UiccAccessRule;
-import android.text.TextUtils;
-
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-import java.util.Arrays;
-import java.util.List;
-import java.util.Objects;
-
-/**
- * Information about an embedded profile (subscription) on an eUICC.
- *
- * @hide
- */
-@SystemApi
-public final class EuiccProfileInfo implements Parcelable {
-
- /** Profile policy rules (bit mask) */
- @Retention(RetentionPolicy.SOURCE)
- @IntDef(flag = true, prefix = { "POLICY_RULE_" }, value = {
- POLICY_RULE_DO_NOT_DISABLE,
- POLICY_RULE_DO_NOT_DELETE,
- POLICY_RULE_DELETE_AFTER_DISABLING
- })
- /** @hide */
- public @interface PolicyRule {}
- /** Once this profile is enabled, it cannot be disabled. */
- public static final int POLICY_RULE_DO_NOT_DISABLE = 1;
- /** This profile cannot be deleted. */
- public static final int POLICY_RULE_DO_NOT_DELETE = 1 << 1;
- /** This profile should be deleted after being disabled. */
- public static final int POLICY_RULE_DELETE_AFTER_DISABLING = 1 << 2;
-
- /** Class of the profile */
- @Retention(RetentionPolicy.SOURCE)
- @IntDef(prefix = { "PROFILE_CLASS_" }, value = {
- PROFILE_CLASS_TESTING,
- PROFILE_CLASS_PROVISIONING,
- PROFILE_CLASS_OPERATIONAL,
- PROFILE_CLASS_UNSET
- })
- /** @hide */
- public @interface ProfileClass {}
- /** Testing profiles */
- public static final int PROFILE_CLASS_TESTING = 0;
- /** Provisioning profiles which are pre-loaded on eUICC */
- public static final int PROFILE_CLASS_PROVISIONING = 1;
- /** Operational profiles which can be pre-loaded or downloaded */
- public static final int PROFILE_CLASS_OPERATIONAL = 2;
- /**
- * Profile class not set.
- * @hide
- */
- public static final int PROFILE_CLASS_UNSET = -1;
-
- /** State of the profile */
- @Retention(RetentionPolicy.SOURCE)
- @IntDef(prefix = { "PROFILE_STATE_" }, value = {
- PROFILE_STATE_DISABLED,
- PROFILE_STATE_ENABLED,
- PROFILE_STATE_UNSET
- })
- /** @hide */
- public @interface ProfileState {}
- /** Disabled profiles */
- public static final int PROFILE_STATE_DISABLED = 0;
- /** Enabled profile */
- public static final int PROFILE_STATE_ENABLED = 1;
- /**
- * Profile state not set.
- * @hide
- */
- public static final int PROFILE_STATE_UNSET = -1;
-
- /** The iccid of the subscription. */
- private final String mIccid;
-
- /** An optional nickname for the subscription. */
- private final @Nullable String mNickname;
-
- /** The service provider name for the subscription. */
- private final String mServiceProviderName;
-
- /** The profile name for the subscription. */
- private final String mProfileName;
-
- /** Profile class for the subscription. */
- @ProfileClass private final int mProfileClass;
-
- /** The profile state of the subscription. */
- @ProfileState private final int mState;
-
- /** The operator Id of the subscription. */
- private final CarrierIdentifier mCarrierIdentifier;
-
- /** The policy rules of the subscription. */
- @PolicyRule private final int mPolicyRules;
-
- /**
- * Optional access rules defining which apps can manage this subscription. If unset, only the
- * platform can manage it.
- */
- private final @Nullable UiccAccessRule[] mAccessRules;
-
- public static final @android.annotation.NonNull Creator<EuiccProfileInfo> CREATOR = new Creator<EuiccProfileInfo>() {
- @Override
- public EuiccProfileInfo createFromParcel(Parcel in) {
- return new EuiccProfileInfo(in);
- }
-
- @Override
- public EuiccProfileInfo[] newArray(int size) {
- return new EuiccProfileInfo[size];
- }
- };
-
- // TODO(b/70292228): Remove this method when LPA can be updated.
- /**
- * @hide
- * @deprecated - Do not use.
- */
- @Deprecated
- @UnsupportedAppUsage
- public EuiccProfileInfo(String iccid, @Nullable UiccAccessRule[] accessRules,
- @Nullable String nickname) {
- if (!TextUtils.isDigitsOnly(iccid)) {
- throw new IllegalArgumentException("iccid contains invalid characters: " + iccid);
- }
- this.mIccid = iccid;
- this.mAccessRules = accessRules;
- this.mNickname = nickname;
-
- this.mServiceProviderName = null;
- this.mProfileName = null;
- this.mProfileClass = PROFILE_CLASS_UNSET;
- this.mState = PROFILE_STATE_UNSET;
- this.mCarrierIdentifier = null;
- this.mPolicyRules = 0;
- }
-
- private EuiccProfileInfo(Parcel in) {
- mIccid = in.readString();
- mNickname = in.readString();
- mServiceProviderName = in.readString();
- mProfileName = in.readString();
- mProfileClass = in.readInt();
- mState = in.readInt();
- byte exist = in.readByte();
- if (exist == (byte) 1) {
- mCarrierIdentifier = CarrierIdentifier.CREATOR.createFromParcel(in);
- } else {
- mCarrierIdentifier = null;
- }
- mPolicyRules = in.readInt();
- mAccessRules = in.createTypedArray(UiccAccessRule.CREATOR);
- }
-
- @Override
- public void writeToParcel(Parcel dest, int flags) {
- dest.writeString(mIccid);
- dest.writeString(mNickname);
- dest.writeString(mServiceProviderName);
- dest.writeString(mProfileName);
- dest.writeInt(mProfileClass);
- dest.writeInt(mState);
- if (mCarrierIdentifier != null) {
- dest.writeByte((byte) 1);
- mCarrierIdentifier.writeToParcel(dest, flags);
- } else {
- dest.writeByte((byte) 0);
- }
- dest.writeInt(mPolicyRules);
- dest.writeTypedArray(mAccessRules, flags);
- }
-
- @Override
- public int describeContents() {
- return 0;
- }
-
- /** The builder to build a new {@link EuiccProfileInfo} instance. */
- public static final class Builder {
- private String mIccid;
- private List<UiccAccessRule> mAccessRules;
- private String mNickname;
- private String mServiceProviderName;
- private String mProfileName;
- @ProfileClass private int mProfileClass;
- @ProfileState private int mState;
- private CarrierIdentifier mCarrierIdentifier;
- @PolicyRule private int mPolicyRules;
-
- public Builder(String value) {
- if (!TextUtils.isDigitsOnly(value)) {
- throw new IllegalArgumentException("iccid contains invalid characters: " + value);
- }
- mIccid = value;
- }
-
- public Builder(EuiccProfileInfo baseProfile) {
- mIccid = baseProfile.mIccid;
- mNickname = baseProfile.mNickname;
- mServiceProviderName = baseProfile.mServiceProviderName;
- mProfileName = baseProfile.mProfileName;
- mProfileClass = baseProfile.mProfileClass;
- mState = baseProfile.mState;
- mCarrierIdentifier = baseProfile.mCarrierIdentifier;
- mPolicyRules = baseProfile.mPolicyRules;
- mAccessRules = Arrays.asList(baseProfile.mAccessRules);
- }
-
- /** Builds the profile instance. */
- public EuiccProfileInfo build() {
- if (mIccid == null) {
- throw new IllegalStateException("ICCID must be set for a profile.");
- }
- return new EuiccProfileInfo(
- mIccid,
- mNickname,
- mServiceProviderName,
- mProfileName,
- mProfileClass,
- mState,
- mCarrierIdentifier,
- mPolicyRules,
- mAccessRules);
- }
-
- /** Sets the iccId of the subscription. */
- public Builder setIccid(String value) {
- if (!TextUtils.isDigitsOnly(value)) {
- throw new IllegalArgumentException("iccid contains invalid characters: " + value);
- }
- mIccid = value;
- return this;
- }
-
- /** Sets the nickname of the subscription. */
- public Builder setNickname(String value) {
- mNickname = value;
- return this;
- }
-
- /** Sets the service provider name of the subscription. */
- public Builder setServiceProviderName(String value) {
- mServiceProviderName = value;
- return this;
- }
-
- /** Sets the profile name of the subscription. */
- public Builder setProfileName(String value) {
- mProfileName = value;
- return this;
- }
-
- /** Sets the profile class of the subscription. */
- public Builder setProfileClass(@ProfileClass int value) {
- mProfileClass = value;
- return this;
- }
-
- /** Sets the state of the subscription. */
- public Builder setState(@ProfileState int value) {
- mState = value;
- return this;
- }
-
- /** Sets the carrier identifier of the subscription. */
- public Builder setCarrierIdentifier(CarrierIdentifier value) {
- mCarrierIdentifier = value;
- return this;
- }
-
- /** Sets the policy rules of the subscription. */
- public Builder setPolicyRules(@PolicyRule int value) {
- mPolicyRules = value;
- return this;
- }
-
- /** Sets the access rules of the subscription. */
- public Builder setUiccAccessRule(@Nullable List<UiccAccessRule> value) {
- mAccessRules = value;
- return this;
- }
- }
-
- private EuiccProfileInfo(
- String iccid,
- @Nullable String nickname,
- String serviceProviderName,
- String profileName,
- @ProfileClass int profileClass,
- @ProfileState int state,
- CarrierIdentifier carrierIdentifier,
- @PolicyRule int policyRules,
- @Nullable List<UiccAccessRule> accessRules) {
- this.mIccid = iccid;
- this.mNickname = nickname;
- this.mServiceProviderName = serviceProviderName;
- this.mProfileName = profileName;
- this.mProfileClass = profileClass;
- this.mState = state;
- this.mCarrierIdentifier = carrierIdentifier;
- this.mPolicyRules = policyRules;
- if (accessRules != null && accessRules.size() > 0) {
- this.mAccessRules = accessRules.toArray(new UiccAccessRule[accessRules.size()]);
- } else {
- this.mAccessRules = null;
- }
- }
-
- /** Gets the ICCID string. */
- public String getIccid() {
- return mIccid;
- }
-
- /** Gets the access rules. */
- @Nullable
- public List<UiccAccessRule> getUiccAccessRules() {
- if (mAccessRules == null) return null;
- return Arrays.asList(mAccessRules);
- }
-
- /** Gets the nickname. */
- @Nullable
- public String getNickname() {
- return mNickname;
- }
-
- /** Gets the service provider name. */
- public String getServiceProviderName() {
- return mServiceProviderName;
- }
-
- /** Gets the profile name. */
- public String getProfileName() {
- return mProfileName;
- }
-
- /** Gets the profile class. */
- @ProfileClass
- public int getProfileClass() {
- return mProfileClass;
- }
-
- /** Gets the state of the subscription. */
- @ProfileState
- public int getState() {
- return mState;
- }
-
- /** Gets the carrier identifier. */
- public CarrierIdentifier getCarrierIdentifier() {
- return mCarrierIdentifier;
- }
-
- /** Gets the policy rules. */
- @PolicyRule
- public int getPolicyRules() {
- return mPolicyRules;
- }
-
- /** Returns whether any policy rule exists. */
- public boolean hasPolicyRules() {
- return mPolicyRules != 0;
- }
-
- /** Checks whether a certain policy rule exists. */
- public boolean hasPolicyRule(@PolicyRule int policy) {
- return (mPolicyRules & policy) != 0;
- }
-
- @Override
- public boolean equals(@Nullable Object obj) {
- if (this == obj) {
- return true;
- }
- if (obj == null || getClass() != obj.getClass()) {
- return false;
- }
-
- EuiccProfileInfo that = (EuiccProfileInfo) obj;
- return Objects.equals(mIccid, that.mIccid)
- && Objects.equals(mNickname, that.mNickname)
- && Objects.equals(mServiceProviderName, that.mServiceProviderName)
- && Objects.equals(mProfileName, that.mProfileName)
- && mProfileClass == that.mProfileClass
- && mState == that.mState
- && Objects.equals(mCarrierIdentifier, that.mCarrierIdentifier)
- && mPolicyRules == that.mPolicyRules
- && Arrays.equals(mAccessRules, that.mAccessRules);
- }
-
- @Override
- public int hashCode() {
- int result = 1;
- result = 31 * result + Objects.hashCode(mIccid);
- result = 31 * result + Objects.hashCode(mNickname);
- result = 31 * result + Objects.hashCode(mServiceProviderName);
- result = 31 * result + Objects.hashCode(mProfileName);
- result = 31 * result + mProfileClass;
- result = 31 * result + mState;
- result = 31 * result + Objects.hashCode(mCarrierIdentifier);
- result = 31 * result + mPolicyRules;
- result = 31 * result + Arrays.hashCode(mAccessRules);
- return result;
- }
-
- @NonNull
- @Override
- public String toString() {
- return "EuiccProfileInfo (nickname="
- + mNickname
- + ", serviceProviderName="
- + mServiceProviderName
- + ", profileName="
- + mProfileName
- + ", profileClass="
- + mProfileClass
- + ", state="
- + mState
- + ", CarrierIdentifier="
- + mCarrierIdentifier
- + ", policyRules="
- + mPolicyRules
- + ", accessRules="
- + Arrays.toString(mAccessRules)
- + ")";
- }
-}
diff --git a/core/java/android/service/euicc/EuiccService.java b/core/java/android/service/euicc/EuiccService.java
deleted file mode 100644
index bc6a9e848e2a..000000000000
--- a/core/java/android/service/euicc/EuiccService.java
+++ /dev/null
@@ -1,838 +0,0 @@
-/*
- * Copyright (C) 2017 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.euicc;
-
-import static android.telephony.euicc.EuiccCardManager.ResetOption;
-
-import android.annotation.CallSuper;
-import android.annotation.IntDef;
-import android.annotation.NonNull;
-import android.annotation.Nullable;
-import android.annotation.SdkConstant;
-import android.annotation.SystemApi;
-import android.app.Service;
-import android.content.Intent;
-import android.os.Bundle;
-import android.os.IBinder;
-import android.os.RemoteException;
-import android.telephony.TelephonyManager;
-import android.telephony.euicc.DownloadableSubscription;
-import android.telephony.euicc.EuiccInfo;
-import android.telephony.euicc.EuiccManager.OtaStatus;
-import android.util.Log;
-
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-import java.util.concurrent.LinkedBlockingQueue;
-import java.util.concurrent.ThreadFactory;
-import java.util.concurrent.ThreadPoolExecutor;
-import java.util.concurrent.TimeUnit;
-import java.util.concurrent.atomic.AtomicInteger;
-
-/**
- * Service interface linking the system with an eUICC local profile assistant (LPA) application.
- *
- * <p>An LPA consists of two separate components (which may both be implemented in the same APK):
- * the LPA backend, and the LPA UI or LUI.
- *
- * <p>To implement the LPA backend, you must extend this class and declare this service in your
- * manifest file. The service must require the
- * {@link android.Manifest.permission#BIND_EUICC_SERVICE} permission and include an intent filter
- * with the {@link #EUICC_SERVICE_INTERFACE} action. It's suggested that the priority of the intent
- * filter to be set to a non-zero value in case multiple implementations are present on the device.
- * See the below example. Note that there will be problem if two LPAs are present and they have the
- * same priority.
- * Example:
- *
- * <pre>{@code
- * <service android:name=".MyEuiccService"
- * android:permission="android.permission.BIND_EUICC_SERVICE">
- * <intent-filter android:priority="100">
- * <action android:name="android.service.euicc.EuiccService" />
- * </intent-filter>
- * </service>
- * }</pre>
- *
- * <p>To implement the LUI, you must provide an activity for the following actions:
- *
- * <ul>
- * <li>{@link #ACTION_MANAGE_EMBEDDED_SUBSCRIPTIONS}
- * <li>{@link #ACTION_PROVISION_EMBEDDED_SUBSCRIPTION}
- * </ul>
- *
- * <p>As with the service, each activity must require the
- * {@link android.Manifest.permission#BIND_EUICC_SERVICE} permission. Each should have an intent
- * filter with the appropriate action, the {@link #CATEGORY_EUICC_UI} category, and a non-zero
- * priority.
- *
- * <p>Old implementations of EuiccService may support passing in slot IDs equal to
- * {@link android.telephony.SubscriptionManager#INVALID_SIM_SLOT_INDEX}, which allows the LPA to
- * decide which eUICC to target when there are multiple eUICCs. This behavior is not supported in
- * Android Q or later.
- *
- * @hide
- */
-@SystemApi
-public abstract class EuiccService extends Service {
- private static final String TAG = "EuiccService";
-
- /** Action which must be included in this service's intent filter. */
- public static final String EUICC_SERVICE_INTERFACE = "android.service.euicc.EuiccService";
-
- /** Category which must be defined to all UI actions, for efficient lookup. */
- public static final String CATEGORY_EUICC_UI = "android.service.euicc.category.EUICC_UI";
-
- // LUI actions. These are passthroughs of the corresponding EuiccManager actions.
-
- /**
- * Action used to bind the carrier app and get the activation code from the carrier app. This
- * activation code will be used to download the eSIM profile during eSIM activation flow.
- */
- public static final String ACTION_BIND_CARRIER_PROVISIONING_SERVICE =
- "android.service.euicc.action.BIND_CARRIER_PROVISIONING_SERVICE";
-
- /**
- * Intent action sent by the LPA to launch a carrier app Activity for eSIM activation, e.g. a
- * carrier login screen. Carrier apps wishing to support this activation method must implement
- * an Activity that responds to this intent action. Upon completion, the Activity must return
- * one of the following results to the LPA:
- *
- * <p>{@code Activity.RESULT_CANCELED}: The LPA should treat this as an back button and abort
- * the activation flow.
- * <p>{@code Activity.RESULT_OK}: The LPA should try to get an activation code from the carrier
- * app by binding to the carrier app service implementing
- * {@link #ACTION_BIND_CARRIER_PROVISIONING_SERVICE}.
- * <p>{@code Activity.RESULT_OK} with
- * {@link android.telephony.euicc.EuiccManager#EXTRA_USE_QR_SCANNER} set to true: The LPA should
- * start a QR scanner for the user to scan an eSIM profile QR code.
- * <p>For other results: The LPA should treat this as an error.
- **/
- @SdkConstant(SdkConstant.SdkConstantType.ACTIVITY_INTENT_ACTION)
- public static final String ACTION_START_CARRIER_ACTIVATION =
- "android.service.euicc.action.START_CARRIER_ACTIVATION";
-
- /**
- * @see android.telephony.euicc.EuiccManager#ACTION_MANAGE_EMBEDDED_SUBSCRIPTIONS
- * The difference is this one is used by system to bring up the LUI.
- */
- public static final String ACTION_MANAGE_EMBEDDED_SUBSCRIPTIONS =
- "android.service.euicc.action.MANAGE_EMBEDDED_SUBSCRIPTIONS";
-
- /** @see android.telephony.euicc.EuiccManager#ACTION_PROVISION_EMBEDDED_SUBSCRIPTION */
- public static final String ACTION_PROVISION_EMBEDDED_SUBSCRIPTION =
- "android.service.euicc.action.PROVISION_EMBEDDED_SUBSCRIPTION";
-
- /**
- * @see android.telephony.euicc.EuiccManager#ACTION_TOGGLE_SUBSCRIPTION_PRIVILEGED. This is
- * a protected intent that can only be sent by the system, and requires the
- * {@link android.Manifest.permission#BIND_EUICC_SERVICE} permission.
- */
- public static final String ACTION_TOGGLE_SUBSCRIPTION_PRIVILEGED =
- "android.service.euicc.action.TOGGLE_SUBSCRIPTION_PRIVILEGED";
-
- /**
- * @see android.telephony.euicc.EuiccManager#ACTION_DELETE_SUBSCRIPTION_PRIVILEGED. This is
- * a protected intent that can only be sent by the system, and requires the
- * {@link android.Manifest.permission#BIND_EUICC_SERVICE} permission.
- */
- public static final String ACTION_DELETE_SUBSCRIPTION_PRIVILEGED =
- "android.service.euicc.action.DELETE_SUBSCRIPTION_PRIVILEGED";
-
- /**
- * @see android.telephony.euicc.EuiccManager#ACTION_RENAME_SUBSCRIPTION_PRIVILEGED. This is
- * a protected intent that can only be sent by the system, and requires the
- * {@link android.Manifest.permission#BIND_EUICC_SERVICE} permission.
- */
- public static final String ACTION_RENAME_SUBSCRIPTION_PRIVILEGED =
- "android.service.euicc.action.RENAME_SUBSCRIPTION_PRIVILEGED";
-
- /**
- * @see android.telephony.euicc.EuiccManager#ACTION_START_EUICC_ACTIVATION. This is
- * a protected intent that can only be sent by the system, and requires the
- * {@link android.Manifest.permission#BIND_EUICC_SERVICE} permission.
- */
- @SdkConstant(SdkConstant.SdkConstantType.ACTIVITY_INTENT_ACTION)
- public static final String ACTION_START_EUICC_ACTIVATION =
- "android.service.euicc.action.START_EUICC_ACTIVATION";
-
- // LUI resolution actions. These are called by the platform to resolve errors in situations that
- // require user interaction.
- // TODO(b/33075886): Define extras for any input parameters to these dialogs once they are
- // more scoped out.
- /**
- * Alert the user that this action will result in an active SIM being deactivated.
- * To implement the LUI triggered by the system, you need to define this in AndroidManifest.xml.
- */
- public static final String ACTION_RESOLVE_DEACTIVATE_SIM =
- "android.service.euicc.action.RESOLVE_DEACTIVATE_SIM";
- /**
- * Alert the user about a download/switch being done for an app that doesn't currently have
- * carrier privileges.
- */
- public static final String ACTION_RESOLVE_NO_PRIVILEGES =
- "android.service.euicc.action.RESOLVE_NO_PRIVILEGES";
-
- /**
- * Ask the user to input carrier confirmation code.
- *
- * @deprecated From Q, the resolvable errors happened in the download step are presented as
- * bit map in {@link #EXTRA_RESOLVABLE_ERRORS}. The corresponding action would be
- * {@link #ACTION_RESOLVE_RESOLVABLE_ERRORS}.
- */
- @Deprecated
- public static final String ACTION_RESOLVE_CONFIRMATION_CODE =
- "android.service.euicc.action.RESOLVE_CONFIRMATION_CODE";
-
- /** Ask the user to resolve all the resolvable errors. */
- public static final String ACTION_RESOLVE_RESOLVABLE_ERRORS =
- "android.service.euicc.action.RESOLVE_RESOLVABLE_ERRORS";
-
- /** @hide */
- @Retention(RetentionPolicy.SOURCE)
- @IntDef(flag = true, prefix = { "RESOLVABLE_ERROR_" }, value = {
- RESOLVABLE_ERROR_CONFIRMATION_CODE,
- RESOLVABLE_ERROR_POLICY_RULES,
- })
- public @interface ResolvableError {}
-
- /**
- * Possible value for the bit map of resolvable errors indicating the download process needs
- * the user to input confirmation code.
- */
- public static final int RESOLVABLE_ERROR_CONFIRMATION_CODE = 1 << 0;
- /**
- * Possible value for the bit map of resolvable errors indicating the download process needs
- * the user's consent to allow profile policy rules.
- */
- public static final int RESOLVABLE_ERROR_POLICY_RULES = 1 << 1;
-
- /**
- * Intent extra set for resolution requests containing the package name of the calling app.
- * This is used by the above actions including ACTION_RESOLVE_DEACTIVATE_SIM,
- * ACTION_RESOLVE_NO_PRIVILEGES and ACTION_RESOLVE_RESOLVABLE_ERRORS.
- */
- public static final String EXTRA_RESOLUTION_CALLING_PACKAGE =
- "android.service.euicc.extra.RESOLUTION_CALLING_PACKAGE";
-
- /**
- * Intent extra set for resolution requests containing the list of resolvable errors to be
- * resolved. Each resolvable error is an integer. Its possible values include:
- * <UL>
- * <LI>{@link #RESOLVABLE_ERROR_CONFIRMATION_CODE}
- * <LI>{@link #RESOLVABLE_ERROR_POLICY_RULES}
- * </UL>
- */
- public static final String EXTRA_RESOLVABLE_ERRORS =
- "android.service.euicc.extra.RESOLVABLE_ERRORS";
-
- /**
- * Intent extra set for resolution requests containing a boolean indicating whether to ask the
- * user to retry another confirmation code.
- */
- public static final String EXTRA_RESOLUTION_CONFIRMATION_CODE_RETRIED =
- "android.service.euicc.extra.RESOLUTION_CONFIRMATION_CODE_RETRIED";
-
- /**
- * Intent extra set for resolution requests containing an int indicating the current card Id.
- */
- public static final String EXTRA_RESOLUTION_CARD_ID =
- "android.service.euicc.extra.RESOLUTION_CARD_ID";
-
- /** @hide */
- @Retention(RetentionPolicy.SOURCE)
- @IntDef(prefix = { "RESULT_" }, value = {
- RESULT_OK,
- RESULT_MUST_DEACTIVATE_SIM,
- RESULT_RESOLVABLE_ERRORS,
- RESULT_NEED_CONFIRMATION_CODE,
- RESULT_FIRST_USER,
- })
- public @interface Result {}
-
- /** Result code for a successful operation. */
- public static final int RESULT_OK = 0;
- /** Result code indicating that an active SIM must be deactivated to perform the operation. */
- public static final int RESULT_MUST_DEACTIVATE_SIM = -1;
- /** Result code indicating that the user must resolve resolvable errors. */
- public static final int RESULT_RESOLVABLE_ERRORS = -2;
- /**
- * Result code indicating that the user must input a carrier confirmation code.
- *
- * @deprecated From Q, the resolvable errors happened in the download step are presented as
- * bit map in {@link #EXTRA_RESOLVABLE_ERRORS}. The corresponding result would be
- * {@link #RESULT_RESOLVABLE_ERRORS}.
- */
- @Deprecated
- public static final int RESULT_NEED_CONFIRMATION_CODE = -2;
- // New predefined codes should have negative values.
-
- /** Start of implementation-specific error results. */
- public static final int RESULT_FIRST_USER = 1;
-
- /**
- * Boolean extra for resolution actions indicating whether the user granted consent.
- * This is used and set by the implementation and used in {@code EuiccOperation}.
- */
- public static final String EXTRA_RESOLUTION_CONSENT =
- "android.service.euicc.extra.RESOLUTION_CONSENT";
- /**
- * String extra for resolution actions indicating the carrier confirmation code.
- * This is used and set by the implementation and used in {@code EuiccOperation}.
- */
- public static final String EXTRA_RESOLUTION_CONFIRMATION_CODE =
- "android.service.euicc.extra.RESOLUTION_CONFIRMATION_CODE";
- /**
- * String extra for resolution actions indicating whether the user allows policy rules.
- * This is used and set by the implementation and used in {@code EuiccOperation}.
- */
- public static final String EXTRA_RESOLUTION_ALLOW_POLICY_RULES =
- "android.service.euicc.extra.RESOLUTION_ALLOW_POLICY_RULES";
-
- private final IEuiccService.Stub mStubWrapper;
-
- private ThreadPoolExecutor mExecutor;
-
- public EuiccService() {
- mStubWrapper = new IEuiccServiceWrapper();
- }
-
- @Override
- @CallSuper
- public void onCreate() {
- super.onCreate();
- // We use a oneway AIDL interface to avoid blocking phone process binder threads on IPCs to
- // an external process, but doing so means the requests are serialized by binder, which is
- // not desired. Spin up a background thread pool to allow requests to be parallelized.
- // TODO(b/38206971): Consider removing this if basic card-level functions like listing
- // profiles are moved to the platform.
- mExecutor = new ThreadPoolExecutor(
- 4 /* corePoolSize */,
- 4 /* maxPoolSize */,
- 30, TimeUnit.SECONDS, /* keepAliveTime */
- new LinkedBlockingQueue<>(), /* workQueue */
- new ThreadFactory() {
- private final AtomicInteger mCount = new AtomicInteger(1);
-
- @Override
- public Thread newThread(Runnable r) {
- return new Thread(r, "EuiccService #" + mCount.getAndIncrement());
- }
- }
- );
- mExecutor.allowCoreThreadTimeOut(true);
- }
-
- @Override
- @CallSuper
- public void onDestroy() {
- mExecutor.shutdownNow();
- super.onDestroy();
- }
-
- /**
- * If overriding this method, call through to the super method for any unknown actions.
- * {@inheritDoc}
- */
- @Override
- @CallSuper
- public IBinder onBind(Intent intent) {
- return mStubWrapper;
- }
-
- /**
- * Callback class for {@link #onStartOtaIfNecessary(int, OtaStatusChangedCallback)}
- *
- * The status of OTA which can be {@code android.telephony.euicc.EuiccManager#EUICC_OTA_}
- *
- * @see IEuiccService#startOtaIfNecessary
- */
- public abstract static class OtaStatusChangedCallback {
- /** Called when OTA status is changed. */
- public abstract void onOtaStatusChanged(int status);
- }
-
- /**
- * Return the EID of the eUICC.
- *
- * @param slotId ID of the SIM slot being queried.
- * @return the EID.
- * @see android.telephony.euicc.EuiccManager#getEid
- */
- // TODO(b/36260308): Update doc when we have multi-SIM support.
- public abstract String onGetEid(int slotId);
-
- /**
- * Return the status of OTA update.
- *
- * @param slotId ID of the SIM slot to use for the operation.
- * @return The status of Euicc OTA update.
- * @see android.telephony.euicc.EuiccManager#getOtaStatus
- */
- public abstract @OtaStatus int onGetOtaStatus(int slotId);
-
- /**
- * Perform OTA if current OS is not the latest one.
- *
- * @param slotId ID of the SIM slot to use for the operation.
- * @param statusChangedCallback Function called when OTA status changed.
- */
- public abstract void onStartOtaIfNecessary(
- int slotId, OtaStatusChangedCallback statusChangedCallback);
-
- /**
- * Populate {@link DownloadableSubscription} metadata for the given downloadable subscription.
- *
- * @param slotId ID of the SIM slot to use for the operation.
- * @param subscription A subscription whose metadata needs to be populated.
- * @param forceDeactivateSim If true, and if an active SIM must be deactivated to access the
- * eUICC, perform this action automatically. Otherwise, {@link #RESULT_MUST_DEACTIVATE_SIM)}
- * should be returned to allow the user to consent to this operation first.
- * @return The result of the operation.
- * @see android.telephony.euicc.EuiccManager#getDownloadableSubscriptionMetadata
- */
- public abstract GetDownloadableSubscriptionMetadataResult onGetDownloadableSubscriptionMetadata(
- int slotId, DownloadableSubscription subscription, boolean forceDeactivateSim);
-
- /**
- * Return metadata for subscriptions which are available for download for this device.
- *
- * @param slotId ID of the SIM slot to use for the operation.
- * @param forceDeactivateSim If true, and if an active SIM must be deactivated to access the
- * eUICC, perform this action automatically. Otherwise, {@link #RESULT_MUST_DEACTIVATE_SIM)}
- * should be returned to allow the user to consent to this operation first.
- * @return The result of the list operation.
- * @see android.telephony.euicc.EuiccManager#getDefaultDownloadableSubscriptionList
- */
- public abstract GetDefaultDownloadableSubscriptionListResult
- onGetDefaultDownloadableSubscriptionList(int slotId, boolean forceDeactivateSim);
-
- /**
- * Download the given subscription.
- *
- * @param slotId ID of the SIM slot to use for the operation.
- * @param subscription The subscription to download.
- * @param switchAfterDownload If true, the subscription should be enabled upon successful
- * download.
- * @param forceDeactivateSim If true, and if an active SIM must be deactivated to access the
- * eUICC, perform this action automatically. Otherwise, {@link #RESULT_MUST_DEACTIVATE_SIM}
- * should be returned to allow the user to consent to this operation first.
- * @param resolvedBundle The bundle containing information on resolved errors. It can contain
- * a string of confirmation code for the key {@link #EXTRA_RESOLUTION_CONFIRMATION_CODE},
- * and a boolean for key {@link #EXTRA_RESOLUTION_ALLOW_POLICY_RULES} indicating whether
- * the user allows profile policy rules or not.
- * @return a DownloadSubscriptionResult instance including a result code, a resolvable errors
- * bit map, and original the card Id. The result code may be one of the predefined
- * {@code RESULT_} constants or any implementation-specific code starting with
- * {@link #RESULT_FIRST_USER}. The resolvable error bit map can be either 0 or values
- * defined in {@code RESOLVABLE_ERROR_}. A subclass should override this method. Otherwise,
- * this method does nothing and returns null by default.
- * @see android.telephony.euicc.EuiccManager#downloadSubscription
- */
- public DownloadSubscriptionResult onDownloadSubscription(int slotId,
- @NonNull DownloadableSubscription subscription, boolean switchAfterDownload,
- boolean forceDeactivateSim, @Nullable Bundle resolvedBundle) {
- return null;
- }
-
- /**
- * Download the given subscription.
- *
- * @param slotId ID of the SIM slot to use for the operation.
- * @param subscription The subscription to download.
- * @param switchAfterDownload If true, the subscription should be enabled upon successful
- * download.
- * @param forceDeactivateSim If true, and if an active SIM must be deactivated to access the
- * eUICC, perform this action automatically. Otherwise, {@link #RESULT_MUST_DEACTIVATE_SIM}
- * should be returned to allow the user to consent to this operation first.
- * @return the result of the download operation. May be one of the predefined {@code RESULT_}
- * constants or any implementation-specific code starting with {@link #RESULT_FIRST_USER}.
- * @see android.telephony.euicc.EuiccManager#downloadSubscription
- *
- * @deprecated From Q, a subclass should use and override the above
- * {@link #onDownloadSubscription(int, DownloadableSubscription, boolean, boolean, Bundle)}. The
- * default return value for this one is Integer.MIN_VALUE.
- */
- @Deprecated public @Result int onDownloadSubscription(int slotId,
- @NonNull DownloadableSubscription subscription, boolean switchAfterDownload,
- boolean forceDeactivateSim) {
- return Integer.MIN_VALUE;
- }
-
- /**
- * Return a list of all @link EuiccProfileInfo}s.
- *
- * @param slotId ID of the SIM slot to use for the operation.
- * @return The result of the operation.
- * @see android.telephony.SubscriptionManager#getAvailableSubscriptionInfoList
- * @see android.telephony.SubscriptionManager#getAccessibleSubscriptionInfoList
- */
- public abstract @NonNull GetEuiccProfileInfoListResult onGetEuiccProfileInfoList(int slotId);
-
- /**
- * Return info about the eUICC chip/device.
- *
- * @param slotId ID of the SIM slot to use for the operation.
- * @return the {@link EuiccInfo} for the eUICC chip/device.
- * @see android.telephony.euicc.EuiccManager#getEuiccInfo
- */
- public abstract @NonNull EuiccInfo onGetEuiccInfo(int slotId);
-
- /**
- * Delete the given subscription.
- *
- * <p>If the subscription is currently active, it should be deactivated first (equivalent to a
- * physical SIM being ejected).
- *
- * @param slotId ID of the SIM slot to use for the operation.
- * @param iccid the ICCID of the subscription to delete.
- * @return the result of the delete operation. May be one of the predefined {@code RESULT_}
- * constants or any implementation-specific code starting with {@link #RESULT_FIRST_USER}.
- * @see android.telephony.euicc.EuiccManager#deleteSubscription
- */
- public abstract @Result int onDeleteSubscription(int slotId, String iccid);
-
- /**
- * Switch to the given subscription.
- *
- * @param slotId ID of the SIM slot to use for the operation.
- * @param iccid the ICCID of the subscription to enable. May be null, in which case the current
- * profile should be deactivated and no profile should be activated to replace it - this is
- * equivalent to a physical SIM being ejected.
- * @param forceDeactivateSim If true, and if an active SIM must be deactivated to access the
- * eUICC, perform this action automatically. Otherwise, {@link #RESULT_MUST_DEACTIVATE_SIM}
- * should be returned to allow the user to consent to this operation first.
- * @return the result of the switch operation. May be one of the predefined {@code RESULT_}
- * constants or any implementation-specific code starting with {@link #RESULT_FIRST_USER}.
- * @see android.telephony.euicc.EuiccManager#switchToSubscription
- */
- public abstract @Result int onSwitchToSubscription(int slotId, @Nullable String iccid,
- boolean forceDeactivateSim);
-
- /**
- * Update the nickname of the given subscription.
- *
- * @param slotId ID of the SIM slot to use for the operation.
- * @param iccid the ICCID of the subscription to update.
- * @param nickname the new nickname to apply.
- * @return the result of the update operation. May be one of the predefined {@code RESULT_}
- * constants or any implementation-specific code starting with {@link #RESULT_FIRST_USER}.
- * @see android.telephony.euicc.EuiccManager#updateSubscriptionNickname
- */
- public abstract int onUpdateSubscriptionNickname(int slotId, String iccid,
- String nickname);
-
- /**
- * Erase all operational subscriptions on the device.
- *
- * <p>This is intended to be used for device resets. As such, the reset should be performed even
- * if an active SIM must be deactivated in order to access the eUICC.
- *
- * @param slotId ID of the SIM slot to use for the operation.
- * @return the result of the erase operation. May be one of the predefined {@code RESULT_}
- * constants or any implementation-specific code starting with {@link #RESULT_FIRST_USER}.
- * @see android.telephony.euicc.EuiccManager#eraseSubscriptions
- *
- * @deprecated From R, callers should specify a flag for specific set of subscriptions to erase
- * and use {@link #onEraseSubscriptions(int, int)} instead
- */
- @Deprecated
- public abstract int onEraseSubscriptions(int slotId);
-
- /**
- * Erase specific subscriptions on the device.
- *
- * <p>This is intended to be used for device resets. As such, the reset should be performed even
- * if an active SIM must be deactivated in order to access the eUICC.
- *
- * @param slotIndex index of the SIM slot to use for the operation.
- * @param options flag for specific group of subscriptions to erase
- * @return the result of the erase operation. May be one of the predefined {@code RESULT_}
- * constants or any implementation-specific code starting with {@link #RESULT_FIRST_USER}.
- * @see android.telephony.euicc.EuiccManager#eraseSubscriptionsWithOptions
- */
- public int onEraseSubscriptions(int slotIndex, @ResetOption int options) {
- throw new UnsupportedOperationException(
- "This method must be overridden to enable the ResetOption parameter");
- }
-
- /**
- * Ensure that subscriptions will be retained on the next factory reset.
- *
- * <p>Called directly before a factory reset. Assumes that a normal factory reset will lead to
- * profiles being erased on first boot (to cover fastboot/recovery wipes), so the implementation
- * should persist some bit that will remain accessible after the factory reset to bypass this
- * flow when this method is called.
- *
- * @param slotId ID of the SIM slot to use for the operation.
- * @return the result of the operation. May be one of the predefined {@code RESULT_} constants
- * or any implementation-specific code starting with {@link #RESULT_FIRST_USER}.
- */
- public abstract int onRetainSubscriptionsForFactoryReset(int slotId);
-
- /**
- * Wrapper around IEuiccService that forwards calls to implementations of {@link EuiccService}.
- */
- private class IEuiccServiceWrapper extends IEuiccService.Stub {
- @Override
- public void downloadSubscription(int slotId, DownloadableSubscription subscription,
- boolean switchAfterDownload, boolean forceDeactivateSim, Bundle resolvedBundle,
- IDownloadSubscriptionCallback callback) {
- mExecutor.execute(new Runnable() {
- @Override
- public void run() {
- DownloadSubscriptionResult result;
- try {
- result =
- EuiccService.this.onDownloadSubscription(
- slotId, subscription, switchAfterDownload, forceDeactivateSim,
- resolvedBundle);
- } catch (AbstractMethodError e) {
- Log.w(TAG, "The new onDownloadSubscription(int, "
- + "DownloadableSubscription, boolean, boolean, Bundle) is not "
- + "implemented. Fall back to the old one.", e);
- int resultCode = EuiccService.this.onDownloadSubscription(
- slotId, subscription, switchAfterDownload, forceDeactivateSim);
- result = new DownloadSubscriptionResult(resultCode,
- 0 /* resolvableErrors */, TelephonyManager.UNSUPPORTED_CARD_ID);
- }
- try {
- callback.onComplete(result);
- } catch (RemoteException e) {
- // Can't communicate with the phone process; ignore.
- }
- }
- });
- }
-
- @Override
- public void getEid(int slotId, IGetEidCallback callback) {
- mExecutor.execute(new Runnable() {
- @Override
- public void run() {
- String eid = EuiccService.this.onGetEid(slotId);
- try {
- callback.onSuccess(eid);
- } catch (RemoteException e) {
- // Can't communicate with the phone process; ignore.
- }
- }
- });
- }
-
- @Override
- public void startOtaIfNecessary(
- int slotId, IOtaStatusChangedCallback statusChangedCallback) {
- mExecutor.execute(new Runnable() {
- @Override
- public void run() {
- EuiccService.this.onStartOtaIfNecessary(slotId, new OtaStatusChangedCallback() {
- @Override
- public void onOtaStatusChanged(int status) {
- try {
- statusChangedCallback.onOtaStatusChanged(status);
- } catch (RemoteException e) {
- // Can't communicate with the phone process; ignore.
- }
- }
- });
- }
- });
- }
-
- @Override
- public void getOtaStatus(int slotId, IGetOtaStatusCallback callback) {
- mExecutor.execute(new Runnable() {
- @Override
- public void run() {
- int status = EuiccService.this.onGetOtaStatus(slotId);
- try {
- callback.onSuccess(status);
- } catch (RemoteException e) {
- // Can't communicate with the phone process; ignore.
- }
- }
- });
- }
-
- @Override
- public void getDownloadableSubscriptionMetadata(int slotId,
- DownloadableSubscription subscription,
- boolean forceDeactivateSim,
- IGetDownloadableSubscriptionMetadataCallback callback) {
- mExecutor.execute(new Runnable() {
- @Override
- public void run() {
- GetDownloadableSubscriptionMetadataResult result =
- EuiccService.this.onGetDownloadableSubscriptionMetadata(
- slotId, subscription, forceDeactivateSim);
- try {
- callback.onComplete(result);
- } catch (RemoteException e) {
- // Can't communicate with the phone process; ignore.
- }
- }
- });
- }
-
- @Override
- public void getDefaultDownloadableSubscriptionList(int slotId, boolean forceDeactivateSim,
- IGetDefaultDownloadableSubscriptionListCallback callback) {
- mExecutor.execute(new Runnable() {
- @Override
- public void run() {
- GetDefaultDownloadableSubscriptionListResult result =
- EuiccService.this.onGetDefaultDownloadableSubscriptionList(
- slotId, forceDeactivateSim);
- try {
- callback.onComplete(result);
- } catch (RemoteException e) {
- // Can't communicate with the phone process; ignore.
- }
- }
- });
- }
-
- @Override
- public void getEuiccProfileInfoList(int slotId, IGetEuiccProfileInfoListCallback callback) {
- mExecutor.execute(new Runnable() {
- @Override
- public void run() {
- GetEuiccProfileInfoListResult result =
- EuiccService.this.onGetEuiccProfileInfoList(slotId);
- try {
- callback.onComplete(result);
- } catch (RemoteException e) {
- // Can't communicate with the phone process; ignore.
- }
- }
- });
- }
-
- @Override
- public void getEuiccInfo(int slotId, IGetEuiccInfoCallback callback) {
- mExecutor.execute(new Runnable() {
- @Override
- public void run() {
- EuiccInfo euiccInfo = EuiccService.this.onGetEuiccInfo(slotId);
- try {
- callback.onSuccess(euiccInfo);
- } catch (RemoteException e) {
- // Can't communicate with the phone process; ignore.
- }
- }
- });
-
- }
-
- @Override
- public void deleteSubscription(int slotId, String iccid,
- IDeleteSubscriptionCallback callback) {
- mExecutor.execute(new Runnable() {
- @Override
- public void run() {
- int result = EuiccService.this.onDeleteSubscription(slotId, iccid);
- try {
- callback.onComplete(result);
- } catch (RemoteException e) {
- // Can't communicate with the phone process; ignore.
- }
- }
- });
- }
-
- @Override
- public void switchToSubscription(int slotId, String iccid, boolean forceDeactivateSim,
- ISwitchToSubscriptionCallback callback) {
- mExecutor.execute(new Runnable() {
- @Override
- public void run() {
- int result =
- EuiccService.this.onSwitchToSubscription(
- slotId, iccid, forceDeactivateSim);
- try {
- callback.onComplete(result);
- } catch (RemoteException e) {
- // Can't communicate with the phone process; ignore.
- }
- }
- });
- }
-
- @Override
- public void updateSubscriptionNickname(int slotId, String iccid, String nickname,
- IUpdateSubscriptionNicknameCallback callback) {
- mExecutor.execute(new Runnable() {
- @Override
- public void run() {
- int result =
- EuiccService.this.onUpdateSubscriptionNickname(slotId, iccid, nickname);
- try {
- callback.onComplete(result);
- } catch (RemoteException e) {
- // Can't communicate with the phone process; ignore.
- }
- }
- });
- }
-
- @Override
- public void eraseSubscriptions(int slotId, IEraseSubscriptionsCallback callback) {
- mExecutor.execute(new Runnable() {
- @Override
- public void run() {
- int result = EuiccService.this.onEraseSubscriptions(slotId);
- try {
- callback.onComplete(result);
- } catch (RemoteException e) {
- // Can't communicate with the phone process; ignore.
- }
- }
- });
- }
-
- @Override
- public void eraseSubscriptionsWithOptions(
- int slotIndex, @ResetOption int options, IEraseSubscriptionsCallback callback) {
- mExecutor.execute(new Runnable() {
- @Override
- public void run() {
- int result = EuiccService.this.onEraseSubscriptions(slotIndex, options);
- try {
- callback.onComplete(result);
- } catch (RemoteException e) {
- // Can't communicate with the phone process; ignore.
- }
- }
- });
- }
-
- @Override
- public void retainSubscriptionsForFactoryReset(int slotId,
- IRetainSubscriptionsForFactoryResetCallback callback) {
- mExecutor.execute(new Runnable() {
- @Override
- public void run() {
- int result = EuiccService.this.onRetainSubscriptionsForFactoryReset(slotId);
- try {
- callback.onComplete(result);
- } catch (RemoteException e) {
- // Can't communicate with the phone process; ignore.
- }
- }
- });
- }
- }
-}
diff --git a/core/java/android/service/euicc/GetDefaultDownloadableSubscriptionListResult.aidl b/core/java/android/service/euicc/GetDefaultDownloadableSubscriptionListResult.aidl
deleted file mode 100644
index c2636a16edee..000000000000
--- a/core/java/android/service/euicc/GetDefaultDownloadableSubscriptionListResult.aidl
+++ /dev/null
@@ -1,19 +0,0 @@
-/*
- * Copyright (C) 2017 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.euicc;
-
-parcelable GetDefaultDownloadableSubscriptionListResult;
diff --git a/core/java/android/service/euicc/GetDefaultDownloadableSubscriptionListResult.java b/core/java/android/service/euicc/GetDefaultDownloadableSubscriptionListResult.java
deleted file mode 100644
index c7a985160730..000000000000
--- a/core/java/android/service/euicc/GetDefaultDownloadableSubscriptionListResult.java
+++ /dev/null
@@ -1,118 +0,0 @@
-/*
- * Copyright (C) 2017 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.euicc;
-
-import android.annotation.Nullable;
-import android.annotation.SystemApi;
-import android.annotation.UnsupportedAppUsage;
-import android.os.Parcel;
-import android.os.Parcelable;
-import android.telephony.euicc.DownloadableSubscription;
-
-import java.util.Arrays;
-import java.util.List;
-
-/**
- * Result of a {@link EuiccService#onGetDefaultDownloadableSubscriptionList} operation.
- * @hide
- */
-@SystemApi
-public final class GetDefaultDownloadableSubscriptionListResult implements Parcelable {
-
- public static final @android.annotation.NonNull Creator<GetDefaultDownloadableSubscriptionListResult> CREATOR =
- new Creator<GetDefaultDownloadableSubscriptionListResult>() {
- @Override
- public GetDefaultDownloadableSubscriptionListResult createFromParcel(Parcel in) {
- return new GetDefaultDownloadableSubscriptionListResult(in);
- }
-
- @Override
- public GetDefaultDownloadableSubscriptionListResult[] newArray(int size) {
- return new GetDefaultDownloadableSubscriptionListResult[size];
- }
- };
-
- /**
- * @hide
- * @deprecated - Do no use. Use getResult() instead.
- */
- @Deprecated
- @UnsupportedAppUsage
- public final int result;
-
- @Nullable
- private final DownloadableSubscription[] mSubscriptions;
-
- /**
- * Gets the result of the operation.
- *
- * <p>May be one of the predefined {@code RESULT_} constants in EuiccService or any
- * implementation-specific code starting with {@link EuiccService#RESULT_FIRST_USER}.
- */
- public int getResult() {
- return result;
- }
-
- /**
- * Gets the available {@link DownloadableSubscription}s (with filled-in metadata).
- *
- * <p>Only non-null if {@link #result} is {@link EuiccService#RESULT_OK}.
- */
- @Nullable
- public List<DownloadableSubscription> getDownloadableSubscriptions() {
- if (mSubscriptions == null) return null;
- return Arrays.asList(mSubscriptions);
- }
-
- /**
- * Construct a new {@link GetDefaultDownloadableSubscriptionListResult}.
- *
- * @param result Result of the operation. May be one of the predefined {@code RESULT_} constants
- * in EuiccService or any implementation-specific code starting with
- * {@link EuiccService#RESULT_FIRST_USER}.
- * @param subscriptions The available subscriptions. Should only be provided if the result is
- * {@link EuiccService#RESULT_OK}.
- */
- public GetDefaultDownloadableSubscriptionListResult(int result,
- @Nullable DownloadableSubscription[] subscriptions) {
- this.result = result;
- if (this.result == EuiccService.RESULT_OK) {
- this.mSubscriptions = subscriptions;
- } else {
- if (subscriptions != null) {
- throw new IllegalArgumentException(
- "Error result with non-null subscriptions: " + result);
- }
- this.mSubscriptions = null;
- }
- }
-
- private GetDefaultDownloadableSubscriptionListResult(Parcel in) {
- this.result = in.readInt();
- this.mSubscriptions = in.createTypedArray(DownloadableSubscription.CREATOR);
- }
-
- @Override
- public void writeToParcel(Parcel dest, int flags) {
- dest.writeInt(result);
- dest.writeTypedArray(mSubscriptions, flags);
- }
-
- @Override
- public int describeContents() {
- return 0;
- }
-}
diff --git a/core/java/android/service/euicc/GetDownloadableSubscriptionMetadataResult.aidl b/core/java/android/service/euicc/GetDownloadableSubscriptionMetadataResult.aidl
deleted file mode 100644
index 791ad9b469ef..000000000000
--- a/core/java/android/service/euicc/GetDownloadableSubscriptionMetadataResult.aidl
+++ /dev/null
@@ -1,19 +0,0 @@
-/*
- * Copyright (C) 2017 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.euicc;
-
-parcelable GetDownloadableSubscriptionMetadataResult;
diff --git a/core/java/android/service/euicc/GetDownloadableSubscriptionMetadataResult.java b/core/java/android/service/euicc/GetDownloadableSubscriptionMetadataResult.java
deleted file mode 100644
index abd4065c754a..000000000000
--- a/core/java/android/service/euicc/GetDownloadableSubscriptionMetadataResult.java
+++ /dev/null
@@ -1,114 +0,0 @@
-/*
- * Copyright (C) 2017 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.euicc;
-
-import android.annotation.Nullable;
-import android.annotation.SystemApi;
-import android.annotation.UnsupportedAppUsage;
-import android.os.Parcel;
-import android.os.Parcelable;
-import android.telephony.euicc.DownloadableSubscription;
-
-/**
- * Result of a {@link EuiccService#onGetDownloadableSubscriptionMetadata} operation.
- * @hide
- */
-@SystemApi
-public final class GetDownloadableSubscriptionMetadataResult implements Parcelable {
-
- public static final @android.annotation.NonNull Creator<GetDownloadableSubscriptionMetadataResult> CREATOR =
- new Creator<GetDownloadableSubscriptionMetadataResult>() {
- @Override
- public GetDownloadableSubscriptionMetadataResult createFromParcel(Parcel in) {
- return new GetDownloadableSubscriptionMetadataResult(in);
- }
-
- @Override
- public GetDownloadableSubscriptionMetadataResult[] newArray(int size) {
- return new GetDownloadableSubscriptionMetadataResult[size];
- }
- };
-
- /**
- * @hide
- * @deprecated - Do no use. Use getResult() instead.
- */
- @Deprecated
- @UnsupportedAppUsage
- public final int result;
-
- @Nullable
- private final DownloadableSubscription mSubscription;
-
- /**
- * Gets the result of the operation.
- *
- * <p>May be one of the predefined {@code RESULT_} constants in EuiccService or any
- * implementation-specific code starting with {@link EuiccService#RESULT_FIRST_USER}.
- */
- public int getResult() {
- return result;
- }
-
- /**
- * Gets the {@link DownloadableSubscription} with filled-in metadata.
- *
- * <p>Only non-null if {@link #result} is {@link EuiccService#RESULT_OK}.
- */
- @Nullable
- public DownloadableSubscription getDownloadableSubscription() {
- return mSubscription;
- }
-
- /**
- * Construct a new {@link GetDownloadableSubscriptionMetadataResult}.
- *
- * @param result Result of the operation. May be one of the predefined {@code RESULT_} constants
- * in EuiccService or any implementation-specific code starting with
- * {@link EuiccService#RESULT_FIRST_USER}.
- * @param subscription The subscription with filled-in metadata. Should only be provided if the
- * result is {@link EuiccService#RESULT_OK}.
- */
- public GetDownloadableSubscriptionMetadataResult(int result,
- @Nullable DownloadableSubscription subscription) {
- this.result = result;
- if (this.result == EuiccService.RESULT_OK) {
- this.mSubscription = subscription;
- } else {
- if (subscription != null) {
- throw new IllegalArgumentException(
- "Error result with non-null subscription: " + result);
- }
- this.mSubscription = null;
- }
- }
-
- private GetDownloadableSubscriptionMetadataResult(Parcel in) {
- this.result = in.readInt();
- this.mSubscription = in.readTypedObject(DownloadableSubscription.CREATOR);
- }
-
- @Override
- public void writeToParcel(Parcel dest, int flags) {
- dest.writeInt(result);
- dest.writeTypedObject(this.mSubscription, flags);
- }
-
- @Override
- public int describeContents() {
- return 0;
- }
-} \ No newline at end of file
diff --git a/core/java/android/service/euicc/GetEuiccProfileInfoListResult.java b/core/java/android/service/euicc/GetEuiccProfileInfoListResult.java
deleted file mode 100644
index 9add38e40d9b..000000000000
--- a/core/java/android/service/euicc/GetEuiccProfileInfoListResult.java
+++ /dev/null
@@ -1,126 +0,0 @@
-/*
- * Copyright (C) 2017 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.euicc;
-
-import android.annotation.Nullable;
-import android.annotation.SystemApi;
-import android.os.Parcel;
-import android.os.Parcelable;
-
-import java.util.Arrays;
-import java.util.List;
-
-/**
- * Result of a {@link EuiccService#onGetEuiccProfileInfoList} operation.
- * @hide
- */
-@SystemApi
-public final class GetEuiccProfileInfoListResult implements Parcelable {
-
- public static final @android.annotation.NonNull Creator<GetEuiccProfileInfoListResult> CREATOR =
- new Creator<GetEuiccProfileInfoListResult>() {
- @Override
- public GetEuiccProfileInfoListResult createFromParcel(Parcel in) {
- return new GetEuiccProfileInfoListResult(in);
- }
-
- @Override
- public GetEuiccProfileInfoListResult[] newArray(int size) {
- return new GetEuiccProfileInfoListResult[size];
- }
- };
-
- /**
- * @hide
- * @deprecated - Do no use. Use getResult() instead.
- */
- @Deprecated
- public final int result;
-
- @Nullable
- private final EuiccProfileInfo[] mProfiles;
-
- private final boolean mIsRemovable;
-
- /**
- * Gets the result of the operation.
- *
- * <p>May be one of the predefined {@code RESULT_} constants in EuiccService or any
- * implementation-specific code starting with {@link EuiccService#RESULT_FIRST_USER}.
- */
- public int getResult() {
- return result;
- }
-
- /** Gets the profile list (only upon success). */
- @Nullable
- public List<EuiccProfileInfo> getProfiles() {
- if (mProfiles == null) return null;
- return Arrays.asList(mProfiles);
- }
-
- /** Gets whether the eUICC is removable. */
- public boolean getIsRemovable() {
- return mIsRemovable;
- }
-
- /**
- * Construct a new {@link GetEuiccProfileInfoListResult}.
- *
- * @param result Result of the operation. May be one of the predefined {@code RESULT_} constants
- * in EuiccService or any implementation-specific code starting with
- * {@link EuiccService#RESULT_FIRST_USER}.
- * @param profiles the list of profiles. Should only be provided if the result is
- * {@link EuiccService#RESULT_OK}.
- * @param isRemovable whether the eUICC in this slot is removable. If true, the profiles
- * returned here will only be considered accessible as long as this eUICC is present.
- * Otherwise, they will remain accessible until the next time a response with isRemovable
- * set to false is returned.
- */
- public GetEuiccProfileInfoListResult(
- int result, @Nullable EuiccProfileInfo[] profiles, boolean isRemovable) {
- this.result = result;
- this.mIsRemovable = isRemovable;
- if (this.result == EuiccService.RESULT_OK) {
- this.mProfiles = profiles;
- } else {
- // For error case, profiles is either null or 0 size.
- if (profiles != null && profiles.length > 0) {
- throw new IllegalArgumentException(
- "Error result with non-empty profiles: " + result);
- }
- this.mProfiles = null;
- }
- }
-
- private GetEuiccProfileInfoListResult(Parcel in) {
- this.result = in.readInt();
- this.mProfiles = in.createTypedArray(EuiccProfileInfo.CREATOR);
- this.mIsRemovable = in.readBoolean();
- }
-
- @Override
- public void writeToParcel(Parcel dest, int flags) {
- dest.writeInt(result);
- dest.writeTypedArray(mProfiles, flags);
- dest.writeBoolean(mIsRemovable);
- }
-
- @Override
- public int describeContents() {
- return 0;
- }
-}
diff --git a/core/java/android/service/euicc/IDeleteSubscriptionCallback.aidl b/core/java/android/service/euicc/IDeleteSubscriptionCallback.aidl
deleted file mode 100644
index aff8f1b7b346..000000000000
--- a/core/java/android/service/euicc/IDeleteSubscriptionCallback.aidl
+++ /dev/null
@@ -1,23 +0,0 @@
-/*
- * Copyright (C) 2017 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.euicc;
-
-/** @hide */
-oneway interface IDeleteSubscriptionCallback {
- @UnsupportedAppUsage
- void onComplete(int result);
-} \ No newline at end of file
diff --git a/core/java/android/service/euicc/IDownloadSubscriptionCallback.aidl b/core/java/android/service/euicc/IDownloadSubscriptionCallback.aidl
deleted file mode 100644
index 50ecbebf5e84..000000000000
--- a/core/java/android/service/euicc/IDownloadSubscriptionCallback.aidl
+++ /dev/null
@@ -1,24 +0,0 @@
-/*
- * Copyright (C) 2017 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.euicc;
-
-import android.service.euicc.DownloadSubscriptionResult;
-
-/** @hide */
-oneway interface IDownloadSubscriptionCallback {
- void onComplete(in DownloadSubscriptionResult result);
-} \ No newline at end of file
diff --git a/core/java/android/service/euicc/IEraseSubscriptionsCallback.aidl b/core/java/android/service/euicc/IEraseSubscriptionsCallback.aidl
deleted file mode 100644
index 34b53cc71dfb..000000000000
--- a/core/java/android/service/euicc/IEraseSubscriptionsCallback.aidl
+++ /dev/null
@@ -1,23 +0,0 @@
-/*
- * Copyright (C) 2017 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.euicc;
-
-/** @hide */
-oneway interface IEraseSubscriptionsCallback {
- @UnsupportedAppUsage
- void onComplete(int result);
-} \ No newline at end of file
diff --git a/core/java/android/service/euicc/IEuiccService.aidl b/core/java/android/service/euicc/IEuiccService.aidl
deleted file mode 100644
index 2acc47aae919..000000000000
--- a/core/java/android/service/euicc/IEuiccService.aidl
+++ /dev/null
@@ -1,59 +0,0 @@
-/*
- * Copyright (C) 2017 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.euicc;
-
-import android.service.euicc.IDeleteSubscriptionCallback;
-import android.service.euicc.IDownloadSubscriptionCallback;
-import android.service.euicc.IEraseSubscriptionsCallback;
-import android.service.euicc.IGetDefaultDownloadableSubscriptionListCallback;
-import android.service.euicc.IGetDownloadableSubscriptionMetadataCallback;
-import android.service.euicc.IGetEidCallback;
-import android.service.euicc.IGetEuiccInfoCallback;
-import android.service.euicc.IGetEuiccProfileInfoListCallback;
-import android.service.euicc.IGetOtaStatusCallback;
-import android.service.euicc.IOtaStatusChangedCallback;
-import android.service.euicc.IRetainSubscriptionsForFactoryResetCallback;
-import android.service.euicc.ISwitchToSubscriptionCallback;
-import android.service.euicc.IUpdateSubscriptionNicknameCallback;
-import android.telephony.euicc.DownloadableSubscription;
-import android.os.Bundle;
-
-/** @hide */
-oneway interface IEuiccService {
- void downloadSubscription(int slotId, in DownloadableSubscription subscription,
- boolean switchAfterDownload, boolean forceDeactivateSim, in Bundle resolvedBundle,
- in IDownloadSubscriptionCallback callback);
- void getDownloadableSubscriptionMetadata(int slotId, in DownloadableSubscription subscription,
- boolean forceDeactivateSim, in IGetDownloadableSubscriptionMetadataCallback callback);
- void getEid(int slotId, in IGetEidCallback callback);
- void getOtaStatus(int slotId, in IGetOtaStatusCallback callback);
- void startOtaIfNecessary(int slotId, in IOtaStatusChangedCallback statusChangedCallback);
- void getEuiccProfileInfoList(int slotId, in IGetEuiccProfileInfoListCallback callback);
- void getDefaultDownloadableSubscriptionList(int slotId, boolean forceDeactivateSim,
- in IGetDefaultDownloadableSubscriptionListCallback callback);
- void getEuiccInfo(int slotId, in IGetEuiccInfoCallback callback);
- void deleteSubscription(int slotId, String iccid, in IDeleteSubscriptionCallback callback);
- void switchToSubscription(int slotId, String iccid, boolean forceDeactivateSim,
- in ISwitchToSubscriptionCallback callback);
- void updateSubscriptionNickname(int slotId, String iccid, String nickname,
- in IUpdateSubscriptionNicknameCallback callback);
- void eraseSubscriptions(int slotId, in IEraseSubscriptionsCallback callback);
- void eraseSubscriptionsWithOptions(
- int slotIndex, int options, in IEraseSubscriptionsCallback callback);
- void retainSubscriptionsForFactoryReset(
- int slotId, in IRetainSubscriptionsForFactoryResetCallback callback);
-} \ No newline at end of file
diff --git a/core/java/android/service/euicc/IGetDefaultDownloadableSubscriptionListCallback.aidl b/core/java/android/service/euicc/IGetDefaultDownloadableSubscriptionListCallback.aidl
deleted file mode 100644
index ad69ef132428..000000000000
--- a/core/java/android/service/euicc/IGetDefaultDownloadableSubscriptionListCallback.aidl
+++ /dev/null
@@ -1,25 +0,0 @@
-/*
- * Copyright (C) 2017 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.euicc;
-
-import android.service.euicc.GetDefaultDownloadableSubscriptionListResult;
-
-/** @hide */
-oneway interface IGetDefaultDownloadableSubscriptionListCallback {
- @UnsupportedAppUsage
- void onComplete(in GetDefaultDownloadableSubscriptionListResult result);
-} \ No newline at end of file
diff --git a/core/java/android/service/euicc/IGetDownloadableSubscriptionMetadataCallback.aidl b/core/java/android/service/euicc/IGetDownloadableSubscriptionMetadataCallback.aidl
deleted file mode 100644
index 01f187ed11e2..000000000000
--- a/core/java/android/service/euicc/IGetDownloadableSubscriptionMetadataCallback.aidl
+++ /dev/null
@@ -1,25 +0,0 @@
-/*
- * Copyright (C) 2017 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.euicc;
-
-import android.service.euicc.GetDownloadableSubscriptionMetadataResult;
-
-/** @hide */
-oneway interface IGetDownloadableSubscriptionMetadataCallback {
- @UnsupportedAppUsage
- void onComplete(in GetDownloadableSubscriptionMetadataResult result);
-} \ No newline at end of file
diff --git a/core/java/android/service/euicc/IGetEidCallback.aidl b/core/java/android/service/euicc/IGetEidCallback.aidl
deleted file mode 100644
index e405a981c85a..000000000000
--- a/core/java/android/service/euicc/IGetEidCallback.aidl
+++ /dev/null
@@ -1,23 +0,0 @@
-/*
- * Copyright (C) 2017 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.euicc;
-
-/** @hide */
-oneway interface IGetEidCallback {
- @UnsupportedAppUsage
- void onSuccess(String eid);
-} \ No newline at end of file
diff --git a/core/java/android/service/euicc/IGetEuiccInfoCallback.aidl b/core/java/android/service/euicc/IGetEuiccInfoCallback.aidl
deleted file mode 100644
index c0611825ff0f..000000000000
--- a/core/java/android/service/euicc/IGetEuiccInfoCallback.aidl
+++ /dev/null
@@ -1,25 +0,0 @@
-/*
- * Copyright (C) 2017 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.euicc;
-
-import android.telephony.euicc.EuiccInfo;
-
-/** @hide */
-oneway interface IGetEuiccInfoCallback {
- @UnsupportedAppUsage
- void onSuccess(in EuiccInfo euiccInfo);
-} \ No newline at end of file
diff --git a/core/java/android/service/euicc/IGetEuiccProfileInfoListCallback.aidl b/core/java/android/service/euicc/IGetEuiccProfileInfoListCallback.aidl
deleted file mode 100644
index 0485f7be29d3..000000000000
--- a/core/java/android/service/euicc/IGetEuiccProfileInfoListCallback.aidl
+++ /dev/null
@@ -1,25 +0,0 @@
-/*
- * Copyright (C) 2017 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.euicc;
-
-import android.service.euicc.GetEuiccProfileInfoListResult;
-
-/** @hide */
-oneway interface IGetEuiccProfileInfoListCallback {
- @UnsupportedAppUsage
- void onComplete(in GetEuiccProfileInfoListResult result);
-} \ No newline at end of file
diff --git a/core/java/android/service/euicc/IGetOtaStatusCallback.aidl b/core/java/android/service/euicc/IGetOtaStatusCallback.aidl
deleted file mode 100644
index f6678889ccc7..000000000000
--- a/core/java/android/service/euicc/IGetOtaStatusCallback.aidl
+++ /dev/null
@@ -1,22 +0,0 @@
-/*
- * Copyright (C) 2017 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.euicc;
-
-/** @hide */
-oneway interface IGetOtaStatusCallback {
- void onSuccess(int status);
-} \ No newline at end of file
diff --git a/core/java/android/service/euicc/IOtaStatusChangedCallback.aidl b/core/java/android/service/euicc/IOtaStatusChangedCallback.aidl
deleted file mode 100644
index caec75f13f61..000000000000
--- a/core/java/android/service/euicc/IOtaStatusChangedCallback.aidl
+++ /dev/null
@@ -1,22 +0,0 @@
-/*
- * Copyright (C) 2017 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.euicc;
-
-/** @hide */
-oneway interface IOtaStatusChangedCallback {
- void onOtaStatusChanged(int status);
-} \ No newline at end of file
diff --git a/core/java/android/service/euicc/IRetainSubscriptionsForFactoryResetCallback.aidl b/core/java/android/service/euicc/IRetainSubscriptionsForFactoryResetCallback.aidl
deleted file mode 100644
index 340401fe89cb..000000000000
--- a/core/java/android/service/euicc/IRetainSubscriptionsForFactoryResetCallback.aidl
+++ /dev/null
@@ -1,23 +0,0 @@
-/*
- * Copyright (C) 2017 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.euicc;
-
-/** @hide */
-oneway interface IRetainSubscriptionsForFactoryResetCallback {
- @UnsupportedAppUsage
- void onComplete(int result);
-} \ No newline at end of file
diff --git a/core/java/android/service/euicc/ISwitchToSubscriptionCallback.aidl b/core/java/android/service/euicc/ISwitchToSubscriptionCallback.aidl
deleted file mode 100644
index b8f984d1c28b..000000000000
--- a/core/java/android/service/euicc/ISwitchToSubscriptionCallback.aidl
+++ /dev/null
@@ -1,23 +0,0 @@
-/*
- * Copyright (C) 2017 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.euicc;
-
-/** @hide */
-oneway interface ISwitchToSubscriptionCallback {
- @UnsupportedAppUsage
- void onComplete(int result);
-} \ No newline at end of file
diff --git a/core/java/android/service/euicc/IUpdateSubscriptionNicknameCallback.aidl b/core/java/android/service/euicc/IUpdateSubscriptionNicknameCallback.aidl
deleted file mode 100644
index 0aa66978bb91..000000000000
--- a/core/java/android/service/euicc/IUpdateSubscriptionNicknameCallback.aidl
+++ /dev/null
@@ -1,23 +0,0 @@
-/*
- * Copyright (C) 2017 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.euicc;
-
-/** @hide */
-oneway interface IUpdateSubscriptionNicknameCallback {
- @UnsupportedAppUsage
- void onComplete(int result);
-} \ No newline at end of file
diff --git a/core/java/android/util/FeatureFlagUtils.java b/core/java/android/util/FeatureFlagUtils.java
index 7e0974033fa7..236e5ae6f952 100644
--- a/core/java/android/util/FeatureFlagUtils.java
+++ b/core/java/android/util/FeatureFlagUtils.java
@@ -41,6 +41,7 @@ public class FeatureFlagUtils {
public static final String SCREENRECORD_LONG_PRESS = "settings_screenrecord_long_press";
public static final String DYNAMIC_SYSTEM = "settings_dynamic_system";
public static final String SETTINGS_WIFITRACKER2 = "settings_wifitracker2";
+ public static final String SETTINGS_FUSE_FLAG = "settings_fuse";
private static final Map<String, String> DEFAULT_FLAGS;
@@ -48,6 +49,7 @@ public class FeatureFlagUtils {
DEFAULT_FLAGS = new HashMap<>();
DEFAULT_FLAGS.put("settings_audio_switcher", "true");
DEFAULT_FLAGS.put("settings_systemui_theme", "true");
+ DEFAULT_FLAGS.put(SETTINGS_FUSE_FLAG, "false");
DEFAULT_FLAGS.put(DYNAMIC_SYSTEM, "false");
DEFAULT_FLAGS.put(SEAMLESS_TRANSFER, "false");
DEFAULT_FLAGS.put(HEARING_AID_SETTINGS, "false");
diff --git a/core/java/android/view/SurfaceControl.java b/core/java/android/view/SurfaceControl.java
index 6458737d326d..1855a2645b7a 100644
--- a/core/java/android/view/SurfaceControl.java
+++ b/core/java/android/view/SurfaceControl.java
@@ -161,6 +161,8 @@ public final class SurfaceControl implements Parcelable {
private static native boolean nativeSetAllowedDisplayConfigs(IBinder displayToken,
int[] allowedConfigs);
private static native int[] nativeGetAllowedDisplayConfigs(IBinder displayToken);
+ private static native boolean nativeSetDesiredDisplayConfigSpecs(IBinder displayToken,
+ int defaultModeId, float minRefreshRate, float maxRefreshRate);
private static native int[] nativeGetDisplayColorModes(IBinder displayToken);
private static native SurfaceControl.DisplayPrimaries nativeGetDisplayNativePrimaries(
IBinder displayToken);
@@ -1492,6 +1494,19 @@ public final class SurfaceControl implements Parcelable {
/**
* @hide
*/
+ public static boolean setDesiredDisplayConfigSpecs(IBinder displayToken,
+ int defaultModeId, float minRefreshRate, float maxRefreshRate) {
+ if (displayToken == null) {
+ throw new IllegalArgumentException("displayToken must not be null");
+ }
+
+ return nativeSetDesiredDisplayConfigSpecs(displayToken, defaultModeId, minRefreshRate,
+ maxRefreshRate);
+ }
+
+ /**
+ * @hide
+ */
public static int[] getDisplayColorModes(IBinder displayToken) {
if (displayToken == null) {
throw new IllegalArgumentException("displayToken must not be null");
diff --git a/core/java/android/view/WindowlessViewRoot.java b/core/java/android/view/WindowlessViewRoot.java
index addf8e242e3d..68f2bde9c265 100644
--- a/core/java/android/view/WindowlessViewRoot.java
+++ b/core/java/android/view/WindowlessViewRoot.java
@@ -32,6 +32,14 @@ import android.os.IBinder;
public class WindowlessViewRoot {
private ViewRootImpl mViewRoot;
private WindowlessWindowManager mWm;
+
+ /** @hide */
+ public WindowlessViewRoot(@NonNull Context c, @NonNull Display d,
+ @NonNull WindowlessWindowManager wwm) {
+ mWm = wwm;
+ mViewRoot = new ViewRootImpl(c, d, mWm);
+ }
+
public WindowlessViewRoot(@NonNull Context c, @NonNull Display d,
@NonNull SurfaceControl rootSurface,
@Nullable IBinder hostInputToken) {
@@ -55,4 +63,12 @@ public class WindowlessViewRoot {
public void dispose() {
mViewRoot.dispatchDetachedFromWindow();
}
+
+ /**
+ * Tell this viewroot to clean itself up.
+ * @hide
+ */
+ public void die() {
+ mViewRoot.die(false /* immediate */);
+ }
}
diff --git a/core/java/android/view/WindowlessWindowManager.java b/core/java/android/view/WindowlessWindowManager.java
index cf39979ff7f9..2ba09750b001 100644
--- a/core/java/android/view/WindowlessWindowManager.java
+++ b/core/java/android/view/WindowlessWindowManager.java
@@ -34,7 +34,7 @@ import java.util.HashMap;
* By parcelling the root surface, the app can offer another app content for embedding.
* @hide
*/
-class WindowlessWindowManager implements IWindowSession {
+public class WindowlessWindowManager implements IWindowSession {
private final static String TAG = "WindowlessWindowManager";
private class State {
@@ -45,6 +45,7 @@ class WindowlessWindowManager implements IWindowSession {
mParams.copyFrom(p);
}
};
+
/**
* Used to store SurfaceControl we've built for clients to
* reconfigure them if relayout is called.
@@ -67,13 +68,18 @@ class WindowlessWindowManager implements IWindowSession {
private int mForceHeight = -1;
private int mForceWidth = -1;
- WindowlessWindowManager(Configuration c, SurfaceControl rootSurface, IBinder hostInputToken) {
+ public WindowlessWindowManager(Configuration c, SurfaceControl rootSurface,
+ IBinder hostInputToken) {
mRootSurface = rootSurface;
mConfiguration = new Configuration(c);
mRealWm = WindowManagerGlobal.getWindowSession();
mHostInputToken = hostInputToken;
}
+ protected void setConfiguration(Configuration configuration) {
+ mConfiguration.setTo(configuration);
+ }
+
/**
* Utility API.
*/
@@ -125,6 +131,17 @@ class WindowlessWindowManager implements IWindowSession {
@Override
public void remove(android.view.IWindow window) throws RemoteException {
mRealWm.remove(window);
+ State state;
+ synchronized (this) {
+ state = mStateForWindow.remove(window.asBinder());
+ }
+ if (state == null) {
+ throw new IllegalArgumentException(
+ "Invalid window token (never added or removed already)");
+ }
+ try (SurfaceControl.Transaction t = new SurfaceControl.Transaction()) {
+ t.remove(state.mSurfaceControl).apply();
+ }
}
private boolean isOpaque(WindowManager.LayoutParams attrs) {
@@ -165,10 +182,14 @@ class WindowlessWindowManager implements IWindowSession {
int height = surfaceInsets != null ?
attrs.height + surfaceInsets.top + surfaceInsets.bottom : attrs.height;
- t.show(sc)
- .setBufferSize(sc, width, height)
- .setOpaque(sc, isOpaque(attrs))
- .apply();
+ t.setBufferSize(sc, width, height)
+ .setOpaque(sc, isOpaque(attrs));
+ if (viewFlags == View.VISIBLE) {
+ t.show(sc);
+ } else {
+ t.hide(sc);
+ }
+ t.apply();
outSurfaceControl.copyFrom(sc);
outFrame.set(0, 0, attrs.width, attrs.height);
diff --git a/core/java/android/view/accessibility/AccessibilityEvent.java b/core/java/android/view/accessibility/AccessibilityEvent.java
index 32b0f413321a..34654edd00e8 100644
--- a/core/java/android/view/accessibility/AccessibilityEvent.java
+++ b/core/java/android/view/accessibility/AccessibilityEvent.java
@@ -17,6 +17,7 @@
package android.view.accessibility;
import android.annotation.IntDef;
+import android.annotation.NonNull;
import android.annotation.UnsupportedAppUsage;
import android.os.Build;
import android.os.Parcel;
@@ -796,10 +797,32 @@ public final class AccessibilityEvent extends AccessibilityRecord implements Par
private ArrayList<AccessibilityRecord> mRecords;
- /*
- * Hide constructor from clients.
+ /**
+ * Creates a new {@link AccessibilityEvent}.
*/
- private AccessibilityEvent() {
+ public AccessibilityEvent() {
+ if (DEBUG_ORIGIN) originStackTrace = Thread.currentThread().getStackTrace();
+ }
+
+
+ /**
+ * Creates a new {@link AccessibilityEvent} with the given <code>eventType</code>.
+ *
+ * @param eventType The event type.
+ */
+ public AccessibilityEvent(int eventType) {
+ mEventType = eventType;
+ if (DEBUG_ORIGIN) originStackTrace = Thread.currentThread().getStackTrace();
+ }
+
+ /**
+ * Copy constructor. Creates a new {@link AccessibilityEvent}, and this instance is initialized
+ * from the given <code>event</code>.
+ *
+ * @param event The other event.
+ */
+ public AccessibilityEvent(@NonNull AccessibilityEvent event) {
+ init(event);
}
/**
@@ -816,6 +839,15 @@ public final class AccessibilityEvent extends AccessibilityRecord implements Par
mWindowChangeTypes = event.mWindowChangeTypes;
mEventTime = event.mEventTime;
mPackageName = event.mPackageName;
+ if (event.mRecords != null) {
+ final int recordCount = event.mRecords.size();
+ mRecords = new ArrayList<>(recordCount);
+ for (int i = 0; i < recordCount; i++) {
+ final AccessibilityRecord record = event.mRecords.get(i);
+ final AccessibilityRecord recordClone = new AccessibilityRecord(record);
+ mRecords.add(recordClone);
+ }
+ }
if (DEBUG_ORIGIN) originStackTrace = event.originStackTrace;
}
@@ -1109,6 +1141,9 @@ public final class AccessibilityEvent extends AccessibilityRecord implements Par
* Returns a cached instance if such is available or a new one is
* instantiated with its type property set.
*
+ * <p>In most situations object pooling is not beneficial. Create a new instance using the
+ * constructor {@link #AccessibilityEvent(int)} instead.
+ *
* @param eventType The event type.
* @return An instance.
*/
@@ -1123,23 +1158,15 @@ public final class AccessibilityEvent extends AccessibilityRecord implements Par
* created. The returned instance is initialized from the given
* <code>event</code>.
*
+ * <p>In most situations object pooling is not beneficial. Create a new instance using the
+ * constructor {@link #AccessibilityEvent(AccessibilityEvent)} instead.
+ *
* @param event The other event.
* @return An instance.
*/
public static AccessibilityEvent obtain(AccessibilityEvent event) {
AccessibilityEvent eventClone = AccessibilityEvent.obtain();
eventClone.init(event);
-
- if (event.mRecords != null) {
- final int recordCount = event.mRecords.size();
- eventClone.mRecords = new ArrayList<AccessibilityRecord>(recordCount);
- for (int i = 0; i < recordCount; i++) {
- final AccessibilityRecord record = event.mRecords.get(i);
- final AccessibilityRecord recordClone = AccessibilityRecord.obtain(record);
- eventClone.mRecords.add(recordClone);
- }
- }
-
return eventClone;
}
@@ -1147,6 +1174,9 @@ public final class AccessibilityEvent extends AccessibilityRecord implements Par
* Returns a cached instance if such is available or a new one is
* instantiated.
*
+ * <p>In most situations object pooling is not beneficial. Create a new instance using the
+ * constructor {@link #AccessibilityEvent()} instead.
+ *
* @return An instance.
*/
public static AccessibilityEvent obtain() {
@@ -1162,6 +1192,8 @@ public final class AccessibilityEvent extends AccessibilityRecord implements Par
* <b>Note: You must not touch the object after calling this function.</b>
* </p>
*
+ * <p>In most situations object pooling is not beneficial, and recycling is not necessary.
+ *
* @throws IllegalStateException If the event is already recycled.
*/
@Override
diff --git a/core/java/android/view/accessibility/AccessibilityNodeInfo.java b/core/java/android/view/accessibility/AccessibilityNodeInfo.java
index a38955540927..66bf982894aa 100644
--- a/core/java/android/view/accessibility/AccessibilityNodeInfo.java
+++ b/core/java/android/view/accessibility/AccessibilityNodeInfo.java
@@ -775,15 +775,38 @@ public class AccessibilityNodeInfo implements Parcelable {
private TouchDelegateInfo mTouchDelegateInfo;
/**
- * Hide constructor from clients.
+ * Creates a new {@link AccessibilityNodeInfo}.
*/
- private AccessibilityNodeInfo() {
- /* do nothing */
+ public AccessibilityNodeInfo() {
}
- /** @hide */
- AccessibilityNodeInfo(AccessibilityNodeInfo info) {
- init(info);
+ /**
+ * Creates a new {@link AccessibilityNodeInfo} with the given <code>source</code>.
+ *
+ * @param source The source view.
+ */
+ public AccessibilityNodeInfo(@NonNull View source) {
+ setSource(source);
+ }
+
+ /**
+ * Creates a new {@link AccessibilityNodeInfo} with the given <code>source</code>.
+ *
+ * @param root The root of the virtual subtree.
+ * @param virtualDescendantId The id of the virtual descendant.
+ */
+ public AccessibilityNodeInfo(@NonNull View root, int virtualDescendantId) {
+ setSource(root, virtualDescendantId);
+ }
+
+ /**
+ * Copy constructor. Creates a new {@link AccessibilityNodeInfo}, and this new instance is
+ * initialized from the given <code>info</code>.
+ *
+ * @param info The other info.
+ */
+ public AccessibilityNodeInfo(@NonNull AccessibilityNodeInfo info) {
+ init(info, false /* usePoolingInfo */);
}
/**
@@ -911,7 +934,7 @@ public class AccessibilityNodeInfo implements Parcelable {
// when it is obtained. Enforce sealing again before we init to fail when a node has been
// recycled during a refresh to catch such errors earlier.
enforceSealed();
- init(refreshedInfo);
+ init(refreshedInfo, true /* usePoolingInfo */);
refreshedInfo.recycle();
return true;
}
@@ -3299,6 +3322,9 @@ public class AccessibilityNodeInfo implements Parcelable {
* Returns a cached instance if such is available otherwise a new one
* and sets the source.
*
+ * <p>In most situations object pooling is not beneficial. Create a new instance using the
+ * constructor {@link #AccessibilityNodeInfo(View)} instead.
+ *
* @param source The source view.
* @return An instance.
*
@@ -3314,6 +3340,9 @@ public class AccessibilityNodeInfo implements Parcelable {
* Returns a cached instance if such is available otherwise a new one
* and sets the source.
*
+ * <p>In most situations object pooling is not beneficial. Create a new instance using the
+ * constructor {@link #AccessibilityNodeInfo(View, int)} instead.
+ *
* @param root The root of the virtual subtree.
* @param virtualDescendantId The id of the virtual descendant.
* @return An instance.
@@ -3329,6 +3358,9 @@ public class AccessibilityNodeInfo implements Parcelable {
/**
* Returns a cached instance if such is available otherwise a new one.
*
+ * <p>In most situations object pooling is not beneficial. Create a new instance using the
+ * constructor {@link #AccessibilityNodeInfo()} instead.
+ *
* @return An instance.
*/
public static AccessibilityNodeInfo obtain() {
@@ -3344,12 +3376,15 @@ public class AccessibilityNodeInfo implements Parcelable {
* create. The returned instance is initialized from the given
* <code>info</code>.
*
+ * <p>In most situations object pooling is not beneficial. Create a new instance using the
+ * constructor {@link #AccessibilityNodeInfo(AccessibilityNodeInfo)} instead.
+ *
* @param info The other info.
* @return An instance.
*/
public static AccessibilityNodeInfo obtain(AccessibilityNodeInfo info) {
AccessibilityNodeInfo infoClone = AccessibilityNodeInfo.obtain();
- infoClone.init(info);
+ infoClone.init(info, true /* usePoolingInfo */);
return infoClone;
}
@@ -3358,6 +3393,8 @@ public class AccessibilityNodeInfo implements Parcelable {
* <p>
* <strong>Note:</strong> You must not touch the object after calling this function.
*
+ * <p>In most situations object pooling is not beneficial, and recycling is not necessary.
+ *
* @throws IllegalStateException If the info is already recycled.
*/
public void recycle() {
@@ -3647,8 +3684,9 @@ public class AccessibilityNodeInfo implements Parcelable {
* Initializes this instance from another one.
*
* @param other The other instance.
+ * @param usePoolingInfos whether using pooled object internally or not
*/
- private void init(AccessibilityNodeInfo other) {
+ private void init(AccessibilityNodeInfo other, boolean usePoolingInfos) {
mSealed = other.mSealed;
mSourceNodeId = other.mSourceNodeId;
mParentNodeId = other.mParentNodeId;
@@ -3707,6 +3745,18 @@ public class AccessibilityNodeInfo implements Parcelable {
mExtras = other.mExtras != null ? new Bundle(other.mExtras) : null;
+ if (usePoolingInfos) {
+ initPoolingInfos(other);
+ } else {
+ initCopyInfos(other);
+ }
+
+ final TouchDelegateInfo otherInfo = other.mTouchDelegateInfo;
+ mTouchDelegateInfo = (otherInfo != null)
+ ? new TouchDelegateInfo(otherInfo.mTargetMap, true) : null;
+ }
+
+ private void initPoolingInfos(AccessibilityNodeInfo other) {
if (mRangeInfo != null) mRangeInfo.recycle();
mRangeInfo = (other.mRangeInfo != null)
? RangeInfo.obtain(other.mRangeInfo) : null;
@@ -3716,10 +3766,20 @@ public class AccessibilityNodeInfo implements Parcelable {
if (mCollectionItemInfo != null) mCollectionItemInfo.recycle();
mCollectionItemInfo = (other.mCollectionItemInfo != null)
? CollectionItemInfo.obtain(other.mCollectionItemInfo) : null;
+ }
- final TouchDelegateInfo otherInfo = other.mTouchDelegateInfo;
- mTouchDelegateInfo = (otherInfo != null)
- ? new TouchDelegateInfo(otherInfo.mTargetMap, true) : null;
+ private void initCopyInfos(AccessibilityNodeInfo other) {
+ RangeInfo ri = other.mRangeInfo;
+ mRangeInfo = (ri == null) ? null
+ : new RangeInfo(ri.mType, ri.mMin, ri.mMax, ri.mCurrent);
+ CollectionInfo ci = other.mCollectionInfo;
+ mCollectionInfo = (ci == null) ? null
+ : new CollectionInfo(ci.mRowCount, ci.mColumnCount,
+ ci.mHierarchical, ci.mSelectionMode);
+ CollectionItemInfo cii = other.mCollectionItemInfo;
+ mCollectionItemInfo = (cii == null) ? null
+ : new CollectionItemInfo(cii.mRowIndex, cii.mRowSpan, cii.mColumnIndex,
+ cii.mColumnSpan, cii.mHeading, cii.mSelected);
}
/**
@@ -3854,7 +3914,7 @@ public class AccessibilityNodeInfo implements Parcelable {
* Clears the state of this instance.
*/
private void clear() {
- init(DEFAULT);
+ init(DEFAULT, true /* usePoolingInfo */);
}
private static boolean isDefaultStandardAction(AccessibilityAction action) {
@@ -4709,6 +4769,10 @@ public class AccessibilityNodeInfo implements Parcelable {
/**
* Obtains a pooled instance that is a clone of another one.
*
+ * <p>In most situations object pooling is not beneficial. Create a new instance using the
+ * constructor {@link AccessibilityNodeInfo.RangeInfo#AccessibilityNodeInfo.RangeInfo(int,
+ * float, float, float)} instead.
+ *
* @param other The instance to clone.
*
* @hide
@@ -4720,6 +4784,10 @@ public class AccessibilityNodeInfo implements Parcelable {
/**
* Obtains a pooled instance.
*
+ * <p>In most situations object pooling is not beneficial. Create a new instance using the
+ * constructor {@link AccessibilityNodeInfo.RangeInfo#AccessibilityNodeInfo.RangeInfo(int,
+ * float, float, float)} instead.
+ *
* @param type The type of the range.
* @param min The minimum value. Use {@code Float.NEGATIVE_INFINITY} if the range has no
* minimum.
@@ -4750,7 +4818,7 @@ public class AccessibilityNodeInfo implements Parcelable {
* maximum.
* @param current The current value.
*/
- private RangeInfo(int type, float min, float max, float current) {
+ public RangeInfo(int type, float min, float max, float current) {
mType = type;
mMin = min;
mMax = max;
@@ -4799,6 +4867,8 @@ public class AccessibilityNodeInfo implements Parcelable {
/**
* Recycles this instance.
+ *
+ * <p>In most situations object pooling is not beneficial, and recycling is not necessary.
*/
void recycle() {
clear();
@@ -4849,6 +4919,10 @@ public class AccessibilityNodeInfo implements Parcelable {
/**
* Obtains a pooled instance that is a clone of another one.
*
+ * <p>In most situations object pooling is not beneficial. Create a new instance using the
+ * constructor {@link
+ * AccessibilityNodeInfo.CollectionInfo#AccessibilityNodeInfo.CollectionInfo} instead.
+ *
* @param other The instance to clone.
* @hide
*/
@@ -4860,6 +4934,11 @@ public class AccessibilityNodeInfo implements Parcelable {
/**
* Obtains a pooled instance.
*
+ * <p>In most situations object pooling is not beneficial. Create a new instance using the
+ * constructor {@link
+ * AccessibilityNodeInfo.CollectionInfo#AccessibilityNodeInfo.CollectionInfo(int, int,
+ * boolean)} instead.
+ *
* @param rowCount The number of rows, or -1 if count is unknown.
* @param columnCount The number of columns, or -1 if count is unknown.
* @param hierarchical Whether the collection is hierarchical.
@@ -4872,6 +4951,11 @@ public class AccessibilityNodeInfo implements Parcelable {
/**
* Obtains a pooled instance.
*
+ * <p>In most situations object pooling is not beneficial. Create a new instance using the
+ * constructor {@link
+ * AccessibilityNodeInfo.CollectionInfo#AccessibilityNodeInfo.CollectionInfo(int, int,
+ * boolean, int)} instead.
+ *
* @param rowCount The number of rows.
* @param columnCount The number of columns.
* @param hierarchical Whether the collection is hierarchical.
@@ -4902,9 +4986,20 @@ public class AccessibilityNodeInfo implements Parcelable {
* @param rowCount The number of rows.
* @param columnCount The number of columns.
* @param hierarchical Whether the collection is hierarchical.
+ */
+ public CollectionInfo(int rowCount, int columnCount, boolean hierarchical) {
+ this(rowCount, columnCount, hierarchical, SELECTION_MODE_NONE);
+ }
+
+ /**
+ * Creates a new instance.
+ *
+ * @param rowCount The number of rows.
+ * @param columnCount The number of columns.
+ * @param hierarchical Whether the collection is hierarchical.
* @param selectionMode The collection's selection mode.
*/
- private CollectionInfo(int rowCount, int columnCount, boolean hierarchical,
+ public CollectionInfo(int rowCount, int columnCount, boolean hierarchical,
int selectionMode) {
mRowCount = rowCount;
mColumnCount = columnCount;
@@ -4955,6 +5050,8 @@ public class AccessibilityNodeInfo implements Parcelable {
/**
* Recycles this instance.
+ *
+ * <p>In most situations object pooling is not beneficial, and recycling is not necessary.
*/
void recycle() {
clear();
@@ -4991,6 +5088,11 @@ public class AccessibilityNodeInfo implements Parcelable {
/**
* Obtains a pooled instance that is a clone of another one.
*
+ * <p>In most situations object pooling is not beneficial. Create a new instance using the
+ * constructor {@link
+ * AccessibilityNodeInfo.CollectionItemInfo#AccessibilityNodeInfo.CollectionItemInfo}
+ * instead.
+ *
* @param other The instance to clone.
* @hide
*/
@@ -5002,6 +5104,11 @@ public class AccessibilityNodeInfo implements Parcelable {
/**
* Obtains a pooled instance.
*
+ * <p>In most situations object pooling is not beneficial. Create a new instance using the
+ * constructor {@link
+ * AccessibilityNodeInfo.CollectionItemInfo#AccessibilityNodeInfo.CollectionItemInfo(int,
+ * int, int, int, boolean)} instead.
+ *
* @param rowIndex The row index at which the item is located.
* @param rowSpan The number of rows the item spans.
* @param columnIndex The column index at which the item is located.
@@ -5017,6 +5124,11 @@ public class AccessibilityNodeInfo implements Parcelable {
/**
* Obtains a pooled instance.
*
+ * <p>In most situations object pooling is not beneficial. Creates a new instance using the
+ * constructor {@link
+ * AccessibilityNodeInfo.CollectionItemInfo#AccessibilityNodeInfo.CollectionItemInfo(int,
+ * int, int, int, boolean, boolean)} instead.
+ *
* @param rowIndex The row index at which the item is located.
* @param rowSpan The number of rows the item spans.
* @param columnIndex The column index at which the item is located.
@@ -5058,7 +5170,22 @@ public class AccessibilityNodeInfo implements Parcelable {
* @param columnSpan The number of columns the item spans.
* @param heading Whether the item is a heading.
*/
- private CollectionItemInfo(int rowIndex, int rowSpan, int columnIndex, int columnSpan,
+ public CollectionItemInfo(int rowIndex, int rowSpan, int columnIndex, int columnSpan,
+ boolean heading) {
+ this(rowIndex, rowSpan, columnIndex, columnSpan, heading, false);
+ }
+
+ /**
+ * Creates a new instance.
+ *
+ * @param rowIndex The row index at which the item is located.
+ * @param rowSpan The number of rows the item spans.
+ * @param columnIndex The column index at which the item is located.
+ * @param columnSpan The number of columns the item spans.
+ * @param heading Whether the item is a heading.
+ * @param selected Whether the item is selected.
+ */
+ public CollectionItemInfo(int rowIndex, int rowSpan, int columnIndex, int columnSpan,
boolean heading, boolean selected) {
mRowIndex = rowIndex;
mRowSpan = rowSpan;
@@ -5126,6 +5253,8 @@ public class AccessibilityNodeInfo implements Parcelable {
/**
* Recycles this instance.
+ *
+ * <p>In most situations object pooling is not beneficial, and recycling is not necessary.
*/
void recycle() {
clear();
diff --git a/core/java/android/view/accessibility/AccessibilityRecord.java b/core/java/android/view/accessibility/AccessibilityRecord.java
index d7d7e210e5f4..4f6c9ef55220 100644
--- a/core/java/android/view/accessibility/AccessibilityRecord.java
+++ b/core/java/android/view/accessibility/AccessibilityRecord.java
@@ -18,6 +18,7 @@ package android.view.accessibility;
import static com.android.internal.util.CollectionUtils.isEmpty;
+import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.UnsupportedAppUsage;
import android.os.Parcelable;
@@ -113,10 +114,20 @@ public class AccessibilityRecord {
int mConnectionId = UNDEFINED;
- /*
- * Hide constructor.
+ /**
+ * Creates a new {@link AccessibilityRecord}.
*/
- AccessibilityRecord() {
+ public AccessibilityRecord() {
+ }
+
+ /**
+ * Copy constructor. Creates a new {@link AccessibilityRecord}, and this instance is initialized
+ * with data from the given <code>record</code>.
+ *
+ * @param record The other record.
+ */
+ public AccessibilityRecord(@NonNull AccessibilityRecord record) {
+ init(record);
}
/**
@@ -790,6 +801,9 @@ public class AccessibilityRecord {
* instantiated. The instance is initialized with data from the
* given record.
*
+ * <p>In most situations object pooling is not beneficial. Create a new instance using the
+ * constructor {@link #AccessibilityRecord(AccessibilityRecord)} instead.
+ *
* @return An instance.
*/
public static AccessibilityRecord obtain(AccessibilityRecord record) {
@@ -802,6 +816,9 @@ public class AccessibilityRecord {
* Returns a cached instance if such is available or a new one is
* instantiated.
*
+ * <p>In most situations object pooling is not beneficial. Create a new instance using the
+ * constructor {@link #AccessibilityRecord()} instead.
+ *
* @return An instance.
*/
public static AccessibilityRecord obtain() {
@@ -823,6 +840,8 @@ public class AccessibilityRecord {
* <p>
* <strong>Note:</strong> You must not touch the object after calling this function.
*
+ * <p>In most situations object pooling is not beneficial, and recycling is not necessary.
+ *
* @throws IllegalStateException If the record is already recycled.
*/
public void recycle() {
diff --git a/core/java/android/view/accessibility/AccessibilityWindowInfo.java b/core/java/android/view/accessibility/AccessibilityWindowInfo.java
index 5fa8a6e0e06b..2cc6e9aebd74 100644
--- a/core/java/android/view/accessibility/AccessibilityWindowInfo.java
+++ b/core/java/android/view/accessibility/AccessibilityWindowInfo.java
@@ -119,12 +119,19 @@ public final class AccessibilityWindowInfo implements Parcelable {
private int mConnectionId = UNDEFINED_WINDOW_ID;
- private AccessibilityWindowInfo() {
- /* do nothing - hide constructor */
+ /**
+ * Creates a new {@link AccessibilityWindowInfo}.
+ */
+ public AccessibilityWindowInfo() {
}
- /** @hide */
- AccessibilityWindowInfo(AccessibilityWindowInfo info) {
+ /**
+ * Copy constructor. Creates a new {@link AccessibilityWindowInfo}, and this new instance is
+ * initialized from given <code>info</code>.
+ *
+ * @param info The other info.
+ */
+ public AccessibilityWindowInfo(@NonNull AccessibilityWindowInfo info) {
init(info);
}
@@ -469,6 +476,9 @@ public final class AccessibilityWindowInfo implements Parcelable {
* Returns a cached instance if such is available or a new one is
* created.
*
+ * <p>In most situations object pooling is not beneficial. Create a new instance using the
+ * constructor {@link #AccessibilityWindowInfo()} instead.
+ *
* @return An instance.
*/
public static AccessibilityWindowInfo obtain() {
@@ -487,6 +497,9 @@ public final class AccessibilityWindowInfo implements Parcelable {
* created. The returned instance is initialized from the given
* <code>info</code>.
*
+ * <p>In most situations object pooling is not beneficial. Create a new instance using the
+ * constructor {@link #AccessibilityWindowInfo(AccessibilityWindowInfo)} instead.
+ *
* @param info The other info.
* @return An instance.
*/
@@ -514,6 +527,8 @@ public final class AccessibilityWindowInfo implements Parcelable {
* <strong>Note:</strong> You must not touch the object after calling this function.
* </p>
*
+ * <p>In most situations object pooling is not beneficial, and recycling is not necessary.
+ *
* @throws IllegalStateException If the info is already recycled.
*/
public void recycle() {
diff --git a/core/java/com/android/internal/content/NativeLibraryHelper.java b/core/java/com/android/internal/content/NativeLibraryHelper.java
index fee8345d1660..0847fbdd2291 100644
--- a/core/java/com/android/internal/content/NativeLibraryHelper.java
+++ b/core/java/com/android/internal/content/NativeLibraryHelper.java
@@ -33,7 +33,6 @@ import android.content.pm.PackageParser.PackageLite;
import android.content.pm.PackageParser.PackageParserException;
import android.os.Build;
import android.os.SELinux;
-import android.os.SystemProperties;
import android.system.ErrnoException;
import android.system.Os;
import android.util.Slog;
@@ -444,6 +443,24 @@ public class NativeLibraryHelper {
return sum;
}
+ /**
+ * Configure the native library files managed by Incremental Service. Makes sure Incremental
+ * Service will create native library directories and set up native library binary files in the
+ * same structure as they are in non-incremental installations.
+ *
+ * @param pkg The package to be installed, including all the APK files.
+ * @param handle The pointer to an zip archive.
+ * @param libraryRoot The root directory of the native library files, e.g., lib/
+ * @param abiList The list of ABIs that are supported by the current device.
+ * @param useIsaSubdir Whether or not to set up a sub dir for the ISA.
+ * @return ABI code if installation succeeds or error code if installation fails.
+ */
+ public static int configureNativeBinariesForSupportedAbi(Package pkg, Handle handle,
+ File libraryRoot, String[] abiList, boolean useIsaSubdir) {
+ // TODO(b/136132412): Implement this.
+ return -1;
+ }
+
// We don't care about the other return values for now.
private static final int BITCODE_PRESENT = 1;
diff --git a/core/java/com/android/internal/os/BatteryStatsImpl.java b/core/java/com/android/internal/os/BatteryStatsImpl.java
index 75a58046faaa..b350028a4d83 100644
--- a/core/java/com/android/internal/os/BatteryStatsImpl.java
+++ b/core/java/com/android/internal/os/BatteryStatsImpl.java
@@ -1870,6 +1870,7 @@ public class BatteryStatsImpl extends BatteryStats {
mCount = computeCurrentCountLocked();
mUnpluggedReportedTotalTime = mCurrentReportedTotalTime = 0;
mUnpluggedReportedCount = mCurrentReportedCount = 0;
+ mTrackingReportedValues = false;
}
public void setUpdateVersion(int version) {
@@ -10800,10 +10801,10 @@ public class BatteryStatsImpl extends BatteryStats {
mHasWifiReporting = true;
// Measured in mAms
- final long txTimeMs = info.getControllerTxTimeMillis();
- final long rxTimeMs = info.getControllerRxTimeMillis();
- final long scanTimeMs = info.getControllerScanTimeMillis();
- final long idleTimeMs = info.getControllerIdleTimeMillis();
+ final long txTimeMs = info.getControllerTxDurationMillis();
+ final long rxTimeMs = info.getControllerRxDurationMillis();
+ final long scanTimeMs = info.getControllerScanDurationMillis();
+ final long idleTimeMs = info.getControllerIdleDurationMillis();
final long totalTimeMs = txTimeMs + rxTimeMs + idleTimeMs;
long leftOverRxTimeMs = rxTimeMs;
@@ -10946,13 +10947,14 @@ public class BatteryStatsImpl extends BatteryStats {
// Update WiFi controller stats.
- mWifiActivity.getRxTimeCounter().addCountLocked(info.getControllerRxTimeMillis());
+ mWifiActivity.getRxTimeCounter().addCountLocked(
+ info.getControllerRxDurationMillis());
mWifiActivity.getTxTimeCounters()[0].addCountLocked(
- info.getControllerTxTimeMillis());
+ info.getControllerTxDurationMillis());
mWifiActivity.getScanTimeCounter().addCountLocked(
- info.getControllerScanTimeMillis());
+ info.getControllerScanDurationMillis());
mWifiActivity.getIdleTimeCounter().addCountLocked(
- info.getControllerIdleTimeMillis());
+ info.getControllerIdleDurationMillis());
// POWER_WIFI_CONTROLLER_OPERATING_VOLTAGE is measured in mV, so convert to V.
final double opVolt = mPowerProfile.getAveragePower(
@@ -10960,7 +10962,7 @@ public class BatteryStatsImpl extends BatteryStats {
if (opVolt != 0) {
// We store the power drain as mAms.
mWifiActivity.getPowerCounter().addCountLocked(
- (long) (info.getControllerEnergyUsed() / opVolt));
+ (long) (info.getControllerEnergyUsedMicroJoules() / opVolt));
}
// Converting uWs to mAms.
// Conversion: (uWs * (1000ms / 1s) * (1mW / 1000uW)) / mV = mAms
diff --git a/core/java/com/android/internal/os/ZygoteInit.java b/core/java/com/android/internal/os/ZygoteInit.java
index 865ec27e00c4..9ee79eada626 100644
--- a/core/java/com/android/internal/os/ZygoteInit.java
+++ b/core/java/com/android/internal/os/ZygoteInit.java
@@ -254,18 +254,6 @@ public class ZygoteInit {
InputStream is;
try {
- // If we are profiling the boot image, avoid preloading classes.
- // Can't use device_config since we are the zygote.
- String prop = SystemProperties.get(
- "persist.device_config.runtime_native_boot.profilebootclasspath", "");
- // Might be empty if the property is unset since the default is "".
- if (prop.length() == 0) {
- prop = SystemProperties.get("dalvik.vm.profilebootclasspath", "");
- }
- if ("true".equals(prop)) {
- return;
- }
-
is = new FileInputStream(PRELOADED_CLASSES);
} catch (FileNotFoundException e) {
Log.e(TAG, "Couldn't find " + PRELOADED_CLASSES + ".");
@@ -345,6 +333,22 @@ public class ZygoteInit {
runtime.preloadDexCaches();
Trace.traceEnd(Trace.TRACE_TAG_DALVIK);
+ // If we are profiling the boot image, reset the Jit counters after preloading the
+ // classes. We want to preload for performance, and we can use method counters to
+ // infer what clases are used after calling resetJitCounters, for profile purposes.
+ // Can't use device_config since we are the zygote.
+ String prop = SystemProperties.get(
+ "persist.device_config.runtime_native_boot.profilebootclasspath", "");
+ // Might be empty if the property is unset since the default is "".
+ if (prop.length() == 0) {
+ prop = SystemProperties.get("dalvik.vm.profilebootclasspath", "");
+ }
+ if ("true".equals(prop)) {
+ Trace.traceBegin(Trace.TRACE_TAG_DALVIK, "ResetJitCounters");
+ runtime.resetJitCounters();
+ Trace.traceEnd(Trace.TRACE_TAG_DALVIK);
+ }
+
// Bring back root. We'll need it later if we're in the zygote.
if (droppedPriviliges) {
try {
diff --git a/core/java/com/android/internal/util/BitUtils.java b/core/java/com/android/internal/util/BitUtils.java
index b4bab809cc00..154ea52bf9ba 100644
--- a/core/java/com/android/internal/util/BitUtils.java
+++ b/core/java/com/android/internal/util/BitUtils.java
@@ -68,9 +68,9 @@ public final class BitUtils {
int[] result = new int[size];
int index = 0;
int bitPos = 0;
- while (val > 0) {
+ while (val != 0) {
if ((val & 1) == 1) result[index++] = bitPos;
- val = val >> 1;
+ val = val >>> 1;
bitPos++;
}
return result;
@@ -79,7 +79,7 @@ public final class BitUtils {
public static long packBits(int[] bits) {
long packed = 0;
for (int b : bits) {
- packed |= (1 << b);
+ packed |= (1L << b);
}
return packed;
}