diff options
40 files changed, 972 insertions, 208 deletions
diff --git a/Android.bp b/Android.bp index f735f9e34f39..90dca0350a0c 100644 --- a/Android.bp +++ b/Android.bp @@ -1418,29 +1418,6 @@ droidstubs { " --show-annotation android.annotation.TestApi ", } -filegroup { - name: "apache-http-stubs-sources", - srcs: [ - "core/java/org/apache/http/conn/ConnectTimeoutException.java", - "core/java/org/apache/http/conn/scheme/HostNameResolver.java", - "core/java/org/apache/http/conn/scheme/LayeredSocketFactory.java", - "core/java/org/apache/http/conn/scheme/SocketFactory.java", - "core/java/org/apache/http/conn/ssl/AbstractVerifier.java", - "core/java/org/apache/http/conn/ssl/AllowAllHostnameVerifier.java", - "core/java/org/apache/http/conn/ssl/AndroidDistinguishedNameParser.java", - "core/java/org/apache/http/conn/ssl/BrowserCompatHostnameVerifier.java", - "core/java/org/apache/http/conn/ssl/SSLSocketFactory.java", - "core/java/org/apache/http/conn/ssl/StrictHostnameVerifier.java", - "core/java/org/apache/http/conn/ssl/X509HostnameVerifier.java", - "core/java/org/apache/http/params/CoreConnectionPNames.java", - "core/java/org/apache/http/params/HttpConnectionParams.java", - "core/java/org/apache/http/params/HttpParams.java", - "core/java/android/net/http/SslCertificate.java", - "core/java/android/net/http/SslError.java", - "core/java/com/android/internal/util/HexDump.java", - ], -} - droidstubs { name: "api-stubs-docs", defaults: ["metalava-api-stubs-default"], diff --git a/api/system-current.txt b/api/system-current.txt index 2321e3e78b18..6574c802b339 100644 --- a/api/system-current.txt +++ b/api/system-current.txt @@ -8159,6 +8159,7 @@ package android.telephony { method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public boolean enableDataConnectivity(); method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public boolean enableModemForSlot(int, boolean); method @Deprecated @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void enableVideoCalling(boolean); + method @RequiresPermission(android.Manifest.permission.CONNECTIVITY_INTERNAL) public void factoryReset(int); method @Nullable @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public String getAidForAppType(int); method @Deprecated @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public java.util.List<android.service.carrier.CarrierIdentifier> getAllowedCarriers(int); method public java.util.List<java.lang.String> getCarrierPackageNamesForIntent(android.content.Intent); @@ -8812,11 +8813,14 @@ package android.telephony.ims { public class ImsMmTelManager { method @NonNull public static android.telephony.ims.ImsMmTelManager createForSubscriptionId(int); + method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public void getFeatureState(@NonNull java.util.function.Consumer<java.lang.Integer>, @NonNull java.util.concurrent.Executor) throws android.telephony.ims.ImsException; method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public int getVoWiFiModeSetting(); method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public int getVoWiFiRoamingModeSetting(); method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public boolean isAdvancedCallingSettingEnabled(); method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public boolean isAvailable(@android.telephony.ims.feature.MmTelFeature.MmTelCapabilities.MmTelCapability int, int); method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public boolean isCapable(@android.telephony.ims.feature.MmTelFeature.MmTelCapabilities.MmTelCapability int, int); + method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public void isSupported(@android.telephony.ims.feature.MmTelFeature.MmTelCapabilities.MmTelCapability int, int, @NonNull java.util.function.Consumer<java.lang.Boolean>, @NonNull java.util.concurrent.Executor) throws android.telephony.ims.ImsException; + method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public boolean isTtyOverVolteEnabled(); method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public boolean isVoWiFiRoamingSettingEnabled(); method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public boolean isVoWiFiSettingEnabled(); method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public boolean isVtSettingEnabled(); @@ -9343,6 +9347,8 @@ package android.telephony.ims.feature { method public final android.telephony.ims.feature.MmTelFeature.MmTelCapabilities queryCapabilityStatus(); method public void setUiTtyMode(int, @Nullable android.os.Message); method @android.telephony.ims.feature.MmTelFeature.ProcessCallResult public int shouldProcessCall(@NonNull String[]); + field public static final String EXTRA_IS_UNKNOWN_CALL = "android.telephony.ims.feature.extra.IS_UNKNOWN_CALL"; + field public static final String EXTRA_IS_USSD = "android.telephony.ims.feature.extra.IS_USSD"; field public static final int PROCESS_CALL_CSFB = 1; // 0x1 field public static final int PROCESS_CALL_IMS = 0; // 0x0 } diff --git a/core/java/android/provider/SettingsStringUtil.java b/core/java/android/provider/SettingsStringUtil.java index a3dc9471a1d0..9e495dd775dc 100644 --- a/core/java/android/provider/SettingsStringUtil.java +++ b/core/java/android/provider/SettingsStringUtil.java @@ -126,7 +126,7 @@ public class SettingsStringUtil { @Override protected String itemToString(ComponentName item) { - return item.flattenToString(); + return item != null ? item.flattenToString() : "null"; } public static String add(String delimitedElements, ComponentName element) { diff --git a/core/java/com/android/internal/compat/CompatibilityChangeConfig.java b/core/java/com/android/internal/compat/CompatibilityChangeConfig.java index fd2ada08edc1..36bc22906695 100644 --- a/core/java/com/android/internal/compat/CompatibilityChangeConfig.java +++ b/core/java/com/android/internal/compat/CompatibilityChangeConfig.java @@ -49,6 +49,18 @@ public final class CompatibilityChangeConfig implements Parcelable { return mChangeConfig.forceDisabledSet(); } + /** + * Returns if a change is enabled or disabled in this config. + */ + public boolean isChangeEnabled(long changeId) { + if (mChangeConfig.isForceEnabled(changeId)) { + return true; + } else if (mChangeConfig.isForceDisabled(changeId)) { + return false; + } + throw new IllegalStateException("Change " + changeId + " is not defined."); + } + private CompatibilityChangeConfig(Parcel in) { long[] enabledArray = in.createLongArray(); long[] disabledArray = in.createLongArray(); diff --git a/core/java/com/android/internal/compat/CompatibilityChangeInfo.aidl b/core/java/com/android/internal/compat/CompatibilityChangeInfo.aidl new file mode 100644 index 000000000000..3bc72771f99c --- /dev/null +++ b/core/java/com/android/internal/compat/CompatibilityChangeInfo.aidl @@ -0,0 +1,19 @@ +/* + * 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 com.android.internal.compat; + +parcelable CompatibilityChangeInfo; diff --git a/core/java/com/android/internal/compat/CompatibilityChangeInfo.java b/core/java/com/android/internal/compat/CompatibilityChangeInfo.java new file mode 100644 index 000000000000..e48e2df4043c --- /dev/null +++ b/core/java/com/android/internal/compat/CompatibilityChangeInfo.java @@ -0,0 +1,92 @@ +/* + * 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 com.android.internal.compat; + +import android.annotation.Nullable; +import android.os.Parcel; +import android.os.Parcelable; + +/** + * This class is a parcelable version of {@link com.android.server.compat.Change}. + * + * @hide + */ +public class CompatibilityChangeInfo implements Parcelable { + private final long mChangeId; + private final @Nullable String mName; + private final int mEnableAfterTargetSdk; + private final boolean mDisabled; + + public long getId() { + return mChangeId; + } + + @Nullable + public String getName() { + return mName; + } + + public int getEnableAfterTargetSdk() { + return mEnableAfterTargetSdk; + } + + public boolean getDisabled() { + return mDisabled; + } + + public CompatibilityChangeInfo( + Long changeId, String name, int enableAfterTargetSdk, boolean disabled) { + this.mChangeId = changeId; + this.mName = name; + this.mEnableAfterTargetSdk = enableAfterTargetSdk; + this.mDisabled = disabled; + } + + private CompatibilityChangeInfo(Parcel in) { + mChangeId = in.readLong(); + mName = in.readString(); + mEnableAfterTargetSdk = in.readInt(); + mDisabled = in.readBoolean(); + } + + @Override + public int describeContents() { + return 0; + } + + @Override + public void writeToParcel(Parcel dest, int flags) { + dest.writeLong(mChangeId); + dest.writeString(mName); + dest.writeInt(mEnableAfterTargetSdk); + dest.writeBoolean(mDisabled); + } + + public static final Parcelable.Creator<CompatibilityChangeInfo> CREATOR = + new Parcelable.Creator<CompatibilityChangeInfo>() { + + @Override + public CompatibilityChangeInfo createFromParcel(Parcel in) { + return new CompatibilityChangeInfo(in); + } + + @Override + public CompatibilityChangeInfo[] newArray(int size) { + return new CompatibilityChangeInfo[size]; + } + }; +} diff --git a/core/java/com/android/internal/compat/IPlatformCompat.aidl b/core/java/com/android/internal/compat/IPlatformCompat.aidl index 8391ad2f12c2..5857642cbd4e 100644 --- a/core/java/com/android/internal/compat/IPlatformCompat.aidl +++ b/core/java/com/android/internal/compat/IPlatformCompat.aidl @@ -17,8 +17,10 @@ package com.android.internal.compat; import android.content.pm.ApplicationInfo; +import java.util.Map; parcelable CompatibilityChangeConfig; +parcelable CompatibilityChangeInfo; /** * Platform private API for talking with the PlatformCompat service. @@ -146,4 +148,21 @@ interface IPlatformCompat * */ void clearOverrides(in String packageName); + + /** + * Get configs for an application. + * + * @param appInfo The application whose config will be returned. + * + * @return A {@link CompatibilityChangeConfig}, representing whether a change is enabled for + * the given app or not. + */ + CompatibilityChangeConfig getAppConfig(in ApplicationInfo appInfo); + + /** + * List all compatibility changes. + * + * @return An array of {@link CompatChangeInfo} known to the service. + */ + CompatibilityChangeInfo[] listAllChanges(); } diff --git a/core/proto/OWNERS b/core/proto/OWNERS index 6ab0fc91d744..74ced8921799 100644 --- a/core/proto/OWNERS +++ b/core/proto/OWNERS @@ -3,8 +3,10 @@ # Metrics joeo@google.com singhtejinder@google.com +yanmin@google.com yaochen@google.com yro@google.com +zhouwenjie@google.com # Settings UI per-file settings_enums.proto=tmfang@google.com diff --git a/location/lib/Android.bp b/location/lib/Android.bp index fe0f669508eb..cd45e8e6ffa6 100644 --- a/location/lib/Android.bp +++ b/location/lib/Android.bp @@ -17,10 +17,8 @@ java_sdk_library { name: "com.android.location.provider", srcs: ["java/**/*.java"], - api_srcs: [":framework-all-sources"], libs: [ "androidx.annotation_annotation", - "framework-all", ], api_packages: ["com.android.location.provider"], } diff --git a/media/jni/Android.bp b/media/jni/Android.bp index e6c1c67b98e5..f873eeb9aa00 100644 --- a/media/jni/Android.bp +++ b/media/jni/Android.bp @@ -100,13 +100,14 @@ cc_library_shared { "android_media_Utils.cpp", ], + header_libs: [ + "libgui_headers", + ], + shared_libs: [ "liblog", - "libgui", - "libnativewindow", "libui", "libutils", - "android.hidl.token@1.0-utils", ], include_dirs: [ diff --git a/media/lib/signer/Android.bp b/media/lib/signer/Android.bp index 6b03e4de57d7..3b2578754087 100644 --- a/media/lib/signer/Android.bp +++ b/media/lib/signer/Android.bp @@ -17,7 +17,5 @@ java_sdk_library { name: "com.android.mediadrm.signer", srcs: ["java/**/*.java"], - api_srcs: [":framework-all-sources"], - libs: ["framework-all"], api_packages: ["com.android.mediadrm.signer"], } diff --git a/packages/Shell/AndroidManifest.xml b/packages/Shell/AndroidManifest.xml index 11b0487a64b2..047ac5984fe3 100644 --- a/packages/Shell/AndroidManifest.xml +++ b/packages/Shell/AndroidManifest.xml @@ -173,6 +173,8 @@ <uses-permission android:name="android.permission.MANAGE_WIFI_WHEN_WIRELESS_CONSENT_REQUIRED" /> <!-- Permission needed to invoke DynamicSystem (AOT) --> <uses-permission android:name="android.permission.INSTALL_DYNAMIC_SYSTEM" /> + <!-- Used to clean up heap dumps on boot. --> + <uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" /> <uses-permission android:name="android.permission.CONTROL_KEYGUARD" /> @@ -201,7 +203,7 @@ <!-- Permission required to test ExplicitHealthCheckServiceImpl. --> <uses-permission android:name="android.permission.BIND_EXPLICIT_HEALTH_CHECK_SERVICE" /> - + <!-- Permission required for CTS test - CrossProfileAppsHostSideTest --> <uses-permission android:name="android.permission.INTERACT_ACROSS_PROFILES"/> @@ -231,12 +233,25 @@ </intent-filter> </provider> + <provider android:name=".HeapDumpProvider" + android:authorities="com.android.shell.heapdump" + android:grantUriPermissions="true" + android:exported="true" /> + <activity android:name=".BugreportWarningActivity" android:finishOnCloseSystemDialogs="true" android:excludeFromRecents="true" android:exported="false" /> + <activity android:name=".HeapDumpActivity" + android:theme="@*android:style/Theme.Translucent.NoTitleBar" + android:label="@*android:string/dump_heap_title" + android:finishOnCloseSystemDialogs="true" + android:noHistory="true" + android:excludeFromRecents="true" + android:exported="false" /> + <receiver android:name=".BugreportReceiver" android:permission="android.permission.DUMP"> @@ -254,6 +269,16 @@ </intent-filter> </receiver> + <receiver + android:name=".HeapDumpReceiver" + android:permission="android.permission.DUMP"> + <intent-filter> + <action android:name="android.intent.action.BOOT_COMPLETED" /> + <action android:name="com.android.internal.intent.action.HEAP_DUMP_FINISHED" /> + <action android:name="com.android.shell.action.DELETE_HEAP_DUMP" /> + </intent-filter> + </receiver> + <service android:name=".BugreportProgressService" android:exported="false"/> diff --git a/packages/Shell/src/com/android/shell/BugreportProgressService.java b/packages/Shell/src/com/android/shell/BugreportProgressService.java index 857cb2af41f6..29c61ee70f7d 100644 --- a/packages/Shell/src/com/android/shell/BugreportProgressService.java +++ b/packages/Shell/src/com/android/shell/BugreportProgressService.java @@ -1410,7 +1410,7 @@ public class BugreportProgressService extends Service { return false; } - private static boolean isTv(Context context) { + static boolean isTv(Context context) { return context.getPackageManager().hasSystemFeature(PackageManager.FEATURE_LEANBACK); } diff --git a/packages/Shell/src/com/android/shell/HeapDumpActivity.java b/packages/Shell/src/com/android/shell/HeapDumpActivity.java new file mode 100644 index 000000000000..0ff0d3353041 --- /dev/null +++ b/packages/Shell/src/com/android/shell/HeapDumpActivity.java @@ -0,0 +1,142 @@ +/* + * 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 com.android.shell; + +import static com.android.shell.HeapDumpProvider.makeUri; +import static com.android.shell.HeapDumpReceiver.ACTION_DELETE_HEAP_DUMP; +import static com.android.shell.HeapDumpReceiver.EXTRA_IS_USER_INITIATED; +import static com.android.shell.HeapDumpReceiver.EXTRA_PROCESS_NAME; +import static com.android.shell.HeapDumpReceiver.EXTRA_REPORT_PACKAGE; +import static com.android.shell.HeapDumpReceiver.EXTRA_SIZE_BYTES; + +import android.app.Activity; +import android.app.ActivityManager; +import android.app.AlertDialog; +import android.content.ActivityNotFoundException; +import android.content.ClipData; +import android.content.Intent; +import android.net.Uri; +import android.os.Bundle; +import android.os.Process; +import android.util.DebugUtils; +import android.util.Log; + +import com.android.internal.R; + +/** + * This activity is displayed when the system has collected a heap dump. + */ +public class HeapDumpActivity extends Activity { + private static final String TAG = "HeapDumpActivity"; + + static final String KEY_URI = "uri"; + + private AlertDialog mDialog; + private Uri mDumpUri; + private boolean mHandled = false; + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + + String process = getIntent().getStringExtra(EXTRA_PROCESS_NAME); + long size = getIntent().getLongExtra(EXTRA_SIZE_BYTES, 0); + final boolean isUserInitiated = getIntent().getBooleanExtra(EXTRA_IS_USER_INITIATED, false); + final int uid = getIntent().getIntExtra(Intent.EXTRA_UID, 0); + final boolean isSystemProcess = uid == Process.SYSTEM_UID; + mDumpUri = makeUri(process); + final String procDisplayName = isSystemProcess + ? getString(com.android.internal.R.string.android_system_label) + : process; + + final Intent sendIntent = new Intent(); + ClipData clip = ClipData.newUri(getContentResolver(), "Heap Dump", mDumpUri); + sendIntent.setClipData(clip); + sendIntent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION); + sendIntent.setType(clip.getDescription().getMimeType(0)); + sendIntent.putExtra(Intent.EXTRA_STREAM, mDumpUri); + + String directLaunchPackage = getIntent().getStringExtra(EXTRA_REPORT_PACKAGE); + if (directLaunchPackage != null) { + sendIntent.setAction(ActivityManager.ACTION_REPORT_HEAP_LIMIT); + sendIntent.setPackage(directLaunchPackage); + try { + startActivity(sendIntent); + mHandled = true; + finish(); + return; + } catch (ActivityNotFoundException e) { + Log.e(TAG, "Unable to direct launch to " + directLaunchPackage, e); + } + } + + final int messageId; + if (isUserInitiated) { + messageId = com.android.internal.R.string.dump_heap_ready_text; + } else if (isSystemProcess) { + messageId = com.android.internal.R.string.dump_heap_system_text; + } else { + messageId = com.android.internal.R.string.dump_heap_text; + } + mDialog = new AlertDialog.Builder(this, android.R.style.Theme_Material_Light_Dialog_Alert) + .setTitle(com.android.internal.R.string.dump_heap_title) + .setMessage(getString(messageId, procDisplayName, + DebugUtils.sizeValueToString(size, null))) + .setNegativeButton(android.R.string.cancel, (dialog, which) -> { + mHandled = true; + finish(); + }) + .setNeutralButton(R.string.delete, (dialog, which) -> { + mHandled = true; + Intent deleteIntent = new Intent(ACTION_DELETE_HEAP_DUMP); + deleteIntent.setClass(getApplicationContext(), HeapDumpReceiver.class); + deleteIntent.putExtra(KEY_URI, mDumpUri.toString()); + sendBroadcast(deleteIntent); + finish(); + }) + .setPositiveButton(android.R.string.ok, (dialog, which) -> { + mHandled = true; + sendIntent.setAction(Intent.ACTION_SEND); + sendIntent.setPackage(null); + startActivity(Intent.createChooser(sendIntent, + getText(com.android.internal.R.string.dump_heap_title))); + finish(); + }) + .show(); + } + + @Override + protected void onStop() { + super.onStop(); + if (!isChangingConfigurations()) { + if (!mHandled) { + Intent deleteIntent = new Intent(ACTION_DELETE_HEAP_DUMP); + deleteIntent.setClass(getApplicationContext(), HeapDumpReceiver.class); + deleteIntent.putExtra(KEY_URI, mDumpUri.toString()); + sendBroadcast(deleteIntent); + } + } + } + + @Override + protected void onDestroy() { + super.onDestroy(); + if (mDialog != null) { + mDialog.dismiss(); + } + } +} diff --git a/packages/Shell/src/com/android/shell/HeapDumpProvider.java b/packages/Shell/src/com/android/shell/HeapDumpProvider.java new file mode 100644 index 000000000000..3eceb9118b12 --- /dev/null +++ b/packages/Shell/src/com/android/shell/HeapDumpProvider.java @@ -0,0 +1,101 @@ +/* + * 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 com.android.shell; + +import android.annotation.NonNull; +import android.content.ContentProvider; +import android.content.ContentValues; +import android.database.Cursor; +import android.net.Uri; +import android.os.Binder; +import android.os.ParcelFileDescriptor; +import android.os.Process; + +import java.io.File; +import java.io.FileNotFoundException; + +/** ContentProvider to write and access heap dumps. */ +public class HeapDumpProvider extends ContentProvider { + private static final String FILENAME_SUFFIX = "_javaheap.bin"; + private static final Object sLock = new Object(); + + private File mRoot; + + @Override + public boolean onCreate() { + synchronized (sLock) { + mRoot = new File(getContext().createCredentialProtectedStorageContext().getFilesDir(), + "heapdumps"); + return mRoot.mkdir(); + } + } + + @Override + public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, + String sortOrder) { + return null; + } + + @Override + public String getType(Uri uri) { + return "application/octet-stream"; + } + + @Override + public Uri insert(Uri uri, ContentValues values) { + throw new UnsupportedOperationException("Insert not allowed."); + } + + @Override + public int delete(Uri uri, String selection, String[] selectionArgs) { + String path = sanitizePath(uri.getEncodedPath()); + String tag = Uri.decode(path); + return (new File(mRoot, tag)).delete() ? 1 : 0; + } + + @Override + public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) { + throw new UnsupportedOperationException("Update not allowed."); + } + + @Override + public ParcelFileDescriptor openFile(Uri uri, String mode) throws FileNotFoundException { + String path = sanitizePath(uri.getEncodedPath()); + String tag = Uri.decode(path); + final int pMode; + if (Binder.getCallingUid() == Process.SYSTEM_UID) { + pMode = ParcelFileDescriptor.MODE_CREATE + | ParcelFileDescriptor.MODE_TRUNCATE + | ParcelFileDescriptor.MODE_WRITE_ONLY; + } else { + pMode = ParcelFileDescriptor.MODE_READ_ONLY; + } + + synchronized (sLock) { + return ParcelFileDescriptor.open(new File(mRoot, tag), pMode); + } + } + + @NonNull + static Uri makeUri(@NonNull String procName) { + return Uri.parse("content://com.android.shell.heapdump/" + procName + FILENAME_SUFFIX); + } + + private String sanitizePath(String path) { + return path.replaceAll("[^a-zA-Z0-9_.]", ""); + } +} diff --git a/packages/Shell/src/com/android/shell/HeapDumpReceiver.java b/packages/Shell/src/com/android/shell/HeapDumpReceiver.java new file mode 100644 index 000000000000..858c521eaed5 --- /dev/null +++ b/packages/Shell/src/com/android/shell/HeapDumpReceiver.java @@ -0,0 +1,188 @@ +/* + * 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 com.android.shell; + +import static com.android.shell.BugreportProgressService.isTv; + +import android.annotation.Nullable; +import android.app.Notification; +import android.app.NotificationChannel; +import android.app.NotificationManager; +import android.app.PendingIntent; +import android.content.BroadcastReceiver; +import android.content.Context; +import android.content.Intent; +import android.net.Uri; +import android.os.AsyncTask; +import android.os.FileUtils; +import android.os.Process; +import android.text.format.DateUtils; +import android.util.Log; + +import java.io.File; + +/** + * Receiver that handles finished heap dumps. + */ +public class HeapDumpReceiver extends BroadcastReceiver { + private static final String TAG = "HeapDumpReceiver"; + + /** + * Broadcast action to determine when to delete a specific dump heap. Must include a {@link + * HeapDumpActivity#KEY_URI} String extra. + */ + static final String ACTION_DELETE_HEAP_DUMP = "com.android.shell.action.DELETE_HEAP_DUMP"; + + /** Broadcast sent when heap dump collection has been completed. */ + private static final String ACTION_HEAP_DUMP_FINISHED = + "com.android.internal.intent.action.HEAP_DUMP_FINISHED"; + + /** The process we are reporting */ + static final String EXTRA_PROCESS_NAME = "com.android.internal.extra.heap_dump.PROCESS_NAME"; + + /** The size limit the process reached. */ + static final String EXTRA_SIZE_BYTES = "com.android.internal.extra.heap_dump.SIZE_BYTES"; + + /** Whether the user initiated the dump or not. */ + static final String EXTRA_IS_USER_INITIATED = + "com.android.internal.extra.heap_dump.IS_USER_INITIATED"; + + /** Optional name of package to directly launch. */ + static final String EXTRA_REPORT_PACKAGE = + "com.android.internal.extra.heap_dump.REPORT_PACKAGE"; + + private static final String NOTIFICATION_CHANNEL_ID = "heapdumps"; + private static final int NOTIFICATION_ID = 2019; + + /** + * Always keep heap dumps taken in the last week. + */ + private static final long MIN_KEEP_AGE_MS = DateUtils.WEEK_IN_MILLIS; + + @Override + public void onReceive(Context context, Intent intent) { + Log.d(TAG, "onReceive(): " + intent); + final String action = intent.getAction(); + if (action == null) { + Log.e(TAG, "null action received"); + return; + } + switch (action) { + case Intent.ACTION_BOOT_COMPLETED: + cleanupOldFiles(context); + break; + case ACTION_DELETE_HEAP_DUMP: + deleteHeapDump(context, intent.getStringExtra(HeapDumpActivity.KEY_URI)); + break; + case ACTION_HEAP_DUMP_FINISHED: + showDumpNotification(context, intent); + break; + } + } + + private void cleanupOldFiles(Context context) { + final PendingResult result = goAsync(); + new AsyncTask<Void, Void, Void>() { + @Override + protected Void doInBackground(Void... params) { + try { + Log.d(TAG, "Deleting from " + new File(context.getFilesDir(), "heapdumps")); + FileUtils.deleteOlderFiles(new File(context.getFilesDir(), "heapdumps"), 0, + MIN_KEEP_AGE_MS); + } catch (RuntimeException e) { + Log.e(TAG, "Couldn't delete old files", e); + } + result.finish(); + return null; + } + }.execute(); + } + + private void deleteHeapDump(Context context, @Nullable final String uri) { + if (uri == null) { + Log.e(TAG, "null URI for delete heap dump intent"); + return; + } + final PendingResult result = goAsync(); + new AsyncTask<Void, Void, Void>() { + @Override + protected Void doInBackground(Void... params) { + context.getContentResolver().delete(Uri.parse(uri), null, null); + result.finish(); + return null; + } + }.execute(); + } + + private void showDumpNotification(Context context, Intent intent) { + final boolean isUserInitiated = intent.getBooleanExtra( + EXTRA_IS_USER_INITIATED, false); + final String procName = intent.getStringExtra(EXTRA_PROCESS_NAME); + final int uid = intent.getIntExtra(Intent.EXTRA_UID, 0); + + final String reportPackage = intent.getStringExtra( + EXTRA_REPORT_PACKAGE); + final long size = intent.getLongExtra(EXTRA_SIZE_BYTES, 0); + + if (procName == null) { + Log.e(TAG, "No process name sent over"); + return; + } + + NotificationManager nm = NotificationManager.from(context); + nm.createNotificationChannel( + new NotificationChannel(NOTIFICATION_CHANNEL_ID, + "Heap dumps", + NotificationManager.IMPORTANCE_DEFAULT)); + + final int titleId = isUserInitiated + ? com.android.internal.R.string.dump_heap_ready_notification + : com.android.internal.R.string.dump_heap_notification; + final String procDisplayName = uid == Process.SYSTEM_UID + ? context.getString(com.android.internal.R.string.android_system_label) + : procName; + String text = context.getString(titleId, procDisplayName); + + Intent shareIntent = new Intent(); + shareIntent.setClassName(context, HeapDumpActivity.class.getName()); + shareIntent.putExtra(EXTRA_PROCESS_NAME, procName); + shareIntent.putExtra(EXTRA_SIZE_BYTES, size); + shareIntent.putExtra(EXTRA_IS_USER_INITIATED, isUserInitiated); + shareIntent.putExtra(Intent.EXTRA_UID, uid); + if (reportPackage != null) { + shareIntent.putExtra(EXTRA_REPORT_PACKAGE, reportPackage); + } + final Notification.Builder builder = new Notification.Builder(context, + NOTIFICATION_CHANNEL_ID) + .setSmallIcon( + isTv(context) ? R.drawable.ic_bug_report_black_24dp + : com.android.internal.R.drawable.stat_sys_adb) + .setLocalOnly(true) + .setColor(context.getColor( + com.android.internal.R.color.system_notification_accent_color)) + .setContentTitle(text) + .setTicker(text) + .setAutoCancel(true) + .setContentText(context.getText( + com.android.internal.R.string.dump_heap_notification_detail)) + .setContentIntent(PendingIntent.getActivity(context, 2, shareIntent, + PendingIntent.FLAG_UPDATE_CURRENT)); + + Log.v(TAG, "Creating share heap dump notification"); + NotificationManager.from(context).notify(NOTIFICATION_ID, builder.build()); + } +} diff --git a/packages/Tethering/Android.bp b/packages/Tethering/Android.bp index ca69c187089d..998572fc5679 100644 --- a/packages/Tethering/Android.bp +++ b/packages/Tethering/Android.bp @@ -21,6 +21,7 @@ java_defaults { "src/**/*.java", ":framework-tethering-shared-srcs", ":services-tethering-shared-srcs", + ":servicescore-tethering-src", ], static_libs: [ "androidx.annotation_annotation", @@ -67,13 +68,23 @@ android_app { // This group will be removed when tethering migration is done. filegroup { - name: "tethering-services-srcs", + name: "tethering-servicescore-srcs", srcs: [ + "src/com/android/server/connectivity/tethering/EntitlementManager.java", "src/com/android/server/connectivity/tethering/TetheringConfiguration.java", + "src/com/android/server/connectivity/tethering/UpstreamNetworkMonitor.java", + ], +} + +// This group will be removed when tethering migration is done. +filegroup { + name: "tethering-servicesnet-srcs", + srcs: [ "src/android/net/dhcp/DhcpServerCallbacks.java", "src/android/net/dhcp/DhcpServingParamsParcelExt.java", "src/android/net/ip/IpServer.java", "src/android/net/ip/RouterAdvertisementDaemon.java", "src/android/net/util/InterfaceSet.java", + "src/android/net/util/PrefixUtils.java", ], } diff --git a/packages/Tethering/AndroidManifestBase.xml b/packages/Tethering/AndroidManifestBase.xml index b9cac1994359..dc013da33869 100644 --- a/packages/Tethering/AndroidManifestBase.xml +++ b/packages/Tethering/AndroidManifestBase.xml @@ -23,7 +23,6 @@ <application android:label="Tethering" android:defaultToDeviceProtectedStorage="true" - android:directBootAware="true" - android:usesCleartextTraffic="true"> + android:directBootAware="true"> </application> </manifest> diff --git a/services/net/java/android/net/util/PrefixUtils.java b/packages/Tethering/src/android/net/util/PrefixUtils.java index f60694aaedc9..f203e9995f3d 100644 --- a/services/net/java/android/net/util/PrefixUtils.java +++ b/packages/Tethering/src/android/net/util/PrefixUtils.java @@ -42,16 +42,19 @@ public class PrefixUtils { public static final IpPrefix DEFAULT_WIFI_P2P_PREFIX = pfx("192.168.49.0/24"); + /** Get non forwardable prefixes. */ public static Set<IpPrefix> getNonForwardablePrefixes() { final HashSet<IpPrefix> prefixes = new HashSet<>(); addNonForwardablePrefixes(prefixes); return prefixes; } + /** Add non forwardable prefixes. */ public static void addNonForwardablePrefixes(Set<IpPrefix> prefixes) { Collections.addAll(prefixes, MIN_NON_FORWARDABLE_PREFIXES); } + /** Get local prefixes from |lp|. */ public static Set<IpPrefix> localPrefixesFrom(LinkProperties lp) { final HashSet<IpPrefix> localPrefixes = new HashSet<>(); if (lp == null) return localPrefixes; @@ -66,10 +69,12 @@ public class PrefixUtils { return localPrefixes; } + /** Convert LinkAddress |addr| to IpPrefix. */ public static IpPrefix asIpPrefix(LinkAddress addr) { return new IpPrefix(addr.getAddress(), addr.getPrefixLength()); } + /** Convert InetAddress |ip| to IpPrefix. */ public static IpPrefix ipAddressAsPrefix(InetAddress ip) { final int bitLength = (ip instanceof Inet4Address) ? NetworkConstants.IPV4_ADDR_BITS diff --git a/services/core/java/com/android/server/connectivity/tethering/EntitlementManager.java b/packages/Tethering/src/com/android/server/connectivity/tethering/EntitlementManager.java index f952bcef5606..6b0f1de7ce85 100644 --- a/services/core/java/com/android/server/connectivity/tethering/EntitlementManager.java +++ b/packages/Tethering/src/com/android/server/connectivity/tethering/EntitlementManager.java @@ -87,7 +87,6 @@ public class EntitlementManager { private static final int EVENT_MAYBE_RUN_PROVISIONING = 3; private static final int EVENT_GET_ENTITLEMENT_VALUE = 4; - // The ArraySet contains enabled downstream types, ex: // {@link ConnectivityManager.TETHERING_WIFI} // {@link ConnectivityManager.TETHERING_USB} @@ -112,7 +111,6 @@ public class EntitlementManager { public EntitlementManager(Context ctx, StateMachine tetherMasterSM, SharedLog log, int permissionChangeMessageCode, MockableSystemProperties systemProperties) { - mContext = ctx; mLog = log.forSubComponent(TAG); mCurrentTethers = new ArraySet<Integer>(); @@ -138,7 +136,7 @@ public class EntitlementManager { /** * Ui entitlement check fails in |downstream|. * - * @param downstream tethering type from ConnectivityManager.TETHERING_{@code *}. + * @param downstream tethering type from ConnectivityManager.TETHERING_{@code *}. */ void onUiEntitlementFailed(int downstream); } @@ -662,7 +660,6 @@ public class EntitlementManager { private void handleGetLatestTetheringEntitlementValue(int downstream, ResultReceiver receiver, boolean showEntitlementUi) { - final TetheringConfiguration config = mFetcher.fetchTetheringConfiguration(); if (!isTetherProvisioningRequired(config)) { receiver.send(TETHER_ERROR_NO_ERROR, null); diff --git a/services/core/java/com/android/server/connectivity/tethering/UpstreamNetworkMonitor.java b/packages/Tethering/src/com/android/server/connectivity/tethering/UpstreamNetworkMonitor.java index 3a9e21f943d8..9769596ab1d0 100644 --- a/services/core/java/com/android/server/connectivity/tethering/UpstreamNetworkMonitor.java +++ b/packages/Tethering/src/com/android/server/connectivity/tethering/UpstreamNetworkMonitor.java @@ -146,6 +146,7 @@ public class UpstreamNetworkMonitor { } } + /** Listen all networks. */ public void startObserveAllNetworks() { stop(); @@ -155,6 +156,13 @@ public class UpstreamNetworkMonitor { cm().registerNetworkCallback(listenAllRequest, mListenAllCallback, mHandler); } + /** + * Stop tracking candidate tethering upstreams and release mobile network request. + * Note: this function is used when tethering is stopped because tethering do not need to + * choose upstream anymore. But it would not stop default network tracking because + * EntitlementManager may need to know default network to decide whether to request entitlement + * check even tethering is not active yet. + */ public void stop() { releaseMobileNetworkRequest(); @@ -165,6 +173,7 @@ public class UpstreamNetworkMonitor { mNetworkMap.clear(); } + /** Setup or teardown DUN connection according to |dunRequired|. */ public void updateMobileRequiresDun(boolean dunRequired) { final boolean valueChanged = (mDunRequired != dunRequired); mDunRequired = dunRequired; @@ -174,10 +183,12 @@ public class UpstreamNetworkMonitor { } } + /** Whether mobile network is requested. */ public boolean mobileNetworkRequested() { return (mMobileNetworkCallback != null); } + /** Request mobile network if mobile upstream is permitted. */ public void registerMobileNetworkRequest() { if (!isCellularUpstreamPermitted()) { mLog.i("registerMobileNetworkRequest() is not permitted"); @@ -209,6 +220,7 @@ public class UpstreamNetworkMonitor { cm().requestNetwork(mobileUpstreamRequest, mMobileNetworkCallback, 0, legacyType, mHandler); } + /** Release mobile network request. */ public void releaseMobileNetworkRequest() { if (mMobileNetworkCallback == null) return; @@ -221,6 +233,9 @@ public class UpstreamNetworkMonitor { // becomes available and useful we (a) file a request to keep it up as // necessary and (b) change all upstream tracking state accordingly (by // passing LinkProperties up to Tethering). + /** + * Select the first available network from |perferredTypes|. + */ public NetworkState selectPreferredUpstreamType(Iterable<Integer> preferredTypes) { final TypeStatePair typeStatePair = findFirstAvailableUpstreamByType( mNetworkMap.values(), preferredTypes, isCellularUpstreamPermitted()); @@ -254,7 +269,11 @@ public class UpstreamNetworkMonitor { return typeStatePair.ns; } - // Returns null if no current upstream available. + /** + * Get current preferred upstream network. If default network is cellular and DUN is required, + * preferred upstream would be DUN otherwise preferred upstream is the same as default network. + * Returns null if no current upstream is available. + */ public NetworkState getCurrentPreferredUpstream() { final NetworkState dfltState = (mDefaultInternetNetwork != null) ? mNetworkMap.get(mDefaultInternetNetwork) @@ -270,10 +289,12 @@ public class UpstreamNetworkMonitor { return findFirstDunNetwork(mNetworkMap.values()); } + /** Tell UpstreamNetworkMonitor which network is the current upstream of tethering. */ public void setCurrentUpstream(Network upstream) { mTetheringUpstreamNetwork = upstream; } + /** Return local prefixes. */ public Set<IpPrefix> getLocalPrefixes() { return (Set<IpPrefix>) mLocalPrefixes.clone(); } @@ -501,8 +522,8 @@ public class UpstreamNetworkMonitor { try { nc = ConnectivityManager.networkCapabilitiesForType(type); } catch (IllegalArgumentException iae) { - Log.e(TAG, "No NetworkCapabilities mapping for legacy type: " + - ConnectivityManager.getNetworkTypeName(type)); + Log.e(TAG, "No NetworkCapabilities mapping for legacy type: " + + ConnectivityManager.getNetworkTypeName(type)); continue; } if (!isCellularUpstreamPermitted && isCellular(nc)) { @@ -547,18 +568,18 @@ public class UpstreamNetworkMonitor { } private static boolean isCellular(NetworkCapabilities nc) { - return (nc != null) && nc.hasTransport(TRANSPORT_CELLULAR) && - nc.hasCapability(NET_CAPABILITY_NOT_VPN); + return (nc != null) && nc.hasTransport(TRANSPORT_CELLULAR) + && nc.hasCapability(NET_CAPABILITY_NOT_VPN); } private static boolean hasCapability(NetworkState ns, int netCap) { - return (ns != null) && (ns.networkCapabilities != null) && - ns.networkCapabilities.hasCapability(netCap); + return (ns != null) && (ns.networkCapabilities != null) + && ns.networkCapabilities.hasCapability(netCap); } private static boolean isNetworkUsableAndNotCellular(NetworkState ns) { - return (ns != null) && (ns.networkCapabilities != null) && (ns.linkProperties != null) && - !isCellular(ns.networkCapabilities); + return (ns != null) && (ns.networkCapabilities != null) && (ns.linkProperties != null) + && !isCellular(ns.networkCapabilities); } private static NetworkState findFirstDunNetwork(Iterable<NetworkState> netStates) { diff --git a/packages/Tethering/tests/unit/Android.bp b/packages/Tethering/tests/unit/Android.bp index da621076bb63..7c06e5f0d7ce 100644 --- a/packages/Tethering/tests/unit/Android.bp +++ b/packages/Tethering/tests/unit/Android.bp @@ -17,7 +17,10 @@ android_test { name: "TetheringTests", certificate: "platform", - srcs: ["src/**/*.java"], + srcs: [ + ":servicescore-tethering-src", + "src/**/*.java", + ], test_suites: ["device-tests"], static_libs: [ "androidx.test.rules", @@ -42,7 +45,9 @@ android_test { filegroup { name: "tethering-tests-src", srcs: [ + "src/com/android/server/connectivity/tethering/EntitlementManagerTest.java", "src/com/android/server/connectivity/tethering/TetheringConfigurationTest.java", + "src/com/android/server/connectivity/tethering/UpstreamNetworkMonitorTest.java", "src/android/net/dhcp/DhcpServingParamsParcelExtTest.java", "src/android/net/ip/IpServerTest.java", "src/android/net/util/InterfaceSetTest.java", diff --git a/tests/net/java/com/android/server/connectivity/tethering/EntitlementManagerTest.java b/packages/Tethering/tests/unit/src/com/android/server/connectivity/tethering/EntitlementManagerTest.java index 5217e26a40ef..5217e26a40ef 100644 --- a/tests/net/java/com/android/server/connectivity/tethering/EntitlementManagerTest.java +++ b/packages/Tethering/tests/unit/src/com/android/server/connectivity/tethering/EntitlementManagerTest.java diff --git a/tests/net/java/com/android/server/connectivity/tethering/UpstreamNetworkMonitorTest.java b/packages/Tethering/tests/unit/src/com/android/server/connectivity/tethering/UpstreamNetworkMonitorTest.java index 0d276cbd1b85..c028d6d9cadc 100644 --- a/tests/net/java/com/android/server/connectivity/tethering/UpstreamNetworkMonitorTest.java +++ b/packages/Tethering/tests/unit/src/com/android/server/connectivity/tethering/UpstreamNetworkMonitorTest.java @@ -87,7 +87,7 @@ public class UpstreamNetworkMonitorTest { // Actual contents of the request don't matter for this test. The lack of // any specific TRANSPORT_* is sufficient to identify this request. - private static final NetworkRequest mDefaultRequest = new NetworkRequest.Builder().build(); + private static final NetworkRequest sDefaultRequest = new NetworkRequest.Builder().build(); @Mock private Context mContext; @Mock private EntitlementManager mEntitleMgr; @@ -140,7 +140,7 @@ public class UpstreamNetworkMonitorTest { @Test public void testDefaultNetworkIsTracked() throws Exception { assertTrue(mCM.hasNoCallbacks()); - mUNM.startTrackDefaultNetwork(mDefaultRequest, mEntitleMgr); + mUNM.startTrackDefaultNetwork(sDefaultRequest, mEntitleMgr); mUNM.startObserveAllNetworks(); assertEquals(1, mCM.trackingDefault.size()); @@ -153,7 +153,7 @@ public class UpstreamNetworkMonitorTest { public void testListensForAllNetworks() throws Exception { assertTrue(mCM.listening.isEmpty()); - mUNM.startTrackDefaultNetwork(mDefaultRequest, mEntitleMgr); + mUNM.startTrackDefaultNetwork(sDefaultRequest, mEntitleMgr); mUNM.startObserveAllNetworks(); assertFalse(mCM.listening.isEmpty()); assertTrue(mCM.isListeningForAll()); @@ -164,9 +164,9 @@ public class UpstreamNetworkMonitorTest { @Test public void testCallbacksRegistered() { - mUNM.startTrackDefaultNetwork(mDefaultRequest, mEntitleMgr); + mUNM.startTrackDefaultNetwork(sDefaultRequest, mEntitleMgr); verify(mCM, times(1)).requestNetwork( - eq(mDefaultRequest), any(NetworkCallback.class), any(Handler.class)); + eq(sDefaultRequest), any(NetworkCallback.class), any(Handler.class)); mUNM.startObserveAllNetworks(); verify(mCM, times(1)).registerNetworkCallback( any(NetworkRequest.class), any(NetworkCallback.class), any(Handler.class)); @@ -191,7 +191,7 @@ public class UpstreamNetworkMonitorTest { mUNM.registerMobileNetworkRequest(); assertTrue(mUNM.mobileNetworkRequested()); assertUpstreamTypeRequested(TYPE_MOBILE_HIPRI); - assertFalse(mCM.isDunRequested()); + assertFalse(isDunRequested()); mUNM.stop(); assertFalse(mUNM.mobileNetworkRequested()); @@ -217,7 +217,7 @@ public class UpstreamNetworkMonitorTest { assertTrue(mUNM.mobileNetworkRequested()); assertUpstreamTypeRequested(TYPE_MOBILE_DUN); - assertTrue(mCM.isDunRequested()); + assertTrue(isDunRequested()); // Try a few things that must not result in any state change. mUNM.registerMobileNetworkRequest(); @@ -226,7 +226,7 @@ public class UpstreamNetworkMonitorTest { assertTrue(mUNM.mobileNetworkRequested()); assertUpstreamTypeRequested(TYPE_MOBILE_DUN); - assertTrue(mCM.isDunRequested()); + assertTrue(isDunRequested()); mUNM.stop(); verify(mCM, times(2)).unregisterNetworkCallback(any(NetworkCallback.class)); @@ -250,7 +250,7 @@ public class UpstreamNetworkMonitorTest { mUNM.registerMobileNetworkRequest(); assertTrue(mUNM.mobileNetworkRequested()); assertUpstreamTypeRequested(TYPE_MOBILE_DUN); - assertTrue(mCM.isDunRequested()); + assertTrue(isDunRequested()); mUNM.stop(); assertFalse(mUNM.mobileNetworkRequested()); @@ -266,17 +266,17 @@ public class UpstreamNetworkMonitorTest { mUNM.registerMobileNetworkRequest(); assertTrue(mUNM.mobileNetworkRequested()); assertUpstreamTypeRequested(TYPE_MOBILE_HIPRI); - assertFalse(mCM.isDunRequested()); + assertFalse(isDunRequested()); mUNM.updateMobileRequiresDun(true); assertTrue(mUNM.mobileNetworkRequested()); assertUpstreamTypeRequested(TYPE_MOBILE_DUN); - assertTrue(mCM.isDunRequested()); + assertTrue(isDunRequested()); // Test going from DUN to no-DUN correctly re-registers callbacks. mUNM.updateMobileRequiresDun(false); assertTrue(mUNM.mobileNetworkRequested()); assertUpstreamTypeRequested(TYPE_MOBILE_HIPRI); - assertFalse(mCM.isDunRequested()); + assertFalse(isDunRequested()); mUNM.stop(); assertFalse(mUNM.mobileNetworkRequested()); @@ -287,7 +287,7 @@ public class UpstreamNetworkMonitorTest { final Collection<Integer> preferredTypes = new ArrayList<>(); preferredTypes.add(TYPE_WIFI); - mUNM.startTrackDefaultNetwork(mDefaultRequest, mEntitleMgr); + mUNM.startTrackDefaultNetwork(sDefaultRequest, mEntitleMgr); mUNM.startObserveAllNetworks(); // There are no networks, so there is nothing to select. assertSatisfiesLegacyType(TYPE_NONE, mUNM.selectPreferredUpstreamType(preferredTypes)); @@ -369,7 +369,7 @@ public class UpstreamNetworkMonitorTest { @Test public void testGetCurrentPreferredUpstream() throws Exception { - mUNM.startTrackDefaultNetwork(mDefaultRequest, mEntitleMgr); + mUNM.startTrackDefaultNetwork(sDefaultRequest, mEntitleMgr); mUNM.startObserveAllNetworks(); mUNM.updateMobileRequiresDun(false); @@ -418,7 +418,7 @@ public class UpstreamNetworkMonitorTest { @Test public void testLocalPrefixes() throws Exception { - mUNM.startTrackDefaultNetwork(mDefaultRequest, mEntitleMgr); + mUNM.startTrackDefaultNetwork(sDefaultRequest, mEntitleMgr); mUNM.startObserveAllNetworks(); // [0] Test minimum set of local prefixes. @@ -431,13 +431,13 @@ public class UpstreamNetworkMonitorTest { final TestNetworkAgent wifiAgent = new TestNetworkAgent(mCM, TRANSPORT_WIFI); final LinkProperties wifiLp = wifiAgent.linkProperties; wifiLp.setInterfaceName("wlan0"); - final String[] WIFI_ADDRS = { + final String[] wifi_addrs = { "fe80::827a:bfff:fe6f:374d", "100.112.103.18", "2001:db8:4:fd00:827a:bfff:fe6f:374d", "2001:db8:4:fd00:6dea:325a:fdae:4ef4", "fd6a:a640:60bf:e985::123", // ULA address for good measure. }; - for (String addrStr : WIFI_ADDRS) { + for (String addrStr : wifi_addrs) { final String cidr = addrStr.contains(":") ? "/64" : "/20"; wifiLp.addLinkAddress(new LinkAddress(addrStr + cidr)); } @@ -458,10 +458,10 @@ public class UpstreamNetworkMonitorTest { final TestNetworkAgent cellAgent = new TestNetworkAgent(mCM, TRANSPORT_CELLULAR); final LinkProperties cellLp = cellAgent.linkProperties; cellLp.setInterfaceName("rmnet_data0"); - final String[] CELL_ADDRS = { + final String[] cell_addrs = { "10.102.211.48", "2001:db8:0:1:b50e:70d9:10c9:433d", }; - for (String addrStr : CELL_ADDRS) { + for (String addrStr : cell_addrs) { final String cidr = addrStr.contains(":") ? "/64" : "/27"; cellLp.addLinkAddress(new LinkAddress(addrStr + cidr)); } @@ -481,10 +481,10 @@ public class UpstreamNetworkMonitorTest { dunAgent.networkCapabilities.removeCapability(NET_CAPABILITY_INTERNET); final LinkProperties dunLp = dunAgent.linkProperties; dunLp.setInterfaceName("rmnet_data1"); - final String[] DUN_ADDRS = { + final String[] dun_addrs = { "192.0.2.48", "2001:db8:1:2:b50e:70d9:10c9:433d", }; - for (String addrStr : DUN_ADDRS) { + for (String addrStr : dun_addrs) { final String cidr = addrStr.contains(":") ? "/64" : "/27"; dunLp.addLinkAddress(new LinkAddress(addrStr + cidr)); } @@ -525,7 +525,7 @@ public class UpstreamNetworkMonitorTest { // Mobile has higher pirority than wifi. preferredTypes.add(TYPE_MOBILE_HIPRI); preferredTypes.add(TYPE_WIFI); - mUNM.startTrackDefaultNetwork(mDefaultRequest, mEntitleMgr); + mUNM.startTrackDefaultNetwork(sDefaultRequest, mEntitleMgr); mUNM.startObserveAllNetworks(); // Setup wifi and make wifi as default network. final TestNetworkAgent wifiAgent = new TestNetworkAgent(mCM, TRANSPORT_WIFI); @@ -556,6 +556,15 @@ public class UpstreamNetworkMonitorTest { mCM.legacyTypeMap.values().iterator().next()); } + private boolean isDunRequested() { + for (NetworkRequest req : mCM.requested.values()) { + if (req.networkCapabilities.hasCapability(NET_CAPABILITY_DUN)) { + return true; + } + } + return false; + } + public static class TestConnectivityManager extends ConnectivityManager { public Map<NetworkCallback, Handler> allCallbacks = new HashMap<>(); public Set<NetworkCallback> trackingDefault = new HashSet<>(); @@ -598,17 +607,10 @@ public class UpstreamNetworkMonitorTest { return false; } - boolean isDunRequested() { - for (NetworkRequest req : requested.values()) { - if (req.networkCapabilities.hasCapability(NET_CAPABILITY_DUN)) { - return true; - } - } - return false; + int getNetworkId() { + return ++mNetworkId; } - int getNetworkId() { return ++mNetworkId; } - void makeDefaultNetwork(TestNetworkAgent agent) { if (Objects.equals(defaultNetwork, agent)) return; @@ -630,7 +632,7 @@ public class UpstreamNetworkMonitorTest { public void requestNetwork(NetworkRequest req, NetworkCallback cb, Handler h) { assertFalse(allCallbacks.containsKey(cb)); allCallbacks.put(cb, h); - if (mDefaultRequest.equals(req)) { + if (sDefaultRequest.equals(req)) { assertFalse(trackingDefault.contains(cb)); trackingDefault.add(cb); } else { @@ -749,9 +751,13 @@ public class UpstreamNetworkMonitorTest { private final State mLoggingState = new LoggingState(); class LoggingState extends State { - @Override public void enter() { messages.clear(); } + @Override public void enter() { + messages.clear(); + } - @Override public void exit() { messages.clear(); } + @Override public void exit() { + messages.clear(); + } @Override public boolean processMessage(Message msg) { messages.add(msg); diff --git a/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java b/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java index 05b937a34626..d4fb9acdad5e 100644 --- a/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java +++ b/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java @@ -82,8 +82,6 @@ import android.os.UserHandle; import android.os.UserManager; import android.os.UserManagerInternal; import android.provider.Settings; -import android.provider.SettingsStringUtil; -import android.provider.SettingsStringUtil.ComponentNameSet; import android.provider.SettingsStringUtil.SettingStringHelper; import android.text.TextUtils; import android.text.TextUtils.SimpleStringSplitter; @@ -2436,12 +2434,12 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub * Enables accessibility service specified by {@param componentName} for the {@param userId}. */ private void enableAccessibilityServiceLocked(ComponentName componentName, int userId) { - final SettingStringHelper setting = - new SettingStringHelper( - mContext.getContentResolver(), - Settings.Secure.ENABLED_ACCESSIBILITY_SERVICES, - userId); - setting.write(ComponentNameSet.add(setting.read(), componentName)); + mTempComponentNameSet.clear(); + readComponentNamesFromSettingLocked(Settings.Secure.ENABLED_ACCESSIBILITY_SERVICES, + userId, mTempComponentNameSet); + mTempComponentNameSet.add(componentName); + persistComponentNamesToSettingLocked(Settings.Secure.ENABLED_ACCESSIBILITY_SERVICES, + mTempComponentNameSet, userId); UserState userState = getUserStateLocked(userId); if (userState.mEnabledServices.add(componentName)) { @@ -2453,12 +2451,12 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub * Disables accessibility service specified by {@param componentName} for the {@param userId}. */ private void disableAccessibilityServiceLocked(ComponentName componentName, int userId) { - final SettingsStringUtil.SettingStringHelper setting = - new SettingStringHelper( - mContext.getContentResolver(), - Settings.Secure.ENABLED_ACCESSIBILITY_SERVICES, - userId); - setting.write(ComponentNameSet.remove(setting.read(), componentName)); + mTempComponentNameSet.clear(); + readComponentNamesFromSettingLocked(Settings.Secure.ENABLED_ACCESSIBILITY_SERVICES, + userId, mTempComponentNameSet); + mTempComponentNameSet.remove(componentName); + persistComponentNamesToSettingLocked(Settings.Secure.ENABLED_ACCESSIBILITY_SERVICES, + mTempComponentNameSet, userId); UserState userState = getUserStateLocked(userId); if (userState.mEnabledServices.remove(componentName)) { diff --git a/services/core/Android.bp b/services/core/Android.bp index 16432212d8e2..fcf012cd3a6b 100644 --- a/services/core/Android.bp +++ b/services/core/Android.bp @@ -20,6 +20,7 @@ java_library_static { ":vold_aidl", ":gsiservice_aidl", ":platform-compat-config", + ":tethering-servicescore-srcs", "java/com/android/server/EventLogTags.logtags", "java/com/android/server/am/EventLogTags.logtags", "java/com/android/server/policy/EventLogTags.logtags", @@ -81,3 +82,11 @@ prebuilt_etc { name: "gps_debug.conf", src: "java/com/android/server/location/gps_debug.conf", } + +// TODO: this should be removed after tethering migration done. +filegroup { + name: "servicescore-tethering-src", + srcs: [ + "java/com/android/server/connectivity/MockableSystemProperties.java", + ], +} diff --git a/services/core/java/com/android/server/am/ActiveServices.java b/services/core/java/com/android/server/am/ActiveServices.java index 7bc2e6d647be..6cbbcddc2b3f 100644 --- a/services/core/java/com/android/server/am/ActiveServices.java +++ b/services/core/java/com/android/server/am/ActiveServices.java @@ -192,34 +192,38 @@ public final class ActiveServices { @Override public void stopForegroundServicesForUidPackage(final int uid, final String packageName) { synchronized (mAm) { - final ServiceMap smap = getServiceMapLocked(UserHandle.getUserId(uid)); - final int N = smap.mServicesByInstanceName.size(); - final ArrayList<ServiceRecord> toStop = new ArrayList<>(N); - for (int i = 0; i < N; i++) { - final ServiceRecord r = smap.mServicesByInstanceName.valueAt(i); - if (uid == r.serviceInfo.applicationInfo.uid - || packageName.equals(r.serviceInfo.packageName)) { - if (r.isForeground) { - toStop.add(r); - } - } - } + stopAllForegroundServicesLocked(uid, packageName); + } + } + } - // Now stop them all - final int numToStop = toStop.size(); - if (numToStop > 0 && DEBUG_FOREGROUND_SERVICE) { - Slog.i(TAG, "Package " + packageName + "/" + uid - + " entering FAS with foreground services"); - } - for (int i = 0; i < numToStop; i++) { - final ServiceRecord r = toStop.get(i); - if (DEBUG_FOREGROUND_SERVICE) { - Slog.i(TAG, " Stopping fg for service " + r); - } - setServiceForegroundInnerLocked(r, 0, null, 0, 0); + void stopAllForegroundServicesLocked(final int uid, final String packageName) { + final ServiceMap smap = getServiceMapLocked(UserHandle.getUserId(uid)); + final int N = smap.mServicesByInstanceName.size(); + final ArrayList<ServiceRecord> toStop = new ArrayList<>(N); + for (int i = 0; i < N; i++) { + final ServiceRecord r = smap.mServicesByInstanceName.valueAt(i); + if (uid == r.serviceInfo.applicationInfo.uid + || packageName.equals(r.serviceInfo.packageName)) { + if (r.isForeground) { + toStop.add(r); } } } + + // Now stop them all + final int numToStop = toStop.size(); + if (numToStop > 0 && DEBUG_FOREGROUND_SERVICE) { + Slog.i(TAG, "Package " + packageName + "/" + uid + + " in FAS with foreground services"); + } + for (int i = 0; i < numToStop; i++) { + final ServiceRecord r = toStop.get(i); + if (DEBUG_FOREGROUND_SERVICE) { + Slog.i(TAG, " Stopping fg for service " + r); + } + setServiceForegroundInnerLocked(r, 0, null, 0, 0); + } } /** @@ -1010,12 +1014,23 @@ public final class ActiveServices { } } if (!aa.mAppOnTop) { - if (active == null) { - active = new ArrayList<>(); + // Transitioning a fg-service host app out of top: if it's bg restricted, + // it loses the fg service state now. + if (!appRestrictedAnyInBackground(aa.mUid, aa.mPackageName)) { + if (active == null) { + active = new ArrayList<>(); + } + if (DEBUG_FOREGROUND_SERVICE) Slog.d(TAG, "Adding active: pkg=" + + aa.mPackageName + ", uid=" + aa.mUid); + active.add(aa); + } else { + if (DEBUG_FOREGROUND_SERVICE) { + Slog.d(TAG, "bg-restricted app " + + aa.mPackageName + "/" + aa.mUid + + " exiting top; demoting fg services "); + } + stopAllForegroundServicesLocked(aa.mUid, aa.mPackageName); } - if (DEBUG_FOREGROUND_SERVICE) Slog.d(TAG, "Adding active: pkg=" - + aa.mPackageName + ", uid=" + aa.mUid); - active.add(aa); } } smap.removeMessages(ServiceMap.MSG_UPDATE_FOREGROUND_APPS); diff --git a/services/core/java/com/android/server/compat/CompatChange.java b/services/core/java/com/android/server/compat/CompatChange.java index bc5973d1b270..87624359ef85 100644 --- a/services/core/java/com/android/server/compat/CompatChange.java +++ b/services/core/java/com/android/server/compat/CompatChange.java @@ -20,6 +20,7 @@ import android.annotation.Nullable; import android.compat.annotation.EnabledAfter; import android.content.pm.ApplicationInfo; +import com.android.internal.compat.CompatibilityChangeInfo; import com.android.server.compat.config.Change; import java.util.HashMap; @@ -35,12 +36,8 @@ import java.util.Map; * * <p>Note, this class is not thread safe so callers must ensure thread safety. */ -public final class CompatChange { +public final class CompatChange extends CompatibilityChangeInfo { - private final long mChangeId; - @Nullable private final String mName; - private final int mEnableAfterTargetSdk; - private final boolean mDisabled; private Map<String, Boolean> mPackageOverrides; public CompatChange(long changeId) { @@ -56,29 +53,15 @@ public final class CompatChange { */ public CompatChange(long changeId, @Nullable String name, int enableAfterTargetSdk, boolean disabled) { - mChangeId = changeId; - mName = name; - mEnableAfterTargetSdk = enableAfterTargetSdk; - mDisabled = disabled; + super(changeId, name, enableAfterTargetSdk, disabled); } /** * @param change an object generated by services/core/xsd/platform-compat-config.xsd */ public CompatChange(Change change) { - mChangeId = change.getId(); - mName = change.getName(); - mEnableAfterTargetSdk = change.getEnableAfterTargetSdk(); - mDisabled = change.getDisabled(); - } - - long getId() { - return mChangeId; - } - - @Nullable - String getName() { - return mName; + super(change.getId(), change.getName(), change.getEnableAfterTargetSdk(), + change.getDisabled()); } /** @@ -121,11 +104,11 @@ public final class CompatChange { if (mPackageOverrides != null && mPackageOverrides.containsKey(app.packageName)) { return mPackageOverrides.get(app.packageName); } - if (mDisabled) { + if (getDisabled()) { return false; } - if (mEnableAfterTargetSdk != -1) { - return app.targetSdkVersion > mEnableAfterTargetSdk; + if (getEnableAfterTargetSdk() != -1) { + return app.targetSdkVersion > getEnableAfterTargetSdk(); } return true; } @@ -133,14 +116,14 @@ public final class CompatChange { @Override public String toString() { StringBuilder sb = new StringBuilder("ChangeId(") - .append(mChangeId); - if (mName != null) { - sb.append("; name=").append(mName); + .append(getId()); + if (getName() != null) { + sb.append("; name=").append(getName()); } - if (mEnableAfterTargetSdk != -1) { - sb.append("; enableAfterTargetSdk=").append(mEnableAfterTargetSdk); + if (getEnableAfterTargetSdk() != -1) { + sb.append("; enableAfterTargetSdk=").append(getEnableAfterTargetSdk()); } - if (mDisabled) { + if (getDisabled()) { sb.append("; disabled"); } if (mPackageOverrides != null && mPackageOverrides.size() > 0) { diff --git a/services/core/java/com/android/server/compat/CompatConfig.java b/services/core/java/com/android/server/compat/CompatConfig.java index 0fabd9aef373..d6ec22b078ea 100644 --- a/services/core/java/com/android/server/compat/CompatConfig.java +++ b/services/core/java/com/android/server/compat/CompatConfig.java @@ -16,6 +16,7 @@ package com.android.server.compat; +import android.compat.Compatibility.ChangeConfig; import android.content.pm.ApplicationInfo; import android.os.Environment; import android.text.TextUtils; @@ -26,6 +27,7 @@ import android.util.Slog; import com.android.internal.annotations.GuardedBy; import com.android.internal.annotations.VisibleForTesting; import com.android.internal.compat.CompatibilityChangeConfig; +import com.android.internal.compat.CompatibilityChangeInfo; import com.android.server.compat.config.Change; import com.android.server.compat.config.XmlParser; @@ -37,6 +39,8 @@ import java.io.FileInputStream; import java.io.IOException; import java.io.InputStream; import java.io.PrintWriter; +import java.util.HashSet; +import java.util.Set; import javax.xml.datatype.DatatypeConfigurationException; /** @@ -243,6 +247,49 @@ public final class CompatConfig { } } + /** + * Get the config for a given app. + * + * @param applicationInfo the {@link ApplicationInfo} for which the info should be dumped. + * @return A {@link CompatibilityChangeConfig} which contains the compat config info for the + * given app. + */ + + public CompatibilityChangeConfig getAppConfig(ApplicationInfo applicationInfo) { + Set<Long> enabled = new HashSet<>(); + Set<Long> disabled = new HashSet<>(); + synchronized (mChanges) { + for (int i = 0; i < mChanges.size(); ++i) { + CompatChange c = mChanges.valueAt(i); + if (c.isEnabled(applicationInfo)) { + enabled.add(c.getId()); + } else { + disabled.add(c.getId()); + } + } + } + return new CompatibilityChangeConfig(new ChangeConfig(enabled, disabled)); + } + + /** + * Dumps all the compatibility change information. + * + * @return An array of {@link CompatibilityChangeInfo} with the current changes. + */ + public CompatibilityChangeInfo[] dumpChanges() { + synchronized (mChanges) { + CompatibilityChangeInfo[] changeInfos = new CompatibilityChangeInfo[mChanges.size()]; + for (int i = 0; i < mChanges.size(); ++i) { + CompatChange change = mChanges.valueAt(i); + changeInfos[i] = new CompatibilityChangeInfo(change.getId(), + change.getName(), + change.getEnableAfterTargetSdk(), + change.getDisabled()); + } + return changeInfos; + } + } + CompatConfig initConfigFromLib(File libraryDir) { if (!libraryDir.exists() || !libraryDir.isDirectory()) { Slog.e(TAG, "No directory " + libraryDir + ", skipping"); diff --git a/services/core/java/com/android/server/compat/PlatformCompat.java b/services/core/java/com/android/server/compat/PlatformCompat.java index 9ac9955493cc..75e2d220898d 100644 --- a/services/core/java/com/android/server/compat/PlatformCompat.java +++ b/services/core/java/com/android/server/compat/PlatformCompat.java @@ -25,6 +25,7 @@ import android.util.StatsLog; import com.android.internal.compat.ChangeReporter; import com.android.internal.compat.CompatibilityChangeConfig; +import com.android.internal.compat.CompatibilityChangeInfo; import com.android.internal.compat.IPlatformCompat; import com.android.internal.util.DumpUtils; @@ -114,6 +115,16 @@ public class PlatformCompat extends IPlatformCompat.Stub { } @Override + public CompatibilityChangeConfig getAppConfig(ApplicationInfo appInfo) { + return CompatConfig.get().getAppConfig(appInfo); + } + + @Override + public CompatibilityChangeInfo[] listAllChanges() { + return CompatConfig.get().dumpChanges(); + } + + @Override protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) { if (!DumpUtils.checkDumpAndUsageStatsPermission(mContext, "platform_compat", pw)) return; CompatConfig.get().dumpConfig(pw); diff --git a/services/net/Android.bp b/services/net/Android.bp index 08cdbfc55cfe..e24dec562a46 100644 --- a/services/net/Android.bp +++ b/services/net/Android.bp @@ -1,12 +1,12 @@ java_library_static { name: "services.net", srcs: [ - ":tethering-services-srcs", + ":tethering-servicesnet-srcs", "java/**/*.java", ], static_libs: [ "dnsresolver_aidl_interface-V2-java", - "netd_aidl_interface-java", + "netd_aidl_interface-unstable-java", "networkstack-client", "tethering-client", ], diff --git a/services/tests/servicestests/Android.bp b/services/tests/servicestests/Android.bp index ecddeb3dda61..eecdeed2cd25 100644 --- a/services/tests/servicestests/Android.bp +++ b/services/tests/servicestests/Android.bp @@ -74,7 +74,7 @@ android_test { "libui", "libunwindstack", "libutils", - "netd_aidl_interface-V2-cpp", + "netd_aidl_interface-cpp", ], dxflags: ["--multi-dex"], diff --git a/services/tests/uiservicestests/Android.bp b/services/tests/uiservicestests/Android.bp index 4a9cef1f1cbd..92198fa8cb0c 100644 --- a/services/tests/uiservicestests/Android.bp +++ b/services/tests/uiservicestests/Android.bp @@ -55,6 +55,6 @@ android_test { "libui", "libunwindstack", "libutils", - "netd_aidl_interface-V2-cpp", + "netd_aidl_interface-cpp", ], } diff --git a/telecomm/java/android/telecom/Connection.java b/telecomm/java/android/telecom/Connection.java index 2ce84fbc0dc7..4f373af984fa 100644 --- a/telecomm/java/android/telecom/Connection.java +++ b/telecomm/java/android/telecom/Connection.java @@ -857,7 +857,7 @@ public abstract class Connection extends Conferenceable { } /** @hide */ - public abstract static class Listener { + abstract static class Listener { public void onStateChanged(Connection c, int state) {} public void onAddressChanged(Connection c, Uri newAddress, int presentation) {} public void onCallerDisplayNameChanged( @@ -2005,7 +2005,7 @@ public abstract class Connection extends Conferenceable { * * @hide */ - public final Connection addConnectionListener(Listener l) { + final Connection addConnectionListener(Listener l) { mListeners.add(l); return this; } @@ -2018,7 +2018,7 @@ public abstract class Connection extends Conferenceable { * * @hide */ - public final Connection removeConnectionListener(Listener l) { + final Connection removeConnectionListener(Listener l) { if (l != null) { mListeners.remove(l); } diff --git a/telephony/java/android/telephony/CarrierConfigManager.java b/telephony/java/android/telephony/CarrierConfigManager.java index 1a8be6d899c3..f3596c092064 100644 --- a/telephony/java/android/telephony/CarrierConfigManager.java +++ b/telephony/java/android/telephony/CarrierConfigManager.java @@ -1838,6 +1838,13 @@ public class CarrierConfigManager { "support_direct_fdn_dialing_bool"; /** + * Int indicating the max number length for FDN + * @hide + */ + public static final String KEY_FDN_NUMBER_LENGTH_LIMIT_INT = + "fdn_number_length_limit_int"; + + /** * Report IMEI as device id even if it's a CDMA/LTE phone. * * @hide @@ -3428,6 +3435,7 @@ public class CarrierConfigManager { sDefaults.putBoolean(KEY_CDMA_HOME_REGISTERED_PLMN_NAME_OVERRIDE_BOOL, false); sDefaults.putString(KEY_CDMA_HOME_REGISTERED_PLMN_NAME_STRING, ""); sDefaults.putBoolean(KEY_SUPPORT_DIRECT_FDN_DIALING_BOOL, false); + sDefaults.putInt(KEY_FDN_NUMBER_LENGTH_LIMIT_INT, 20); sDefaults.putBoolean(KEY_CARRIER_DEFAULT_DATA_ROAMING_ENABLED_BOOL, false); sDefaults.putBoolean(KEY_SKIP_CF_FAIL_TO_DISABLE_DIALOG_BOOL, false); sDefaults.putBoolean(KEY_SUPPORT_ENHANCED_CALL_BLOCKING_BOOL, true); diff --git a/telephony/java/android/telephony/TelephonyManager.java b/telephony/java/android/telephony/TelephonyManager.java index bec0a975108a..c9440a66ab96 100644 --- a/telephony/java/android/telephony/TelephonyManager.java +++ b/telephony/java/android/telephony/TelephonyManager.java @@ -9462,10 +9462,12 @@ public class TelephonyManager { } /** - * Resets telephony manager settings back to factory defaults. + * Resets Telephony and IMS settings back to factory defaults. * * @hide */ + @SystemApi + @RequiresPermission(Manifest.permission.CONNECTIVITY_INTERNAL) public void factoryReset(int subId) { try { Log.d(TAG, "factoryReset: subId=" + subId); diff --git a/telephony/java/android/telephony/ims/ImsMmTelManager.java b/telephony/java/android/telephony/ims/ImsMmTelManager.java index 2fad8479178e..ed292be9cd05 100644 --- a/telephony/java/android/telephony/ims/ImsMmTelManager.java +++ b/telephony/java/android/telephony/ims/ImsMmTelManager.java @@ -25,14 +25,13 @@ import android.annotation.Nullable; import android.annotation.RequiresPermission; import android.annotation.SystemApi; import android.content.Context; -import android.content.pm.IPackageManager; -import android.content.pm.PackageManager; import android.net.Uri; import android.os.Binder; import android.os.RemoteException; import android.os.ServiceManager; import android.os.ServiceSpecificException; import android.telephony.AccessNetworkConstants; +import android.telephony.CarrierConfigManager; import android.telephony.SubscriptionManager; import android.telephony.ims.aidl.IImsCapabilityCallback; import android.telephony.ims.aidl.IImsRegistrationCallback; @@ -42,6 +41,7 @@ import android.telephony.ims.stub.ImsRegistrationImplBase; import android.util.Log; import com.android.internal.annotations.VisibleForTesting; +import com.android.internal.telephony.IIntegerConsumer; import com.android.internal.telephony.ITelephony; import java.lang.annotation.Retention; @@ -49,6 +49,7 @@ import java.lang.annotation.RetentionPolicy; import java.util.HashMap; import java.util.Map; import java.util.concurrent.Executor; +import java.util.function.Consumer; /** * A manager for the MmTel (Multimedia Telephony) feature of an IMS network, given an associated @@ -64,8 +65,6 @@ import java.util.concurrent.Executor; @SystemApi public class ImsMmTelManager { - private static final String TAG = "ImsMmTelManager"; - /** * @hide */ @@ -311,7 +310,7 @@ public class ImsMmTelManager { } } - private int mSubId; + private final int mSubId; /** * Create an instance of {@link ImsMmTelManager} for the subscription id specified. @@ -366,10 +365,6 @@ public class ImsMmTelManager { if (executor == null) { throw new IllegalArgumentException("Must include a non-null Executor."); } - if (!isImsAvailableOnDevice()) { - throw new ImsException("IMS not available on device.", - ImsException.CODE_ERROR_UNSUPPORTED_OPERATION); - } c.setExecutor(executor); try { getITelephony().registerImsRegistrationCallback(mSubId, c.getBinder()); @@ -378,7 +373,7 @@ public class ImsMmTelManager { // Rethrow as runtime error to keep API compatible. throw new IllegalArgumentException(e.getMessage()); } else { - throw new RuntimeException(e.getMessage()); + throw new ImsException(e.getMessage(), e.errorCode); } } catch (RemoteException | IllegalStateException e) { throw new ImsException(e.getMessage(), ImsException.CODE_ERROR_SERVICE_UNAVAILABLE); @@ -441,10 +436,6 @@ public class ImsMmTelManager { if (executor == null) { throw new IllegalArgumentException("Must include a non-null Executor."); } - if (!isImsAvailableOnDevice()) { - throw new ImsException("IMS not available on device.", - ImsException.CODE_ERROR_UNSUPPORTED_OPERATION); - } c.setExecutor(executor); try { getITelephony().registerMmTelCapabilityCallback(mSubId, c.getBinder()); @@ -453,7 +444,7 @@ public class ImsMmTelManager { // Rethrow as runtime error to keep API compatible. throw new IllegalArgumentException(e.getMessage()); } else { - throw new RuntimeException(e.getMessage()); + throw new ImsException(e.getMessage(), e.errorCode); } } catch (RemoteException e) { throw e.rethrowAsRuntimeException(); @@ -618,6 +609,46 @@ public class ImsMmTelManager { } /** + * Query whether or not the requested MmTel capability is supported by the carrier on the + * specified network transport. + * <p> + * This is a configuration option and does not change. The only time this may change is if a + * new IMS configuration is loaded when there is a + * {@link CarrierConfigManager#ACTION_CARRIER_CONFIG_CHANGED} broadcast for this subscription. + * @param capability The capability that is being queried for support on the carrier network. + * @param transportType The transport type of the capability to check support for. + * @param callback A consumer containing a Boolean result specifying whether or not the + * capability is supported on this carrier network for the transport specified. + * @param executor The executor that the callback will be called with. + * @throws ImsException if the subscription is no longer valid or the IMS service is not + * available. + */ + @RequiresPermission(Manifest.permission.READ_PRIVILEGED_PHONE_STATE) + public void isSupported(@MmTelFeature.MmTelCapabilities.MmTelCapability int capability, + @AccessNetworkConstants.TransportType int transportType, + @NonNull Consumer<Boolean> callback, + @NonNull @CallbackExecutor Executor executor) throws ImsException { + if (callback == null) { + throw new IllegalArgumentException("Must include a non-null Consumer."); + } + if (executor == null) { + throw new IllegalArgumentException("Must include a non-null Executor."); + } + try { + getITelephony().isMmTelCapabilitySupported(mSubId, new IIntegerConsumer.Stub() { + @Override + public void accept(int result) { + executor.execute(() -> callback.accept(result == 1)); + } + }, capability, transportType); + } catch (ServiceSpecificException sse) { + throw new ImsException(sse.getMessage(), sse.errorCode); + } catch (RemoteException e) { + e.rethrowAsRuntimeException(); + } + } + + /** * The user's setting for whether or not they have enabled the "Video Calling" setting. * * @throws IllegalArgumentException if the subscription associated with this operation is not @@ -940,7 +971,7 @@ public class ImsMmTelManager { * @see android.telephony.CarrierConfigManager#KEY_CARRIER_VOLTE_TTY_SUPPORTED_BOOL */ @RequiresPermission(Manifest.permission.READ_PRIVILEGED_PHONE_STATE) - boolean isTtyOverVolteEnabled() { + public boolean isTtyOverVolteEnabled() { try { return getITelephony().isTtyOverVolteEnabled(mSubId); } catch (ServiceSpecificException e) { @@ -955,20 +986,39 @@ public class ImsMmTelManager { } } - private static boolean isImsAvailableOnDevice() { - IPackageManager pm = IPackageManager.Stub.asInterface(ServiceManager.getService("package")); - if (pm == null) { - // For some reason package manger is not available.. This will fail internally anyways, - // so do not throw error and allow. - return true; + /** + * Get the status of the MmTel Feature registered on this subscription. + * @param callback A callback containing an Integer describing the current state of the + * MmTel feature, Which will be one of the following: + * {@link ImsFeature#STATE_UNAVAILABLE}, + * {@link ImsFeature#STATE_INITIALIZING}, + * {@link ImsFeature#STATE_READY}. Will be called using the executor + * specified when the service state has been retrieved from the IMS service. + * @param executor The executor that will be used to call the callback. + * @throws ImsException if the IMS service associated with this subscription is not available or + * the IMS service is not available. + */ + @RequiresPermission(Manifest.permission.READ_PRIVILEGED_PHONE_STATE) + public void getFeatureState(@NonNull @ImsFeature.ImsState Consumer<Integer> callback, + @NonNull @CallbackExecutor Executor executor) throws ImsException { + if (callback == null) { + throw new IllegalArgumentException("Must include a non-null Consumer."); + } + if (executor == null) { + throw new IllegalArgumentException("Must include a non-null Executor."); } try { - return pm.hasSystemFeature(PackageManager.FEATURE_TELEPHONY_IMS, 0); + getITelephony().getImsMmTelFeatureState(mSubId, new IIntegerConsumer.Stub() { + @Override + public void accept(int result) { + executor.execute(() -> callback.accept(result)); + } + }); + } catch (ServiceSpecificException sse) { + throw new ImsException(sse.getMessage(), sse.errorCode); } catch (RemoteException e) { - // For some reason package manger is not available.. This will fail internally anyways, - // so do not throw error and allow. + e.rethrowAsRuntimeException(); } - return true; } private static ITelephony getITelephony() { diff --git a/telephony/java/android/telephony/ims/feature/MmTelFeature.java b/telephony/java/android/telephony/ims/feature/MmTelFeature.java index ceb470491dc5..8b27b6fc4bfd 100644 --- a/telephony/java/android/telephony/ims/feature/MmTelFeature.java +++ b/telephony/java/android/telephony/ims/feature/MmTelFeature.java @@ -362,6 +362,25 @@ public class MmTelFeature extends ImsFeature { @Retention(RetentionPolicy.SOURCE) public @interface ProcessCallResult {} + /** + * If the flag is present and true, it indicates that the incoming call is for USSD. + * <p> + * This is an optional boolean flag. + */ + public static final String EXTRA_IS_USSD = "android.telephony.ims.feature.extra.IS_USSD"; + + /** + * If this flag is present and true, this call is marked as an unknown dialing call instead + * of an incoming call. An example of such a call is a call that is originated by sending + * commands (like AT commands) directly to the modem without Android involvement or dialing + * calls appearing over IMS when the modem does a silent redial from circuit-switched to IMS in + * certain situations. + * <p> + * This is an optional boolean flag. + */ + public static final String EXTRA_IS_UNKNOWN_CALL = + "android.telephony.ims.feature.extra.IS_UNKNOWN_CALL"; + private IImsMmTelListener mListener; /** @@ -410,6 +429,8 @@ public class MmTelFeature extends ImsFeature { /** * Notify the framework of an incoming call. * @param c The {@link ImsCallSessionImplBase} of the new incoming call. + * @param extras A bundle containing extra parameters related to the call. See + * {@link #EXTRA_IS_UNKNOWN_CALL} and {@link #EXTRA_IS_USSD} above. */ public final void notifyIncomingCall(@NonNull ImsCallSessionImplBase c, @NonNull Bundle extras) { diff --git a/telephony/java/com/android/internal/telephony/ITelephony.aidl b/telephony/java/com/android/internal/telephony/ITelephony.aidl index d899a596c222..ab3861e2d517 100644 --- a/telephony/java/com/android/internal/telephony/ITelephony.aidl +++ b/telephony/java/com/android/internal/telephony/ITelephony.aidl @@ -864,6 +864,11 @@ interface ITelephony { String getImsService(int slotId, boolean isCarrierImsService); /** + * Get the MmTelFeature state attached to this subscription id. + */ + void getImsMmTelFeatureState(int subId, IIntegerConsumer callback); + + /** * Set the network selection mode to automatic. * * @param subId the id of the subscription to update. @@ -1774,21 +1779,6 @@ interface ITelephony { boolean isInEmergencySmsMode(); /** - * Get a list of SMS apps on a user. - */ - String[] getSmsApps(int userId); - - /** - * Get the default SMS app on a given user. - */ - String getDefaultSmsApp(int userId); - - /** - * Set the default SMS app to a given package on a given user. - */ - void setDefaultSmsApp(int userId, String packageName); - - /** * Return the modem radio power state for slot index. * */ @@ -1826,6 +1816,12 @@ interface ITelephony { boolean isAvailable(int subId, int capability, int regTech); /** + * Return whether or not the MmTel capability is supported for the requested transport type. + */ + void isMmTelCapabilitySupported(int subId, IIntegerConsumer callback, int capability, + int transportType); + + /** * Returns true if the user's setting for 4G LTE is enabled, for the subscription specified. */ boolean isAdvancedCallingSettingEnabled(int subId); diff --git a/tests/net/Android.bp b/tests/net/Android.bp index b9b2238572ac..10f27e243c8c 100644 --- a/tests/net/Android.bp +++ b/tests/net/Android.bp @@ -37,7 +37,7 @@ java_defaults { "libvndksupport", "libziparchive", "libz", - "netd_aidl_interface-V2-cpp", + "netd_aidl_interface-cpp", ], } |