diff options
author | alk3pInjection <webmaster@raspii.tech> | 2021-10-12 16:30:00 +0800 |
---|---|---|
committer | alk3pInjection <webmaster@raspii.tech> | 2021-10-12 16:30:00 +0800 |
commit | 1ba1f89e6edc78f03d649d09b58b25c7c8d935fe (patch) | |
tree | 31fc1df791156dc27089111790c1d0ad81ad820c | |
parent | d2469b4fe8cf9d428606b1bec1acd8e93e9df085 (diff) | |
parent | 7f7fc2562a95be630dbe609e8fb70383dcfada4f (diff) |
Merge remote-tracking branch 'upstream/lineage-18.1' into lineage-18.1
* upstream/lineage-18.1:
[1/2] Add battery info to tvsettings device info
(-) SystemUI: fix volume dialog position on TV
Make sure that only the owner can call stopVpnProfile()
DO NOT MERGE Apply a maximum char count to the load label api
Send targeted broadcasts to prevent other apps from receiving them.
Guard DISABLE_PLUGIN with PLUGIN permission.
Fix a potential thread safety issue in VectorDrawable
Fix background bypass via notifications
Change ownership of the account request notification.
Conflicts:
packages/SystemUI/src/com/android/systemui/volume/VolumeDialogImpl.java
Change-Id: Ic64698088ee30b059623adf0f262d4f33a4e40df
12 files changed, 260 insertions, 17 deletions
diff --git a/core/java/android/app/Notification.java b/core/java/android/app/Notification.java index c273cf08d03b..132afabe82d1 100644 --- a/core/java/android/app/Notification.java +++ b/core/java/android/app/Notification.java @@ -3029,6 +3029,19 @@ public class Notification implements Parcelable } /** + * Sets the token used for background operations for the pending intents associated with this + * notification. + * + * This token is automatically set during deserialization for you, you usually won't need to + * call this unless you want to change the existing token, if any. + * + * @hide + */ + public void setAllowlistToken(@Nullable IBinder token) { + mWhitelistToken = token; + } + + /** * @hide */ public static void addFieldsFromContext(Context context, Notification notification) { diff --git a/core/java/android/content/pm/PackageItemInfo.java b/core/java/android/content/pm/PackageItemInfo.java index 65ce1e7ef079..9cd568fe2aaf 100644 --- a/core/java/android/content/pm/PackageItemInfo.java +++ b/core/java/android/content/pm/PackageItemInfo.java @@ -207,7 +207,9 @@ public class PackageItemInfo { return loadSafeLabel(pm, DEFAULT_MAX_LABEL_SIZE_PX, SAFE_STRING_FLAG_TRIM | SAFE_STRING_FLAG_FIRST_LINE); } else { - return loadUnsafeLabel(pm); + // Trims the label string to the MAX_SAFE_LABEL_LENGTH. This is to prevent that the + // system is overwhelmed by an enormous string returned by the application. + return TextUtils.trimToSize(loadUnsafeLabel(pm), MAX_SAFE_LABEL_LENGTH); } } diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml index d6ee28b93f92..5c659123b027 100644 --- a/core/res/res/values/strings.xml +++ b/core/res/res/values/strings.xml @@ -3780,6 +3780,8 @@ <string name="deny">Deny</string> <string name="permission_request_notification_title">Permission requested</string> <string name="permission_request_notification_with_subtitle">Permission requested\nfor account <xliff:g id="account" example="foo@gmail.com">%s</xliff:g>.</string> + <!-- Title and subtitle for notification shown when app request account access (two lines) [CHAR LIMIT=NONE] --> + <string name="permission_request_notification_for_app_with_subtitle">Permission requested by <xliff:g id="app" example="Gmail">%1$s</xliff:g>\nfor account <xliff:g id="account" example="foo@gmail.com">%2$s</xliff:g>.</string> <!-- Message to show when an intent automatically switches users into the personal profile. --> <string name="forward_intent_to_owner">You\'re using this app outside of your work profile</string> diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml index 3ef0a8dc9daa..3c2aa621864b 100644 --- a/core/res/res/values/symbols.xml +++ b/core/res/res/values/symbols.xml @@ -548,6 +548,7 @@ <java-symbol type="string" name="notification_title" /> <java-symbol type="string" name="other_networks_no_internet" /> <java-symbol type="string" name="permission_request_notification_with_subtitle" /> + <java-symbol type="string" name="permission_request_notification_for_app_with_subtitle" /> <java-symbol type="string" name="prepend_shortcut_label" /> <java-symbol type="string" name="private_dns_broken_detailed" /> <java-symbol type="string" name="paste_as_plain_text" /> diff --git a/graphics/java/android/graphics/drawable/VectorDrawable.java b/graphics/java/android/graphics/drawable/VectorDrawable.java index e6fa866df3ab..a831bb86009c 100644 --- a/graphics/java/android/graphics/drawable/VectorDrawable.java +++ b/graphics/java/android/graphics/drawable/VectorDrawable.java @@ -348,15 +348,19 @@ public class VectorDrawable extends Drawable { private final Rect mTmpBounds = new Rect(); public VectorDrawable() { - this(new VectorDrawableState(null), null); + this(null, null); } /** * The one constructor to rule them all. This is called by all public * constructors to set the state and initialize local properties. */ - private VectorDrawable(@NonNull VectorDrawableState state, @Nullable Resources res) { - mVectorState = state; + private VectorDrawable(@Nullable VectorDrawableState state, @Nullable Resources res) { + // As the mutable, not-thread-safe native instance is stored in VectorDrawableState, we + // need to always do a defensive copy even if mutate() isn't called. Otherwise + // draw() being called on 2 different VectorDrawable instances could still hit the same + // underlying native object. + mVectorState = new VectorDrawableState(state); updateLocalState(res); } diff --git a/packages/SettingsLib/src/com/android/settingslib/deviceinfo/AbstractBatteryStatusPreferenceController.java b/packages/SettingsLib/src/com/android/settingslib/deviceinfo/AbstractBatteryStatusPreferenceController.java new file mode 100644 index 000000000000..d86dae8fd8ba --- /dev/null +++ b/packages/SettingsLib/src/com/android/settingslib/deviceinfo/AbstractBatteryStatusPreferenceController.java @@ -0,0 +1,157 @@ +/* + * 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.settingslib.deviceinfo; + +import androidx.annotation.VisibleForTesting; +import androidx.preference.Preference; +import androidx.preference.PreferenceScreen; + +import android.content.Context; +import android.content.Intent; +import android.content.IntentFilter; +import android.os.BatteryManager; +import android.os.Handler; +import android.os.Message; +import android.os.SystemClock; +import android.text.format.DateUtils; + +import com.android.settingslib.core.AbstractPreferenceController; +import com.android.settingslib.core.lifecycle.Lifecycle; +import com.android.settingslib.core.lifecycle.LifecycleObserver; +import com.android.settingslib.core.lifecycle.events.OnStart; +import com.android.settingslib.core.lifecycle.events.OnStop; +import com.android.settingslib.R; + +import java.lang.ref.WeakReference; + +/** + * Preference controller for battery status + */ +public abstract class AbstractBatteryStatusPreferenceController extends AbstractPreferenceController + implements LifecycleObserver, OnStart, OnStop { + + @VisibleForTesting + static final String KEY_BATTERY_STATUS = "battery_status"; + private static final int EVENT_UPDATE_BATTERY = 700; + + private Preference mBatteryStatus; + private Handler mHandler; + private Context mContext; + + public AbstractBatteryStatusPreferenceController(Context context, Lifecycle lifecycle) { + super(context); + mContext = context; + if (lifecycle != null) { + lifecycle.addObserver(this); + } + } + + @Override + public void onStart() { + getHandler().sendEmptyMessage(EVENT_UPDATE_BATTERY); + } + + @Override + public void onStop() { + getHandler().removeMessages(EVENT_UPDATE_BATTERY); + } + + @Override + public boolean isAvailable() { + Intent intent = mContext.registerReceiver(null, + new IntentFilter(Intent.ACTION_BATTERY_CHANGED)); + + return intent.getBooleanExtra(BatteryManager.EXTRA_PRESENT, false); + } + + @Override + public String getPreferenceKey() { + return KEY_BATTERY_STATUS; + } + + @Override + public void displayPreference(PreferenceScreen screen) { + super.displayPreference(screen); + mBatteryStatus = screen.findPreference(KEY_BATTERY_STATUS); + updateBattery(); + } + + private Handler getHandler() { + if (mHandler == null) { + mHandler = new MyHandler(this); + } + return mHandler; + } + + private void updateBattery() { + Intent intent = mContext.registerReceiver(null, + new IntentFilter(Intent.ACTION_BATTERY_CHANGED)); + + if (mBatteryStatus != null) { + String batterystatus = mContext.getString(R.string.battery_info_status_unknown); + String batterylevel = Integer.toString(Math.round(100.f + * intent.getIntExtra(BatteryManager.EXTRA_LEVEL, 100) + / intent.getIntExtra(BatteryManager.EXTRA_SCALE, 100))) + "%"; + + switch (intent.getIntExtra(BatteryManager.EXTRA_STATUS, -1)) { + case BatteryManager.BATTERY_STATUS_CHARGING: + batterystatus = mContext.getString(R.string.battery_info_status_charging); + break; + case BatteryManager.BATTERY_STATUS_DISCHARGING: + batterystatus = mContext.getString(R.string.battery_info_status_discharging); + break; + case BatteryManager.BATTERY_STATUS_FULL: + batterystatus = mContext.getString(R.string.battery_info_status_full); + break; + case BatteryManager.BATTERY_STATUS_NOT_CHARGING: + batterystatus = mContext.getString(R.string.battery_info_status_not_charging); + break; + case BatteryManager.BATTERY_STATUS_UNKNOWN: + default: + break; + } + + mBatteryStatus.setSummary(batterylevel + " - " + batterystatus); + } + } + + private static class MyHandler extends Handler { + private WeakReference<AbstractBatteryStatusPreferenceController> mStatus; + + public MyHandler(AbstractBatteryStatusPreferenceController activity) { + mStatus = new WeakReference<>(activity); + } + + @Override + public void handleMessage(Message msg) { + AbstractBatteryStatusPreferenceController status = mStatus.get(); + if (status == null) { + return; + } + + switch (msg.what) { + case EVENT_UPDATE_BATTERY: + status.updateBattery(); + sendEmptyMessageDelayed(EVENT_UPDATE_BATTERY, 1000); + break; + + default: + throw new IllegalStateException("Unknown message " + msg.what); + } + } + } +} diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/plugins/PluginManagerImpl.java b/packages/SystemUI/shared/src/com/android/systemui/shared/plugins/PluginManagerImpl.java index 4d1fb38329e9..a687bb89fd75 100644 --- a/packages/SystemUI/shared/src/com/android/systemui/shared/plugins/PluginManagerImpl.java +++ b/packages/SystemUI/shared/src/com/android/systemui/shared/plugins/PluginManagerImpl.java @@ -195,9 +195,12 @@ public class PluginManagerImpl extends BroadcastReceiver implements PluginManage filter.addAction(Intent.ACTION_PACKAGE_CHANGED); filter.addAction(Intent.ACTION_PACKAGE_REPLACED); filter.addAction(Intent.ACTION_PACKAGE_REMOVED); + filter.addDataScheme("package"); + mContext.registerReceiver(this, filter); filter.addAction(PLUGIN_CHANGED); filter.addAction(DISABLE_PLUGIN); filter.addDataScheme("package"); + mContext.registerReceiver(this, filter, PluginInstanceManager.PLUGIN_PERMISSION, null); mContext.registerReceiver(this, filter); filter = new IntentFilter(Intent.ACTION_USER_UNLOCKED); mContext.registerReceiver(this, filter); diff --git a/services/core/java/com/android/server/ConnectivityService.java b/services/core/java/com/android/server/ConnectivityService.java index 3c0fded2b771..6a34fc7324c1 100644 --- a/services/core/java/com/android/server/ConnectivityService.java +++ b/services/core/java/com/android/server/ConnectivityService.java @@ -73,6 +73,7 @@ import android.content.Context; import android.content.Intent; import android.content.IntentFilter; import android.content.pm.PackageManager; +import android.content.pm.PackageManager.NameNotFoundException; import android.content.res.Configuration; import android.database.ContentObserver; import android.net.CaptivePortal; @@ -4788,6 +4789,25 @@ public class ConnectivityService extends IConnectivityManager.Stub } } + private int getAppUid(final String app, final int userId) { + final PackageManager pm = mContext.getPackageManager(); + final long token = Binder.clearCallingIdentity(); + try { + return pm.getPackageUidAsUser(app, userId); + } catch (NameNotFoundException e) { + return -1; + } finally { + Binder.restoreCallingIdentity(token); + } + } + + private void verifyCallingUidAndPackage(String packageName, int callingUid) { + final int userId = UserHandle.getUserId(callingUid); + if (getAppUid(packageName, userId) != callingUid) { + throw new SecurityException(packageName + " does not belong to uid " + callingUid); + } + } + /** * Starts the VPN based on the stored profile for the given package * @@ -4799,7 +4819,9 @@ public class ConnectivityService extends IConnectivityManager.Stub */ @Override public void startVpnProfile(@NonNull String packageName) { - final int user = UserHandle.getUserId(Binder.getCallingUid()); + final int callingUid = Binder.getCallingUid(); + verifyCallingUidAndPackage(packageName, callingUid); + final int user = UserHandle.getUserId(callingUid); synchronized (mVpns) { throwIfLockdownEnabled(); mVpns.get(user).startVpnProfile(packageName, mKeyStore); @@ -4816,7 +4838,9 @@ public class ConnectivityService extends IConnectivityManager.Stub */ @Override public void stopVpnProfile(@NonNull String packageName) { - final int user = UserHandle.getUserId(Binder.getCallingUid()); + final int callingUid = Binder.getCallingUid(); + verifyCallingUidAndPackage(packageName, callingUid); + final int user = UserHandle.getUserId(callingUid); synchronized (mVpns) { mVpns.get(user).stopVpnProfile(packageName); } diff --git a/services/core/java/com/android/server/accounts/AccountManagerService.java b/services/core/java/com/android/server/accounts/AccountManagerService.java index 2e04f9c2bcd1..db3c25a7e43a 100644 --- a/services/core/java/com/android/server/accounts/AccountManagerService.java +++ b/services/core/java/com/android/server/accounts/AccountManagerService.java @@ -449,7 +449,7 @@ public class AccountManagerService if (!checkAccess || hasAccountAccess(account, packageName, UserHandle.getUserHandleForUid(uid))) { cancelNotification(getCredentialPermissionNotificationId(account, - AccountManager.ACCOUNT_ACCESS_TOKEN_TYPE, uid), packageName, + AccountManager.ACCOUNT_ACCESS_TOKEN_TYPE, uid), UserHandle.getUserHandleForUid(uid)); } } @@ -3051,8 +3051,8 @@ public class AccountManagerService String authTokenType = intent.getStringExtra( GrantCredentialsPermissionActivity.EXTRAS_AUTH_TOKEN_TYPE); final String titleAndSubtitle = - mContext.getString(R.string.permission_request_notification_with_subtitle, - account.name); + mContext.getString(R.string.permission_request_notification_for_app_with_subtitle, + getApplicationLabel(packageName), account.name); final int index = titleAndSubtitle.indexOf('\n'); String title = titleAndSubtitle; String subtitle = ""; @@ -3075,7 +3075,16 @@ public class AccountManagerService null, user)) .build(); installNotification(getCredentialPermissionNotificationId( - account, authTokenType, uid), n, packageName, user.getIdentifier()); + account, authTokenType, uid), n, "android", user.getIdentifier()); + } + + private String getApplicationLabel(String packageName) { + try { + return mPackageManager.getApplicationLabel( + mPackageManager.getApplicationInfo(packageName, 0)).toString(); + } catch (PackageManager.NameNotFoundException e) { + return packageName; + } } private Intent newGrantCredentialsPermissionIntent(Account account, String packageName, @@ -3111,7 +3120,7 @@ public class AccountManagerService nId = accounts.credentialsPermissionNotificationIds.get(key); if (nId == null) { String tag = TAG + ":" + SystemMessage.NOTE_ACCOUNT_CREDENTIAL_PERMISSION - + ":" + account.hashCode() + ":" + authTokenType.hashCode(); + + ":" + account.hashCode() + ":" + authTokenType.hashCode() + ":" + uid; int id = SystemMessage.NOTE_ACCOUNT_CREDENTIAL_PERMISSION; nId = new NotificationId(tag, id); accounts.credentialsPermissionNotificationIds.put(key, nId); @@ -4064,7 +4073,7 @@ public class AccountManagerService private void handleAuthenticatorResponse(boolean accessGranted) throws RemoteException { cancelNotification(getCredentialPermissionNotificationId(account, - AccountManager.ACCOUNT_ACCESS_TOKEN_TYPE, uid), packageName, + AccountManager.ACCOUNT_ACCESS_TOKEN_TYPE, uid), UserHandle.getUserHandleForUid(uid)); if (callback != null) { Bundle result = new Bundle(); diff --git a/services/core/java/com/android/server/net/NetworkPolicyManagerService.java b/services/core/java/com/android/server/net/NetworkPolicyManagerService.java index eeccb73da3ae..3cf4a05fdbdf 100644 --- a/services/core/java/com/android/server/net/NetworkPolicyManagerService.java +++ b/services/core/java/com/android/server/net/NetworkPolicyManagerService.java @@ -1381,7 +1381,8 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub { builder.setSmallIcon(R.drawable.stat_notify_error); - final Intent snoozeIntent = buildSnoozeWarningIntent(policy.template); + final Intent snoozeIntent = buildSnoozeWarningIntent(policy.template, + mContext.getPackageName()); builder.setDeleteIntent(PendingIntent.getBroadcast( mContext, 0, snoozeIntent, PendingIntent.FLAG_UPDATE_CURRENT)); @@ -1467,7 +1468,8 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub { builder.setSmallIcon(R.drawable.stat_notify_error); - final Intent snoozeIntent = buildSnoozeRapidIntent(policy.template); + final Intent snoozeIntent = buildSnoozeRapidIntent(policy.template, + mContext.getPackageName()); builder.setDeleteIntent(PendingIntent.getBroadcast( mContext, 0, snoozeIntent, PendingIntent.FLAG_UPDATE_CURRENT)); @@ -5141,17 +5143,19 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub { return new Intent(ACTION_ALLOW_BACKGROUND); } - private static Intent buildSnoozeWarningIntent(NetworkTemplate template) { + private static Intent buildSnoozeWarningIntent(NetworkTemplate template, String targetPackage) { final Intent intent = new Intent(ACTION_SNOOZE_WARNING); intent.addFlags(Intent.FLAG_RECEIVER_FOREGROUND); intent.putExtra(EXTRA_NETWORK_TEMPLATE, template); + intent.setPackage(targetPackage); return intent; } - private static Intent buildSnoozeRapidIntent(NetworkTemplate template) { + private static Intent buildSnoozeRapidIntent(NetworkTemplate template, String targetPackage) { final Intent intent = new Intent(ACTION_SNOOZE_RAPID); intent.addFlags(Intent.FLAG_RECEIVER_FOREGROUND); intent.putExtra(EXTRA_NETWORK_TEMPLATE, template); + intent.setPackage(targetPackage); return intent; } diff --git a/services/core/java/com/android/server/notification/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java index 87cfa7522fd4..c80669eafb00 100755 --- a/services/core/java/com/android/server/notification/NotificationManagerService.java +++ b/services/core/java/com/android/server/notification/NotificationManagerService.java @@ -3898,6 +3898,7 @@ public class NotificationManagerService extends SystemService { } } + /** Notifications returned here will have allowlistToken stripped from them. */ private StatusBarNotification sanitizeSbn(String pkg, int userId, StatusBarNotification sbn) { if (sbn.getUserId() == userId) { @@ -3905,11 +3906,16 @@ public class NotificationManagerService extends SystemService { // We could pass back a cloneLight() but clients might get confused and // try to send this thing back to notify() again, which would not work // very well. + Notification notification = sbn.getNotification().clone(); + // Remove background token before returning notification to untrusted app, this + // ensures the app isn't able to perform background operations that are + // associated with notification interactions. + notification.setAllowlistToken(null); return new StatusBarNotification( sbn.getPackageName(), sbn.getOpPkg(), sbn.getId(), sbn.getTag(), sbn.getUid(), sbn.getInitialPid(), - sbn.getNotification().clone(), + notification, sbn.getUser(), sbn.getOverrideGroupKey(), sbn.getPostTime()); } } diff --git a/tests/net/java/com/android/server/ConnectivityServiceTest.java b/tests/net/java/com/android/server/ConnectivityServiceTest.java index a5554c740e7f..e9301d1dea9d 100644 --- a/tests/net/java/com/android/server/ConnectivityServiceTest.java +++ b/tests/net/java/com/android/server/ConnectivityServiceTest.java @@ -1224,6 +1224,9 @@ public class ConnectivityServiceTest { Arrays.asList(new UserInfo[] { new UserInfo(VPN_USER, "", 0), })); + final int userId = UserHandle.getCallingUserId(); + final UserInfo primaryUser = new UserInfo(userId, "", UserInfo.FLAG_PRIMARY); + doReturn(primaryUser).when(mUserManager).getUserInfo(eq(userId)); final ApplicationInfo applicationInfo = new ApplicationInfo(); applicationInfo.targetSdkVersion = Build.VERSION_CODES.Q; when(mPackageManager.getApplicationInfoAsUser(anyString(), anyInt(), any())) @@ -1368,6 +1371,9 @@ public class ConnectivityServiceTest { buildPackageInfo(/* SYSTEM */ false, APP2_UID), buildPackageInfo(/* SYSTEM */ false, VPN_UID) })); + final int userId = UserHandle.getCallingUserId(); + when(mPackageManager.getPackageUidAsUser(TEST_PACKAGE_NAME, userId)) + .thenReturn(Process.myUid()); } private void verifyActiveNetwork(int transport) { @@ -7069,6 +7075,18 @@ public class ConnectivityServiceTest { } @Test + public void testStartVpnProfileFromDiffPackage() throws Exception { + final String notMyVpnPkg = "com.not.my.vpn"; + assertThrows(SecurityException.class, () -> mService.startVpnProfile(notMyVpnPkg)); + } + + @Test + public void testStopVpnProfileFromDiffPackage() throws Exception { + final String notMyVpnPkg = "com.not.my.vpn"; + assertThrows(SecurityException.class, () -> mService.stopVpnProfile(notMyVpnPkg)); + } + + @Test public void testUidUpdateChangesInterfaceFilteringRule() throws Exception { LinkProperties lp = new LinkProperties(); lp.setInterfaceName("tun0"); |