diff options
Diffstat (limited to 'core')
122 files changed, 10634 insertions, 253 deletions
diff --git a/core/api/system-current.txt b/core/api/system-current.txt index 3aa17f0865b4..16c5253427a8 100644 --- a/core/api/system-current.txt +++ b/core/api/system-current.txt @@ -14031,6 +14031,7 @@ package android.telephony.ims.stub { public class ImsUtImplBase { ctor public ImsUtImplBase(); method public void close(); + method public int queryCFForServiceClass(int, String, int); method public int queryCallBarring(int); method public int queryCallBarringForServiceClass(int, int); method public int queryCallForward(int, String); diff --git a/core/api/system-lint-baseline.txt b/core/api/system-lint-baseline.txt index b435acfccde8..5f3225a01811 100644 --- a/core/api/system-lint-baseline.txt +++ b/core/api/system-lint-baseline.txt @@ -1,4 +1,8 @@ // Baseline format: 1.0 +AcronymName: android.telephony.ims.stub.ImsUtImplBase#queryCFForServiceClass(int, String, int): + Acronyms should not be capitalized in method names: was `queryCFForServiceClass`, should this be `queryCfForServiceClass`? + + ArrayReturn: android.view.contentcapture.ViewNode#getAutofillOptions(): @@ -81,6 +85,9 @@ MissingNullability: android.telephony.SubscriptionPlan.Builder#createRecurringWe MissingNullability: android.telephony.data.DataService#onUnbind(android.content.Intent) parameter #0: +MissingNullability: android.telephony.ims.stub.ImsUtImplBase#queryCFForServiceClass(int, String, int) parameter #1: + Missing nullability on parameter `number` in method `queryCFForServiceClass` + MissingNullability: android.telephony.mbms.DownloadRequest.Builder#setServiceId(String): MissingNullability: android.telephony.mbms.DownloadRequest.Builder#setServiceId(String) parameter #0: diff --git a/core/api/test-lint-baseline.txt b/core/api/test-lint-baseline.txt index 5409165542f4..0aeba4854866 100644 --- a/core/api/test-lint-baseline.txt +++ b/core/api/test-lint-baseline.txt @@ -2013,6 +2013,8 @@ MissingNullability: android.telephony.ims.stub.ImsSmsImplBase#sendSms(int, int, MissingNullability: android.telephony.ims.stub.ImsUtImplBase#queryCallForward(int, String) parameter #1: +MissingNullability: android.telephony.ims.stub.ImsUtImplBase#queryCFForServiceClass(int, String, int) parameter #1: + MissingNullability: android.telephony.ims.stub.ImsUtImplBase#setListener(android.telephony.ims.ImsUtListener) parameter #0: MissingNullability: android.telephony.ims.stub.ImsUtImplBase#transact(android.os.Bundle) parameter #0: diff --git a/core/java/android/accounts/AccountManager.java b/core/java/android/accounts/AccountManager.java index 79fb86365b74..3183c172bac5 100644 --- a/core/java/android/accounts/AccountManager.java +++ b/core/java/android/accounts/AccountManager.java @@ -608,6 +608,7 @@ public class AccountManager { * @return The account's password, null if none or if the account doesn't exist */ public String getPassword(final Account account) { + android.util.SeempLog.record(22); if (account == null) throw new IllegalArgumentException("account is null"); try { return mService.getPassword(account); @@ -638,6 +639,7 @@ public class AccountManager { * @return The user data, null if the account, key doesn't exist, or the user is locked */ public String getUserData(final Account account, final String key) { + android.util.SeempLog.record(23); return mUserDataCache.query(new AccountKeyData(account,key)); } @@ -877,6 +879,7 @@ public class AccountManager { return new Future2Task<String>(handler, callback) { @Override public void doWork() throws RemoteException { + android.util.SeempLog.record(31); mService.getAuthTokenLabel(mResponse, accountType, authTokenType); } @@ -921,6 +924,7 @@ public class AccountManager { return new Future2Task<Boolean>(handler, callback) { @Override public void doWork() throws RemoteException { + android.util.SeempLog.record(31); mService.hasFeatures(mResponse, account, features, mContext.getOpPackageName()); } @Override @@ -981,6 +985,7 @@ public class AccountManager { return new Future2Task<Account[]>(handler, callback) { @Override public void doWork() throws RemoteException { + android.util.SeempLog.record(31); mService.getAccountsByFeatures(mResponse, type, features, mContext.getOpPackageName()); } @@ -1025,6 +1030,7 @@ public class AccountManager { * already exists, the account is null, the user is locked, or another error occurs. */ public boolean addAccountExplicitly(Account account, String password, Bundle userdata) { + android.util.SeempLog.record(24); if (account == null) throw new IllegalArgumentException("account is null"); try { return mService.addAccountExplicitly( @@ -1243,6 +1249,7 @@ public class AccountManager { return new Future2Task<Account>(handler, callback) { @Override public void doWork() throws RemoteException { + android.util.SeempLog.record(31); mService.renameAccount(mResponse, account, newName); } @Override @@ -1304,6 +1311,7 @@ public class AccountManager { @Deprecated public AccountManagerFuture<Boolean> removeAccount(final Account account, AccountManagerCallback<Boolean> callback, Handler handler) { + android.util.SeempLog.record(25); return removeAccountAsUser(account, callback, handler, mContext.getUser()); } @@ -1351,6 +1359,7 @@ public class AccountManager { @UserHandleAware public AccountManagerFuture<Bundle> removeAccount(final Account account, final Activity activity, AccountManagerCallback<Bundle> callback, Handler handler) { + android.util.SeempLog.record(28); return removeAccountAsUser(account, activity, callback, handler, mContext.getUser()); } @@ -1370,6 +1379,7 @@ public class AccountManager { return new Future2Task<Boolean>(handler, callback) { @Override public void doWork() throws RemoteException { + android.util.SeempLog.record(31); mService.removeAccountAsUser(mResponse, account, false, userHandle.getIdentifier()); } @Override @@ -1396,6 +1406,7 @@ public class AccountManager { return new AmsTask(activity, handler, callback) { @Override public void doWork() throws RemoteException { + android.util.SeempLog.record(34); mService.removeAccountAsUser(mResponse, account, activity != null, userHandle.getIdentifier()); } @@ -1509,6 +1520,7 @@ public class AccountManager { * @param password The password to set, null to clear the password */ public void setPassword(final Account account, final String password) { + android.util.SeempLog.record(26); if (account == null) throw new IllegalArgumentException("account is null"); try { mService.setPassword(account, password); @@ -1537,6 +1549,7 @@ public class AccountManager { * @param account The account whose password to clear */ public void clearPassword(final Account account) { + android.util.SeempLog.record(27); if (account == null) throw new IllegalArgumentException("account is null"); try { mService.clearPassword(account); @@ -1564,6 +1577,7 @@ public class AccountManager { * @param value String value to set, {@code null} to clear this user data key */ public void setUserData(final Account account, final String key, final String value) { + android.util.SeempLog.record(28); if (account == null) throw new IllegalArgumentException("account is null"); if (key == null) throw new IllegalArgumentException("key is null"); try { @@ -1714,6 +1728,7 @@ public class AccountManager { return new AmsTask(activity, handler, callback) { @Override public void doWork() throws RemoteException { + android.util.SeempLog.record(31); mService.getAuthToken(mResponse, account, authTokenType, false /* notifyOnAuthFailure */, true /* expectActivityLaunch */, optionsIn); @@ -1885,6 +1900,7 @@ public class AccountManager { return new AmsTask(null, handler, callback) { @Override public void doWork() throws RemoteException { + android.util.SeempLog.record(31); mService.getAuthToken(mResponse, account, authTokenType, notifyAuthFailure, false /* expectActivityLaunch */, optionsIn); } @@ -1947,6 +1963,7 @@ public class AccountManager { final Bundle addAccountOptions, final Activity activity, AccountManagerCallback<Bundle> callback, Handler handler) { if (Process.myUserHandle().equals(mContext.getUser())) { + android.util.SeempLog.record(29); if (accountType == null) throw new IllegalArgumentException("accountType is null"); final Bundle optionsIn = new Bundle(); if (addAccountOptions != null) { @@ -1957,6 +1974,7 @@ public class AccountManager { return new AmsTask(activity, handler, callback) { @Override public void doWork() throws RemoteException { + android.util.SeempLog.record(31); mService.addAccount(mResponse, accountType, authTokenType, requiredFeatures, activity != null, optionsIn); } @@ -1986,6 +2004,7 @@ public class AccountManager { return new AmsTask(activity, handler, callback) { @Override public void doWork() throws RemoteException { + android.util.SeempLog.record(31); mService.addAccountAsUser(mResponse, accountType, authTokenType, requiredFeatures, activity != null, optionsIn, userHandle.getIdentifier()); } @@ -2035,6 +2054,7 @@ public class AccountManager { return new Future2Task<Boolean>(handler, callback) { @Override public void doWork() throws RemoteException { + android.util.SeempLog.record(34); mService.copyAccountToUser( mResponse, account, fromUser.getIdentifier(), toUser.getIdentifier()); } @@ -2134,6 +2154,7 @@ public class AccountManager { return new AmsTask(activity, handler, callback) { @Override public void doWork() throws RemoteException { + android.util.SeempLog.record(31); mService.confirmCredentialsAsUser(mResponse, account, options, activity != null, userId); } @@ -2247,10 +2268,12 @@ public class AccountManager { public AccountManagerFuture<Bundle> editProperties(final String accountType, final Activity activity, final AccountManagerCallback<Bundle> callback, final Handler handler) { + android.util.SeempLog.record(30); if (accountType == null) throw new IllegalArgumentException("accountType is null"); return new AmsTask(activity, handler, callback) { @Override public void doWork() throws RemoteException { + android.util.SeempLog.record(31); mService.editProperties(mResponse, accountType, activity != null); } }.start(); @@ -2677,6 +2700,7 @@ public class AccountManager { @Override public void doWork() throws RemoteException { + android.util.SeempLog.record(31); getAccountByTypeAndFeatures(mAccountType, mFeatures, new AccountManagerCallback<Bundle>() { @Override diff --git a/core/java/android/app/ActivityManagerInternal.java b/core/java/android/app/ActivityManagerInternal.java index 7be4c3e1465b..4aa219f5c472 100644 --- a/core/java/android/app/ActivityManagerInternal.java +++ b/core/java/android/app/ActivityManagerInternal.java @@ -639,6 +639,9 @@ public abstract class ActivityManagerInternal { */ public abstract @TempAllowListType int getPushMessagingOverQuotaBehavior(); + // Starts a process as empty. + public abstract int startActivityAsUserEmpty(Bundle options); + /** * Returns the capability of the given uid */ diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java index 8af74edb88ff..d255870ecc5c 100644 --- a/core/java/android/app/ActivityThread.java +++ b/core/java/android/app/ActivityThread.java @@ -157,6 +157,7 @@ import android.system.StructStat; import android.telephony.TelephonyFrameworkInitializer; import android.util.AndroidRuntimeException; import android.util.ArrayMap; +import android.util.BoostFramework; import android.util.DisplayMetrics; import android.util.EventLog; import android.util.Log; @@ -6464,6 +6465,8 @@ public final class ActivityThread extends ClientTransactionHandler @UnsupportedAppUsage private void handleBindApplication(AppBindData data) { + long st_bindApp = SystemClock.uptimeMillis(); + BoostFramework ux_perf = null; // Register the UI Thread as a sensitive thread to the runtime. VMRuntime.registerSensitiveThread(); // In the case the stack depth property exists, pass it down to the runtime. @@ -6576,10 +6579,17 @@ public final class ActivityThread extends ClientTransactionHandler /** * Switch this process to density compatibility mode if needed. */ - if ((data.appInfo.flags&ApplicationInfo.FLAG_SUPPORTS_SCREEN_DENSITIES) + if ((data.appInfo.flags & ApplicationInfo.FLAG_SUPPORTS_SCREEN_DENSITIES) == 0) { mDensityCompatMode = true; Bitmap.setDefaultDensity(DisplayMetrics.DENSITY_DEFAULT); + } else { + int overrideDensity = data.appInfo.getOverrideDensity(); + if(overrideDensity != 0) { + Log.d(TAG, "override app density from " + DisplayMetrics.DENSITY_DEVICE + " to " + overrideDensity); + mDensityCompatMode = true; + Bitmap.setDefaultDensity(overrideDensity); + } } mConfigurationController.updateDefaultDensity(data.config.densityDpi); @@ -6678,6 +6688,15 @@ public final class ActivityThread extends ClientTransactionHandler } if (!Process.isIsolated()) { + final int old_mask = StrictMode.allowThreadDiskWritesMask(); + try { + ux_perf = new BoostFramework(appContext); + } finally { + StrictMode.setThreadPolicyMask(old_mask); + } + } + + if (!Process.isIsolated()) { final int oldMask = StrictMode.allowThreadDiskWritesMask(); try { setupGraphicsSupport(appContext); @@ -6796,6 +6815,28 @@ public final class ActivityThread extends ClientTransactionHandler throw e.rethrowFromSystemServer(); } } + long end_bindApp = SystemClock.uptimeMillis(); + int bindApp_dur = (int) (end_bindApp - st_bindApp); + String pkg_name = null; + if (appContext != null) { + pkg_name = appContext.getPackageName(); + } + if (ux_perf != null && !Process.isIsolated() && pkg_name != null) { + String pkgDir = null; + try + { + String codePath = appContext.getPackageCodePath(); + pkgDir = codePath.substring(0, codePath.lastIndexOf('/')); + } + catch(Exception e) + { + Slog.e(TAG, "HeavyGameThread () : Exception_1 = " + e); + } + ux_perf.perfUXEngine_events(BoostFramework.UXE_EVENT_BINDAPP, 0, + pkg_name, + bindApp_dur, + pkgDir); + } } private void handleSetContentCaptureOptionsCallback(String packageName) { diff --git a/core/java/android/app/Instrumentation.java b/core/java/android/app/Instrumentation.java index fd6fa57b9e8d..a445267b36a9 100644 --- a/core/java/android/app/Instrumentation.java +++ b/core/java/android/app/Instrumentation.java @@ -509,6 +509,7 @@ public class Instrumentation { */ @NonNull public Activity startActivitySync(@NonNull Intent intent, @Nullable Bundle options) { + android.util.SeempLog.record_str(376, intent.toString()); validateNotAppThread(); final Activity activity; @@ -1722,6 +1723,7 @@ public class Instrumentation { public ActivityResult execStartActivity( Context who, IBinder contextThread, IBinder token, Activity target, Intent intent, int requestCode, Bundle options) { + android.util.SeempLog.record_str(377, intent.toString()); IApplicationThread whoThread = (IApplicationThread) contextThread; Uri referrer = target != null ? target.onProvideReferrer() : null; if (referrer != null) { @@ -1797,6 +1799,7 @@ public class Instrumentation { public int execStartActivitiesAsUser(Context who, IBinder contextThread, IBinder token, Activity target, Intent[] intents, Bundle options, int userId) { + android.util.SeempLog.record_str(378, intents.toString()); IApplicationThread whoThread = (IApplicationThread) contextThread; if (mActivityMonitors != null) { synchronized (mSync) { @@ -1871,6 +1874,7 @@ public class Instrumentation { public ActivityResult execStartActivity( Context who, IBinder contextThread, IBinder token, String target, Intent intent, int requestCode, Bundle options) { + android.util.SeempLog.record_str(377, intent.toString()); IApplicationThread whoThread = (IApplicationThread) contextThread; if (mActivityMonitors != null) { synchronized (mSync) { @@ -1941,6 +1945,7 @@ public class Instrumentation { public ActivityResult execStartActivity( Context who, IBinder contextThread, IBinder token, String resultWho, Intent intent, int requestCode, Bundle options, UserHandle user) { + android.util.SeempLog.record_str(377, intent.toString()); IApplicationThread whoThread = (IApplicationThread) contextThread; if (mActivityMonitors != null) { synchronized (mSync) { @@ -2040,6 +2045,7 @@ public class Instrumentation { public void execStartActivityFromAppTask( Context who, IBinder contextThread, IAppTask appTask, Intent intent, Bundle options) { + android.util.SeempLog.record_str(380, intent.toString()); IApplicationThread whoThread = (IApplicationThread) contextThread; if (mActivityMonitors != null) { synchronized (mSync) { diff --git a/core/java/android/app/PendingIntent.java b/core/java/android/app/PendingIntent.java index 0136a35e3975..2150fc9dc0e7 100644 --- a/core/java/android/app/PendingIntent.java +++ b/core/java/android/app/PendingIntent.java @@ -51,8 +51,10 @@ import android.os.Parcel; import android.os.Parcelable; import android.os.RemoteException; import android.os.UserHandle; +import android.os.SystemProperties; import android.util.AndroidException; import android.util.ArraySet; +import android.util.Log; import android.util.proto.ProtoOutputStream; import com.android.internal.os.IResultReceiver; @@ -140,6 +142,7 @@ public final class PendingIntent implements Parcelable { @EnabledAfter(targetSdkVersion = android.os.Build.VERSION_CODES.R) static final long PENDING_INTENT_EXPLICIT_MUTABILITY_REQUIRED = 160794467L; + /** @hide */ @IntDef(flag = true, value = { diff --git a/core/java/android/app/WallpaperManager.java b/core/java/android/app/WallpaperManager.java index fca4c698c49c..b337396ebe5d 100644 --- a/core/java/android/app/WallpaperManager.java +++ b/core/java/android/app/WallpaperManager.java @@ -680,7 +680,7 @@ public class WallpaperManager { cmProxy.doColorManagement(decoder, info); } })); - } catch (OutOfMemoryError | IOException e) { + } catch (OutOfMemoryError | IOException | ArrayIndexOutOfBoundsException e) { Log.w(TAG, "Can't decode file", e); } } diff --git a/core/java/android/bluetooth/BluetoothAdapter.java b/core/java/android/bluetooth/BluetoothAdapter.java index 5094498dbee5..76e743f155dc 100644 --- a/core/java/android/bluetooth/BluetoothAdapter.java +++ b/core/java/android/bluetooth/BluetoothAdapter.java @@ -84,7 +84,9 @@ import java.util.WeakHashMap; import java.util.concurrent.Executor; import java.util.concurrent.TimeoutException; import java.util.concurrent.locks.ReentrantReadWriteLock; - +import java.lang.reflect.Method; +import java.lang.reflect.Constructor; +import java.lang.reflect.InvocationTargetException; /** * Represents the local device Bluetooth adapter. The {@link BluetoothAdapter} * lets you perform fundamental Bluetooth tasks, such as initiate @@ -829,6 +831,7 @@ public final class BluetoothAdapter { */ @RequiresNoPermission public BluetoothDevice getRemoteDevice(String address) { + android.util.SeempLog.record(62); final BluetoothDevice res = new BluetoothDevice(address); res.setAttributionSource(mAttributionSource); return res; @@ -847,6 +850,7 @@ public final class BluetoothAdapter { */ @RequiresNoPermission public BluetoothDevice getRemoteDevice(byte[] address) { + android.util.SeempLog.record(62); if (address == null || address.length != 6) { throw new IllegalArgumentException("Bluetooth address must have 6 bytes"); } @@ -1054,7 +1058,10 @@ public final class BluetoothAdapter { @SuppressLint("AndroidFrameworkRequiresPermission") protected Integer recompute(Void query) { try { - return mService.getState(); + if (mService != null) { + return mService.getState(); + } + return BluetoothAdapter.STATE_OFF; } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } @@ -1110,6 +1117,7 @@ public final class BluetoothAdapter { @RequiresNoPermission @AdapterState public int getState() { + android.util.SeempLog.record(63); int state = getStateInternal(); // Consider all internal states as OFF @@ -1195,6 +1203,7 @@ public final class BluetoothAdapter { @RequiresBluetoothConnectPermission @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public boolean enable() { + android.util.SeempLog.record(56); if (isEnabled()) { if (DBG) { Log.d(TAG, "enable(): BT already enabled!"); @@ -1234,6 +1243,7 @@ public final class BluetoothAdapter { @RequiresBluetoothConnectPermission @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public boolean disable() { + android.util.SeempLog.record(57); try { return mManagerService.disable(mAttributionSource, true); } catch (RemoteException e) { @@ -1253,6 +1263,7 @@ public final class BluetoothAdapter { @RequiresBluetoothConnectPermission @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public boolean disable(boolean persist) { + android.util.SeempLog.record(57); try { return mManagerService.disable(mAttributionSource, persist); @@ -1328,13 +1339,14 @@ public final class BluetoothAdapter { public boolean factoryReset() { try { mServiceLock.readLock().lock(); - if (mService != null && mService.factoryReset(mAttributionSource) - && mManagerService != null - && mManagerService.onFactoryReset(mAttributionSource)) { - return true; + if (mManagerService != null) { + SystemProperties.set("persist.bluetooth.factoryreset", "true"); + /* factoryReset handles both bluetooth reset and config remove + * functionality, hence remove onFactoryReset call to avoid redundant code + */ + return mManagerService.factoryReset(); } Log.e(TAG, "factoryReset(): Setting persist.bluetooth.factoryreset to retry later"); - SystemProperties.set("persist.bluetooth.factoryreset", "true"); } catch (RemoteException e) { Log.e(TAG, "", e); } finally { @@ -1818,6 +1830,7 @@ public final class BluetoothAdapter { @RequiresBluetoothLocationPermission @RequiresPermission(android.Manifest.permission.BLUETOOTH_SCAN) public boolean startDiscovery() { + android.util.SeempLog.record(58); if (getState() != STATE_ON) { return false; } @@ -2003,7 +2016,21 @@ public final class BluetoothAdapter { return false; } - + /** @hide */ + @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) + public boolean isBroadcastActive() { + try { + mServiceLock.readLock().lock(); + if (mService != null) { + return mService.isBroadcastActive(mAttributionSource); + } + } catch (RemoteException e) { + Log.e(TAG, "", e); + } finally { + mServiceLock.readLock().unlock(); + } + return false; + } /** * Connects all enabled and supported bluetooth profiles between the local and remote device. * Connection is asynchronous and you should listen to each profile's broadcast intent @@ -2308,6 +2335,13 @@ public final class BluetoothAdapter { } /** + * @hide + */ + public void btCmdGetFunctionCallmap(boolean isdump) { + Log.d(TAG, "btCmdGetFunctionCallmap: " + isdump); + } + + /** * Return true if Hearing Aid Profile is supported. * * @return true if phone supports Hearing Aid Profile @@ -2481,6 +2515,7 @@ public final class BluetoothAdapter { @RequiresBluetoothConnectPermission @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public Set<BluetoothDevice> getBondedDevices() { + android.util.SeempLog.record(61); if (getState() != STATE_ON) { return toDeviceSet(Arrays.asList()); } @@ -2661,6 +2696,7 @@ public final class BluetoothAdapter { @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) @SuppressLint("AndroidFrameworkRequiresPermission") public int getProfileConnectionState(int profile) { + android.util.SeempLog.record(64); if (getState() != STATE_ON) { return BluetoothProfile.STATE_DISCONNECTED; } @@ -2790,6 +2826,7 @@ public final class BluetoothAdapter { @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public BluetoothServerSocket listenUsingInsecureRfcommWithServiceRecord(String name, UUID uuid) throws IOException { + android.util.SeempLog.record(59); return createNewRfcommSocketAndRecord(name, uuid, false, false); } @@ -2987,6 +3024,92 @@ public final class BluetoothAdapter { return null; } + private void closeBCProfile(BluetoothProfile proxy) { + Class<?> bshClass = null; + Method bshClose = null; + try { + bshClass = Class.forName("android.bluetooth.BluetoothSyncHelper"); + } catch (ClassNotFoundException ex) { + Log.e(TAG, "no BSH: exists"); + bshClass = null; + } + if (bshClass != null) { + Log.d(TAG, "Able to get BSH class handle"); + try { + bshClose = bshClass.getDeclaredMethod("close", null); + } catch (NoSuchMethodException e) { + Log.e(TAG, "no BSH:isSupported method exists"); + } + if (bshClose != null) { + try { + bshClose.invoke(proxy, null); + } catch(IllegalAccessException e) { + Log.e(TAG, "bshClose IllegalAccessException"); + } catch (InvocationTargetException e) { + Log.e(TAG, "bshClose InvocationTargetException"); + } + } + } + Log.d(TAG, "CloseBCProfile returns"); + } + + private boolean getBCProfile(Context context, BluetoothProfile.ServiceListener sl) { + boolean ret = true; + boolean isProfileSupported = false; + Class<?> bshClass = null; + Method bshSupported = null; + Constructor bshCons = null; + Object bshObj = null; + try { + bshClass = Class.forName("android.bluetooth.BluetoothSyncHelper"); + } catch (ClassNotFoundException ex) { + Log.e(TAG, "no BSH: exists"); + bshClass = null; + } + if (bshClass != null) { + Log.d(TAG, "Able to get BSH class handle"); + try { + bshSupported = bshClass.getDeclaredMethod("isSupported", null); + } catch (NoSuchMethodException e) { + Log.e(TAG, "no BSH:isSupported method exists: gdm"); + } + try { + bshCons = + bshClass.getDeclaredConstructor( + new Class[]{Context.class, + BluetoothProfile.ServiceListener.class}); + } catch (NoSuchMethodException ex) { + Log.e(TAG, "bshCons: NoSuchMethodException: gdm" + ex); + } + } + if (bshClass != null && bshSupported != null && bshCons != null) { + try { + isProfileSupported = (boolean)bshSupported.invoke(null, null); + } catch(IllegalAccessException e) { + Log.e(TAG, "BSH:isSupported IllegalAccessException"); + } catch (InvocationTargetException e) { + Log.e(TAG, "BSH:isSupported InvocationTargetException"); + } + if (isProfileSupported) { + try { + bshObj = bshCons.newInstance( + context, sl); + } catch (InstantiationException ex) { + Log.e(TAG, "bshCons InstantiationException:" + ex); + } catch (IllegalAccessException ex) { + Log.e(TAG, "bshCons InstantiationException:" + ex); + } catch (InvocationTargetException ex) { + Log.e(TAG, "bshCons InvocationTargetException:" + ex); + } + } + } + if (bshObj == null) { + ret = false; + } + Log.d(TAG, "getBCService returns" + ret); + return ret; + } + /** * Get the profile proxy object associated with the profile. * @@ -3034,6 +3157,9 @@ public final class BluetoothAdapter { } else if (profile == BluetoothProfile.PBAP) { BluetoothPbap pbap = new BluetoothPbap(context, listener, this); return true; + } else if (profile == BluetoothProfile.DUN) { + BluetoothDun dun = new BluetoothDun(context, listener); + return true; } else if (profile == BluetoothProfile.HEALTH) { Log.e(TAG, "getProfileProxy(): BluetoothHealth is deprecated"); return false; @@ -3056,12 +3182,22 @@ public final class BluetoothAdapter { } else if (profile == BluetoothProfile.HID_DEVICE) { BluetoothHidDevice hidDevice = new BluetoothHidDevice(context, listener, this); return true; + } else if (profile == BluetoothProfile.BROADCAST) { + return getBroadcastProfile(context, listener); + } else if (profile == BluetoothProfile.BC_PROFILE) { + return getBCProfile(context, listener); } else if (profile == BluetoothProfile.HEARING_AID) { if (isHearingAidProfileSupported()) { BluetoothHearingAid hearingAid = new BluetoothHearingAid(context, listener, this); return true; } return false; + } else if (profile == BluetoothProfile.GROUP_CLIENT) { + BluetoothDeviceGroup groupClient = new BluetoothDeviceGroup(context, listener); + return true; + } else if (profile == BluetoothProfile.VCP) { + BluetoothVcp vcp = new BluetoothVcp(context, listener); + return true; } else if (profile == BluetoothProfile.LE_AUDIO) { BluetoothLeAudio leAudio = new BluetoothLeAudio(context, listener, this); return true; @@ -3118,6 +3254,10 @@ public final class BluetoothAdapter { BluetoothPbap pbap = (BluetoothPbap) proxy; pbap.close(); break; + case BluetoothProfile.DUN: + BluetoothDun dun = (BluetoothDun)proxy; + dun.close(); + break; case BluetoothProfile.GATT: BluetoothGatt gatt = (BluetoothGatt) proxy; gatt.close(); @@ -3150,6 +3290,12 @@ public final class BluetoothAdapter { BluetoothHidDevice hidDevice = (BluetoothHidDevice) proxy; hidDevice.close(); break; + case BluetoothProfile.BROADCAST: + closeBroadcastProfile(proxy); + break; + case BluetoothProfile.BC_PROFILE: + closeBCProfile(proxy); + break; case BluetoothProfile.HEARING_AID: BluetoothHearingAid hearingAid = (BluetoothHearingAid) proxy; hearingAid.close(); @@ -3157,6 +3303,71 @@ public final class BluetoothAdapter { case BluetoothProfile.LE_AUDIO: BluetoothLeAudio leAudio = (BluetoothLeAudio) proxy; leAudio.close(); + break; + case BluetoothProfile.GROUP_CLIENT: + BluetoothDeviceGroup groupClient = (BluetoothDeviceGroup) proxy; + groupClient.close(); + break; + case BluetoothProfile.VCP: + BluetoothVcp vcp = (BluetoothVcp) proxy; + vcp.close(); + break; + } + } + private boolean getBroadcastProfile(Context context, + BluetoothProfile.ServiceListener listener) { + boolean ret = true; + Class<?> broadcastClass = null; + Constructor bcastConstructor = null; + Object broadcastObj = null; + try { + broadcastClass = Class.forName("android.bluetooth.BluetoothBroadcast"); + } catch (ClassNotFoundException ex) { + Log.e(TAG, "no BluetoothBroadcast: exists"); + } + if (broadcastClass != null) { + try { + bcastConstructor = + broadcastClass.getDeclaredConstructor(new Class[]{Context.class, + BluetoothProfile.ServiceListener.class}); + } catch (NoSuchMethodException ex) { + Log.e(TAG, "bcastConstructor: NoSuchMethodException: gdm" + ex); + } + } + if (bcastConstructor != null) { + try { + broadcastObj = bcastConstructor.newInstance(context, listener); + } catch (InstantiationException | IllegalAccessException | + InvocationTargetException ex) { + ex.printStackTrace(); + } + } + if (broadcastObj == null) { + return false; + } + return true; + } + private void closeBroadcastProfile(BluetoothProfile proxy) { + Class<?> broadcastClass = null; + Method broadcastClose = null; + try { + broadcastClass = Class.forName("android.bluetooth.BluetootBroadcast"); + } catch (ClassNotFoundException ex) { + Log.e(TAG, "no BluetoothBroadcast: exists"); + } + if (broadcastClass != null) { + try { + broadcastClose = broadcastClass.getDeclaredMethod("close", null); + } catch (NoSuchMethodException e) { + Log.e(TAG, "no Broadcast:close method exists"); + } + if (broadcastClose != null) { + try { + broadcastClose.invoke(proxy, null); + } catch(IllegalAccessException | InvocationTargetException ex) { + ex.printStackTrace(); + } + } } } @@ -3244,8 +3455,10 @@ public final class BluetoothAdapter { synchronized (mBluetoothConnectionCallbackExecutorMap) { if (!mBluetoothConnectionCallbackExecutorMap.isEmpty()) { try { - mService.registerBluetoothConnectionCallback(mConnectionCallback, - mAttributionSource); + if (mService != null) { + mService.registerBluetoothConnectionCallback + (mConnectionCallback, mAttributionSource); + } } catch (RemoteException e) { Log.e(TAG, "onBluetoothServiceUp: Failed to register bluetooth" + "connection callback", e); @@ -3253,7 +3466,6 @@ public final class BluetoothAdapter { } } } - public void onBluetoothServiceDown() { synchronized (mServiceLock.writeLock()) { mService = null; @@ -3267,8 +3479,8 @@ public final class BluetoothAdapter { mBluetoothLeScanner.cleanup(); } } + Log.d(TAG, "onBluetoothServiceDown: Finished sending callbacks to registered clients"); } - public void onBrEdrDown() { } }; @@ -3497,6 +3709,22 @@ public final class BluetoothAdapter { } } + /** + * @hide + */ + public void unregisterAdapter() { + try { + //mServiceLock.writeLock().lock(); + if (mManagerService != null){ + mManagerService.unregisterAdapter(mManagerCallback); + } + } catch (RemoteException e) { + Log.e(TAG, "", e); + } finally { + //mServiceLock.writeLock().unlock(); + } + } + private Set<BluetoothDevice> toDeviceSet(List<BluetoothDevice> devices) { Set<BluetoothDevice> deviceSet = new HashSet<BluetoothDevice>(devices); return Collections.unmodifiableSet(deviceSet); diff --git a/core/java/android/bluetooth/BluetoothClass.java b/core/java/android/bluetooth/BluetoothClass.java index 7fe18a0704ba..1d19c9431e69 100755..100644 --- a/core/java/android/bluetooth/BluetoothClass.java +++ b/core/java/android/bluetooth/BluetoothClass.java @@ -119,6 +119,11 @@ public final class BluetoothClass implements Parcelable { private static final int BITMASK = 0xFFE000; public static final int LIMITED_DISCOVERABILITY = 0x002000; + /** + * @hide + */ + public static final int GROUP = 0x004000; + public static final int POSITIONING = 0x010000; public static final int NETWORKING = 0x020000; public static final int RENDER = 0x040000; diff --git a/core/java/android/bluetooth/BluetoothCodecConfig.java b/core/java/android/bluetooth/BluetoothCodecConfig.java index 1d0bf97c34eb..1184d20107ba 100644 --- a/core/java/android/bluetooth/BluetoothCodecConfig.java +++ b/core/java/android/bluetooth/BluetoothCodecConfig.java @@ -46,7 +46,9 @@ public final class BluetoothCodecConfig implements Parcelable { SOURCE_CODEC_TYPE_APTX, SOURCE_CODEC_TYPE_APTX_HD, SOURCE_CODEC_TYPE_LDAC, - SOURCE_CODEC_TYPE_MAX, + SOURCE_CODEC_TYPE_APTX_ADAPTIVE, + SOURCE_CODEC_TYPE_APTX_TWSP, + SOURCE_QVA_CODEC_TYPE_MAX, SOURCE_CODEC_TYPE_INVALID }) @Retention(RetentionPolicy.SOURCE) @@ -71,6 +73,22 @@ public final class BluetoothCodecConfig implements Parcelable { public static final int SOURCE_CODEC_TYPE_MAX = 5; @UnsupportedAppUsage + public static final int SOURCE_CODEC_TYPE_APTX_ADAPTIVE = SOURCE_CODEC_TYPE_MAX; + + @UnsupportedAppUsage + public static final int SOURCE_CODEC_TYPE_APTX_TWSP = SOURCE_CODEC_TYPE_MAX + 1; + + @UnsupportedAppUsage + public static final int SOURCE_QVA_CODEC_TYPE_MAX = SOURCE_CODEC_TYPE_MAX + 2; + + /* CELT is not an A2DP Codec and only used to fetch encoder + ** format for BA usecase, moving out of a2dp codec value list + */ + @UnsupportedAppUsage + public static final int SOURCE_CODEC_TYPE_CELT = 8; + + public static final int SOURCE_CODEC_TYPE_LC3 = 9; + public static final int SOURCE_CODEC_TYPE_INVALID = 1000 * 1000; /** @hide */ @@ -126,6 +144,14 @@ public final class BluetoothCodecConfig implements Parcelable { @UnsupportedAppUsage public static final int SAMPLE_RATE_192000 = 0x1 << 5; + public static final int SAMPLE_RATE_16000 = 0x1 << 6; + + public static final int SAMPLE_RATE_24000 = 0x1 << 7; + + public static final int SAMPLE_RATE_32000 = 0x1 << 8; + + public static final int SAMPLE_RATE_8000 = 0x1 << 9; + /** @hide */ @IntDef(prefix = "BITS_PER_SAMPLE_", value = { @@ -167,6 +193,7 @@ public final class BluetoothCodecConfig implements Parcelable { @UnsupportedAppUsage public static final int CHANNEL_MODE_STEREO = 0x1 << 1; + public static final int CHANNEL_MODE_JOINT_STEREO = 0x1 << 2; private final @SourceCodecType int mCodecType; private @CodecPriority int mCodecPriority; @@ -403,6 +430,10 @@ public final class BluetoothCodecConfig implements Parcelable { return "aptX HD"; case SOURCE_CODEC_TYPE_LDAC: return "LDAC"; + case SOURCE_CODEC_TYPE_APTX_ADAPTIVE: + return "aptX Adaptive"; + case SOURCE_CODEC_TYPE_APTX_TWSP: + return "aptX TWS+"; case SOURCE_CODEC_TYPE_INVALID: return "INVALID CODEC"; default: @@ -652,6 +683,10 @@ public final class BluetoothCodecConfig implements Parcelable { if (mCodecSpecific1 != other.mCodecSpecific1) { return false; } + case SOURCE_CODEC_TYPE_APTX_ADAPTIVE: + if (other.mCodecSpecific4 > 0) { + return false; + } // fall through default: return true; diff --git a/core/java/android/bluetooth/BluetoothDevice.java b/core/java/android/bluetooth/BluetoothDevice.java index 5a5fac4a7664..7b8c061deefc 100644 --- a/core/java/android/bluetooth/BluetoothDevice.java +++ b/core/java/android/bluetooth/BluetoothDevice.java @@ -1,4 +1,39 @@ /* + * Copyright (C) 2017, The Linux Foundation. All rights reserved. + * Not a Contribution. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted (subject to the limitations in the + * disclaimer below) provided that the following conditions are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * + * * Neither the name of The Linux Foundation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE + * GRANTED BY THIS LICENSE. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT + * HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* * Copyright (C) 2009 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -218,6 +253,18 @@ public final class BluetoothDevice implements Parcelable, Attributable { public static final String ACTION_BOND_STATE_CHANGED = "android.bluetooth.device.action.BOND_STATE_CHANGED"; + /** + * Broadcast Action: Broadcast details of IOT device when an IOT + * related issue is observed. + * <p>Always contains the extra fields {@link #EXTRA_NAME}. + * <p>Requires {@link android.Manifest.permission#BLUETOOTH} to receive. + * @hide + **/ + + @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) + public static final String ACTION_REMOTE_ISSUE_OCCURRED = + "org.codeaurora.intent.bluetooth.action.REMOTE_ISSUE_OCCURRED"; + /** * Broadcast Action: Indicates the battery level of a remote device has * been retrieved for the first time, or changed since the last retrieval @@ -259,6 +306,17 @@ public final class BluetoothDevice implements Parcelable, Attributable { public static final int BATTERY_LEVEL_BLUETOOTH_OFF = -100; /** + * Broadcast Action: Indicates the remote devices are TWS plus earbuds pair. + * <p>Always contains the extra fields {@link #EXTRA_TWS_PLUS_DEVICE1}, + * {@link #EXTRA_TWS_PLUS_DEVICE2}. + * <p>Requires {@link android.Manifest.permission#BLUETOOTH} to receive. + * @hide + */ + @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) + public static final String ACTION_TWS_PLUS_DEVICE_PAIR = + "android.bluetooth.device.action.TWS_PLUS_DEVICE_PAIR"; + + /** * Used as a Parcelable {@link BluetoothDevice} extra field in every intent * broadcast by this class. It contains the {@link BluetoothDevice} that * the intent applies to. @@ -272,6 +330,77 @@ public final class BluetoothDevice implements Parcelable, Attributable { public static final String EXTRA_NAME = "android.bluetooth.device.extra.NAME"; /** + * Used as a Parcelable {@link BluetoothQualityReport} extra field in + * {@link #ACTION_REMOTE_ISSUE_OCCURRED} intent. It contains the {@link BluetoothQualityReport}. + * @hide + */ + public static final String EXTRA_BQR = "android.bluetooth.qti.extra.EXTRA_BQR"; + + /** + * Used as a String extra field in {@link #ACTION_REMOTE_ISSUE_OCCURRED} + * intents. It contains the type of IOT issue that occurred. + * @hide + */ + public static final String EXTRA_ISSUE_TYPE = "android.bluetooth.qti.extra.ERROR_TYPE"; + + /** + * Used as a String extra field in {@link #ACTION_REMOTE_ISSUE_OCCURRED} intents. + * It contains the details of details of the issue. + * @hide + */ + public static final String EXTRA_ERROR_CODE = "android.bluetooth.qti.extra.ERROR_CODE"; + + /** + * Used as a String extra field in {@link #ACTION_REMOTE_ISSUE_OCCURRED} intents. + * It contains the SoC event mask when issue occurred. + * @hide + */ + public static final String EXTRA_ERROR_EVENT_MASK = "android.bluetooth.qti.extra.ERROR_EVENT_MASK"; + + /** + * Used as a String extra field in {@link #ACTION_REMOTE_ISSUE_OCCURRED} intents. + * It contains the LMP Version of IOT device. + * @hide + */ + public static final String EXTRA_LMP_VERSION = "android.bluetooth.qti.extra.EXTRA_LMP_VERSION"; + + /** + * Used as a String extra field in {@link #ACTION_REMOTE_ISSUE_OCCURRED} intents. + * It contains the LMP Sub Version of IOT device. + * @hide + */ + public static final String EXTRA_LMP_SUBVER = "android.bluetooth.qti.extra.EXTRA_LMP_SUBVER"; + + /** + * Used as a String extra field in {@link #ACTION_REMOTE_ISSUE_OCCURRED} intents. + * It contains the Manufacturer ID of IOT device. + * @hide + */ + public static final String EXTRA_MANUFACTURER = "android.bluetooth.qti.extra.EXTRA_MANUFACTURER"; + + /** + * Used as a String extra field in {@link #ACTION_REMOTE_ISSUE_OCCURRED} intents. + * It contains the Power level. + * @hide + */ + public static final String EXTRA_POWER_LEVEL = "android.bluetooth.qti.extra.EXTRA_POWER_LEVEL"; + + /** + * Used as a String extra field in {@link #ACTION_REMOTE_ISSUE_OCCURRED} intents. + * It contains the Link Quality of the connection. + * @hide + */ + public static final String EXTRA_LINK_QUALITY = "android.bluetooth.qti.extra.EXTRA_LINK_QUALITY"; + + /** + * Used as a String extra field in {@link #ACTION_REMOTE_ISSUE_OCCURRED} intents. + * It contains the coutnt of glitches occured since last broadcast. + * @hide + */ + public static final String EXTRA_GLITCH_COUNT = "android.bluetooth.qti.extra.EXTRA_GLITCH_COUNT"; + + + /** * Used as an optional short extra field in {@link #ACTION_FOUND} intents. * Contains the RSSI value of the remote device as reported by the * Bluetooth hardware. @@ -303,6 +432,23 @@ public final class BluetoothDevice implements Parcelable, Attributable { */ public static final String EXTRA_PREVIOUS_BOND_STATE = "android.bluetooth.device.extra.PREVIOUS_BOND_STATE"; + + /** + * Used as a String extra field in {@link #ACTION_TWS+_DEVICE_PAIR} + * intents. It contains the first TWS+ earbud address of pair. + * @hide + */ + public static final String EXTRA_TWS_PLUS_DEVICE1 = + "android.bluetooth.device.extra.EXTRA_TWS_PLUS_DEVICE1"; + + /** + * Used as a String extra field in {@link #ACTION_TWS+_DEVICE_PAIR} + * intents. It contains the second TWS+ earbud address of pair. + * @hide + */ + public static final String EXTRA_TWS_PLUS_DEVICE2 = + "android.bluetooth.device.extra.EXTRA_TWS_PLUS_DEVICE2"; + /** * Indicates the remote device is not bonded (paired). * <p>There is no shared link key with the remote device, so communication @@ -1111,10 +1257,12 @@ public final class BluetoothDevice implements Parcelable, Attributable { /*package*/ @UnsupportedAppUsage static IBluetooth getService() { + BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter(); + IBluetooth tService = adapter.getBluetoothService(sStateChangeCallback); + synchronized (BluetoothDevice.class) { if (sService == null) { - BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter(); - sService = adapter.getBluetoothService(sStateChangeCallback); + sService = tService; } } return sService; @@ -1125,9 +1273,10 @@ public final class BluetoothDevice implements Parcelable, Attributable { public void onBluetoothServiceUp(IBluetooth bluetoothService) throws RemoteException { synchronized (BluetoothDevice.class) { - if (sService == null) { - sService = bluetoothService; + if (sService != null) { + Log.w(TAG, "sService is not NULL"); } + sService = bluetoothService; } } @@ -1496,6 +1645,16 @@ public final class BluetoothDevice implements Parcelable, Attributable { Log.w(TAG, "BT not enabled, createBondOutOfBand failed"); return false; } + BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter(); + if (adapter != null && + (((transport == TRANSPORT_LE || transport == TRANSPORT_AUTO) + && !adapter.isLeEnabled()) + || ((transport == TRANSPORT_BREDR || transport == TRANSPORT_AUTO) + && !isBluetoothEnabled()))) { + Log.w(TAG, "creatBond() initiated in improper adapter state : " + adapter.getState() + + " transport = " + transport); + return false; + } try { return service.createBond( this, transport, remoteP192Data, remoteP256Data, mAttributionSource); @@ -1530,6 +1689,25 @@ public final class BluetoothDevice implements Parcelable, Attributable { return false; } + /** @hide */ + @UnsupportedAppUsage + @RequiresLegacyBluetoothPermission + @RequiresBluetoothConnectPermission + @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) + public void setBondingInitiatedLocally(boolean localInitiated) { + final IBluetooth service = sService; + if (service == null) { + Log.w(TAG, "BT not enabled, setBondingInitiatedLocally failed"); + return; + } + try { + service.setBondingInitiatedLocally(this, localInitiated, mAttributionSource); + } catch (RemoteException e) { + Log.e(TAG, "", e); + } + return; + } + /** * Cancel an in-progress bonding request started with {@link #createBond}. * @@ -1572,6 +1750,13 @@ public final class BluetoothDevice implements Parcelable, Attributable { Log.e(TAG, "BT not enabled. Cannot remove Remote Device bond"); return false; } + BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter(); + if (adapter != null && !adapter.isLeEnabled()) { + Log.w(TAG, "removeBond() initiated in improper adapter state : " + + adapter.getState()); + return false; + } + try { Log.i(TAG, "removeBond() for device " + getAddress() + " called by pid: " + Process.myPid() @@ -1839,6 +2024,47 @@ public final class BluetoothDevice implements Parcelable, Attributable { } /** + * Returns whether if the device is TWS+ device. + * + * @return True if the devcie is TWS+ device. + * @hide + */ + @RequiresLegacyBluetoothPermission + @RequiresBluetoothConnectPermission + @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) + public boolean isTwsPlusDevice() { + if (sService == null) { + Log.e(TAG, "BT not enabled. Cannot query remote device sdp records"); + return false; + } + try { + return sService.isTwsPlusDevice(this, mAttributionSource); + } catch (RemoteException e) {Log.e(TAG, "", e);} + return false; + } + + /** + * Get the TWS+ peer address of the remote device. + * + * @return the TWS+ peer address of the remote device if available, otherwise + * null. + * @hide + */ + @RequiresLegacyBluetoothPermission + @RequiresBluetoothConnectPermission + @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) + public String getTwsPlusPeerAddress() { + if (sService == null) { + Log.e(TAG, "BT not enabled. Cannot get Remote Device name"); + return null; + } + try { + return sService.getTwsPlusPeerAddress(this, mAttributionSource); + } catch (RemoteException e) {Log.e(TAG, "", e);} + return null; + } + + /** * Set the pin during pairing when the pairing method is {@link #PAIRING_VARIANT_PIN} * * @return true pin has been set false for error @@ -2539,6 +2765,48 @@ public final class BluetoothDevice implements Parcelable, Attributable { public BluetoothGatt connectGatt(Context context, boolean autoConnect, BluetoothGattCallback callback, int transport, boolean opportunistic, int phy, Handler handler) { + return connectGatt(context, autoConnect, callback, transport, opportunistic, + phy, handler, false); + } + + /** + * Connect to GATT Server hosted by this device. Caller acts as GATT client. + * The callback is used to deliver results to Caller, such as connection status as well + * as any further GATT client operations. + * The method returns a BluetoothGatt instance. You can use BluetoothGatt to conduct + * GATT client operations. + * + * @param callback GATT callback handler that will receive asynchronous callbacks. + * @param autoConnect Whether to directly connect to the remote device (false) or to + * automatically connect as soon as the remote device becomes available (true). + * @param transport preferred transport for GATT connections to remote dual-mode devices {@link + * BluetoothDevice#TRANSPORT_AUTO} or {@link BluetoothDevice#TRANSPORT_BREDR} or {@link + * BluetoothDevice#TRANSPORT_LE} + * @param opportunistic Whether this GATT client is opportunistic. An opportunistic GATT client + * does not hold a GATT connection. It automatically disconnects when no other GATT connections + * are active for the remote device. + * @param phy preferred PHY for connections to remote LE device. Bitwise OR of any of {@link + * BluetoothDevice#PHY_LE_1M_MASK}, {@link BluetoothDevice#PHY_LE_2M_MASK}, an d{@link + * BluetoothDevice#PHY_LE_CODED_MASK}. This option does not take effect if {@code autoConnect} + * is set to true. + * @param handler The handler to use for the callback. If {@code null}, callbacks will happen on + * an un-specified background thread. + * @param eattSupport specifies whether client app needs EATT channel for client operations. + * If both local and remote devices support EATT and local app asks for EATT, GATT client + * operations will be performed using EATT channel. + * If either local or remote device doesn't support EATT but local App asks for EATT, GATT + * client operations will be performed using unenhanced ATT channel. + * + * @return A BluetoothGatt instance. You can use BluetoothGatt to conduct GATT client + * operations. + * + * @throws NullPointerException if callback is null + * + * @hide + */ + public BluetoothGatt connectGatt(Context context, boolean autoConnect, + BluetoothGattCallback callback, int transport, boolean opportunistic, + int phy, Handler handler, boolean eattSupport) { if (callback == null) { throw new NullPointerException("callback is null"); } @@ -2555,7 +2823,7 @@ public final class BluetoothDevice implements Parcelable, Attributable { } BluetoothGatt gatt = new BluetoothGatt( iGatt, this, transport, opportunistic, phy, mAttributionSource); - gatt.connect(autoConnect, callback, handler); + gatt.connect(autoConnect, callback, handler, eattSupport); return gatt; } catch (RemoteException e) { Log.e(TAG, "", e); @@ -2701,4 +2969,42 @@ public final class BluetoothDevice implements Parcelable, Attributable { public static @MetadataKey int getMaxMetadataKey() { return METADATA_UNTETHERED_CASE_LOW_BATTERY_THRESHOLD; } + + /** + * Returns Device type. + * + * @return device type. + * @hide + */ + @RequiresPermission(allOf = { + android.Manifest.permission.BLUETOOTH_CONNECT, + android.Manifest.permission.BLUETOOTH_PRIVILEGED, + }) + public int getDeviceType() { + if (sService == null) { + Log.e(TAG, "getDeviceType query remote device info failed"); + return -1; + } + try { + return sService.getDeviceType(this, mAttributionSource); + } catch (RemoteException e) { + Log.e(TAG, "getDeviceType fail ", e); + } + return -1; + } + + /** + * Used as a String extra field in {@link #ACTION_BOND_STATE_CHANGED} intents. + * It contains the Group ID of IOT device. + * @hide + */ + public static final String EXTRA_GROUP_ID = "android.bluetooth.qti.extra.GROUP_ID"; + + /** + * Used as a String extra field in {@link #ACTION_BOND_STATE_CHANGED} intents. + * It contains the IGNORE DEVICE flag of IOT device. + * @hide + */ + public static final String EXTRA_IS_PRIVATE_ADDRESS = + "android.bluetooth.qti.extra.IS_PRIVATE_ADDRESS"; } diff --git a/core/java/android/bluetooth/BluetoothDeviceGroup.java b/core/java/android/bluetooth/BluetoothDeviceGroup.java new file mode 100644 index 000000000000..e271fac12b45 --- /dev/null +++ b/core/java/android/bluetooth/BluetoothDeviceGroup.java @@ -0,0 +1,892 @@ +/****************************************************************************** + * Copyright (c) 2020, The Linux Foundation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of The Linux Foundation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +package android.bluetooth; + +import android.annotation.RequiresPermission; +import android.bluetooth.annotations.RequiresBluetoothConnectPermission; +import android.bluetooth.annotations.RequiresBluetoothScanPermission; +import android.compat.annotation.UnsupportedAppUsage; +import android.content.AttributionSource; +import android.annotation.SdkConstant; +import android.annotation.SdkConstant.SdkConstantType; +import android.bluetooth.IBluetoothGroupCallback; +import android.content.Context; +import android.os.Binder; +import android.os.Handler; +import android.os.IBinder; +import android.os.ParcelUuid; +import android.os.RemoteException; +import android.util.Log; + +import java.util.ArrayList; +import java.util.List; +import java.util.UUID; + + +/** + * This class provides the public APIs to perform operations of + * the Group Identification Profile. + * + * <p> This class provides functionalities to enable communication with remote + * devices which are grouped together to achieve common use cases in + * synchronized manner. + * <p> BluetoothDeviceGroup is a proxy object for controlling the Bluetooth Group + * Service via IPC. Use {@link BluetoothAdapter#getProfileProxy} to get the BluetoothDeviceGroup + * proxy object. Use {@link BluetoothAdapter#closeProfileProxy} to close connection + * of the BluetoothDeviceGroup proxy object with the profile service. + * <p> BluetoothDeviceGroup proxy object can be used to identify and fetch Device Group. + * Also, API’s are exposed to get exclusive access of group devices for critical + * operations. Implement BluetoothGroupCallback to get results invoked API's. + * + * @hide + */ + + +public final class BluetoothDeviceGroup implements BluetoothProfile { + private static final String TAG = "BluetoothDeviceGroup"; + private static final boolean DBG = true; + private static final boolean VDBG = false; + + /** Group Client App is registerd for callbacks successfully */ + public static final int APP_REGISTRATION_SUCCESSFUL = 0; + /** Group Client App registration failed for callbacks */ + public static final int APP_REGISTRATION_FAILED = 1; + + /** Group Discovery Status when discovery is started */ + public static final int GROUP_DISCOVERY_STARTED = 0x00; + + /** Group Discovery Status when discovery is stopped */ + public static final int GROUP_DISCOVERY_STOPPED = 0x01; + + /** When Application starts Group discovery */ + public static final int DISCOVERY_STARTED_BY_APPL = 0x00; + + /** When Application stops Group discovery */ + public static final int DISCOVERY_STOPPED_BY_APPL = 0x01; + + /** When Group discovery is started as a result of + * change in Group property. */ + public static final int DISCOVERY_STARTED_GROUP_PROP_CHANGED = 0x02; + + /** When all devices of Group are discovered */ + public static final int DISCOVERY_COMPLETED = 0x03; + + /** Group discovery by timeeut. Group device not found in 10 sec. */ + public static final int DISCOVERY_STOPPED_BY_TIMEOUT = 0x04; + + /** Invalid params are provided for Group discovery */ + public static final int DISCOVERY_NOT_STARTED_INVALID_PARAMS = 0x05; + + /** Value to release Exclusive Access */ + public static final int ACCESS_RELEASED = 0x01; + + /** Value to acquire Exclusive Access */ + public static final int ACCESS_GRANTED = 0x02; + + /** When exclusive access is changed to #ACCESS_RELEASED for all reqested Group devices */ + public static final int EXCLUSIVE_ACCESS_RELEASED = 0x00; + + /** When exclusive access of the Group device is changed to #ACCESS_RELEASED by timeout */ + public static final int EXCLUSIVE_ACCESS_RELEASED_BY_TIMEOUT = 0x01; + + /** When exclusive access of all requested Group devices is changed to #ACCESS_GRANTED */ + public static final int ALL_DEVICES_GRANTED_ACCESS = 0x02; + + /** When exclusive access of some of the requested Group devices is changed to #ACCESS_GRANTED + * because of timeout in #setExclusiveAccess operation */ + public static final int SOME_GRANTED_ACCESS_REASON_TIMEOUT = 0x03; + + /** When access value of some of the requested Group devices is changed to #ACCESS_GRANTED + * because some of the Group devices were disconnected */ + public static final int SOME_GRANTED_ACCESS_REASON_DISCONNECTION = 0x04; + + /** When Exclusive Access couldnt be fetched as one of the Group devices denied + * to set value to #ACCESS_DENIED*/ + public static final int ACCESS_DENIED = 0x05; + + /** Suggests that invalid parameters are passed in #setExclusiveAccess request*/ + public static final int INVALID_ACCESS_REQ_PARAMS = 0x06; + + /** Invalid Group ID */ + public static final int INVALID_GROUP_ID = 0x10; + + /** MIN GROUP_ID Value*/ + public static final int GROUP_ID_MIN = 0x00; + /** MAX GROUP_ID Value*/ + public static final int GROUP_ID_MAX = 0x0F; + + /** Invalid APP ID */ + public static final int INVALID_APP_ID = 0x10; + + /** MIN APP_ID Value*/ + public static final int APP_ID_MIN = 0x00; + /** MAX APP_ID Value*/ + public static final int APP_ID_MAX = 0x0F; + + public static final String ACTION_CONNECTION_STATE_CHANGED = + "android.bluetooth.group.profile.action.CONNECTION_STATE_CHANGED"; + + private int mAppId; + private boolean mAppRegistered = false; + private Handler mHandler; + private BluetoothGroupCallback mCallback; + + private BluetoothAdapter mAdapter; + private final AttributionSource mAttributionSource; + private final BluetoothProfileConnector<IBluetoothDeviceGroup> mProfileConnector = + new BluetoothProfileConnector(this, BluetoothProfile.GROUP_CLIENT, + "BluetoothDeviceGroup", IBluetoothDeviceGroup.class.getName()) { + @Override + public IBluetoothDeviceGroup getServiceInterface(IBinder service) { + return IBluetoothDeviceGroup.Stub.asInterface(Binder.allowBlocking(service)); + } + }; + + /** + * Creates a BluetoothDeviceGroup proxy object for interacting with the local + * Bluetooth Service which handles Group operations. + * @hide + */ + /*package*/ BluetoothDeviceGroup(Context context, ServiceListener listener) { + mProfileConnector.connect(context, listener); + mAdapter = BluetoothAdapter.getDefaultAdapter(); + mAttributionSource = mAdapter.getAttributionSource(); + IBluetoothManager mgr = mAdapter.getBluetoothManager(); + if (mgr != null) { + try { + mgr.registerStateChangeCallback(mBluetoothStateChangeCallback); + } catch (RemoteException re) { + Log.e(TAG, "", re); + } + } + } + + private final IBluetoothStateChangeCallback mBluetoothStateChangeCallback = + new IBluetoothStateChangeCallback.Stub() { + public void onBluetoothStateChange(boolean up) { + if (!up) { + mAppRegistered = false; + } + } + }; + + /** + * Close this BluetoothGroupDevice client object. + * + * Application should call this method as soon as it is done with + * Group operations. + */ + /*package*/ void close() { + if (VDBG) log("close()"); + + mAppRegistered = false; + final IBluetoothDeviceGroup service = getService(); + if (service != null) { + try { + service.unregisterGroupClientApp(mAppId, mAttributionSource); + } catch (RemoteException e) { + Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable())); + } + } + + mProfileConnector.disconnect(); + } + + /** + * @hide + */ + private IBluetoothDeviceGroup getService() { + return mProfileConnector.getService(); + } + + /** + * {@inheritDoc} + */ + @Override + public void finalize() { + close(); + } + + /** + * {@inheritDoc} + */ + @Override + public List<BluetoothDevice> getConnectedDevices() { + if (VDBG) log("getConnectedDevices()"); + + return null; + } + + /** + * {@inheritDoc} + */ + @Override + public List<BluetoothDevice> getDevicesMatchingConnectionStates(int[] states) { + if (VDBG) log("getDevicesMatchingStates()"); + + return null; + } + + private boolean isEnabled() { + return mAdapter.getState() == BluetoothAdapter.STATE_ON; + } + + private static boolean isValidDevice(BluetoothDevice device) { + return device != null && + BluetoothAdapter.checkBluetoothAddress(device.getAddress()); + } + + /** + * {@inheritDoc} + */ + @Override + public int getConnectionState(BluetoothDevice device) { + if (VDBG) log("getState(" + device + ")"); + return BluetoothProfile.STATE_DISCONNECTED; + } + + private final IBluetoothGroupCallback.Stub mBluetoothGroupCallback = + new IBluetoothGroupCallback.Stub() { + + @Override + public void onGroupClientAppRegistered(int status, int appId) { + if (DBG) { + Log.d(TAG, "onGroupClientAppRegistered() - status=" + status + + " appId = " + appId); + } + + if (status != APP_REGISTRATION_SUCCESSFUL) { + mAppRegistered = false; + } + + mAppId = appId; + runOrQueueCallback(new Runnable() { + @Override + public void run() { + final BluetoothGroupCallback callback = mCallback; + if (callback != null) { + callback.onGroupClientAppRegistered(status, appId); + } + } + }); + } + + @Override + public void onGroupClientAppUnregistered(int status) { + if (DBG) { + Log.d(TAG, "onGroupClientAppUnregistered() - status=" + status + + " mAppId=" + mAppId); + } + } + + @Override + public void onConnectionStateChanged (int state, BluetoothDevice device) { + if (DBG) { + Log.d(TAG, "onConnectionStateChanged() - state = " + state + + " device = " + device); + } + + runOrQueueCallback(new Runnable() { + @Override + public void run() { + final BluetoothGroupCallback callback = mCallback; + if (callback != null) { + callback.onConnectionStateChanged(state, device); + } + } + }); + } + + @Override + public void onNewGroupFound(int groupId, BluetoothDevice device, + ParcelUuid uuid) { + if (DBG) { + Log.d(TAG, "onNewGroupFound() - appId = " + mAppId + + ", groupId = " + groupId + ", device: " + device + + ", Including service UUID: " + uuid.toString()); + } + + runOrQueueCallback(new Runnable() { + @Override + public void run() { + final BluetoothGroupCallback callback = mCallback; + if (callback != null) { + callback.onNewGroupFound(groupId, device, uuid.getUuid()); + } + } + }); + } + + @Override + public void onGroupDiscoveryStatusChanged(int groupId, int status, int reason) { + if (DBG) { + Log.d(TAG, "onGroupDiscoveryStatusChanged() - appId = " + mAppId + + ", groupId = " + groupId + ", status: " + status + + ", reason: " + reason); + } + + runOrQueueCallback(new Runnable() { + @Override + public void run() { + final BluetoothGroupCallback callback = mCallback; + if (callback != null) { + callback.onGroupDiscoveryStatusChanged(groupId, status, reason); + } + } + }); + } + + @Override + public void onGroupDeviceFound(int groupId, BluetoothDevice device) { + if (DBG) { + Log.d(TAG, "onGroupDeviceFound() - appId = " + mAppId + ", device = " + device); + } + + runOrQueueCallback(new Runnable() { + @Override + public void run() { + final BluetoothGroupCallback callback = mCallback; + if (callback != null) { + callback.onGroupDeviceFound(groupId, device); + } + } + }); + } + + @Override + public void onExclusiveAccessChanged(int groupId, int value, int status, + List<BluetoothDevice> devices) { + if (DBG) { + Log.d(TAG, "onExclusiveAccessChanged() - appId = " + mAppId + + ", groupId = " + groupId + ", value = " + value + + " accessStatus = " + status + ", devices: " + devices); + } + + runOrQueueCallback(new Runnable() { + @Override + public void run() { + final BluetoothGroupCallback callback = mCallback; + if (callback != null) { + callback.onExclusiveAccessChanged(groupId, value, status, devices); + } + } + }); + } + + @Override + public void onExclusiveAccessStatusFetched(int groupId, int accessValue) { + } + + @Override + public void onExclusiveAccessAvailable (int groupId, BluetoothDevice device) { + if (DBG) { + Log.d(TAG, "onExclusiveAccessAvailable() - appId = " + mAppId + + ", groupId = " + groupId + ", device: " + device); + } + + runOrQueueCallback(new Runnable() { + @Override + public void run() { + final BluetoothGroupCallback callback = mCallback; + if (callback != null) { + callback.onExclusiveAccessAvailable(groupId, device); + } + } + }); + } + }; + + /** + * Registers callbacks to be received by application on completion of + * required operations. + * + * @param callbacks Reference of BluetoothGroupCallback implemented in + * application. + * @param handler handler that will receive asynchronous callbacks. + * @return true, if operation was initiated successfully. + */ + @RequiresBluetoothConnectPermission + @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) + public boolean registerGroupClientApp(BluetoothGroupCallback callbacks, Handler handler) { + if (DBG) log("registerGroupClientApp() mAppRegistered = " + mAppRegistered); + + /* Check if app is trying multiple registrations */ + if (mAppRegistered) { + Log.e(TAG, "App already registered."); + return false; + } + + mHandler = handler; + mCallback = callbacks; + + final IBluetoothDeviceGroup service = getService(); + if (service == null) { + Log.e(TAG, "Proxy not attached to Profile Service. Can't register App."); + return false; + } + + mAppRegistered = true; + try { + UUID uuid = UUID.randomUUID(); + service.registerGroupClientApp(new ParcelUuid(uuid), mBluetoothGroupCallback, + mAttributionSource); + } catch (RemoteException e) { + Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable())); + } + return true; + } + + /** + * Starts discovery of the remaining Group devices which are part of the group. + * + * <p> This API should be called when onNewGroupFound() is received in the + * application and when given group is the required device group. This + * API can also be used to rediscover the undiscovered Group devices. + * + * <p> To the application that started group discovery, + * {@link BluetoothGroupCallback#onGroupDeviceFound} callback will be given when + * a new Group device is found and {@link BluetoothGroupCallback#onGroupDiscoveryStatusChanged} + * callback will be given when discovery is started. + * + * @param groupId Identifier of the Group for which group + * discovery has to be started. + * @return true, if operation was initiated successfully. + */ + @RequiresBluetoothConnectPermission + @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) + public boolean startGroupDiscovery(int groupId) { + if (DBG) log("startGroupDiscovery() : groupId = " + groupId); + + if (!mAppRegistered) { + Log.e(TAG, "App not registered for Group operations." + + " Register App using registerGroupClientApp"); + return false; + } + + final IBluetoothDeviceGroup service = getService(); + if (service == null) { + Log.e(TAG, "Proxy is not attached to Profile Service. Can't start group discovery"); + return false; + } + + try { + UUID uuid = UUID.randomUUID(); + service.startGroupDiscovery(mAppId ,groupId, mAttributionSource); + } catch (RemoteException e) { + Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable())); + } + return true; + } + + /** + * Stops ongoing group discovery for Group identified by groupId. + * + * <p> {@link BluetoothGroupCallback#onGroupDiscoveryStatusChanged} is given + * when group discovery is stopped. + * + * @param groupId Identifier of the Group for which group + * discovery has to be stopped. + * @return true, if operation was initiated successfully. + */ + @RequiresBluetoothConnectPermission + @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) + public boolean stopGroupDiscovery(int groupId) { + if (DBG) log("stopGroupDiscovery() : groupId = " + groupId); + + if (!mAppRegistered) { + Log.e(TAG, "App not registered for Group operations." + + " Register App using registerGroupClientApp"); + return false; + } + + final IBluetoothDeviceGroup service = getService(); + if (service == null) { + Log.e(TAG, "Proxy is not attached to Profile Service. Can't Stop group discovery"); + return false; + } + + try { + service.stopGroupDiscovery(mAppId ,groupId, mAttributionSource); + } catch (RemoteException e) { + Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable())); + } + return true; + } + + /** + * Fetches already discovered Groups. + * + * @return List of DeviceGroup that are already discovered. + */ + @RequiresBluetoothConnectPermission + @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) + public List<DeviceGroup> getDiscoveredGroups() { + return getDiscoveredGroups(false); + } + + /** + * Fetches already discovered device groups. + * + * @param mPublicAddr All discovered device groups with public address of devices. + * @return List of Device Groups that are already discovered. + * @hide + */ + @RequiresBluetoothConnectPermission + @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) + public List<DeviceGroup> getDiscoveredGroups(boolean mPublicAddr) { + if (DBG) log("getDiscoveredGroups()"); + + if (!mAppRegistered) { + Log.e(TAG, "App not registered for Group operations." + + " Register App using registerGroupClientApp"); + return null; + } + + final IBluetoothDeviceGroup service = getService(); + if (service == null) { + Log.e(TAG, "Proxy is not attached to Profile Service. Can't fetch Groups."); + return null; + } + + try { + List<DeviceGroup> groups = service.getDiscoveredGroups(mPublicAddr, mAttributionSource); + return groups; + } catch (RemoteException e) { + Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable())); + } + + return null; + } + + /** + * Fetch details of a already discovered Group identified by groupId. + * + * @param groupId Identifier of the Group for which Group details are required. + * @return Required DeviceGroup. + */ + @RequiresBluetoothConnectPermission + @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) + public DeviceGroup getGroup(int groupId) { + return getGroup(groupId, false); + } + + /** + * Fetch details of a already discovered Group identified by groupId. + * + * @param groupId Identifier of the device group for which group + * details are required. + * @param mPublicAddr DeviceGroup with Public Address of the group devices. + * @return Required DeviceGroup. + * @hide + */ + @RequiresBluetoothConnectPermission + @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) + public DeviceGroup getGroup(int groupId, boolean mPublicAddr) { + if (DBG) log("getGroup() : groupId = " + groupId); + + if (!mAppRegistered) { + Log.e(TAG, "App not registered for Group operations." + + " Register App using registerGroupClientApp"); + return null; + } + + final IBluetoothDeviceGroup service = getService(); + if (service == null) { + Log.e(TAG, "Proxy is not attached to Profile Service. Can't fetch Group."); + return null; + } + + try { + DeviceGroup group = service.getDeviceGroup(groupId, mPublicAddr, mAttributionSource); + return group; + } catch (RemoteException e) { + Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable())); + } + + return null; + } + + /** + * Get Group Identifier of the remote device to which it belongs. + * + * @param device BluetoothDevice instance of the remote device. + * @param uuid ParcelUuid of the primary service in which this + * Group Service is included. + * @return Group identifier of the required device. + */ + @RequiresBluetoothConnectPermission + @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) + public int getRemoteDeviceGroupId (BluetoothDevice device, ParcelUuid uuid) { + return getRemoteDeviceGroupId(device, uuid, false); + } + + /** + * Get Group Identifier of the remote device to which it belongs. + * + * @param device BluetoothDevice instance of the remote device. + * @param uuid ParcelUuid of the primary service in which this + * Group Service is included. + * @param mPublicAddr Suggests that group identifier is required for passed + * public address of the remote device. + * @return Group identifier of the required group for the device + * @hide + */ + @RequiresBluetoothConnectPermission + @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) + public int getRemoteDeviceGroupId (BluetoothDevice device, ParcelUuid uuid, + boolean mPublicAddr) { + if (DBG) log("getRemoteDeviceGroupId() : device = " + device); + + if (!mAppRegistered) { + Log.e(TAG, "App not registered for Group operations." + + " Register App using registerGroupClientApp"); + return INVALID_GROUP_ID; + } + + final IBluetoothDeviceGroup service = getService(); + if (service == null) { + Log.e(TAG, "Proxy is not attached to Profile Service." + + "Can't get group id for device."); + return INVALID_GROUP_ID; + } + + try { + return service.getRemoteDeviceGroupId(device, uuid, mPublicAddr, mAttributionSource); + } catch (RemoteException e) { + Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable())); + } + return INVALID_GROUP_ID; + } + + /** + * Suggests whether discovery for a given Group is ongoing. + * + * @param groupId Identifier of the Group for which discovery + * status is to be known. + * @return true, if group discovery is ongoing for mentioned group. + * Otherwise, false. + */ + @RequiresBluetoothScanPermission + @RequiresPermission(android.Manifest.permission.BLUETOOTH_SCAN) + public boolean isGroupDiscoveryInProgress (int groupId) { + if (DBG) log("isGroupDiscoveryInProgress() : groupId = " + groupId); + + if (!mAppRegistered) { + Log.e(TAG, "App not registered for Group operations." + + " Register App using registerGroupClientApp"); + return false; + } + + final IBluetoothDeviceGroup service = getService(); + if (service == null) { + Log.e(TAG, "Proxy is not attached to Profile Service.Can't get discovery status."); + return false; + } + + try { + return service.isGroupDiscoveryInProgress(groupId, mAttributionSource); + } catch (RemoteException e) { + Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable())); + } + return false; + } + + /** + * Acquires/Releases exclusive access of a given Group or subgroup. + * The result of this operation is returned in + * {@link BluetoothGroupCallback#onExclusiveAccessChanged} callback. + * + * @param groupId Identifier of the Group. + * @param devices List of BluetoothDevice for which access has to be changed. + * If this parameter is passed as null, all Group devices in the + * mentioned group will be considered for request. + * @param value Access which required to be changed. + * 0x01 – Access released ({@link #ACCESS_RELEASED}). + * 0x02 - Access granted ({@link #ACCESS_GRANTED}). + * @return true, if operation was initiated successfully. + */ + @RequiresPermission(allOf = { + android.Manifest.permission.BLUETOOTH_CONNECT, + android.Manifest.permission.BLUETOOTH_PRIVILEGED, + }) + public boolean setExclusiveAccess(int groupId, List<BluetoothDevice> devices, int value) { + if (DBG) log("setExclusiveAccess() : groupId = " + groupId + + ", access value: " + value); + + if (!mAppRegistered) { + Log.e(TAG, "App not registered for Group operations." + + " Register App using registerGroupClientApp"); + return false; + } + + final IBluetoothDeviceGroup service = getService(); + if (service == null) { + Log.e(TAG, "Proxy is not attached to Profile Service. Can't proceed."); + return false; + } + + try { + service.setExclusiveAccess(mAppId, groupId, devices, value, mAttributionSource); + } catch (RemoteException e) { + Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable())); + } + return true; + } + + /** + * Returns Status of the exclusive access for mentioned Group. + * + * @param groupId Identifier of the Group. + * @param devices List of BluetoothDevice for which access value has to be known. + * If this parameter is passed as null, all Group devices in the + * mentioned group will be queried for access status. + * @return true, if operation was initiated successfully. + * @hide + */ + @RequiresPermission(allOf = { + android.Manifest.permission.BLUETOOTH_CONNECT, + android.Manifest.permission.BLUETOOTH_PRIVILEGED, + }) + public boolean getExclusiveAccessStatus (int groupId, List<BluetoothDevice> devices) { + if (DBG) log("getExclusiveAccessStatus() : groupId = " + groupId); + + if (!mAppRegistered) { + Log.e(TAG, "App not registered for Group operations." + + " Register App using registerGroupClientApp"); + return false; + } + + final IBluetoothDeviceGroup service = getService(); + if (service == null) { + Log.e(TAG, "Proxy is not attached to Profile Service." + + " Can't get exclusive access status."); + return false; + } + + try { + service.getExclusiveAccessStatus(mAppId, groupId, devices, mAttributionSource); + } catch (RemoteException e) { + Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable())); + } + return true; + } + + /** + * Creates GATT Connection with remote device for Group Operations. + * + * <p> This API acts as trigger to start service discovery to identify + * new device group on remote device once connection has been established + * successfully. Application calling connect will get + * {@link BluetoothGroupCallback#onNewGroupFoundcallback} after + * {@link #onConnectionStateChanged} (once connection has been established + * and group discovery is completed.) + * + * @param device BluetoothDevice instance od remote device with which + * Connection is required to be established. + * @return true, if operation was initiated successfully. + */ + @RequiresBluetoothConnectPermission + @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) + public boolean connect (BluetoothDevice device) { + if (DBG) log("connect : device = " + device); + + if (!mAppRegistered) { + Log.e(TAG, "App not registered for Group operations." + + " Register App using registerGroupClientApp"); + return false; + } + + final IBluetoothDeviceGroup service = getService(); + if (service == null) { + Log.e(TAG, "Proxy is not attached to Profile Service. Can't connect."); + return false; + } + + try { + service.connect(mAppId, device, mAttributionSource); + } catch (RemoteException e) { + Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable())); + } + return true; + } + + /** + * Initiates GATT disconnection for Group Operations. + * + * @param device BluetoothDevice instance of remote device. + * This API must be called if application is not + * interested in any Group operations. + * @return true, if operation was initiated successfully. + */ + @RequiresBluetoothConnectPermission + @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) + public boolean disconnect (BluetoothDevice device) { + if (DBG) log("disconnect : device = " + device); + + if (!mAppRegistered) { + Log.e(TAG, "App not registered for Group operations." + + " Register App using registerGroupClientApp"); + return false; + } + + final IBluetoothDeviceGroup service = getService(); + if (service == null) { + Log.e(TAG, "Proxy is not attached to Profile Service. Can't disconnect"); + return false; + } + + try { + service.disconnect(mAppId, device, mAttributionSource); + } catch (RemoteException e) { + Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable())); + } + return true; + } + + private static void log(String msg) { + Log.d(TAG, msg); + } + + /** + * Queue the runnable on a {@link Handler} provided by the user, or execute the runnable + * immediately if no Handler was provided. + */ + private void runOrQueueCallback(final Runnable cb) { + if (mHandler == null) { + try { + cb.run(); + } catch (Exception ex) { + Log.w(TAG, "Unhandled exception in callback", ex); + } + } else { + mHandler.post(cb); + } + } +} diff --git a/core/java/android/bluetooth/BluetoothDun.java b/core/java/android/bluetooth/BluetoothDun.java new file mode 100644 index 000000000000..cbf44e54dd77 --- /dev/null +++ b/core/java/android/bluetooth/BluetoothDun.java @@ -0,0 +1,296 @@ +/* +*Copyright (c) 2018, The Linux Foundation. All rights reserved. +* +*Redistribution and use in source and binary forms, with or without +*modification, are permitted provided that the following conditions are +*met: +* * Redistributions of source code must retain the above copyright +* notice, this list of conditions and the following disclaimer. +* * Redistributions in binary form must reproduce the above +* copyright notice, this list of conditions and the following +* disclaimer in the documentation and/or other materials provided +* with the distribution. +* * Neither the name of The Linux Foundation nor the names of its +* contributors may be used to endorse or promote products derived +* from this software without specific prior written permission. +* +*THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED +*WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +*MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT +*ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS +*BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +*CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +*SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR +*BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +*WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE +*OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN +*IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + + +package android.bluetooth; + +import android.annotation.SdkConstant; +import android.annotation.SdkConstant.SdkConstantType; +import android.content.ComponentName; +import android.content.Context; +import android.content.Intent; +import android.content.ServiceConnection; +import android.os.IBinder; +import android.os.RemoteException; +import android.util.Log; + +import java.util.ArrayList; +import java.util.List; + +/** + * This class provides the APIs to control the Bluetooth Dun + * Profile. + * + *<p>BluetoothDun is a proxy object for controlling the Bluetooth DUN + * Service via IPC. Use {@link BluetoothAdapter#getProfileProxy} to get + * the BluetoothDun proxy object. + * + *<p>Each method is protected with its appropriate permission. + *@hide + */ +public final class BluetoothDun implements BluetoothProfile { + private static final String TAG = "BluetoothDun"; + private static final boolean DBG = false; + private static final boolean VDBG = false; + + /** + * Intent used to broadcast the change in connection state of the Dun + * profile. + * + * <p>This intent will have 3 extras: + * <ul> + * <li> {@link #EXTRA_STATE} - The current state of the profile. </li> + * <li> {@link #EXTRA_PREVIOUS_STATE}- The previous state of the profile.</li> + * <li> {@link BluetoothDevice#EXTRA_DEVICE} - The remote device. </li> + * </ul> + * + * <p>{@link #EXTRA_STATE} or {@link #EXTRA_PREVIOUS_STATE} can be any of + * {@link #STATE_DISCONNECTED}, {@link #STATE_CONNECTED}. + * + * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission to + * receive. + */ + @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) + public static final String ACTION_CONNECTION_STATE_CHANGED = + "codeaurora.bluetooth.dun.profile.action.CONNECTION_STATE_CHANGED"; + + private Context mContext; + private ServiceListener mServiceListener; + private BluetoothAdapter mAdapter; + private IBluetoothDun mDunService; + + /** + * Create a BluetoothDun proxy object for interacting with the local + * Bluetooth Service which handles the Dun profile + * + */ + /*package*/ BluetoothDun(Context context, ServiceListener l) { + mContext = context; + mServiceListener = l; + mAdapter = BluetoothAdapter.getDefaultAdapter(); + try { + mAdapter.getBluetoothManager().registerStateChangeCallback(mStateChangeCallback); + } catch (RemoteException re) { + Log.w(TAG,"Unable to register BluetoothStateChangeCallback",re); + } + Log.d(TAG, "BluetoothDun() call bindService"); + doBind(); + } + + boolean doBind() { + Intent intent = new Intent(IBluetoothDun.class.getName()); + ComponentName comp = intent.resolveSystemService(mContext.getPackageManager(), 0); + intent.setComponent(comp); + if (comp == null || !mContext.bindServiceAsUser(intent, mConnection, 0, + android.os.Process.myUserHandle())) { + Log.e(TAG, "Could not bind to Bluetooth Dun Service with " + intent); + return false; + } + return true; + } + + + /*package*/ void close() { + if (VDBG) log("close()"); + mServiceListener = null; + IBluetoothManager mgr = mAdapter.getBluetoothManager(); + if (mgr != null) { + try { + mgr.unregisterStateChangeCallback(mStateChangeCallback); + } catch (RemoteException re) { + Log.w(TAG,"Unable to unregister BluetoothStateChangeCallback",re); + } + } + + synchronized (mConnection) { + if ( mDunService != null) { + try { + mDunService = null; + mContext.unbindService(mConnection); + } catch (Exception re) { + Log.e(TAG,"",re); + } + } + } + } + + protected void finalize() { + close(); + } + + private IBluetoothStateChangeCallback mStateChangeCallback = + new IBluetoothStateChangeCallback.Stub() { + + @Override + public void onBluetoothStateChange(boolean on) { + //Handle enable request to bind again. + Log.d(TAG, "onBluetoothStateChange on: " + on); + if (on) { + try { + if (mDunService == null) { + Log.d(TAG, "onBluetoothStateChange call bindService"); + doBind(); + } + } catch (IllegalStateException e) { + Log.e(TAG,"onBluetoothStateChange: could not bind to DUN service: ", e); + } catch (SecurityException e) { + Log.e(TAG,"onBluetoothStateChange: could not bind to DUN service: ", e); + } + } else { + if (VDBG) Log.d(TAG,"Unbinding service..."); + synchronized (mConnection) { + if ( mDunService != null) { + try { + mDunService = null; + mContext.unbindService(mConnection); + } catch (Exception re) { + Log.e(TAG,"",re); + } + } + } + } + } + }; + + /** + * Initiate disconnection from DUN server. + * + * <p> Once the disconnection is initiated by any device either local host + * or remote device, the state will transition from {@link #STATE_CONNECTED} + * to {@link #STATE_DISCONNECTED}. + * + * <p>Requires {@link android.Manifest.permission#BLUETOOTH_ADMIN} + * permission. + * + * @param device Remote Bluetooth Device + * @return false on immediate error, + * true otherwise + * @hide + */ + public boolean disconnect(BluetoothDevice device) { + if (DBG) log("disconnect(" + device + ")"); + if (mDunService != null && isEnabled() && + isValidDevice(device)) { + try { + return mDunService.disconnect(device); + } catch (RemoteException e) { + Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable())); + return false; + } + } + if (mDunService == null) Log.w(TAG, "Proxy not attached to service"); + return false; + } + /** + * {@inheritDoc} + */ + public List<BluetoothDevice> getConnectedDevices() { + if (VDBG) log("getConnectedDevices()"); + if (mDunService != null && isEnabled()) { + try { + return mDunService.getConnectedDevices(); + } catch (RemoteException e) { + Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable())); + return new ArrayList<BluetoothDevice>(); + } + } + if (mDunService == null) Log.w(TAG, "Proxy not attached to service"); + return new ArrayList<BluetoothDevice>(); + } + + /** + * {@inheritDoc} + */ + public List<BluetoothDevice> getDevicesMatchingConnectionStates(int[] states) { + if (VDBG) log("getDevicesMatchingStates()"); + if (mDunService != null && isEnabled()) { + try { + return mDunService.getDevicesMatchingConnectionStates(states); + } catch (RemoteException e) { + Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable())); + return new ArrayList<BluetoothDevice>(); + } + } + if (mDunService == null) Log.w(TAG, "Proxy not attached to service"); + return new ArrayList<BluetoothDevice>(); + } + + /** + * {@inheritDoc} + */ + public int getConnectionState(BluetoothDevice device) { + if (VDBG) log("getState(" + device + ")"); + if (mDunService != null && isEnabled() + && isValidDevice(device)) { + try { + return mDunService.getConnectionState(device); + } catch (RemoteException e) { + Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable())); + return BluetoothProfile.STATE_DISCONNECTED; + } + } + if (mDunService == null) Log.w(TAG, "Proxy not attached to service"); + return BluetoothProfile.STATE_DISCONNECTED; + } + + private ServiceConnection mConnection = new ServiceConnection() { + public void onServiceConnected(ComponentName className, IBinder service) { + if (DBG) Log.d(TAG, "BluetoothDUN Proxy object connected"); + mDunService = IBluetoothDun.Stub.asInterface(service); + + if (mServiceListener != null) { + mServiceListener.onServiceConnected(BluetoothProfile.DUN, + BluetoothDun.this); + } + } + public void onServiceDisconnected(ComponentName className) { + if (DBG) Log.d(TAG, "BluetoothDUN Proxy object disconnected"); + mDunService = null; + if (mServiceListener != null) { + mServiceListener.onServiceDisconnected(BluetoothProfile.DUN); + } + } + }; + + private boolean isEnabled() { + if (mAdapter.getState() == BluetoothAdapter.STATE_ON) return true; + return false; + } + + private boolean isValidDevice(BluetoothDevice device) { + if (device == null) return false; + + if (BluetoothAdapter.checkBluetoothAddress(device.getAddress())) return true; + return false; + } + + private static void log(String msg) { + Log.d(TAG, msg); + } +} diff --git a/core/java/android/bluetooth/BluetoothGatt.java b/core/java/android/bluetooth/BluetoothGatt.java index aea82102ca36..5d4f2ae87b48 100644 --- a/core/java/android/bluetooth/BluetoothGatt.java +++ b/core/java/android/bluetooth/BluetoothGatt.java @@ -927,9 +927,45 @@ public final class BluetoothGatt implements BluetoothProfile { @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) /*package*/ boolean connect(Boolean autoConnect, BluetoothGattCallback callback, Handler handler) { + return connect(autoConnect, callback, handler, false); + } + + /** + * Initiate a connection to a Bluetooth GATT capable device. + * + * <p>The connection may not be established right away, but will be + * completed when the remote device is available. A + * {@link BluetoothGattCallback#onConnectionStateChange} callback will be + * invoked when the connection state changes as a result of this function. + * + * <p>The autoConnect parameter determines whether to actively connect to + * the remote device, or rather passively scan and finalize the connection + * when the remote device is in range/available. Generally, the first ever + * connection to a device should be direct (autoConnect set to false) and + * subsequent connections to known devices should be invoked with the + * autoConnect parameter set to true. + * + * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission. + * + * @param device Remote device to connect to + * @param autoConnect Whether to directly connect to the remote device (false) or to + * automatically connect as soon as the remote device becomes available (true). + * @param eattSupport specifies whether client app needs EATT channel for client operations. + * If both local and remote devices support EATT and local app asks for EATT, GATT client + * operations will be performed using EATT channel. + * If either local or remote device doesn't support EATT but local App asks for EATT, GATT + * client operations will be performed using unenhanced ATT channel. + * @return true, if the connection attempt was initiated successfully + * + * @hide + */ + @UnsupportedAppUsage + /*package*/ boolean connect(Boolean autoConnect, BluetoothGattCallback callback, + Handler handler, boolean eattSupport) { if (DBG) { Log.d(TAG, - "connect() - device: " + mDevice.getAddress() + ", auto: " + autoConnect); + "connect() - device: " + mDevice.getAddress() + ", auto: " + autoConnect + + ", eattSupport: " + eattSupport); } synchronized (mStateLock) { if (mConnState != CONN_STATE_IDLE) { @@ -940,7 +976,7 @@ public final class BluetoothGatt implements BluetoothProfile { mAutoConnect = autoConnect; - if (!registerApp(callback, handler)) { + if (!registerApp(callback, handler, eattSupport)) { synchronized (mStateLock) { mConnState = CONN_STATE_IDLE; } diff --git a/core/java/android/bluetooth/BluetoothGroupCallback.java b/core/java/android/bluetooth/BluetoothGroupCallback.java new file mode 100644 index 000000000000..a818cc77fd3a --- /dev/null +++ b/core/java/android/bluetooth/BluetoothGroupCallback.java @@ -0,0 +1,132 @@ +/****************************************************************************** + * Copyright (c) 2020, The Linux Foundation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of The Linux Foundation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +package android.bluetooth; + +import java.util.UUID; +import java.util.List; +/** + * This abstract class is used to implement {@link BluetoothDeviceGroup} callbacks. + * @hide + */ +public abstract class BluetoothGroupCallback { + /** + * This Callback gives connection state changed with specific group device. + * + * @param state Connection state of the {@link BluetoothProfile} group device. + * @param device Remote device for which connection state has changed. + */ + public void onConnectionStateChanged (int state, BluetoothDevice device) { + } + + /** + * This callback is given when application is registered for Group operation + * callbacks. This callback is given after {@link BluetoothDeviceGroup#registerGroupClientApp} + * is called. + * + * @param status Status of the group client app registration. + * @param appId Identifier of the application for group operations. + */ + public void onGroupClientAppRegistered(int status, int appId) { + } + + /** + * This callback is triggered when a new device group has been identified + * from one of the connected device. After this callback is received, application + * can choose to trigger discovery of device group using API + * {@link BluetoothDeviceGroup#startGroupDiscovery} + * + * @param groupId Identifier of the Device Group. + * @param device Remote device with which Device Group is found. + * @param uuid UUID of the primary Service for this Device Group Service. + */ + public void onNewGroupFound (int groupId, BluetoothDevice device, UUID uuid) { + } + + /** + * This Callback is triggered when device group discovery is either started/stopped. + * + * @param groupId Identifier of the device group. + * @param status Device Group Discovery status. + * {@link BluetoothDeviceGroup#GROUP_DISCOVERY_STARTED} + * or {@link BluetoothDeviceGroup#GROUP_DISCOVERY_STOPPED}. + * @param reason Reason for change in the discovery status. + */ + public void onGroupDiscoveryStatusChanged (int groupId, int status, int reason) { + } + + /** + * This callback is triggered when new group device has been found after group + * discovery has been started. This callback is given on discovery of every + * new group device. + * + * @param groupId Identifier of the device group. + * @param device {@link BluetoothDevice} instance of discovered group device. + */ + public void onGroupDeviceFound (int groupId, BluetoothDevice device) { + } + + /** + * This callback is triggered after exclusive access status of the group + * or subgroup has been changed after the request from application. + * + * @param groupId Identifier of the device group. + * @param value Changed value of the exclusive access. + * @param status Status associated with the exclusive access. + * @param devices List of devices for which exclusive access has been changed. + */ + public void onExclusiveAccessChanged (int groupId, int value, int status, + List<BluetoothDevice> devices) { + } + + /** + * This callback gives access status of requested group/subgroup once + * it is fetched. + * + * @param groupId Identifier of the device group. + * @param accessStatus Value of the Exclusive Access. + */ + public void onExclusiveAccessStatusFetched (int groupId, int accessStatus) { + } + + /** + * This callback is given to application when exclusive access is available + * for the device of a given group for which was denied earlier. + * <p> Exclusive Access is considered available when group device sends notification + * for access changed to BluetoothDeviceGroup#ACCESS_RELEASED. This callback is + * given to the application which has requested the access earlier and the request + * had failed as one of the group device had DENIED the access. + * + * @param groupId Identifier of the device group. + * @param device {@link BluetoothDevice} which has exclusive access available. + */ + public void onExclusiveAccessAvailable (int groupId, BluetoothDevice device) { + } + +}
\ No newline at end of file diff --git a/core/java/android/bluetooth/BluetoothHeadset.java b/core/java/android/bluetooth/BluetoothHeadset.java index b594ae34436e..aadd036250fe 100644 --- a/core/java/android/bluetooth/BluetoothHeadset.java +++ b/core/java/android/bluetooth/BluetoothHeadset.java @@ -43,8 +43,11 @@ import android.os.RemoteException; import android.util.CloseGuard; import android.util.Log; +import com.android.internal.annotations.GuardedBy; + import java.util.ArrayList; import java.util.List; +import java.util.concurrent.locks.ReentrantReadWriteLock; /** * Public API for controlling the Bluetooth Headset Service. This includes both @@ -270,6 +273,13 @@ public final class BluetoothHeadset implements BluetoothProfile { public static final String VENDOR_SPECIFIC_HEADSET_EVENT_XEVENT_BATTERY_LEVEL = "BATTERY"; /** + * Headset state when SCO audio is disconnecting. + * + * @hide + */ + public static final int STATE_AUDIO_DISCONNECTING = 13; + + /** * Headset state when SCO audio is not connected. * This state can be one of * {@link #EXTRA_STATE} or {@link #EXTRA_PREVIOUS_STATE} of @@ -294,6 +304,41 @@ public final class BluetoothHeadset implements BluetoothProfile { public static final int STATE_AUDIO_CONNECTED = 12; /** + * Intent used to broadcast the Battery status of TWS+ devices + * + * <p>This intent will have 2 extras: + * <ul> + * <li> {@link #EXTRA_HF_TWSP_BATTERY_STATE} - Current Battey state of TWS+ + * device. 0 for Discharging, 1 for Charging + * <\li> + * <li> {@link #EXTRA_HF_TWSP_BATTERY_LEVEL} - Current Battey charging level + * in percentage of TWS+ device. + * <\li> + * + * @hide + */ + public static final String ACTION_HF_TWSP_BATTERY_STATE_CHANGED = + "android.bluetooth.headset.action.HF_TWSP_BATTERY_STATE_CHANGED"; + + /** + * A int extra field in {@link #EXTRA_HF_TWSP_BATTERY_STATE} + * intents that contains the battery state of TWS+ device + * + * @hide + */ + public static final String EXTRA_HF_TWSP_BATTERY_STATE = + "android.bluetooth.headset.extra.HF_TWSP_BATTERY_STATE"; + + /** + * A int extra field in {@link #EXTRA_HF_TWSP_BATTERY_LEVEL} + * intents that contains the value of battery level in percentage for TWS+ device + * @hide + */ + public static final String EXTRA_HF_TWSP_BATTERY_LEVEL = + "android.bluetooth.headset.extra.HF_TWSP_BATTERY_LEVEL"; + + + /** * Intent used to broadcast the headset's indicator status * * <p>This intent will have 3 extras: @@ -344,7 +389,8 @@ public final class BluetoothHeadset implements BluetoothProfile { private Context mContext; private ServiceListener mServiceListener; - private volatile IBluetoothHeadset mService; + private final ReentrantReadWriteLock mServiceLock = new ReentrantReadWriteLock(); + @GuardedBy("mServiceLock") private IBluetoothHeadset mService; private final BluetoothAdapter mAdapter; private final AttributionSource mAttributionSource; @@ -395,7 +441,7 @@ public final class BluetoothHeadset implements BluetoothProfile { private boolean doBind() { synchronized (mConnection) { if (mService == null) { - if (VDBG) Log.d(TAG, "Binding service..."); + if (DBG) Log.d(TAG, "Binding service..."); try { return mAdapter.getBluetoothManager().bindBluetoothProfileService( BluetoothProfile.HEADSET, mConnection); @@ -409,15 +455,17 @@ public final class BluetoothHeadset implements BluetoothProfile { private void doUnbind() { synchronized (mConnection) { + if (DBG) Log.d(TAG, "Unbinding service..."); if (mService != null) { - if (VDBG) Log.d(TAG, "Unbinding service..."); try { mAdapter.getBluetoothManager().unbindBluetoothProfileService( BluetoothProfile.HEADSET, mConnection); } catch (RemoteException e) { Log.e(TAG, "Unable to unbind HeadsetService", e); } finally { + mServiceLock.writeLock().lock(); mService = null; + mServiceLock.writeLock().unlock(); } } } @@ -542,19 +590,24 @@ public final class BluetoothHeadset implements BluetoothProfile { @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public List<BluetoothDevice> getConnectedDevices() { if (VDBG) log("getConnectedDevices()"); - final IBluetoothHeadset service = mService; - if (service != null && isEnabled()) { - try { - return Attributable.setAttributionSource( - service.getConnectedDevicesWithAttribution(mAttributionSource), - mAttributionSource); - } catch (RemoteException e) { - Log.e(TAG, Log.getStackTraceString(new Throwable())); - return new ArrayList<BluetoothDevice>(); + try { + mServiceLock.readLock().lock(); + final IBluetoothHeadset service = mService; + if (service != null && isEnabled()) { + try { + return Attributable.setAttributionSource( + service.getConnectedDevicesWithAttribution(mAttributionSource), + mAttributionSource); + } catch (RemoteException e) { + Log.e(TAG, Log.getStackTraceString(new Throwable())); + return new ArrayList<BluetoothDevice>(); + } } + if (service == null) Log.w(TAG, "Proxy not attached to service"); + return new ArrayList<BluetoothDevice>(); + } finally { + mServiceLock.readLock().unlock(); } - if (service == null) Log.w(TAG, "Proxy not attached to service"); - return new ArrayList<BluetoothDevice>(); } /** @@ -872,14 +925,19 @@ public final class BluetoothHeadset implements BluetoothProfile { public boolean isAudioConnected(BluetoothDevice device) { if (VDBG) log("isAudioConnected()"); final IBluetoothHeadset service = mService; - if (service != null && isEnabled() && isValidDevice(device)) { - try { - return service.isAudioConnected(device, mAttributionSource); - } catch (RemoteException e) { - Log.e(TAG, Log.getStackTraceString(new Throwable())); + try { + mServiceLock.readLock().lock(); + if (service != null && isEnabled() && isValidDevice(device)) { + try { + return service.isAudioConnected(device, mAttributionSource); + } catch (RemoteException e) { + Log.e(TAG, Log.getStackTraceString(new Throwable())); + } } + if (service == null) Log.w(TAG, "Proxy not attached to service"); + } finally { + mServiceLock.readLock().unlock(); } - if (service == null) Log.w(TAG, "Proxy not attached to service"); return false; } @@ -1381,17 +1439,26 @@ public final class BluetoothHeadset implements BluetoothProfile { @Override public void onServiceConnected(ComponentName className, IBinder service) { if (DBG) Log.d(TAG, "Proxy object connected"); - mService = IBluetoothHeadset.Stub.asInterface(Binder.allowBlocking(service)); - mHandler.sendMessage(mHandler.obtainMessage( - MESSAGE_HEADSET_SERVICE_CONNECTED)); + try { + mServiceLock.writeLock().lock(); + mService = IBluetoothHeadset.Stub.asInterface(Binder.allowBlocking(service)); + mHandler.sendMessage(mHandler.obtainMessage( + MESSAGE_HEADSET_SERVICE_CONNECTED)); + } finally { + mServiceLock.writeLock().unlock(); + } } @Override public void onServiceDisconnected(ComponentName className) { if (DBG) Log.d(TAG, "Proxy object disconnected"); - doUnbind(); - mHandler.sendMessage(mHandler.obtainMessage( - MESSAGE_HEADSET_SERVICE_DISCONNECTED)); + try { + mServiceLock.writeLock().lock(); + mHandler.sendMessage(mHandler.obtainMessage( + MESSAGE_HEADSET_SERVICE_DISCONNECTED)); + } finally { + mServiceLock.writeLock().unlock(); + } } }; @@ -1433,4 +1500,60 @@ public final class BluetoothHeadset implements BluetoothProfile { } } }; + + /** + * Notify Headset of phone state change. + * This is a backdoor for phone app to call BluetoothHeadset since + * there is currently not a good way to get precise call state change outside + * of phone app. + * + * @hide + */ + @RequiresBluetoothConnectPermission + @RequiresPermission(allOf = { + android.Manifest.permission.BLUETOOTH_CONNECT, + android.Manifest.permission.MODIFY_PHONE_STATE, + }) + public void phoneStateChangedDsDa(int numActive, int numHeld, int callState, String number, + int type, String name) { + final IBluetoothHeadset service = mService; + if (service != null && isEnabled()) { + try { + service.phoneStateChangedDsDa(numActive, numHeld, callState, number, type, name, + mAttributionSource); + } catch (RemoteException e) { + Log.e(TAG, e.toString()); + } + } else { + Log.w(TAG, "Proxy not attached to service"); + if (DBG) Log.d(TAG, Log.getStackTraceString(new Throwable())); + } + } + + /** + * Send Headset of CLCC response + * + * @hide + */ + @RequiresBluetoothConnectPermission + @RequiresPermission(allOf = { + android.Manifest.permission.BLUETOOTH_CONNECT, + android.Manifest.permission.MODIFY_PHONE_STATE, + }) + public void clccResponseDsDa(int index, int direction, int status, int mode, boolean mpty, + String number, int type) { + final IBluetoothHeadset service = mService; + if (service != null && isEnabled()) { + try { + service.clccResponseDsDa(index, direction, status, mode, mpty, number, type, + mAttributionSource); + } catch (RemoteException e) { + Log.e(TAG, e.toString()); + } + } else { + Log.w(TAG, "Proxy not attached to service"); + if (DBG) Log.d(TAG, Log.getStackTraceString(new Throwable())); + } + } + } diff --git a/core/java/android/bluetooth/BluetoothProfile.java b/core/java/android/bluetooth/BluetoothProfile.java index 161c843f0398..5f9d953bd730 100644 --- a/core/java/android/bluetooth/BluetoothProfile.java +++ b/core/java/android/bluetooth/BluetoothProfile.java @@ -213,12 +213,60 @@ public interface BluetoothProfile { int LE_AUDIO = 22; /** + * DUN + * @hide + */ + public static final int DUN = 23; + + /** + * Group Operation Profile (Client Role) + * @hide + */ + public int GROUP_CLIENT = 24; + + /** + * Broadcast + * @hide + */ + public int BROADCAST = 25; + + /** + * VCP + * @hide + */ + public static final int VCP = 26; + + /** + * BC_PROFILE + * @hide + */ + public static final int BC_PROFILE = 27; + + /** + * PC_PROFILE + * @hide + */ + public static final int PC_PROFILE = 28; + + /** + * CC_SERVER + * @hide + */ + public static final int CC_SERVER = 29; + + /** + * MCP_SERVER + * @hide + */ + public static final int MCP_SERVER = 30; + + /** * Max profile ID. This value should be updated whenever a new profile is added to match * the largest value assigned to a profile. * * @hide */ - int MAX_PROFILE_ID = 22; + int MAX_PROFILE_ID = 30; /** * Default priority for devices that we try to auto-connect to and @@ -416,6 +464,10 @@ public interface BluetoothProfile { return "OPP"; case HEARING_AID: return "HEARING_AID"; + case BROADCAST: + return "BROADCAST"; + case VCP: + return "VCP"; default: return "UNKNOWN_PROFILE"; } diff --git a/core/java/android/bluetooth/BluetoothQualityReport.java b/core/java/android/bluetooth/BluetoothQualityReport.java new file mode 100644 index 000000000000..e9ed008b6954 --- /dev/null +++ b/core/java/android/bluetooth/BluetoothQualityReport.java @@ -0,0 +1,1447 @@ +/* + * Copyright (c) 2019, The Linux Foundation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of The Linux Foundation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +package android.bluetooth; + +import android.annotation.NonNull; +import android.content.Context; +import android.os.Parcel; +import android.os.Parcelable; +import android.util.Log; + +import java.nio.BufferUnderflowException; +import java.nio.ByteBuffer; +import java.nio.ByteOrder; +import java.util.Arrays; + +/** + * This class provides the public APIs to access the data of BQR event reported + * from firmware side. Currently it supports five event types: Quality monitor event, + * Approaching LSTO event, A2DP choppy event, SCO choppy event and Connect fail event. + * To know which kind of event is wrapped in this {@link BluetoothQualityReport} object, + * you need to call {@link #getQualityReportId}. + * <ul> + * <li> For Quality monitor event, you can call {@link #getBqrCommon} to get a + * {@link BluetoothQualityReport.BqrCommon} object, and call {@link #getBqrVsCommon} to get a + * {@link BluetoothQualityReport.BqrVsCommon} object. + * <li> For Approaching LSTO event, you can call {@link #getBqrCommon} to get a + * {@link BluetoothQualityReport.BqrCommon} object, and call {@link #getBqrVsCommon} to get a + * {@link BluetoothQualityReport.BqrVsCommon} object, and call {@link #getBqrVsLsto} to get a + * {@link BluetoothQualityReport.BqrVsLsto} object. + * <li> For A2DP choppy event, you can call {@link #getBqrCommon} to get a + * {@link BluetoothQualityReport.BqrCommon} object, and call {@link #getBqrVsCommon} to get a + * {@link BluetoothQualityReport.BqrVsCommon} object, and call {@link #getBqrVsA2dpChoppy} to + * get a {@link BluetoothQualityReport.BqrVsA2dpChoppy} object. + * <li> For SCO choppy event, you can call {@link #getBqrCommon} to get a + * {@link BluetoothQualityReport.BqrCommon} object, and call {@link #getBqrVsCommon} to get a + * {@link BluetoothQualityReport.BqrVsCommon} object, and call {@link #getBqrVsScoChoppy} to + * get a {@link BluetoothQualityReport.BqrVsScoChoppy} object. + * <li> For Connect fail event, you can call {@link #getBqrCommon} to get a + * {@link BluetoothQualityReport.BqrCommon} object, and call {@link #getBqrVsCommon} to get a + * {@link BluetoothQualityReport.BqrVsCommon} object, and call {@link #getBqrVsConnectFail} to + * get a {@link BluetoothQualityReport.BqrVsConnectFail} object. + * </ul> + * + * @hide + */ +public final class BluetoothQualityReport implements Parcelable { + private static final String TAG = "BluetoothQualityReport"; + + public static final int QUALITY_REPORT_ID_MONITOR = 0x01; + public static final int QUALITY_REPORT_ID_APPROACH_LSTO = 0x02; + public static final int QUALITY_REPORT_ID_A2DP_CHOPPY = 0x03; + public static final int QUALITY_REPORT_ID_SCO_CHOPPY = 0x04; + /* Vendor Specific Report IDs from 0x20 */ + public static final int QUALITY_REPORT_ID_CONN_FAIL = 0x20; + + private String mAddr; + private int mLmpVer; + private int mLmpSubVer; + private int mManufacturerId; + private String mName; + private int mBluetoothClass; + + private BqrCommon mBqrCommon; + + private BqrVsCommon mBqrVsCommon; + private BqrVsLsto mBqrVsLsto; + private BqrVsA2dpChoppy mBqrVsA2dpChoppy; + private BqrVsScoChoppy mBqrVsScoChoppy; + private BqrVsConnectFail mBqrVsConnectFail; + + enum PacketType { + INVALID, TYPE_ID, TYPE_NULL, TYPE_POLL, TYPE_FHS, TYPE_HV1, TYPE_HV2, TYPE_HV3, + TYPE_DV, TYPE_EV3, TYPE_EV4, TYPE_EV5, TYPE_2EV3, TYPE_2EV5, TYPE_3EV3, TYPE_3EV5, + TYPE_DM1, TYPE_DH1, TYPE_DM3, TYPE_DH3, TYPE_DM5, TYPE_DH5, TYPE_AUX1, TYPE_2DH1, + TYPE_2DH3, TYPE_2DH5, TYPE_3DH1, TYPE_3DH3, TYPE_3DH5; + + private static PacketType[] sAllValues = values(); + + static PacketType fromOrdinal(int n) { + if (n < sAllValues.length) { + return sAllValues[n]; + } + return INVALID; + } + } + + enum ConnState { + CONN_IDLE(0x00), CONN_ACTIVE(0x81), CONN_HOLD(0x02), CONN_SNIFF_IDLE(0x03), + CONN_SNIFF_ACTIVE(0x84), CONN_SNIFF_MASTER_TRANSITION(0x85), CONN_PARK(0x06), + CONN_PARK_PEND(0x47), CONN_UNPARK_PEND(0x08), CONN_UNPARK_ACTIVE(0x89), + CONN_DISCONNECT_PENDING(0x4A), CONN_PAGING(0x0B), CONN_PAGE_SCAN(0x0C), + CONN_LOCAL_LOOPBACK(0x0D), CONN_LE_ACTIVE(0x0E), CONN_ANT_ACTIVE(0x0F), + CONN_TRIGGER_SCAN(0x10), CONN_RECONNECTING(0x11), CONN_SEMI_CONN(0x12); + + private int mValue; + private static ConnState[] sAllStates = values(); + + private ConnState(int val) { + mValue = val; + } + + public static String getName(int val) { + for (ConnState state: sAllStates) { + if (state.mValue == val) { + return state.toString(); + } + } + return "INVALID"; + } + } + + enum LinkQuality { + ULTRA_HIGH, HIGH, STANDARD, MEDIUM, LOW, INVALID; + + private static LinkQuality[] sAllValues = values(); + + static LinkQuality fromOrdinal(int n) { + if (n < sAllValues.length - 1) { + return sAllValues[n]; + } + return INVALID; + } + } + + enum AirMode { + uLaw, aLaw, CVSD, transparent_msbc, INVALID; + + private static AirMode[] sAllValues = values(); + + static AirMode fromOrdinal(int n) { + if (n < sAllValues.length - 1) { + return sAllValues[n]; + } + return INVALID; + } + } + + public BluetoothQualityReport(String remoteAddr, int lmpVer, int lmpSubVer, + int manufacturerId, String remoteName, int remoteCoD, byte[] rawData) { + if (!BluetoothAdapter.checkBluetoothAddress(remoteAddr)) { + Log.d(TAG, "remote addr is invalid"); + mAddr = "00:00:00:00:00:00"; + } else { + mAddr = remoteAddr; + } + + mLmpVer = lmpVer; + mLmpSubVer = lmpSubVer; + mManufacturerId = manufacturerId; + if (remoteName == null) { + Log.d(TAG, "remote name is null"); + mName = ""; + } else { + mName = remoteName; + } + mBluetoothClass = remoteCoD; + + mBqrCommon = new BqrCommon(rawData, 0); + + mBqrVsCommon = new BqrVsCommon(rawData, BqrCommon.BQR_COMMON_LEN); + int id = mBqrCommon.getQualityReportId(); + if (id == QUALITY_REPORT_ID_MONITOR) + return; + + int vsPartOffset = BqrCommon.BQR_COMMON_LEN + mBqrVsCommon.getLength(); + if (id == QUALITY_REPORT_ID_APPROACH_LSTO) { + mBqrVsLsto = new BqrVsLsto(rawData, vsPartOffset); + } else if (id == QUALITY_REPORT_ID_A2DP_CHOPPY) { + mBqrVsA2dpChoppy = new BqrVsA2dpChoppy(rawData, vsPartOffset); + } else if (id == QUALITY_REPORT_ID_SCO_CHOPPY) { + mBqrVsScoChoppy = new BqrVsScoChoppy(rawData, vsPartOffset); + } else if (id == QUALITY_REPORT_ID_CONN_FAIL) { + mBqrVsConnectFail = new BqrVsConnectFail(rawData, vsPartOffset); + } else { + throw new IllegalArgumentException(TAG + ": unkown quality report id:" + id); + } + } + + private BluetoothQualityReport(Parcel in) { + mBqrCommon = new BqrCommon(in); + mAddr = in.readString(); + mLmpVer = in.readInt(); + mLmpSubVer = in.readInt(); + mManufacturerId = in.readInt(); + mName = in.readString(); + mBluetoothClass = in.readInt(); + + mBqrVsCommon = new BqrVsCommon(in); + int id = mBqrCommon.getQualityReportId(); + if (id == QUALITY_REPORT_ID_APPROACH_LSTO) { + mBqrVsLsto = new BqrVsLsto(in); + } else if (id == QUALITY_REPORT_ID_A2DP_CHOPPY) { + mBqrVsA2dpChoppy = new BqrVsA2dpChoppy(in); + } else if (id == QUALITY_REPORT_ID_SCO_CHOPPY) { + mBqrVsScoChoppy = new BqrVsScoChoppy(in); + } else if (id == QUALITY_REPORT_ID_CONN_FAIL) { + mBqrVsConnectFail = new BqrVsConnectFail(in); + } + } + + /** + * Get the quality report id. + * @return the id, is one of {@link #QUALITY_REPORT_ID_MONITOR}, + * {@link #QUALITY_REPORT_ID_APPROACH_LSTO}, {@link #QUALITY_REPORT_ID_A2DP_CHOPPY}, + * {@link #QUALITY_REPORT_ID_SCO_CHOPPY}, {@link #QUALITY_REPORT_ID_CONN_FAIL}. + */ + public int getQualityReportId() { + return mBqrCommon.getQualityReportId(); + } + + /** + * Get the string of the quality report id. + * @return the string of the id. + */ + public String getQualityReportIdStr() { + int id = mBqrCommon.getQualityReportId(); + switch (id) { + case QUALITY_REPORT_ID_MONITOR: + return "Quality monitor"; + case QUALITY_REPORT_ID_APPROACH_LSTO: + return "Approaching LSTO"; + case QUALITY_REPORT_ID_A2DP_CHOPPY: + return "A2DP choppy"; + case QUALITY_REPORT_ID_SCO_CHOPPY: + return "SCO choppy"; + case QUALITY_REPORT_ID_CONN_FAIL: + return "Connect fail"; + default: + return "INVALID"; + } + } + + /** + * Get bluetooth address of remote device in this report. + * @return bluetooth address of remote device. + */ + public String getAddress() { + return mAddr; + } + + /** + * Get LMP version of remote device in this report. + * @return LMP version of remote device. + */ + public int getLmpVersion() { + return mLmpVer; + } + + /** + * Get LMP subVersion of remote device in this report. + * @return LMP subVersion of remote device. + */ + public int getLmpSubVersion() { + return mLmpSubVer; + } + + /** + * Get manufacturer id of remote device in this report. + * @return manufacturer id of remote device. + */ + public int getManufacturerId() { + return mManufacturerId; + } + + /** + * Get the name of remote device in this report. + * @return the name of remote device. + */ + public String getName() { + return mName; + } + + /** + * Get the class of remote device in this report. + * @return the class of remote device. + */ + public int getBluetoothClass() { + return mBluetoothClass; + } + + /** + * Get the {@link BluetoothQualityReport.BqrCommon} object. + * @return the {@link BluetoothQualityReport.BqrCommon} object. + */ + public BqrCommon getBqrCommon() { + return mBqrCommon; + } + + /** + * Get the {@link BluetoothQualityReport.BqrVsCommon} object. + * @return the {@link BluetoothQualityReport.BqrVsCommon} object. + */ + public BqrVsCommon getBqrVsCommon() { + return mBqrVsCommon; + } + + /** + * Get the {@link BluetoothQualityReport.BqrVsLsto} object. + * @return the {@link BluetoothQualityReport.BqrVsLsto} object + * or null if report id is not {@link #QUALITY_REPORT_ID_APPROACH_LSTO}. + */ + public BqrVsLsto getBqrVsLsto() { + return mBqrVsLsto; + } + + /** + * Get the {@link BluetoothQualityReport.BqrVsA2dpChoppy} object. + * @return the {@link BluetoothQualityReport.BqrVsA2dpChoppy} object + * or null if report id is not {@link #QUALITY_REPORT_ID_A2DP_CHOPPY}. + */ + public BqrVsA2dpChoppy getBqrVsA2dpChoppy() { + return mBqrVsA2dpChoppy; + } + + /** + * Get the {@link BluetoothQualityReport.BqrVsScoChoppy} object. + * @return the {@link BluetoothQualityReport.BqrVsScoChoppy} object + * or null if report id is not {@link #QUALITY_REPORT_ID_SCO_CHOPPY}. + */ + public BqrVsScoChoppy getBqrVsScoChoppy() { + return mBqrVsScoChoppy; + } + + /** + * Get the {@link BluetoothQualityReport.BqrVsConnectFail} object. + * @return the {@link BluetoothQualityReport.BqrVsConnectFail} object + * or null if report id is not {@link #QUALITY_REPORT_ID_CONN_FAIL}. + */ + public BqrVsConnectFail getBqrVsConnectFail() { + return mBqrVsConnectFail; + } + + public static final @android.annotation.NonNull Parcelable.Creator<BluetoothQualityReport> CREATOR = + new Parcelable.Creator<BluetoothQualityReport>() { + public BluetoothQualityReport createFromParcel(Parcel in) { + return new BluetoothQualityReport(in); + } + + public BluetoothQualityReport[] newArray(int size) { + return new BluetoothQualityReport[size]; + } + }; + + public int describeContents() { + return 0; + } + + @Override + public void writeToParcel(Parcel out, int flags) { + mBqrCommon.writeToParcel(out, flags); + out.writeString(mAddr); + out.writeInt(mLmpVer); + out.writeInt(mLmpSubVer); + out.writeInt(mManufacturerId); + out.writeString(mName); + out.writeInt(mBluetoothClass); + mBqrVsCommon.writeToParcel(out, flags); + int id = mBqrCommon.getQualityReportId(); + if (id == QUALITY_REPORT_ID_APPROACH_LSTO) { + mBqrVsLsto.writeToParcel(out, flags); + } else if (id == QUALITY_REPORT_ID_A2DP_CHOPPY) { + mBqrVsA2dpChoppy.writeToParcel(out, flags); + } else if (id == QUALITY_REPORT_ID_SCO_CHOPPY) { + mBqrVsScoChoppy.writeToParcel(out, flags); + } else if (id == QUALITY_REPORT_ID_CONN_FAIL) { + mBqrVsConnectFail.writeToParcel(out, flags); + } + } + + @Override + public String toString() { + String str; + str = "BQR: {\n" + + " mAddr: " + mAddr + + ", mLmpVer: " + String.format("0x%02X", mLmpVer) + + ", mLmpSubVer: " + String.format("0x%04X", mLmpSubVer) + + ", mManufacturerId: " + String.format("0x%04X", mManufacturerId) + + ", mName: " + mName + + ", mBluetoothClass: " + String.format("0x%X", mBluetoothClass) + + ",\n" + + mBqrCommon + "\n" + + mBqrVsCommon + "\n"; + + int id = mBqrCommon.getQualityReportId(); + if (id == QUALITY_REPORT_ID_APPROACH_LSTO) { + str += mBqrVsLsto + "\n}"; + } else if (id == QUALITY_REPORT_ID_A2DP_CHOPPY) { + str += mBqrVsA2dpChoppy + "\n}"; + } else if (id == QUALITY_REPORT_ID_SCO_CHOPPY) { + str += mBqrVsScoChoppy + "\n}"; + } else if (id == QUALITY_REPORT_ID_CONN_FAIL) { + str += mBqrVsConnectFail + "\n}"; + } else if (id == QUALITY_REPORT_ID_MONITOR) { + str += "}"; + } + + return str; + } + + /** + * This class provides the public APIs to access the common part of BQR event. + */ + public class BqrCommon implements Parcelable { + private static final String TAG = BluetoothQualityReport.TAG + ".BqrCommon"; + static final int BQR_COMMON_LEN = 48; + + private int mQualityReportId; + private int mPacketType; + private int mConnectionHandle; + private int mConnectionRole; + private int mTxPowerLevel; + private int mRssi; + private int mSnr; + private int mUnusedAfhChannelCount; + private int mAfhSelectUnidealChannelCount; + private int mLsto; + private long mPiconetClock; + private long mRetransmissionCount; + private long mNoRxCount; + private long mNakCount; + private long mLastTxAckTimestamp; + private long mFlowOffCount; + private long mLastFlowOnTimestamp; + private long mOverflowCount; + private long mUnderflowCount; + + private BqrCommon(byte[] rawData, int offset) { + if (rawData == null || rawData.length < offset + BQR_COMMON_LEN) { + throw new IllegalArgumentException(TAG + ": BQR raw data length is abnormal."); + } + + ByteBuffer bqrBuf = ByteBuffer.wrap(rawData, offset, rawData.length - offset) + .asReadOnlyBuffer(); + bqrBuf.order(ByteOrder.LITTLE_ENDIAN); + + mQualityReportId = bqrBuf.get() & 0xFF; + mPacketType = bqrBuf.get() & 0xFF; + mConnectionHandle = bqrBuf.getShort() & 0xFFFF; + mConnectionRole = bqrBuf.get() & 0xFF; + mTxPowerLevel = bqrBuf.get() & 0xFF; + mRssi = bqrBuf.get(); + mSnr = bqrBuf.get(); + mUnusedAfhChannelCount = bqrBuf.get() & 0xFF; + mAfhSelectUnidealChannelCount = bqrBuf.get() & 0xFF; + mLsto = bqrBuf.getShort() & 0xFFFF; + mPiconetClock = bqrBuf.getInt() & 0xFFFFFFFFL; + mRetransmissionCount = bqrBuf.getInt() & 0xFFFFFFFFL; + mNoRxCount = bqrBuf.getInt() & 0xFFFFFFFFL; + mNakCount = bqrBuf.getInt() & 0xFFFFFFFFL; + mLastTxAckTimestamp = bqrBuf.getInt() & 0xFFFFFFFFL; + mFlowOffCount = bqrBuf.getInt() & 0xFFFFFFFFL; + mLastFlowOnTimestamp = bqrBuf.getInt() & 0xFFFFFFFFL; + mOverflowCount = bqrBuf.getInt() & 0xFFFFFFFFL; + mUnderflowCount = bqrBuf.getInt() & 0xFFFFFFFFL; + } + + private BqrCommon(Parcel in) { + mQualityReportId = in.readInt(); + mPacketType = in.readInt(); + mConnectionHandle = in.readInt(); + mConnectionRole = in.readInt(); + mTxPowerLevel = in.readInt(); + mRssi = in.readInt(); + mSnr = in.readInt(); + mUnusedAfhChannelCount = in.readInt(); + mAfhSelectUnidealChannelCount = in.readInt(); + mLsto = in.readInt(); + mPiconetClock = in.readLong(); + mRetransmissionCount = in.readLong(); + mNoRxCount = in.readLong(); + mNakCount = in.readLong(); + mLastTxAckTimestamp = in.readLong(); + mFlowOffCount = in.readLong(); + mLastFlowOnTimestamp = in.readLong(); + mOverflowCount = in.readLong(); + mUnderflowCount = in.readLong(); + } + + int getQualityReportId() { + return mQualityReportId; + } + + /** + * Get the packet type of the connection. + * @return the packet type. + */ + public int getPacketType() { + return mPacketType; + } + + /** + * Get the string of packet type + * @return the string of packet type. + */ + public String getPacketTypeStr() { + PacketType type = PacketType.fromOrdinal(mPacketType); + return type.toString(); + } + + /** + * Get the connecton handle of the connection + * @return the connecton handle. + */ + public int getConnectionHandle() { + return mConnectionHandle; + } + + /** + * Get the connecton Role of the connection, "Master" or "Slave". + * @return the connecton Role. + */ + public String getConnectionRole() { + if (mConnectionRole == 0) { + return "Master"; + } else if (mConnectionRole == 1) { + return "Slave"; + } else { + return "INVALID:" + mConnectionRole; + } + } + + /** + * Get the current transmit power level for the connection. + * @return the TX power level. + */ + public int getTxPowerLevel() { + return mTxPowerLevel; + } + + /** + * Get the Received Signal Strength Indication (RSSI) value for the connection. + * @return the RSSI. + */ + public int getRssi() { + return mRssi; + } + + /** + * get the Signal-to-Noise Ratio (SNR) value for the connection. + * @return the SNR. + */ + public int getSnr() { + return mSnr; + } + + /** + * Get the number of unused channels in AFH_channel_map. + * @return the number of unused channels. + */ + public int getUnusedAfhChannelCount() { + return mUnusedAfhChannelCount; + } + + /** + * Get the number of the channels which are interfered and quality is + * bad but are still selected for AFH. + * @return the number of the selected unideal channels. + */ + public int getAfhSelectUnidealChannelCount() { + return mAfhSelectUnidealChannelCount; + } + + /** + * Get the current link supervision timeout setting. + * time_ms: N * 0.625 ms (1 slot). + * @return link supervision timeout value. + */ + public int getLsto() { + return mLsto; + } + + /** + * Get the piconet clock for the specified Connection_Handle. + * time_ms: N * 0.3125 ms (1 Bluetooth Clock). + * @return the piconet clock. + */ + public long getPiconetClock() { + return mPiconetClock; + } + + /** + * Get the count of retransmission. + * @return the count of retransmission. + */ + public long getRetransmissionCount() { + return mRetransmissionCount; + } + + /** + * Get the count of no RX. + * @return the count of no RX. + */ + public long getNoRxCount() { + return mNoRxCount; + } + + /** + * Get the count of NAK(Negative Acknowledge). + * @return the count of NAK. + */ + public long getNakCount() { + return mNakCount; + } + + /** + * Get the timestamp of last TX ACK. + * time_ms: N * 0.3125 ms (1 Bluetooth Clock). + * @return the timestamp of last TX ACK. + */ + public long getLastTxAckTimestamp() { + return mLastTxAckTimestamp; + } + + /** + * Get the count of flow-off. + * @return the count of flow-off. + */ + public long getFlowOffCount() { + return mFlowOffCount; + } + + /** + * Get the timestamp of last flow-on. + * @return the timestamp of last flow-on. + */ + public long getLastFlowOnTimestamp() { + return mLastFlowOnTimestamp; + } + + /** + * Get the buffer overflow count (how many bytes of TX data are dropped) since the + * last event. + * @return the buffer overflow count. + */ + public long getOverflowCount() { + return mOverflowCount; + } + + /** + * Get the buffer underflow count (in byte). + * @return the buffer underflow count. + */ + public long getUnderflowCount() { + return mUnderflowCount; + } + + public int describeContents() { + return 0; + } + + @Override + public void writeToParcel(Parcel dest, int flags) { + dest.writeInt(mQualityReportId); + dest.writeInt(mPacketType); + dest.writeInt(mConnectionHandle); + dest.writeInt(mConnectionRole); + dest.writeInt(mTxPowerLevel); + dest.writeInt(mRssi); + dest.writeInt(mSnr); + dest.writeInt(mUnusedAfhChannelCount); + dest.writeInt(mAfhSelectUnidealChannelCount); + dest.writeInt(mLsto); + dest.writeLong(mPiconetClock); + dest.writeLong(mRetransmissionCount); + dest.writeLong(mNoRxCount); + dest.writeLong(mNakCount); + dest.writeLong(mLastTxAckTimestamp); + dest.writeLong(mFlowOffCount); + dest.writeLong(mLastFlowOnTimestamp); + dest.writeLong(mOverflowCount); + dest.writeLong(mUnderflowCount); + } + + @Override + public String toString() { + String str; + str = " BqrCommon: {\n" + + " mQualityReportId: " + BluetoothQualityReport.this.getQualityReportIdStr() + + "(" + String.format("0x%02X", mQualityReportId) + ")" + + ", mPacketType: " + getPacketTypeStr() + + "(" + String.format("0x%02X", mPacketType) + ")" + + ", mConnectionHandle: " + String.format("0x%04X", mConnectionHandle) + + ", mConnectionRole: " + getConnectionRole() + "(" + mConnectionRole + ")" + + ", mTxPowerLevel: " + mTxPowerLevel + + ", mRssi: " + mRssi + + ", mSnr: " + mSnr + + ", mUnusedAfhChannelCount: " + mUnusedAfhChannelCount + + ",\n" + + " mAfhSelectUnidealChannelCount: " + mAfhSelectUnidealChannelCount + + ", mLsto: " + mLsto + + ", mPiconetClock: " + String.format("0x%08X", mPiconetClock) + + ", mRetransmissionCount: " + mRetransmissionCount + + ", mNoRxCount: " + mNoRxCount + + ", mNakCount: " + mNakCount + + ", mLastTxAckTimestamp: " + String.format("0x%08X", mLastTxAckTimestamp) + + ", mFlowOffCount: " + mFlowOffCount + + ",\n" + + " mLastFlowOnTimestamp: " + String.format("0x%08X", mLastFlowOnTimestamp) + + ", mOverflowCount: " + mOverflowCount + + ", mUnderflowCount: " + mUnderflowCount + + "\n }"; + + return str; + } + + } + + /** + * This class provides the public APIs to access the vendor specific common part of + * BQR event. + */ + public class BqrVsCommon implements Parcelable { + private static final String TAG = BluetoothQualityReport.TAG + ".BqrVsCommon"; + private static final int BQR_VS_COMMON_LEN = 6 + 1; + + private String mAddr; + private int mCalFailedItemCount; + + private BqrVsCommon(byte[] rawData, int offset) { + if (rawData == null || rawData.length < offset + BQR_VS_COMMON_LEN) { + throw new IllegalArgumentException(TAG + ": BQR raw data length is abnormal."); + } + + ByteBuffer bqrBuf = ByteBuffer.wrap(rawData, offset, rawData.length - offset) + .asReadOnlyBuffer(); + bqrBuf.order(ByteOrder.LITTLE_ENDIAN); + + mAddr = String.format("%02X:%02X:%02X:%02X:%02X:%02X", bqrBuf.get(offset+5), + bqrBuf.get(offset+4), bqrBuf.get(offset+3), bqrBuf.get(offset+2), + bqrBuf.get(offset+1), bqrBuf.get(offset+0)); + bqrBuf.position(offset+6); + mCalFailedItemCount = bqrBuf.get() & 0xFF; + } + + private BqrVsCommon(Parcel in) { + mAddr = in.readString(); + mCalFailedItemCount = in.readInt(); + } + + /** + * Get the count of calibration failed items. + * @return the count of calibration failure. + */ + public int getCalFailedItemCount() { + return mCalFailedItemCount; + } + + int getLength() { + return BQR_VS_COMMON_LEN; + } + + public int describeContents() { + return 0; + } + + @Override + public void writeToParcel(Parcel dest, int flags) { + dest.writeString(mAddr); + dest.writeInt(mCalFailedItemCount); + } + + @Override + public String toString() { + String str; + str = " BqrVsCommon: {\n" + + " mAddr: " + mAddr + + ", mCalFailedItemCount: " + mCalFailedItemCount + + "\n }"; + + return str; + } + } + + /** + * This class provides the public APIs to access the vendor specific part of + * Approaching LSTO event. + */ + public class BqrVsLsto implements Parcelable { + private static final String TAG = BluetoothQualityReport.TAG + ".BqrVsLsto"; + + private int mConnState; + private long mBasebandStats; + private long mSlotsUsed; + private int mCxmDenials; + private int mTxSkipped; + private int mRfLoss; + private long mNativeClock; + private long mLastTxAckTimestamp; + + private BqrVsLsto(byte[] rawData, int offset) { + if (rawData == null || rawData.length <= offset) { + throw new IllegalArgumentException(TAG + ": BQR raw data length is abnormal."); + } + + ByteBuffer bqrBuf = ByteBuffer.wrap(rawData, offset, rawData.length - offset) + .asReadOnlyBuffer(); + bqrBuf.order(ByteOrder.LITTLE_ENDIAN); + + mConnState = bqrBuf.get() & 0xFF; + mBasebandStats = bqrBuf.getInt() & 0xFFFFFFFFL; + mSlotsUsed = bqrBuf.getInt() & 0xFFFFFFFFL; + mCxmDenials = bqrBuf.getShort() & 0xFFFF; + mTxSkipped = bqrBuf.getShort() & 0xFFFF; + mRfLoss = bqrBuf.getShort() & 0xFFFF; + mNativeClock = bqrBuf.getInt() & 0xFFFFFFFFL; + mLastTxAckTimestamp = bqrBuf.getInt() & 0xFFFFFFFFL; + } + + private BqrVsLsto(Parcel in) { + mConnState = in.readInt(); + mBasebandStats = in.readLong(); + mSlotsUsed = in.readLong(); + mCxmDenials = in.readInt(); + mTxSkipped = in.readInt(); + mRfLoss = in.readInt(); + mNativeClock = in.readLong(); + mLastTxAckTimestamp = in.readLong(); + } + + /** + * Get the conn state of sco. + * @return the conn state. + */ + public int getConnState() { + return mConnState; + } + + /** + * Get the string of conn state of sco. + * @return the string of conn state. + */ + public String getConnStateStr() { + return ConnState.getName(mConnState); + } + + /** + * Get the baseband statistics. + * @return the baseband statistics. + */ + public long getBasebandStats() { + return mBasebandStats; + } + + /** + * Get the count of slots allocated for current connection. + * @return the count of slots allocated for current connection. + */ + public long getSlotsUsed() { + return mSlotsUsed; + } + + /** + * Get the count of Coex denials. + * @return the count of CXM denials. + */ + public int getCxmDenials() { + return mCxmDenials; + } + + /** + * Get the count of TX skipped when no poll from remote device. + * @return the count of TX skipped. + */ + public int getTxSkipped() { + return mTxSkipped; + } + + /** + * Get the count of RF loss. + * @return the count of RF loss. + */ + public int getRfLoss() { + return mRfLoss; + } + + /** + * Get the timestamp when issue happened. + * time_ms: N * 0.3125 ms (1 Bluetooth Clock). + * @return the timestamp when issue happened. + */ + public long getNativeClock() { + return mNativeClock; + } + + /** + * Get the timestamp of last TX ACK. + * time_ms: N * 0.3125 ms (1 Bluetooth Clock). + * @return the timestamp of last TX ACK. + */ + public long getLastTxAckTimestamp() { + return mLastTxAckTimestamp; + } + + public int describeContents() { + return 0; + } + + @Override + public void writeToParcel(Parcel dest, int flags) { + dest.writeInt(mConnState); + dest.writeLong(mBasebandStats); + dest.writeLong(mSlotsUsed); + dest.writeInt(mCxmDenials); + dest.writeInt(mTxSkipped); + dest.writeInt(mRfLoss); + dest.writeLong(mNativeClock); + dest.writeLong(mLastTxAckTimestamp); + } + + @Override + public String toString() { + String str; + str = " BqrVsLsto: {\n" + + " mConnState: " + getConnStateStr() + + "(" + String.format("0x%02X", mConnState) + ")" + + ", mBasebandStats: " + String.format("0x%08X", mBasebandStats) + + ", mSlotsUsed: " + mSlotsUsed + + ", mCxmDenials: " + mCxmDenials + + ", mTxSkipped: " + mTxSkipped + + ", mRfLoss: " + mRfLoss + + ", mNativeClock: " + String.format("0x%08X", mNativeClock) + + ", mLastTxAckTimestamp: " + String.format("0x%08X", mLastTxAckTimestamp) + + "\n }"; + + return str; + } + } + + /** + * This class provides the public APIs to access the vendor specific part of + * A2dp choppy event. + */ + public class BqrVsA2dpChoppy implements Parcelable { + private static final String TAG = BluetoothQualityReport.TAG + ".BqrVsA2dpChoppy"; + + private long mArrivalTime; + private long mScheduleTime; + private int mGlitchCount; + private int mTxCxmDenials; + private int mRxCxmDenials; + private int mAclTxQueueLength; + private int mLinkQuality; + + private BqrVsA2dpChoppy(byte[] rawData, int offset) { + if (rawData == null || rawData.length <= offset) { + throw new IllegalArgumentException(TAG + ": BQR raw data length is abnormal."); + } + + ByteBuffer bqrBuf = ByteBuffer.wrap(rawData, offset, rawData.length - offset) + .asReadOnlyBuffer(); + bqrBuf.order(ByteOrder.LITTLE_ENDIAN); + + mArrivalTime = bqrBuf.getInt() & 0xFFFFFFFFL; + mScheduleTime = bqrBuf.getInt() & 0xFFFFFFFFL; + mGlitchCount = bqrBuf.getShort() & 0xFFFF; + mTxCxmDenials = bqrBuf.getShort() & 0xFFFF; + mRxCxmDenials = bqrBuf.getShort() & 0xFFFF; + mAclTxQueueLength = bqrBuf.get() & 0xFF; + mLinkQuality = bqrBuf.get() & 0xFF; + } + + private BqrVsA2dpChoppy(Parcel in) { + mArrivalTime = in.readLong(); + mScheduleTime = in.readLong(); + mGlitchCount = in.readInt(); + mTxCxmDenials = in.readInt(); + mRxCxmDenials = in.readInt(); + mAclTxQueueLength = in.readInt(); + mLinkQuality = in.readInt(); + } + + /** + * Get the timestamp of a2dp packet arrived. + * time_ms: N * 0.3125 ms (1 Bluetooth Clock). + * @return the timestamp of a2dp packet arrived. + */ + public long getArrivalTime() { + return mArrivalTime; + } + + /** + * Get the timestamp of a2dp packet scheduled. + * time_ms: N * 0.3125 ms (1 Bluetooth Clock). + * @return the timestamp of a2dp packet scheduled. + */ + public long getScheduleTime() { + return mScheduleTime; + } + + /** + * Get the a2dp glitch count since the last event. + * @return the a2dp glitch count. + */ + public int getGlitchCount() { + return mGlitchCount; + } + + /** + * Get the count of Coex TX denials. + * @return the count of Coex TX denials. + */ + public int getTxCxmDenials() { + return mTxCxmDenials; + } + + /** + * Get the count of Coex RX denials. + * @return the count of Coex RX denials. + */ + public int getRxCxmDenials() { + return mRxCxmDenials; + } + + /** + * Get the ACL queue length which are pending TX in FW. + * @return the ACL queue length. + */ + public int getAclTxQueueLength() { + return mAclTxQueueLength; + } + + /** + * Get the link quality for the current connection. + * @return the link quality. + */ + public int getLinkQuality() { + return mLinkQuality; + } + + /** + * Get the string of link quality for the current connection. + * @return the string of link quality. + */ + public String getLinkQualityStr() { + LinkQuality q = LinkQuality.fromOrdinal(mLinkQuality); + return q.toString(); + } + + public int describeContents() { + return 0; + } + + @Override + public void writeToParcel(Parcel dest, int flags) { + dest.writeLong(mArrivalTime); + dest.writeLong(mScheduleTime); + dest.writeInt(mGlitchCount); + dest.writeInt(mTxCxmDenials); + dest.writeInt(mRxCxmDenials); + dest.writeInt(mAclTxQueueLength); + dest.writeInt(mLinkQuality); + } + + @Override + public String toString() { + String str; + str = " BqrVsA2dpChoppy: {\n" + + " mArrivalTime: " + String.format("0x%08X", mArrivalTime) + + ", mScheduleTime: " + String.format("0x%08X", mScheduleTime) + + ", mGlitchCount: " + mGlitchCount + + ", mTxCxmDenials: " + mTxCxmDenials + + ", mRxCxmDenials: " + mRxCxmDenials + + ", mAclTxQueueLength: " + mAclTxQueueLength + + ", mLinkQuality: " + getLinkQualityStr() + + "(" + String.format("0x%02X", mLinkQuality) + ")" + + "\n }"; + + return str; + } + + } + + /** + * This class provides the public APIs to access the vendor specific part of + * SCO choppy event. + */ + public class BqrVsScoChoppy implements Parcelable { + private static final String TAG = BluetoothQualityReport.TAG + ".BqrVsScoChoppy"; + + private int mGlitchCount; + private int mIntervalEsco; + private int mWindowEsco; + private int mAirFormat; + private int mInstanceCount; + private int mTxCxmDenials; + private int mRxCxmDenials; + private int mTxAbortCount; + private int mLateDispatch; + private int mMicIntrMiss; + private int mLpaIntrMiss; + private int mSprIntrMiss; + private int mPlcFillCount; + private int mPlcDiscardCount; + private int mMissedInstanceCount; + private int mTxRetransmitSlotCount; + private int mRxRetransmitSlotCount; + private int mGoodRxFrameCount; + + private BqrVsScoChoppy(byte[] rawData, int offset) { + if (rawData == null || rawData.length <= offset) { + throw new IllegalArgumentException(TAG + ": BQR raw data length is abnormal."); + } + + ByteBuffer bqrBuf = ByteBuffer.wrap(rawData, offset, rawData.length - offset) + .asReadOnlyBuffer(); + bqrBuf.order(ByteOrder.LITTLE_ENDIAN); + + mGlitchCount = bqrBuf.getShort() & 0xFFFF; + mIntervalEsco = bqrBuf.get() & 0xFF; + mWindowEsco = bqrBuf.get() & 0xFF; + mAirFormat = bqrBuf.get() & 0xFF; + mInstanceCount = bqrBuf.getShort() & 0xFFFF; + mTxCxmDenials = bqrBuf.getShort() & 0xFFFF; + mRxCxmDenials = bqrBuf.getShort() & 0xFFFF; + mTxAbortCount = bqrBuf.getShort() & 0xFFFF; + mLateDispatch = bqrBuf.getShort() & 0xFFFF; + mMicIntrMiss = bqrBuf.getShort() & 0xFFFF; + mLpaIntrMiss = bqrBuf.getShort() & 0xFFFF; + mSprIntrMiss = bqrBuf.getShort() & 0xFFFF; + mPlcFillCount = bqrBuf.getShort() & 0xFFFF; + mPlcDiscardCount = bqrBuf.getShort() & 0xFFFF; + try { + mMissedInstanceCount = bqrBuf.getShort() & 0xFFFF; + mTxRetransmitSlotCount = bqrBuf.getShort() & 0xFFFF; + mRxRetransmitSlotCount = bqrBuf.getShort() & 0xFFFF; + mGoodRxFrameCount = bqrBuf.getShort() & 0xFFFF; + } catch (BufferUnderflowException e) { + Log.v(TAG, "some fields are not contained"); + } + } + + private BqrVsScoChoppy(Parcel in) { + mGlitchCount = in.readInt(); + mIntervalEsco = in.readInt(); + mWindowEsco = in.readInt(); + mAirFormat = in.readInt(); + mInstanceCount = in.readInt(); + mTxCxmDenials = in.readInt(); + mRxCxmDenials = in.readInt(); + mTxAbortCount = in.readInt(); + mLateDispatch = in.readInt(); + mMicIntrMiss = in.readInt(); + mLpaIntrMiss = in.readInt(); + mSprIntrMiss = in.readInt(); + mPlcFillCount = in.readInt(); + mPlcDiscardCount = in.readInt(); + mMissedInstanceCount = in.readInt(); + mTxRetransmitSlotCount = in.readInt(); + mRxRetransmitSlotCount = in.readInt(); + mGoodRxFrameCount = in.readInt(); + } + + /** + * Get the sco glitch count since the last event. + * @return the sco glitch count. + */ + public int getGlitchCount() { + return mGlitchCount; + } + + /** + * Get ESCO interval in slots. It is the value of Transmission_Interval parameter in + * Synchronous Connection Complete event. + * @return ESCO interval in slots. + */ + public int getIntervalEsco() { + return mIntervalEsco; + } + + /** + * Get ESCO window in slots. It is the value of Retransmission Window parameter in + * Synchronous Connection Complete event. + * @return ESCO window in slots. + */ + public int getWindowEsco() { + return mWindowEsco; + } + + /** + * Get the air mode. It is the value of Air Mode parameter in + * Synchronous Connection Complete event. + * @return the air mode. + */ + public int getAirFormat() { + return mAirFormat; + } + + /** + * Get the string of air mode. + * @return the string of air mode. + */ + public String getAirFormatStr() { + AirMode m = AirMode.fromOrdinal(mAirFormat); + return m.toString(); + } + + /** + * Get the xSCO instance count. + * @return the xSCO instance count. + */ + public int getInstanceCount() { + return mInstanceCount; + } + + /** + * Get the count of Coex TX denials. + * @return the count of Coex TX denials. + */ + public int getTxCxmDenials() { + return mTxCxmDenials; + } + + /** + * Get the count of Coex RX denials. + * @return the count of Coex RX denials. + */ + public int getRxCxmDenials() { + return mRxCxmDenials; + } + + /** + * Get the count of sco packets aborted. + * @return the count of sco packets aborted. + */ + public int getTxAbortCount() { + return mTxAbortCount; + } + + /** + * Get the count of sco packets dispatched late. + * @return the count of sco packets dispatched late. + */ + public int getLateDispatch() { + return mLateDispatch; + } + + /** + * Get the count of missed Mic interrrupts. + * @return the count of missed Mic interrrupts. + */ + public int getMicIntrMiss() { + return mMicIntrMiss; + } + + /** + * Get the count of missed LPA interrrupts. + * @return the count of missed LPA interrrupts. + */ + public int getLpaIntrMiss() { + return mLpaIntrMiss; + } + + /** + * Get the count of missed Speaker interrrupts. + * @return the count of missed Speaker interrrupts. + */ + public int getSprIntrMiss() { + return mSprIntrMiss; + } + + /** + * Get the count of packet loss concealment filled. + * @return the count of packet loss concealment filled. + */ + public int getPlcFillCount() { + return mPlcFillCount; + } + + /** + * Get the count of packet loss concealment discarded. + * @return the count of packet loss concealment discarded. + */ + public int getPlcDiscardCount() { + return mPlcDiscardCount; + } + + /** + * Get the count of sco instances missed. + * @return the count of sco instances missed. + */ + public int getMissedInstanceCount() { + return mMissedInstanceCount; + } + + /** + * Get the count of slots for Tx retransmission. + * @return the count of slots for Tx retransmission. + */ + public int getTxRetransmitSlotCount() { + return mTxRetransmitSlotCount; + } + + /** + * Get the count of slots for Rx retransmission. + * @return the count of slots for Rx retransmission. + */ + public int getRxRetransmitSlotCount() { + return mRxRetransmitSlotCount; + } + + /** + * Get the count of Rx good packets + * @return the count of Rx good packets. + */ + public int getGoodRxFrameCount() { + return mGoodRxFrameCount; + } + + public int describeContents() { + return 0; + } + + @Override + public void writeToParcel(Parcel dest, int flags) { + dest.writeInt(mGlitchCount); + dest.writeInt(mIntervalEsco); + dest.writeInt(mWindowEsco); + dest.writeInt(mAirFormat); + dest.writeInt(mInstanceCount); + dest.writeInt(mTxCxmDenials); + dest.writeInt(mRxCxmDenials); + dest.writeInt(mTxAbortCount); + dest.writeInt(mLateDispatch); + dest.writeInt(mMicIntrMiss); + dest.writeInt(mLpaIntrMiss); + dest.writeInt(mSprIntrMiss); + dest.writeInt(mPlcFillCount); + dest.writeInt(mPlcDiscardCount); + dest.writeInt(mMissedInstanceCount); + dest.writeInt(mTxRetransmitSlotCount); + dest.writeInt(mRxRetransmitSlotCount); + dest.writeInt(mGoodRxFrameCount); + } + + @Override + public String toString() { + String str; + str = " BqrVsScoChoppy: {\n" + + " mGlitchCount: " + mGlitchCount + + ", mIntervalEsco: " + mIntervalEsco + + ", mWindowEsco: " + mWindowEsco + + ", mAirFormat: " + getAirFormatStr() + + "(" + String.format("0x%02X", mAirFormat) + ")" + + ", mInstanceCount: " + mInstanceCount + + ", mTxCxmDenials: " + mTxCxmDenials + + ", mRxCxmDenials: " + mRxCxmDenials + + ", mTxAbortCount: " + mTxAbortCount + + ",\n" + + " mLateDispatch: " + mLateDispatch + + ", mMicIntrMiss: " + mMicIntrMiss + + ", mLpaIntrMiss: " + mLpaIntrMiss + + ", mSprIntrMiss: " + mSprIntrMiss + + ", mPlcFillCount: " + mPlcFillCount + + ", mPlcDiscardCount: " + mPlcDiscardCount + + ", mMissedInstanceCount: " + mMissedInstanceCount + + ", mTxRetransmitSlotCount: " + mTxRetransmitSlotCount + + ",\n" + + " mRxRetransmitSlotCount: " + mRxRetransmitSlotCount + + ", mGoodRxFrameCount: " + mGoodRxFrameCount + + "\n }"; + + return str; + } + + } + + /** + * This class provides the public APIs to access the vendor specific part of + * Connect fail event. + */ + public class BqrVsConnectFail implements Parcelable { + private static final String TAG = BluetoothQualityReport.TAG + ".BqrVsConnectFail"; + + private int mFailReason; + + private BqrVsConnectFail(byte[] rawData, int offset) { + if (rawData == null || rawData.length <= offset) { + throw new IllegalArgumentException(TAG + ": BQR raw data length is abnormal."); + } + + ByteBuffer bqrBuf = ByteBuffer.wrap(rawData, offset, rawData.length - offset) + .asReadOnlyBuffer(); + bqrBuf.order(ByteOrder.LITTLE_ENDIAN); + + mFailReason = bqrBuf.get() & 0xFF; + } + + private BqrVsConnectFail(Parcel in) { + mFailReason = in.readInt(); + } + + /** + * Get the fail reason. + * @return the fail reason. + */ + public int getFailReason() { + return mFailReason; + } + + public int describeContents() { + return 0; + } + + @Override + public void writeToParcel(Parcel dest, int flags) { + dest.writeInt(mFailReason); + } + + @Override + public String toString() { + String str; + str = " BqrVsConnectFail: {\n" + + " mFailReason: " + String.format("0x%02X", mFailReason) + + "\n }"; + + return str; + } + } + +} diff --git a/core/java/android/bluetooth/BluetoothSocket.java b/core/java/android/bluetooth/BluetoothSocket.java index 1655b62bbfec..0d2bd216f19f 100644 --- a/core/java/android/bluetooth/BluetoothSocket.java +++ b/core/java/android/bluetooth/BluetoothSocket.java @@ -27,7 +27,6 @@ import android.os.ParcelFileDescriptor; import android.os.ParcelUuid; import android.os.RemoteException; import android.util.Log; - import java.io.Closeable; import java.io.FileDescriptor; import java.io.IOException; @@ -272,6 +271,7 @@ public final class BluetoothSocket implements Closeable { as.mSocketOS = as.mSocket.getOutputStream(); as.mAddress = remoteAddr; as.mDevice = BluetoothAdapter.getDefaultAdapter().getRemoteDevice(remoteAddr); + as.mPort = mPort; return as; } @@ -806,5 +806,65 @@ public final class BluetoothSocket implements Closeable { return ret; } + /** + * setSocketOpt for the Buetooth Socket. + * + * @param optionName socket option name + * @param optionVal socket option value + * @param optionLen socket option length + * @return -1 on immediate error, + * 0 otherwise + * @hide + */ + @UnsupportedAppUsage + @RequiresBluetoothConnectPermission + @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) + public int setSocketOpt(int optionName, byte [] optionVal, int optionLen) throws IOException { + int ret = 0; + if (mSocketState == SocketState.CLOSED) throw new IOException("socket closed"); + IBluetooth bluetoothProxy = BluetoothAdapter.getDefaultAdapter().getBluetoothService(null); + if (bluetoothProxy == null) { + Log.e(TAG, "setSocketOpt fail, reason: bluetooth is off"); + return -1; + } + try { + if(VDBG) Log.d(TAG, "setSocketOpt(), mType: " + mType + " mPort: " + mPort); + ret = bluetoothProxy.setSocketOpt(mType, mPort, optionName, optionVal, optionLen); + } catch (RemoteException e) { + Log.e(TAG, Log.getStackTraceString(new Throwable())); + return -1; + } + return ret; + } + + /** + * getSocketOpt for the Buetooth Socket. + * + * @param optionName socket option name + * @param optionVal socket option value + * @return -1 on immediate error, + * length of returned socket option otherwise + * @hide + */ + @UnsupportedAppUsage + @RequiresBluetoothConnectPermission + @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) + public int getSocketOpt(int optionName, byte [] optionVal) throws IOException { + int ret = 0; + if (mSocketState == SocketState.CLOSED) throw new IOException("socket closed"); + IBluetooth bluetoothProxy = BluetoothAdapter.getDefaultAdapter().getBluetoothService(null); + if (bluetoothProxy == null) { + Log.e(TAG, "getSocketOpt fail, reason: bluetooth is off"); + return -1; + } + try { + if(VDBG) Log.d(TAG, "getSocketOpt(), mType: " + mType + " mPort: " + mPort); + ret = bluetoothProxy.getSocketOpt(mType, mPort, optionName, optionVal); + } catch (RemoteException e) { + Log.e(TAG, Log.getStackTraceString(new Throwable())); + return -1; + } + return ret; + } } diff --git a/core/java/android/bluetooth/BluetoothUuid.java b/core/java/android/bluetooth/BluetoothUuid.java index bc3754a2fc56..02f9044445a2 100644 --- a/core/java/android/bluetooth/BluetoothUuid.java +++ b/core/java/android/bluetooth/BluetoothUuid.java @@ -177,6 +177,41 @@ public final class BluetoothUuid { public static final ParcelUuid BASE_UUID = ParcelUuid.fromString("00000000-0000-1000-8000-00805F9B34FB"); + /** @hide */ + @NonNull + public static ParcelUuid ADVANCE_HEARINGAID_UUID = + ParcelUuid.fromString("00006AD2-0000-1000-8000-00805F9B34FB"); + + /** @hide */ + @NonNull + public static ParcelUuid ADVANCE_MEDIA_T_UUID = + ParcelUuid.fromString("00006AD0-0000-1000-8000-00805F9B34FB"); + + /** @hide */ + @NonNull + public static ParcelUuid ADVANCE_MEDIA_P_UUID = + ParcelUuid.fromString("00006AD1-0000-1000-8000-00805F9B34FB"); + + /** @hide */ + @NonNull + public static ParcelUuid ADVANCE_MEDIA_G_UUID = + ParcelUuid.fromString("00006AD3-0000-1000-8000-00805F9B34FB"); + + /** @hide */ + @NonNull + public static ParcelUuid ADVANCE_MEDIA_W_UUID = + ParcelUuid.fromString("2587db3c-ce70-4fc9-935f-777ab4188fd7"); + + /** @hide */ + @NonNull + public static ParcelUuid ADVANCE_VOICE_P_UUID = + ParcelUuid.fromString("00006AD4-0000-1000-8000-00805F9B34FB"); + + /** @hide */ + @NonNull + public static ParcelUuid ADVANCE_VOICE_T_UUID = + ParcelUuid.fromString("00006AD5-0000-1000-8000-00805F9B34FB"); + /** * Length of bytes for 16 bit UUID * diff --git a/core/java/android/bluetooth/BluetoothVcp.java b/core/java/android/bluetooth/BluetoothVcp.java new file mode 100644 index 000000000000..1f8498c62fb4 --- /dev/null +++ b/core/java/android/bluetooth/BluetoothVcp.java @@ -0,0 +1,420 @@ +/* + *Copyright (c) 2020, The Linux Foundation. All rights reserved. + *Not a contribution + */ + +/* + * Copyright 2018 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.bluetooth; + +import android.annotation.RequiresPermission; +import android.bluetooth.annotations.RequiresBluetoothConnectPermission; +import android.content.AttributionSource; +import android.content.Context; +import android.os.Binder; +import android.os.IBinder; +import android.os.RemoteException; +import android.util.Log; + +import java.util.ArrayList; +import java.util.List; + +/** + * This class provides the public APIs to control the Bluetooth VCP profile. + * + * <p>BluetoothVcp is a proxy object for controlling the Bluetooth VolumeControl + * Service via IPC. Use {@link BluetoothAdapter#getProfileProxy} to get + * the BluetoothVcp proxy object. + * + * {@hide} + */ +public final class BluetoothVcp implements BluetoothProfile { + private static final String TAG = "BluetoothVcp"; + private static final boolean DBG = true; + private static final boolean VDBG = true; + + /** + * Intent used to broadcast the change in connection state of the VCP + * profile. + * + * <p>This intent will have 3 extras: + * <ul> + * <li> {@link #EXTRA_STATE} - The current state of the profile. </li> + * <li> {@link #EXTRA_PREVIOUS_STATE}- The previous state of the profile.</li> + * <li> {@link BluetoothDevice#EXTRA_DEVICE} - The remote device. </li> + * </ul> + * + * <p>{@link #EXTRA_STATE} or {@link #EXTRA_PREVIOUS_STATE} can be any of + * {@link #STATE_DISCONNECTED}, {@link #STATE_CONNECTING}, + * {@link #STATE_CONNECTED}, {@link #STATE_DISCONNECTING}. + * + * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission to + * receive. + */ + @RequiresBluetoothConnectPermission + @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) + public static final String ACTION_CONNECTION_STATE_CHANGED = + "android.bluetooth.vcp.profile.action.CONNECTION_STATE_CHANGED"; + + /** + * Intent used to broadcast the volume change of the Volume Renderer device + * + * <p>This intent will have 1 extras: + * <ul> + * <li> {@link #EXTRA_VOLUME} - Current volume settings of Renderer device + * device. Range: 0 - 255. + * + * @hide + */ + @RequiresBluetoothConnectPermission + @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) + public static final String ACTION_VOLUME_CHANGED = + "android.bluetooth.vcp.profile.action.VOLUME_CHANGED"; + + /** + * A int extra field in {@link #ACTION_VOLUME_CHANGED} + * intents that contains the volume of the Volume Renderer device. + */ + public static final String EXTRA_VOLUME = + "android.bluetooth.vcp.profile.extra.VOLUME"; + + /** + * Intent used to broadcast the mute change of the Volume Renderer device + * + * <p>This intent will have 1 extras: + * <ul> + * <li> {@link #EXTRA_MUTE} - Current mute status of Renderer device + * device. False: unmute, True: mute. + * + * @hide + */ + @RequiresBluetoothConnectPermission + @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) + public static final String ACTION_MUTE_CHANGED = + "android.bluetooth.vcp.profile.action.MUTE_CHANGED"; + + /** + * A boolean extra field in {@link #ACTION_MUTE_CHANGED} + * intents that contains the mute status of the Volume Renderer device. + */ + public static final String EXTRA_MUTE = + "android.bluetooth.vcp.profile.extra.MUTE"; + + /** + * Intent used to broadcast the connection mode change of the VCP + * + * <p>This intent will have 1 extras: + * <ul> + * <li> {@link #EXTRA_MODE} - Current connection mode of VCP + * can be any of {@link #MODE_NONE}, {@link #MODE_UNICAST}, + * {@link #MODE_BROADCAST}, {@link #MODE_UNICAST_BROADCAST}, + * + * @hide + */ + @RequiresBluetoothConnectPermission + @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) + public static final String ACTION_CONNECTION_MODE_CHANGED = + "android.bluetooth.vcp.profile.action.CONNECTION_MODE_CHANGED"; + + /** + * A int extra field in {@link #ACTION_CONNECTION_MODE_CHANGED} + * intents that contains the connection mode of the VCP. + */ + public static final String EXTRA_MODE = + "android.bluetooth.vcp.profile.extra.MODE"; + + /** None VCP connection */ + public static final int MODE_NONE = 0x00; + /** VCP connection setup with unicast mode */ + public static final int MODE_UNICAST = 0x01; + /** VCP connection setup with broadcast mode */ + public static final int MODE_BROADCAST = 0x02; + /** VCP connection setup with unicast and broadcast mode */ + public static final int MODE_UNICAST_BROADCAST = 0x03; + + public static final int A2DP = 0x0001; + public static final int HFP = 0x0002; + public static final int LE_MEDIA = 0x0010; + public static final int LE_VOICE = 0x2000; + + public static final int CALL_STREAM = 0; + public static final int MEDIA_STREAM = 1; + + private BluetoothAdapter mAdapter; + private final AttributionSource mAttributionSource; + private final BluetoothProfileConnector<IBluetoothVcp> mProfileConnector = + new BluetoothProfileConnector(this, BluetoothProfile.VCP, + "BluetoothVcp", IBluetoothVcp.class.getName()) { + @Override + public IBluetoothVcp getServiceInterface(IBinder service) { + return IBluetoothVcp.Stub.asInterface( + Binder.allowBlocking(service)); + } + }; + + /** + * Create a BluetoothVcp proxy object for interacting with the local + * Bluetooth VCP service. + */ + /*package*/ BluetoothVcp(Context context, ServiceListener listener) { + mAdapter = BluetoothAdapter.getDefaultAdapter(); + mProfileConnector.connect(context, listener); + mAttributionSource = mAdapter.getAttributionSource(); + } + + /*package*/ void close() { + mProfileConnector.disconnect(); + } + + private IBluetoothVcp getService() { + return mProfileConnector.getService(); + } + + @Override + public void finalize() { + close(); + } + + /** + * {@inheritDoc} + */ + @Override + public List<BluetoothDevice> getConnectedDevices() { + if (VDBG) log("getConnectedDevices()"); + return null; + } + + /** + * {@inheritDoc} + */ + @Override + public List<BluetoothDevice> getDevicesMatchingConnectionStates(int[] states) { + if (VDBG) log("getDevicesMatchingStates()"); + return null; + } + + /** + * {@inheritDoc} + */ + @Override + @RequiresBluetoothConnectPermission + @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) + public int getConnectionState(BluetoothDevice device) { + if (VDBG) log("getConnectionState(" + device + ")"); + final IBluetoothVcp service = + getService(); + if (service != null && isEnabled() && isValidDevice(device)) { + try { + return service.getConnectionState(device, mAttributionSource); + } catch (RemoteException e) { + Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable())); + return BluetoothProfile.STATE_DISCONNECTED; + } + } + if (service == null) Log.w(TAG, "Proxy not attached to service"); + return BluetoothProfile.STATE_DISCONNECTED; + } + + /** + * Get current VCP Connection mode + * + * @param device: remote device instance + * @return current connection mode of VCP: + * {@link #BluetoothVcp.MODE_NONE} if none VCP connection + * {@link #BluetoothVcp.MODE_UNICAST} if VCP is connected for unicast + * {@link #BluetoothVcp.MODE_BROADCAST} if VCP is connected for broadcast + * {@link #BluetoothVcp.MODE_UNICAST_BROADCAST} if VCP + * is connected for unicast and broadcast + */ + @RequiresBluetoothConnectPermission + @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) + public int getConnectionMode(BluetoothDevice device) { + if (VDBG) log("getConnectionMode(" + device + ")"); + final IBluetoothVcp service = + getService(); + if (service != null && isEnabled() && isValidDevice(device)) { + try { + return service.getConnectionMode(device, mAttributionSource); + } catch (RemoteException e) { + Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable())); + return MODE_NONE; + } + } + if (service == null) Log.w(TAG, "Proxy not attached to service"); + return MODE_NONE; + } + + /** + * Set absolute volume to remote device via VCP connection + * + * @param device: remote device instance + * @prarm volume: requested volume settings for remote device + */ + @RequiresBluetoothConnectPermission + @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) + public void setAbsoluteVolume(BluetoothDevice device, int volume) { + if (VDBG) log("setAbsoluteVolume(" + device + ")"); + final IBluetoothVcp service = + getService(); + if (service != null && isEnabled() && isValidDevice(device)) { + try { + service.setAbsoluteVolume(device, volume, mAttributionSource); + return; + } catch (RemoteException e) { + Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable())); + return; + } + } + if (service == null) Log.w(TAG, "Proxy not attached to service"); + } + + /** + * Get current absolute volume of the remote device + * + * @param device: remote device instance + * @return current absolute volume of the remote device + */ + @RequiresBluetoothConnectPermission + @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) + public int getAbsoluteVolume(BluetoothDevice device) { + if (VDBG) log("getAbsoluteVolume(" + device + ")"); + final IBluetoothVcp service = + getService(); + if (service != null && isEnabled() && isValidDevice(device)) { + try { + return service.getAbsoluteVolume(device, mAttributionSource); + } catch (RemoteException e) { + Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable())); + return -1; + } + } + if (service == null) Log.w(TAG, "Proxy not attached to service"); + return -1; + } + + /** + * Mute or unmute remote device via VCP connection + * + * @param device: remote device instance + * @prarm enableMute: true if mute, false if unmute + */ + @RequiresBluetoothConnectPermission + @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) + public void setMute(BluetoothDevice device, boolean enableMute) { + if (VDBG) log("setMute(" + device + ")" +" enableMute: " + enableMute); + final IBluetoothVcp service = + getService(); + if (service != null && isEnabled() && isValidDevice(device)) { + try { + service.setMute(device, enableMute, mAttributionSource); + return; + } catch (RemoteException e) { + Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable())); + return; + } + } + if (service == null) Log.w(TAG, "Proxy not attached to service"); + } + + /** + * Get mute status of remote device + * + * @param device: remote device instance + * @return current mute status of the remote device + * true if mute status, false if unmute status + */ + @RequiresBluetoothConnectPermission + @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) + public boolean isMute(BluetoothDevice device) { + if (VDBG) log("isMute(" + device + ")"); + final IBluetoothVcp service = + getService(); + if (service != null && isEnabled() && isValidDevice(device)) { + try { + return service.isMute(device, mAttributionSource); + } catch (RemoteException e) { + Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable())); + return false; + } + } + if (service == null) Log.w(TAG, "Proxy not attached to service"); + return false; + } + + /** + * set active stream for a DuMo device + * + * @param device: remote device instance + * @param audioType: call/media audio + * @param profile: profile that is needed to be active + * @return success/failure + */ + @RequiresBluetoothConnectPermission + @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) + public boolean setActiveProfile(BluetoothDevice device, int audioType, int profile) { + if (VDBG) log("setActiveProfile(" + device + ")"); + final IBluetoothVcp service = + getService(); + if (service != null && isEnabled() && isValidDevice(device)) { + try { + return service.setActiveProfile(device, audioType, profile, mAttributionSource); + } catch (RemoteException e) { + Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable())); + return false; + } + } + if (service == null) Log.w(TAG, "Proxy not attached to service"); + return false; + } + + /** + * set active stream for a DuMo device + * + * @param audioType: call/media audio + * @return ID of current active profile + */ + @RequiresBluetoothConnectPermission + @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) + public int getActiveProfile(int audioType) { + if (VDBG) log("getActiveProfile(" + audioType + ")"); + final IBluetoothVcp service = + getService(); + if (service != null && isEnabled()) { + try { + return service.getActiveProfile(audioType, mAttributionSource); + } catch (RemoteException e) { + Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable())); + return -1; + } + } + if (service == null) Log.w(TAG, "Proxy not attached to service"); + return -1; + } + + private boolean isEnabled() { + return mAdapter.getState() == BluetoothAdapter.STATE_ON; + } + + private static boolean isValidDevice(BluetoothDevice device) { + return device != null && BluetoothAdapter.checkBluetoothAddress(device.getAddress()); + } + + private static void log(String msg) { + Log.d(TAG, msg); + } +} + diff --git a/core/java/android/bluetooth/DeviceGroup.java b/core/java/android/bluetooth/DeviceGroup.java new file mode 100644 index 000000000000..0dac87f3d8f6 --- /dev/null +++ b/core/java/android/bluetooth/DeviceGroup.java @@ -0,0 +1,177 @@ +/****************************************************************************** + * Copyright (c) 2020, The Linux Foundation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of The Linux Foundation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +package android.bluetooth; + +import android.os.Parcel; +import android.os.Parcelable; +import android.os.ParcelUuid; + +import java.util.Arrays; +import java.util.ArrayList; +import java.util.List; +import java.util.Objects; +import java.util.UUID; +import java.util.concurrent.CopyOnWriteArrayList; + +/** + * Provides Device Group details. + * + * {@see BluetoothDeviceGroup} + * @hide + * + */ + +public final class DeviceGroup implements Parcelable { + /** Identifier of the Device Group */ + private int mGroupId; + /** Size of the Device Group. */ + private int mSize; + /** List of all group devices {@link BluetoothDevice} */ + private CopyOnWriteArrayList <BluetoothDevice> mGroupDevices + = new CopyOnWriteArrayList<BluetoothDevice>(); + /** Primary Service UUID which has included required Device Group service*/ + private final ParcelUuid mIncludingSrvcUUID; + /** Suggests whether exclusive access can be taken for this device group */ + private final boolean mExclusiveAccessSupport; + + /** + * Constructor. + * @hide + */ + public DeviceGroup(int groupId, int size, List<BluetoothDevice> groupDevices, + ParcelUuid includingSrvcUUID, boolean exclusiveAccessSupport) { + mGroupId = groupId; + mSize = size; + mGroupDevices.addAll(groupDevices); + mIncludingSrvcUUID = includingSrvcUUID; + mExclusiveAccessSupport = exclusiveAccessSupport; + } + + public DeviceGroup(Parcel in) { + mGroupId = in.readInt(); + mSize = in.readInt(); + in.readList(mGroupDevices, BluetoothDevice.class.getClassLoader()); + mIncludingSrvcUUID = in.readParcelable(ParcelUuid.class.getClassLoader()); + mExclusiveAccessSupport = in.readBoolean(); + } + + /** + * Used to retrieve identifier of the Device Group. + * + * @return Identifier of the Device Group. + */ + public int getDeviceGroupId() { + return mGroupId; + } + + /** + * Used to know total number group devices which are part of this Device Group. + * + * @return size of the Device Group + */ + public int getDeviceGroupSize() { + return mSize; + } + + /** + * Indicates total number of group devices discovered in Group Discovery procedure. + * + * @return total group devices discovered in the Device Group. + */ + public int getTotalDiscoveredGroupDevices() { + return mGroupDevices.size(); + } + + + /** + * Used to fetch group devices of the Device Group. + * + *@return List of group devices {@link BluetoothDevice} in the Device Group. + */ + public List<BluetoothDevice> getDeviceGroupMembers() { + return mGroupDevices; + } + + /** + * Suggests primary GATT service which has included this DeviceGroup Service + * for this device group. If remote device is part of multiple Device Groups then + * this uuid cant be null. If remote device is part of only one device froup + * then this returned parameter can be null. + * + *@return UUID of the GATT primary Service which has included this device group. + */ + public ParcelUuid getIncludingServiceUUID() { + return mIncludingSrvcUUID; + } + + /** + * Suggests whether exclusive access is supported by this Device Group. + * + * @return true, if exclusive access operation is supported by this Device Group. + * Otherwise, false. + */ + public boolean isExclusiveAccessSupported() { + return mExclusiveAccessSupport; + } + + /** + * Indicates whether all devices of this Device Group are discovered. + * + * @return true, if all group devices are discovered. Otherwise, false. + */ + public boolean isGroupDiscoveredCompleted() { + return (mSize == getTotalDiscoveredGroupDevices()); + } + + @Override + public void writeToParcel(Parcel dest, int flags) { + dest.writeInt(mGroupId); + dest.writeInt(mSize); + dest.writeList(mGroupDevices); + dest.writeParcelable(mIncludingSrvcUUID, 0); + dest.writeBoolean(mExclusiveAccessSupport); + } + + @Override + public int describeContents() { + return 0; + } + + public static final Parcelable.Creator<DeviceGroup> CREATOR = + new Parcelable.Creator<DeviceGroup>() { + public DeviceGroup createFromParcel(Parcel in) { + return new DeviceGroup(in); + } + + public DeviceGroup[] newArray(int size) { + return new DeviceGroup[size]; + } + }; +} diff --git a/core/java/android/bluetooth/le/AdvertiseData.java b/core/java/android/bluetooth/le/AdvertiseData.java index cec658049ca5..f0075263894f 100644 --- a/core/java/android/bluetooth/le/AdvertiseData.java +++ b/core/java/android/bluetooth/le/AdvertiseData.java @@ -51,19 +51,22 @@ public final class AdvertiseData implements Parcelable { private final Map<ParcelUuid, byte[]> mServiceData; private final boolean mIncludeTxPowerLevel; private final boolean mIncludeDeviceName; + private final byte[] mTransportDiscoveryData; private AdvertiseData(List<ParcelUuid> serviceUuids, List<ParcelUuid> serviceSolicitationUuids, SparseArray<byte[]> manufacturerData, Map<ParcelUuid, byte[]> serviceData, boolean includeTxPowerLevel, - boolean includeDeviceName) { + boolean includeDeviceName, + byte[] transportDiscoveryData) { mServiceUuids = serviceUuids; mServiceSolicitationUuids = serviceSolicitationUuids; mManufacturerSpecificData = manufacturerData; mServiceData = serviceData; mIncludeTxPowerLevel = includeTxPowerLevel; mIncludeDeviceName = includeDeviceName; + mTransportDiscoveryData = transportDiscoveryData; } /** @@ -112,12 +115,20 @@ public final class AdvertiseData implements Parcelable { } /** + * Returns an array of Transport Discovery data. + * @hide + */ + public byte[] getTransportDiscoveryData() { + return mTransportDiscoveryData; + } + + /** * @hide */ @Override public int hashCode() { return Objects.hash(mServiceUuids, mServiceSolicitationUuids, mManufacturerSpecificData, - mServiceData, mIncludeDeviceName, mIncludeTxPowerLevel); + mServiceData, mIncludeDeviceName, mIncludeTxPowerLevel, mTransportDiscoveryData); } /** @@ -138,7 +149,8 @@ public final class AdvertiseData implements Parcelable { other.mManufacturerSpecificData) && BluetoothLeUtils.equals(mServiceData, other.mServiceData) && mIncludeDeviceName == other.mIncludeDeviceName - && mIncludeTxPowerLevel == other.mIncludeTxPowerLevel; + && mIncludeTxPowerLevel == other.mIncludeTxPowerLevel + && BluetoothLeUtils.equals(mTransportDiscoveryData, other.mTransportDiscoveryData); } @Override @@ -148,7 +160,8 @@ public final class AdvertiseData implements Parcelable { + BluetoothLeUtils.toString(mManufacturerSpecificData) + ", mServiceData=" + BluetoothLeUtils.toString(mServiceData) + ", mIncludeTxPowerLevel=" + mIncludeTxPowerLevel + ", mIncludeDeviceName=" - + mIncludeDeviceName + "]"; + + mIncludeDeviceName + ", mTransportDiscoveryData=" + + BluetoothLeUtils.toString(mTransportDiscoveryData)+ "]"; } @Override @@ -175,6 +188,10 @@ public final class AdvertiseData implements Parcelable { } dest.writeByte((byte) (getIncludeTxPowerLevel() ? 1 : 0)); dest.writeByte((byte) (getIncludeDeviceName() ? 1 : 0)); + dest.writeInt(mTransportDiscoveryData != null ? mTransportDiscoveryData.length : 0); + if (mTransportDiscoveryData != null) { + dest.writeByteArray(mTransportDiscoveryData); + } } public static final @android.annotation.NonNull Parcelable.Creator<AdvertiseData> CREATOR = @@ -211,6 +228,11 @@ public final class AdvertiseData implements Parcelable { } builder.setIncludeTxPowerLevel(in.readByte() == 1); builder.setIncludeDeviceName(in.readByte() == 1); + int transportDiscoveryDataSize = in.readInt(); + if (transportDiscoveryDataSize > 0) { + byte[] transportDiscoveryData = in.createByteArray(); + builder.addTransportDiscoveryData(transportDiscoveryData); + } return builder.build(); } }; @@ -227,6 +249,7 @@ public final class AdvertiseData implements Parcelable { private Map<ParcelUuid, byte[]> mServiceData = new ArrayMap<ParcelUuid, byte[]>(); private boolean mIncludeTxPowerLevel; private boolean mIncludeDeviceName; + private byte[] mTransportDiscoveryData; /** * Add a service UUID to advertise data. @@ -315,12 +338,24 @@ public final class AdvertiseData implements Parcelable { } /** + * Add Transport Discovery data + * @hide + */ + public Builder addTransportDiscoveryData(byte[] transportDiscoveryData) { + if ((transportDiscoveryData == null) || (transportDiscoveryData.length == 0)) { + throw new IllegalArgumentException("transportDiscoveryData is null"); + } + mTransportDiscoveryData = transportDiscoveryData; + return this; + } + + /** * Build the {@link AdvertiseData}. */ public AdvertiseData build() { return new AdvertiseData(mServiceUuids, mServiceSolicitationUuids, mManufacturerSpecificData, mServiceData, mIncludeTxPowerLevel, - mIncludeDeviceName); + mIncludeDeviceName, mTransportDiscoveryData); } } } diff --git a/core/java/android/bluetooth/le/AdvertisingSetParameters.java b/core/java/android/bluetooth/le/AdvertisingSetParameters.java index e39b198ae384..360e8f8815e0 100644 --- a/core/java/android/bluetooth/le/AdvertisingSetParameters.java +++ b/core/java/android/bluetooth/le/AdvertisingSetParameters.java @@ -20,6 +20,7 @@ import android.bluetooth.BluetoothAdapter; import android.bluetooth.BluetoothDevice; import android.os.Parcel; import android.os.Parcelable; +import android.app.ActivityThread; /** * The {@link AdvertisingSetParameters} provide a way to adjust advertising @@ -389,10 +390,20 @@ public final class AdvertisingSetParameters implements Parcelable { * {@link AdvertisingSetParameters#TX_POWER_MEDIUM}, * or {@link AdvertisingSetParameters#TX_POWER_HIGH}. * @throws IllegalArgumentException If the {@code txPowerLevel} is invalid. + * Allow tx power level to be set more than {@link AdvertisingSetParameters#TX_POWER_HIGH}, + * if the setTxPowerLevel is invoked from com.android.bluetooth process */ public Builder setTxPowerLevel(int txPowerLevel) { - if (txPowerLevel < TX_POWER_MIN || txPowerLevel > TX_POWER_MAX) { - throw new IllegalArgumentException("unknown txPowerLevel " + txPowerLevel); + String packageName = ActivityThread.currentPackageName(); + if (packageName.equals("com.android.bluetooth")) { + int maxPowerLevel = 20; + if (txPowerLevel < TX_POWER_MIN || txPowerLevel > maxPowerLevel) { + throw new IllegalArgumentException("invalid txPowerLevel " + txPowerLevel); + } + } else { + if (txPowerLevel < TX_POWER_MIN || txPowerLevel > TX_POWER_MAX) { + throw new IllegalArgumentException("unknown txPowerLevel " + txPowerLevel); + } } mTxPowerLevel = txPowerLevel; return this; diff --git a/core/java/android/bluetooth/le/BluetoothLeScanner.java b/core/java/android/bluetooth/le/BluetoothLeScanner.java index 34aac8bfdb25..2afe24f1439a 100644 --- a/core/java/android/bluetooth/le/BluetoothLeScanner.java +++ b/core/java/android/bluetooth/le/BluetoothLeScanner.java @@ -38,6 +38,7 @@ import android.os.RemoteException; import android.os.WorkSource; import android.util.Log; +import java.util.Arrays; import java.util.ArrayList; import java.util.HashMap; import java.util.List; @@ -260,6 +261,13 @@ public final class BluetoothLeScanner { if (gatt == null) { return postCallbackErrorOrReturn(callback, ScanCallback.SCAN_FAILED_INTERNAL_ERROR); } + + if ((settings.getCallbackType() == ScanSettings.CALLBACK_TYPE_SENSOR_ROUTING) + && (filters == null || filters.isEmpty())) { + ScanFilter filter = (new ScanFilter.Builder()).build(); + filters = Arrays.asList(filter); + } + if (!isSettingsConfigAllowedForScan(settings)) { return postCallbackErrorOrReturn(callback, ScanCallback.SCAN_FAILED_FEATURE_UNSUPPORTED); @@ -272,6 +280,10 @@ public final class BluetoothLeScanner { return postCallbackErrorOrReturn(callback, ScanCallback.SCAN_FAILED_FEATURE_UNSUPPORTED); } + if (!isRoutingAllowedForScan(settings)) { + return postCallbackErrorOrReturn(callback, + ScanCallback.SCAN_FAILED_FEATURE_UNSUPPORTED); + } if (callback != null) { BleScanCallbackWrapper wrapper = new BleScanCallbackWrapper(gatt, filters, settings, workSource, callback, resultStorages); @@ -648,4 +660,14 @@ public final class BluetoothLeScanner { } return true; } + + private boolean isRoutingAllowedForScan(ScanSettings settings) { + final int callbackType = settings.getCallbackType(); + + if (callbackType == ScanSettings.CALLBACK_TYPE_SENSOR_ROUTING + && settings.getScanMode() == ScanSettings.SCAN_MODE_OPPORTUNISTIC) { + return false; + } + return true; + } } diff --git a/core/java/android/bluetooth/le/BluetoothLeUtils.java b/core/java/android/bluetooth/le/BluetoothLeUtils.java index 6381f557c1b2..f8d1c517540d 100644 --- a/core/java/android/bluetooth/le/BluetoothLeUtils.java +++ b/core/java/android/bluetooth/le/BluetoothLeUtils.java @@ -77,6 +77,28 @@ public class BluetoothLeUtils { } /** + * Returns a string composed from a byte array. + */ + static <T> String toString(byte[] data) { + if (data == null) { + return "null"; + } + if (data.length == 0) { + return "{}"; + } + StringBuilder buffer = new StringBuilder(); + buffer.append('{'); + for(int i=0; i < data.length; i++) { + buffer.append(data[i]); + if ((i+1) < data.length) { + buffer.append(", "); + } + } + buffer.append('}'); + return buffer.toString(); + } + + /** * Check whether two {@link SparseArray} equal. */ static boolean equals(SparseArray<byte[]> array, SparseArray<byte[]> otherArray) { @@ -126,6 +148,25 @@ public class BluetoothLeUtils { } /** + * Check whether two byte arrays are equal. + */ + static <T> boolean equals(byte[] data, byte[] otherData) { + if (data == otherData) { + return true; + } + if (data == null || otherData == null) { + return false; + } + if (data.length != otherData.length) { + return false; + } + if (!Objects.deepEquals(data, otherData)) { + return false; + } + return true; + } + + /** * Ensure Bluetooth is turned on. * * @throws IllegalStateException If {@code adapter} is null or Bluetooth state is not {@link diff --git a/core/java/android/bluetooth/le/PeriodicAdvertisingCallback.java b/core/java/android/bluetooth/le/PeriodicAdvertisingCallback.java index 14ac911fcb7f..b3fd484f699f 100644 --- a/core/java/android/bluetooth/le/PeriodicAdvertisingCallback.java +++ b/core/java/android/bluetooth/le/PeriodicAdvertisingCallback.java @@ -78,4 +78,13 @@ public abstract class PeriodicAdvertisingCallback { */ public void onSyncLost(int syncHandle) { } + + /** + * Callback when periodic sync transfered. + * + * @param device + * @param status + */ + public void onSyncTransfered(BluetoothDevice device, int status) { + } } diff --git a/core/java/android/bluetooth/le/PeriodicAdvertisingManager.java b/core/java/android/bluetooth/le/PeriodicAdvertisingManager.java index dea686d18ea2..ff9a41b92f34 100644 --- a/core/java/android/bluetooth/le/PeriodicAdvertisingManager.java +++ b/core/java/android/bluetooth/le/PeriodicAdvertisingManager.java @@ -259,6 +259,75 @@ public final class PeriodicAdvertisingManager { } }); } + + public void onSyncTransfered(BluetoothDevice device, int status) { + handler.post(new Runnable() { + @Override + public void run() { + callback.onSyncTransfered(device, status); + // App can still unregister the sync until notified it's lost. + // Remove callback after app was notifed. + //mCallbackWrappers.remove(callback); + } + }); + } }; } + + public void transferSync(BluetoothDevice bda, int service_data, int sync_handle) { + IBluetoothGatt gatt; + try { + gatt = mBluetoothManager.getBluetoothGatt(); + } catch (RemoteException e) { + Log.e(TAG, "Failed to get Bluetooth gatt - ", e); + PeriodicAdvertisingCallback callback = null; + for (PeriodicAdvertisingCallback cb : mCallbackWrappers.keySet()) { + callback = cb; + } + if (callback != null) { + callback.onSyncTransfered(bda, + PeriodicAdvertisingCallback.SYNC_NO_RESOURCES); + } + return; + } + try { + gatt.transferSync(bda, service_data , sync_handle); + } catch (RemoteException e) { + Log.e(TAG, "Failed to register sync - ", e); + return; + } + } + + public void transferSetInfo(BluetoothDevice bda, int service_data, + int adv_handle, PeriodicAdvertisingCallback callback) { + transferSetInfo(bda, service_data, adv_handle, callback, null); + } + + public void transferSetInfo (BluetoothDevice bda, int service_data, + int adv_handle, PeriodicAdvertisingCallback callback, Handler handler) { + if (callback == null) { + throw new IllegalArgumentException("callback can't be null"); + } + IBluetoothGatt gatt; + try { + gatt = mBluetoothManager.getBluetoothGatt(); + } catch (RemoteException e) { + Log.e(TAG, "Failed to get Bluetooth gatt - ", e); + return; + } + if (handler == null) { + handler = new Handler(Looper.getMainLooper()); + } + IPeriodicAdvertisingCallback wrapper = wrap(callback, handler); + if (wrapper == null) { + throw new IllegalArgumentException("callback was not properly registered"); + } + try { + gatt.transferSetInfo(bda, service_data , adv_handle, wrapper); + } catch (RemoteException e) { + Log.e(TAG, "Failed to register sync - ", e); + return; + } + + } } diff --git a/core/java/android/bluetooth/le/ScanFilter.java b/core/java/android/bluetooth/le/ScanFilter.java index 8ff018121ab0..20ed49850b1d 100644 --- a/core/java/android/bluetooth/le/ScanFilter.java +++ b/core/java/android/bluetooth/le/ScanFilter.java @@ -51,6 +51,12 @@ import java.util.UUID; */ public final class ScanFilter implements Parcelable { + /** + * Provide TDS data scan results for WiFi Alliance Org id + * @hide + */ + public static final int WIFI_ALLIANCE_ORG_ID = 2; + @Nullable private final String mDeviceName; @@ -85,6 +91,15 @@ public final class ScanFilter implements Parcelable { @Nullable private final byte[] mManufacturerDataMask; + private final int mOrgId; + private final int mTDSFlags; + private final int mTDSFlagsMask; + private final byte[] mWifiNANHash; + + private final boolean mGroupBasedFiltering; + + private static final int GROUP_DATA_LEN = 6; + /** @hide */ public static final ScanFilter EMPTY = new ScanFilter.Builder().build(); @@ -93,7 +108,9 @@ public final class ScanFilter implements Parcelable { ParcelUuid solicitationUuidMask, ParcelUuid serviceDataUuid, byte[] serviceData, byte[] serviceDataMask, int manufacturerId, byte[] manufacturerData, byte[] manufacturerDataMask, - @AddressType int addressType, @Nullable byte[] irk) { + @AddressType int addressType, @Nullable byte[] irk, + int orgId, int TDSFlags, int TDSFlagsMask, byte[] wifiNANHash, + boolean groupBasedFiltering) { mDeviceName = name; mServiceUuid = uuid; mServiceUuidMask = uuidMask; @@ -108,6 +125,11 @@ public final class ScanFilter implements Parcelable { mManufacturerDataMask = manufacturerDataMask; mAddressType = addressType; mIrk = irk; + mOrgId = orgId; + mTDSFlags = TDSFlags; + mTDSFlagsMask = TDSFlagsMask; + mWifiNANHash = wifiNANHash; + mGroupBasedFiltering = groupBasedFiltering; } @Override @@ -177,6 +199,18 @@ public final class ScanFilter implements Parcelable { dest.writeByteArray(mIrk); } } + dest.writeInt(mOrgId); + dest.writeInt(mOrgId < 0 ? 0 : 1); + if(mOrgId >= 0) { + dest.writeInt(mTDSFlags); + dest.writeInt(mTDSFlagsMask); + dest.writeInt(mWifiNANHash == null ? 0 : 1); + if (mWifiNANHash != null) { + dest.writeInt(mWifiNANHash.length); + dest.writeByteArray(mWifiNANHash); + } + } + dest.writeBoolean(mGroupBasedFiltering); } /** @@ -267,6 +301,25 @@ public final class ScanFilter implements Parcelable { builder.setDeviceAddress(address, addressType); } } + + int orgId = in.readInt(); + if(in.readInt() == 1) { + int tdsFlags = in.readInt(); + int tdsFlagsMask = in.readInt(); + if (in.readInt() == 1) { + int wifiNANHashLength = in.readInt(); + byte[] wifiNanHash = new byte[wifiNANHashLength]; + in.readByteArray(wifiNanHash); + builder.setTransportDiscoveryData(orgId, tdsFlags, tdsFlagsMask, + wifiNanHash); + } + else { + builder.setTransportDiscoveryData(orgId, tdsFlags, tdsFlagsMask, null); + } + } + + boolean groupBasedFiltering = in.readBoolean(); + builder.setGroupBasedFiltering(groupBasedFiltering); return builder.build(); } }; @@ -363,6 +416,45 @@ public final class ScanFilter implements Parcelable { } /** + * @hide + * Returns the organization id. -1 if the organization id is not set. + */ + public int getOrgId() { + return mOrgId; + } + + /** + * @hide + * Returns the TDS flags. -1 if TDS flags is not set. + */ + public int getTDSFlags() { + return mTDSFlags; + } + + /** + * @hide + * Returns the TDS flags mask. -1 if TDS flags mask is not set. + */ + public int getTDSFlagsMask() { + return mTDSFlagsMask; + } + + /** + * @hide + */ + public byte[] getWifiNANHash() { + return mWifiNANHash; + } + + /** + * @hide + * Returns true, if Group AD Type based filtering is enabled. Otherwise, false. + */ + public boolean getGroupFilteringValue() { + return mGroupBasedFiltering; + } + + /** * Check if the scan filter matches a {@code scanResult}. A scan result is considered as a match * if it matches all the field filters. */ @@ -419,6 +511,26 @@ public final class ScanFilter implements Parcelable { return false; } } + + //Transport Discovery data match + if(mOrgId >= 0) { + byte[] tdsData = scanRecord.getTDSData(); + if ((tdsData != null) && (tdsData.length > 0)) { + if ((mOrgId != tdsData[0]) || + ((mTDSFlags & mTDSFlagsMask) != (tdsData[1] & mTDSFlagsMask))) { + return false; + } + } + } + + // Group AD Type filter match + if (mGroupBasedFiltering) { + byte [] groupIdData = scanRecord.getGroupIdentifierData(); + if (groupIdData != null && groupIdData.length != GROUP_DATA_LEN) { + return false; + } + } + // All filters match. return true; } @@ -513,7 +625,11 @@ public final class ScanFilter implements Parcelable { + Arrays.toString(mServiceData) + ", mServiceDataMask=" + Arrays.toString(mServiceDataMask) + ", mManufacturerId=" + mManufacturerId + ", mManufacturerData=" + Arrays.toString(mManufacturerData) - + ", mManufacturerDataMask=" + Arrays.toString(mManufacturerDataMask) + "]"; + + ", mManufacturerDataMask=" + Arrays.toString(mManufacturerDataMask) + + ", mOrganizationId=" + mOrgId + ", mTDSFlags=" + mTDSFlags + + ", mTDSFlagsMask=" + mTDSFlagsMask + + ", mWifiNANHash=" + Arrays.toString(mWifiNANHash) +"]" + + ", mGroupBasedFiltering=" + mGroupBasedFiltering; } @Override @@ -525,7 +641,9 @@ public final class ScanFilter implements Parcelable { Arrays.hashCode(mServiceData), Arrays.hashCode(mServiceDataMask), mServiceUuid, mServiceUuidMask, - mServiceSolicitationUuid, mServiceSolicitationUuidMask); + mServiceSolicitationUuid, mServiceSolicitationUuidMask, + mOrgId, mTDSFlags, mTDSFlagsMask, Arrays.hashCode(mWifiNANHash), + mGroupBasedFiltering); } @Override @@ -549,7 +667,12 @@ public final class ScanFilter implements Parcelable { && Objects.equals(mServiceUuidMask, other.mServiceUuidMask) && Objects.equals(mServiceSolicitationUuid, other.mServiceSolicitationUuid) && Objects.equals(mServiceSolicitationUuidMask, - other.mServiceSolicitationUuidMask); + other.mServiceSolicitationUuidMask) + && mOrgId == other.mOrgId + && mTDSFlags == other.mTDSFlags + && mTDSFlagsMask == other.mTDSFlagsMask + && Objects.deepEquals(mWifiNANHash, other.mWifiNANHash) + && mGroupBasedFiltering == other.mGroupBasedFiltering; } /** @@ -591,6 +714,13 @@ public final class ScanFilter implements Parcelable { private byte[] mManufacturerData; private byte[] mManufacturerDataMask; + private int mOrgId = -1; + private int mTDSFlags = -1; + private int mTDSFlagsMask = -1; + private byte[] mWifiNANHash; + + private boolean mGroupBasedFiltering; + /** * Set filter on device name. */ @@ -895,6 +1025,38 @@ public final class ScanFilter implements Parcelable { return this; } + + /** + * @hide + * Set filter on transport discovery data. + * @throws IllegalArgumentException If the {@code orgId} is invalid or {@code + * wifiNANhash} is not null while {@code orgId} is non-Wifi. + */ + public Builder setTransportDiscoveryData(int orgId, int TDSFlags, int TDSFlagsMask, + byte[] wifiNANHash) { + if (orgId < 0) { + throw new IllegalArgumentException("invalid organization id"); + } + if ((orgId != WIFI_ALLIANCE_ORG_ID) && (wifiNANHash != null)) { + throw new IllegalArgumentException("Wifi NAN Hash is not null for non-Wifi Org Id"); + } + mOrgId = orgId; + mTDSFlags = TDSFlags; + mTDSFlagsMask = TDSFlagsMask; + mWifiNANHash = wifiNANHash; + return this; + } + + /** + * @hide + * Enable filter on Group AD Type. + */ + public @NonNull Builder setGroupBasedFiltering( + boolean enable) { + mGroupBasedFiltering = enable; + return this; + } + /** * Build {@link ScanFilter}. * @@ -906,7 +1068,9 @@ public final class ScanFilter implements Parcelable { mServiceSolicitationUuidMask, mServiceDataUuid, mServiceData, mServiceDataMask, mManufacturerId, mManufacturerData, mManufacturerDataMask, - mAddressType, mIrk); + mAddressType, mIrk, + mOrgId, mTDSFlags, mTDSFlagsMask, mWifiNANHash, + mGroupBasedFiltering); } } } diff --git a/core/java/android/bluetooth/le/ScanRecord.java b/core/java/android/bluetooth/le/ScanRecord.java index 9b8c2eaf4d19..28dbfbef993f 100644 --- a/core/java/android/bluetooth/le/ScanRecord.java +++ b/core/java/android/bluetooth/le/ScanRecord.java @@ -59,6 +59,11 @@ public final class ScanRecord { private static final int DATA_TYPE_SERVICE_SOLICITATION_UUIDS_32_BIT = 0x1F; private static final int DATA_TYPE_SERVICE_SOLICITATION_UUIDS_128_BIT = 0x15; private static final int DATA_TYPE_MANUFACTURER_SPECIFIC_DATA = 0xFF; + private static final int DATA_TYPE_TRANSPORT_DISCOVERY_DATA = 0x26; + /** + * @hide + */ + public static int DATA_TYPE_GROUP_AD_TYPE = 0x00; // Flags of the advertising data. private final int mAdvertiseFlags; @@ -81,6 +86,12 @@ public final class ScanRecord { // Raw bytes of scan record. private final byte[] mBytes; + // Transport Discovery data. + private final byte[] mTDSData; + + // Group Identifier Data + private final byte[] mGroupIdentifierData; + /** * Returns the advertising flags indicating the discoverable mode and capability of the device. * Returns -1 if the flag field is not set. @@ -165,6 +176,22 @@ public final class ScanRecord { } /** + * @hide + * Returns Transport Discovery data + */ + public byte[] getTDSData() { + return mTDSData; + } + + /** + * @hide + * Returns Group Identifier data + */ + public byte[] getGroupIdentifierData() { + return mGroupIdentifierData; + } + + /** * Returns raw bytes of scan record. */ public byte[] getBytes() { @@ -197,7 +224,7 @@ public final class ScanRecord { SparseArray<byte[]> manufacturerData, Map<ParcelUuid, byte[]> serviceData, int advertiseFlags, int txPowerLevel, - String localName, byte[] bytes) { + String localName, byte[] tdsData, byte[] groupIdentifierData, byte[] bytes) { mServiceSolicitationUuids = serviceSolicitationUuids; mServiceUuids = serviceUuids; mManufacturerSpecificData = manufacturerData; @@ -205,6 +232,8 @@ public final class ScanRecord { mDeviceName = localName; mAdvertiseFlags = advertiseFlags; mTxPowerLevel = txPowerLevel; + mTDSData = tdsData; + mGroupIdentifierData = groupIdentifierData; mBytes = bytes; } @@ -235,6 +264,9 @@ public final class ScanRecord { SparseArray<byte[]> manufacturerData = new SparseArray<byte[]>(); Map<ParcelUuid, byte[]> serviceData = new ArrayMap<ParcelUuid, byte[]>(); + byte[] tdsData = null; + byte[] groupIdentifierData = null; + try { while (currentPos < scanRecord.length) { // length is unsigned int. @@ -312,8 +344,15 @@ public final class ScanRecord { dataLength - 2); manufacturerData.put(manufacturerId, manufacturerDataBytes); break; + case DATA_TYPE_TRANSPORT_DISCOVERY_DATA: + tdsData = extractBytes(scanRecord, currentPos, dataLength); + break; + default: - // Just ignore, we don't handle such data type. + if (fieldType == DATA_TYPE_GROUP_AD_TYPE) { + Log.d(TAG, "Parsing Group Identifier data"); + groupIdentifierData = extractBytes(scanRecord, currentPos, dataLength); + } break; } currentPos += dataLength; @@ -323,12 +362,14 @@ public final class ScanRecord { serviceUuids = null; } return new ScanRecord(serviceUuids, serviceSolicitationUuids, manufacturerData, - serviceData, advertiseFlag, txPowerLevel, localName, scanRecord); + serviceData, advertiseFlag, txPowerLevel, localName, tdsData, + groupIdentifierData, scanRecord); } catch (Exception e) { Log.e(TAG, "unable to parse scan record: " + Arrays.toString(scanRecord)); // As the record is invalid, ignore all the parsed results for this packet // and return an empty record with raw scanRecord bytes in results - return new ScanRecord(null, null, null, null, -1, Integer.MIN_VALUE, null, scanRecord); + return new ScanRecord(null, null, null, null, -1, Integer.MIN_VALUE, null, null, + null, scanRecord); } } @@ -339,7 +380,8 @@ public final class ScanRecord { + ", mManufacturerSpecificData=" + BluetoothLeUtils.toString( mManufacturerSpecificData) + ", mServiceData=" + BluetoothLeUtils.toString(mServiceData) - + ", mTxPowerLevel=" + mTxPowerLevel + ", mDeviceName=" + mDeviceName + "]"; + + ", mTxPowerLevel=" + mTxPowerLevel + ", mDeviceName=" + mDeviceName + + ", mTDSData=" + BluetoothLeUtils.toString(mTDSData) +"]"; } // Parse service UUIDs. diff --git a/core/java/android/bluetooth/le/ScanResult.java b/core/java/android/bluetooth/le/ScanResult.java index 522845628487..40ff3bec817e 100644 --- a/core/java/android/bluetooth/le/ScanResult.java +++ b/core/java/android/bluetooth/le/ScanResult.java @@ -93,6 +93,7 @@ public final class ScanResult implements Parcelable, Attributable { private int mAdvertisingSid; private int mTxPower; private int mPeriodicAdvertisingInterval; + private int mAddressType; /** * Constructs a new ScanResult. @@ -117,6 +118,7 @@ public final class ScanResult implements Parcelable, Attributable { mAdvertisingSid = SID_NOT_PRESENT; mTxPower = 127; mPeriodicAdvertisingInterval = 0; + mAddressType = -1; } /** @@ -146,6 +148,42 @@ public final class ScanResult implements Parcelable, Attributable { mPeriodicAdvertisingInterval = periodicAdvertisingInterval; mScanRecord = scanRecord; mTimestampNanos = timestampNanos; + mAddressType = -1; + } + + /** + * Constructs a new ScanResult. + * + * @param device Remote Bluetooth device found. + * @param addressType addressType for the Scan result + * @param eventType Event type. + * @param primaryPhy Primary advertising phy. + * @param secondaryPhy Secondary advertising phy. + * @param advertisingSid Advertising set ID. + * @param txPower Transmit power. + * @param rssi Received signal strength. + * @param periodicAdvertisingInterval Periodic advertising interval. + * @param scanRecord Scan record including both advertising data and scan response data. + * @param timestampNanos Timestamp at which the scan result was observed. + * @param addressType addressType for the Scan result + * + *@hide + */ + public ScanResult(BluetoothDevice device, int addressType, int eventType, int primaryPhy, + int secondaryPhy, + int advertisingSid, int txPower, int rssi, int periodicAdvertisingInterval, + ScanRecord scanRecord, long timestampNanos) { + mDevice = device; + mEventType = eventType; + mPrimaryPhy = primaryPhy; + mSecondaryPhy = secondaryPhy; + mAdvertisingSid = advertisingSid; + mTxPower = txPower; + mRssi = rssi; + mPeriodicAdvertisingInterval = periodicAdvertisingInterval; + mScanRecord = scanRecord; + mTimestampNanos = timestampNanos; + mAddressType = addressType; } private ScanResult(Parcel in) { @@ -174,6 +212,7 @@ public final class ScanResult implements Parcelable, Attributable { dest.writeInt(mAdvertisingSid); dest.writeInt(mTxPower); dest.writeInt(mPeriodicAdvertisingInterval); + dest.writeInt(mAddressType); } private void readFromParcel(Parcel in) { @@ -191,6 +230,7 @@ public final class ScanResult implements Parcelable, Attributable { mAdvertisingSid = in.readInt(); mTxPower = in.readInt(); mPeriodicAdvertisingInterval = in.readInt(); + mAddressType = in.readInt(); } @Override @@ -308,6 +348,14 @@ public final class ScanResult implements Parcelable, Attributable { return mPeriodicAdvertisingInterval; } + /** + * + *@hide + */ + public int getAddressType() { + return mAddressType; + } + @Override public int hashCode() { return Objects.hash(mDevice, mRssi, mScanRecord, mTimestampNanos, @@ -333,7 +381,8 @@ public final class ScanResult implements Parcelable, Attributable { && mSecondaryPhy == other.mSecondaryPhy && mAdvertisingSid == other.mAdvertisingSid && mTxPower == other.mTxPower - && mPeriodicAdvertisingInterval == other.mPeriodicAdvertisingInterval; + && mPeriodicAdvertisingInterval == other.mPeriodicAdvertisingInterval + && mAddressType == other.mAddressType; } @Override diff --git a/core/java/android/bluetooth/le/ScanSettings.java b/core/java/android/bluetooth/le/ScanSettings.java index 1aa7cb5111ce..f946cadc7311 100644 --- a/core/java/android/bluetooth/le/ScanSettings.java +++ b/core/java/android/bluetooth/le/ScanSettings.java @@ -79,6 +79,12 @@ public final class ScanSettings implements Parcelable { */ public static final int CALLBACK_TYPE_MATCH_LOST = 4; + /** + * Provide results to sensor router instead of the apps processor + * @hide + */ + public static final int CALLBACK_TYPE_SENSOR_ROUTING = 8; + /** * Determines how many advertisements to match per filter, as this is scarce hw resource @@ -319,7 +325,8 @@ public final class ScanSettings implements Parcelable { private boolean isValidCallbackType(int callbackType) { if (callbackType == CALLBACK_TYPE_ALL_MATCHES || callbackType == CALLBACK_TYPE_FIRST_MATCH - || callbackType == CALLBACK_TYPE_MATCH_LOST) { + || callbackType == CALLBACK_TYPE_MATCH_LOST + || callbackType == CALLBACK_TYPE_SENSOR_ROUTING) { return true; } return callbackType == (CALLBACK_TYPE_FIRST_MATCH | CALLBACK_TYPE_MATCH_LOST); diff --git a/core/java/android/content/ContentResolver.java b/core/java/android/content/ContentResolver.java index 265ff331ffa0..4956e3780000 100644 --- a/core/java/android/content/ContentResolver.java +++ b/core/java/android/content/ContentResolver.java @@ -1104,6 +1104,7 @@ public abstract class ContentResolver implements ContentInterface { public final @Nullable Cursor query(@RequiresPermission.Read @NonNull Uri uri, @Nullable String[] projection, @Nullable String selection, @Nullable String[] selectionArgs, @Nullable String sortOrder) { + android.util.SeempLog.record_uri(13, uri); return query(uri, projection, selection, selectionArgs, sortOrder, null); } @@ -1190,6 +1191,7 @@ public abstract class ContentResolver implements ContentInterface { public final @Nullable Cursor query(final @RequiresPermission.Read @NonNull Uri uri, @Nullable String[] projection, @Nullable Bundle queryArgs, @Nullable CancellationSignal cancellationSignal) { + android.util.SeempLog.record_uri(13, uri); Objects.requireNonNull(uri, "uri"); try { @@ -2176,6 +2178,7 @@ public abstract class ContentResolver implements ContentInterface { @Override public final @Nullable Uri insert(@RequiresPermission.Write @NonNull Uri url, @Nullable ContentValues values, @Nullable Bundle extras) { + android.util.SeempLog.record_uri(37, url); Objects.requireNonNull(url, "url"); try { diff --git a/core/java/android/content/Intent.java b/core/java/android/content/Intent.java index 35794d79b49d..75d2634ca2f9 100644 --- a/core/java/android/content/Intent.java +++ b/core/java/android/content/Intent.java @@ -2900,6 +2900,18 @@ public class Intent implements Parcelable, Cloneable { public static final String ACTION_PACKAGE_NEEDS_VERIFICATION = "android.intent.action.PACKAGE_NEEDS_VERIFICATION"; /** + * Broadcast Action: Sent to the optional package verifier when a package + * needs to be verified. The data contains the package URI. + * <p class="note"> + * This is a protected intent. + * </p> + * + * @hide + */ + @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) + public static final String ACTION_PACKAGE_NEEDS_OPTIONAL_VERIFICATION = "com.qualcomm.qti.intent.action.PACKAGE_NEEDS_OPTIONAL_VERIFICATION"; + + /** * Broadcast Action: Sent to the system package verifier when a package is * verified. The data contains the package URI. * <p class="note"> @@ -11408,6 +11420,7 @@ public class Intent implements Parcelable, Cloneable { case ACTION_MEDIA_SCANNER_SCAN_FILE: case ACTION_PACKAGE_NEEDS_VERIFICATION: case ACTION_PACKAGE_NEEDS_INTEGRITY_VERIFICATION: + case ACTION_PACKAGE_NEEDS_OPTIONAL_VERIFICATION: case ACTION_PACKAGE_VERIFIED: case ACTION_PACKAGE_ENABLE_ROLLBACK: // Ignore legacy actions diff --git a/core/java/android/content/pm/ApplicationInfo.java b/core/java/android/content/pm/ApplicationInfo.java index 2c4ff5889263..9934823abd47 100644 --- a/core/java/android/content/pm/ApplicationInfo.java +++ b/core/java/android/content/pm/ApplicationInfo.java @@ -29,6 +29,8 @@ import android.content.res.Resources; import android.graphics.drawable.Drawable; import android.os.Build; import android.os.Environment; +import android.os.SystemProperties; +import android.util.DisplayMetrics; import android.os.Parcel; import android.os.Parcelable; import android.os.UserHandle; @@ -61,58 +63,58 @@ public class ApplicationInfo extends PackageItemInfo implements Parcelable { private static ForBoolean sForBoolean = Parcelling.Cache.getOrCreate(ForBoolean.class); /** - * Default task affinity of all activities in this application. See - * {@link ActivityInfo#taskAffinity} for more information. This comes - * from the "taskAffinity" attribute. + * Default task affinity of all activities in this application. See + * {@link ActivityInfo#taskAffinity} for more information. This comes + * from the "taskAffinity" attribute. */ public String taskAffinity; - + /** * Optional name of a permission required to be able to access this * application's components. From the "permission" attribute. */ public String permission; - + /** * The name of the process this application should run in. From the * "process" attribute or, if not set, the same as * <var>packageName</var>. */ public String processName; - + /** * Class implementing the Application object. From the "class" * attribute. */ public String className; - + /** * A style resource identifier (in the package's resources) of the * description of an application. From the "description" attribute * or, if not set, 0. */ - public int descriptionRes; - + public int descriptionRes; + /** * A style resource identifier (in the package's resources) of the * default visual theme of the application. From the "theme" attribute * or, if not set, 0. */ public int theme; - + /** * Class implementing the Application's manage space * functionality. From the "manageSpaceActivity" * attribute. This is an optional attribute and will be null if * applications don't specify it in their manifest */ - public String manageSpaceActivityName; - + public String manageSpaceActivityName; + /** * Class implementing the Application's backup functionality. From * the "backupAgent" attribute. This is an optional attribute and * will be null if the application does not specify it in its manifest. - * + * * <p>If android:allowBackup is set to false, this attribute is ignored. */ public String backupAgentName; @@ -173,7 +175,7 @@ public class ApplicationInfo extends PackageItemInfo implements Parcelable { * {@code signatureOrSystem}. */ public static final int FLAG_SYSTEM = 1<<0; - + /** * Value for {@link #flags}: set to true if this application would like to * allow debugging of its @@ -182,7 +184,7 @@ public class ApplicationInfo extends PackageItemInfo implements Parcelable { * android:debuggable} of the <application> tag. */ public static final int FLAG_DEBUGGABLE = 1<<1; - + /** * Value for {@link #flags}: set to true if this application has code * associated with it. Comes @@ -190,7 +192,7 @@ public class ApplicationInfo extends PackageItemInfo implements Parcelable { * android:hasCode} of the <application> tag. */ public static final int FLAG_HAS_CODE = 1<<2; - + /** * Value for {@link #flags}: set to true if this application is persistent. * Comes from {@link android.R.styleable#AndroidManifestApplication_persistent @@ -211,20 +213,20 @@ public class ApplicationInfo extends PackageItemInfo implements Parcelable { * android:allowTaskReparenting} of the <application> tag. */ public static final int FLAG_ALLOW_TASK_REPARENTING = 1<<5; - + /** * Value for {@link #flags}: default value for the corresponding ActivityInfo flag. * Comes from {@link android.R.styleable#AndroidManifestApplication_allowClearUserData * android:allowClearUserData} of the <application> tag. */ public static final int FLAG_ALLOW_CLEAR_USER_DATA = 1<<6; - + /** * Value for {@link #flags}: this is set if this application has been * installed as an update to a built-in system application. */ public static final int FLAG_UPDATED_SYSTEM_APP = 1<<7; - + /** * Value for {@link #flags}: this is set if the application has specified * {@link android.R.styleable#AndroidManifestApplication_testOnly @@ -239,15 +241,15 @@ public class ApplicationInfo extends PackageItemInfo implements Parcelable { * android:smallScreens}. */ public static final int FLAG_SUPPORTS_SMALL_SCREENS = 1<<9; - + /** * Value for {@link #flags}: true when the application's window can be * displayed on normal screens. Corresponds to * {@link android.R.styleable#AndroidManifestSupportsScreens_normalScreens * android:normalScreens}. */ - public static final int FLAG_SUPPORTS_NORMAL_SCREENS = 1<<10; - + public static final int FLAG_SUPPORTS_NORMAL_SCREENS = 1<<10; + /** * Value for {@link #flags}: true when the application's window can be * increased in size for larger screens. Corresponds to @@ -255,7 +257,7 @@ public class ApplicationInfo extends PackageItemInfo implements Parcelable { * android:largeScreens}. */ public static final int FLAG_SUPPORTS_LARGE_SCREENS = 1<<11; - + /** * Value for {@link #flags}: true when the application knows how to adjust * its UI for different screen sizes. Corresponds to @@ -263,7 +265,7 @@ public class ApplicationInfo extends PackageItemInfo implements Parcelable { * android:resizeable}. */ public static final int FLAG_RESIZEABLE_FOR_SCREENS = 1<<12; - + /** * Value for {@link #flags}: true when the application knows how to * accommodate different screen densities. Corresponds to @@ -275,7 +277,7 @@ public class ApplicationInfo extends PackageItemInfo implements Parcelable { */ @Deprecated public static final int FLAG_SUPPORTS_SCREEN_DENSITIES = 1<<13; - + /** * Value for {@link #flags}: set to true if this application would like to * request the VM to operate under the safe mode. Comes from @@ -287,7 +289,7 @@ public class ApplicationInfo extends PackageItemInfo implements Parcelable { /** * Value for {@link #flags}: set to <code>false</code> if the application does not wish * to permit any OS-driven backups of its data; <code>true</code> otherwise. - * + * * <p>Comes from the * {@link android.R.styleable#AndroidManifestApplication_allowBackup android:allowBackup} * attribute of the <application> tag. @@ -350,7 +352,7 @@ public class ApplicationInfo extends PackageItemInfo implements Parcelable { * android:xlargeScreens}. */ public static final int FLAG_SUPPORTS_XLARGE_SCREENS = 1<<19; - + /** * Value for {@link #flags}: true when the application has requested a * large heap for its processes. Corresponds to @@ -845,6 +847,19 @@ public class ApplicationInfo extends PackageItemInfo implements Parcelable { public static final String METADATA_PRELOADED_FONTS = "preloaded_fonts"; /** + * Boolean indicating whether the resolution of the SurfaceView associated + * with this appplication can be overriden. + * {@hide} + */ + public int overrideRes = 0; + + /** + * In case, app needs different density than device density, set this value. + * {@hide} + */ + public int overrideDensity = 0; + + /** * The required smallest screen width the application can run on. If 0, * nothing has been specified. Comes from * {@link android.R.styleable#AndroidManifestSupportsScreens_requiresSmallestWidthDp @@ -1113,7 +1128,7 @@ public class ApplicationInfo extends PackageItemInfo implements Parcelable { * the same uid). */ public int uid; - + /** * The minimum SDK version this application can run on. It will not run * on earlier versions. @@ -1785,7 +1800,7 @@ public class ApplicationInfo extends PackageItemInfo implements Parcelable { if (sb == null) { sb = ab.packageName; } - + return sCollator.compare(sa.toString(), sb.toString()); } @@ -1797,7 +1812,7 @@ public class ApplicationInfo extends PackageItemInfo implements Parcelable { public ApplicationInfo() { } - + public ApplicationInfo(ApplicationInfo orig) { super(orig); taskAffinity = orig.taskAffinity; @@ -1808,6 +1823,8 @@ public class ApplicationInfo extends PackageItemInfo implements Parcelable { flags = orig.flags; privateFlags = orig.privateFlags; privateFlagsExt = orig.privateFlagsExt; + overrideRes = orig.overrideRes; + overrideDensity = orig.overrideDensity; requiresSmallestWidthDp = orig.requiresSmallestWidthDp; compatibleWidthLimitDp = orig.compatibleWidthLimitDp; largestWidthLimitDp = orig.largestWidthLimitDp; @@ -1893,6 +1910,8 @@ public class ApplicationInfo extends PackageItemInfo implements Parcelable { dest.writeInt(flags); dest.writeInt(privateFlags); dest.writeInt(privateFlagsExt); + dest.writeInt(overrideRes); + dest.writeInt(overrideDensity); dest.writeInt(requiresSmallestWidthDp); dest.writeInt(compatibleWidthLimitDp); dest.writeInt(largestWidthLimitDp); @@ -1983,6 +2002,8 @@ public class ApplicationInfo extends PackageItemInfo implements Parcelable { flags = source.readInt(); privateFlags = source.readInt(); privateFlagsExt = source.readInt(); + overrideRes = source.readInt(); + overrideDensity = source.readInt(); requiresSmallestWidthDp = source.readInt(); compatibleWidthLimitDp = source.readInt(); largestWidthLimitDp = source.readInt(); @@ -2069,7 +2090,7 @@ public class ApplicationInfo extends PackageItemInfo implements Parcelable { /** * Disable compatibility mode - * + * * @hide */ @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023) @@ -2290,7 +2311,7 @@ public class ApplicationInfo extends PackageItemInfo implements Parcelable { } return pm.getDefaultActivityIcon(); } - + @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023) private boolean isPackageUnavailable(PackageManager pm) { try { @@ -2511,6 +2532,11 @@ public class ApplicationInfo extends PackageItemInfo implements Parcelable { return output.toArray(new String[output.size()]); } + /** @hide */ + public int getOverrideDensity() { + return overrideDensity; + } + /** {@hide} */ public void setCodePath(String codePath) { scanSourceDir = codePath; } /** {@hide} */ public void setBaseCodePath(String baseCodePath) { sourceDir = baseCodePath; } /** {@hide} */ public void setSplitCodePaths(String[] splitCodePaths) { splitSourceDirs = splitCodePaths; } @@ -2526,6 +2552,7 @@ public class ApplicationInfo extends PackageItemInfo implements Parcelable { public void setRequestRawExternalStorageAccess(@Nullable Boolean value) { requestRawExternalStorageAccess = value; } + /** {@hide} */ public void setOverrideRes(int overrideResolution) { overrideRes = overrideResolution; } /** {@hide} */ @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) @@ -2548,7 +2575,6 @@ public class ApplicationInfo extends PackageItemInfo implements Parcelable { public int getMemtagMode() { return memtagMode; } - /** * Returns whether the application has requested automatic zero-initialization of native heap * memory allocations to be enabled or disabled. @@ -2557,4 +2583,5 @@ public class ApplicationInfo extends PackageItemInfo implements Parcelable { public int getNativeHeapZeroInitialized() { return nativeHeapZeroInitialized; } + /** {@hide} */ public int canOverrideRes() { return overrideRes; } } diff --git a/core/java/android/content/res/CompatibilityInfo.java b/core/java/android/content/res/CompatibilityInfo.java index 439c6396f1d0..8f0d50d94d18 100644 --- a/core/java/android/content/res/CompatibilityInfo.java +++ b/core/java/android/content/res/CompatibilityInfo.java @@ -34,6 +34,7 @@ import android.view.InsetsState; import android.view.MotionEvent; import android.view.WindowManager; import android.view.WindowManager.LayoutParams; +import android.util.Log; /** * CompatibilityInfo class keeps the information about the screen compatibility mode that the @@ -47,6 +48,8 @@ public class CompatibilityInfo implements Parcelable { public static final CompatibilityInfo DEFAULT_COMPATIBILITY_INFO = new CompatibilityInfo() { }; + static final String TAG = "CompatibilityInfo"; + /** * This is the number of pixels we would like to have along the * short axis of an app that needs to run on a normal size screen. @@ -163,11 +166,18 @@ public class CompatibilityInfo implements Parcelable { // Let the user decide. compatFlags |= NEEDS_SCREEN_COMPAT; } - - // Modern apps always support densities. - applicationDensity = DisplayMetrics.DENSITY_DEVICE; - applicationScale = 1.0f; - applicationInvertedScale = 1.0f; + int density = appInfo.getOverrideDensity(); + if(density != 0) { + applicationDensity = density; + applicationScale = DisplayMetrics.DENSITY_DEVICE / (float) applicationDensity; + applicationInvertedScale = 1.0f / applicationScale; + compatFlags |= SCALING_REQUIRED; + } else { + // Modern apps always support densities. + applicationDensity = DisplayMetrics.DENSITY_DEVICE; + applicationScale = 1.0f; + applicationInvertedScale = 1.0f; + } } else { /** @@ -254,26 +264,31 @@ public class CompatibilityInfo implements Parcelable { compatFlags |= NEVER_NEEDS_COMPAT; } - if (overrideScale != 1.0f) { + int density = appInfo.getOverrideDensity(); + if ((appInfo.flags & ApplicationInfo.FLAG_SUPPORTS_SCREEN_DENSITIES) == 0) { + applicationDensity = DisplayMetrics.DENSITY_DEFAULT; + applicationScale = DisplayMetrics.DENSITY_DEVICE + / (float) DisplayMetrics.DENSITY_DEFAULT; + applicationInvertedScale = 1.0f / applicationScale; + compatFlags |= SCALING_REQUIRED; + } else if((density != 0) || (overrideScale != 1.0f)) { applicationScale = overrideScale; applicationInvertedScale = 1.0f / overrideScale; applicationDensity = (int) ((DisplayMetrics.DENSITY_DEVICE_STABLE * applicationInvertedScale) + .5f); compatFlags |= HAS_OVERRIDE_SCALING; - } else if ((appInfo.flags & ApplicationInfo.FLAG_SUPPORTS_SCREEN_DENSITIES) != 0) { + } else { applicationDensity = DisplayMetrics.DENSITY_DEVICE; applicationScale = 1.0f; applicationInvertedScale = 1.0f; - } else { - applicationDensity = DisplayMetrics.DENSITY_DEFAULT; - applicationScale = DisplayMetrics.DENSITY_DEVICE - / (float) DisplayMetrics.DENSITY_DEFAULT; - applicationInvertedScale = 1.0f / applicationScale; - compatFlags |= SCALING_REQUIRED; } } mCompatibilityFlags = compatFlags; + + Log.d(TAG, "mCompatibilityFlags - " + Integer.toHexString(mCompatibilityFlags)); + Log.d(TAG, "applicationDensity - " + applicationDensity); + Log.d(TAG, "applicationScale - " + applicationScale); } private CompatibilityInfo(int compFlags, diff --git a/core/java/android/hardware/Camera.java b/core/java/android/hardware/Camera.java index 3bdd39f5d7d7..0e6f46a79fe6 100644 --- a/core/java/android/hardware/Camera.java +++ b/core/java/android/hardware/Camera.java @@ -45,6 +45,7 @@ import android.os.Message; import android.os.Process; import android.os.RemoteException; import android.os.ServiceManager; +import android.os.SystemProperties; import android.renderscript.Allocation; import android.renderscript.Element; import android.renderscript.RSIllegalArgumentException; @@ -54,6 +55,7 @@ import android.text.TextUtils; import android.util.Log; import android.view.Surface; import android.view.SurfaceHolder; +import android.os.SystemProperties; import com.android.internal.annotations.GuardedBy; import com.android.internal.app.IAppOpsCallback; @@ -171,6 +173,10 @@ public class Camera { private static final int CAMERA_MSG_RAW_IMAGE_NOTIFY = 0x200; private static final int CAMERA_MSG_PREVIEW_METADATA = 0x400; private static final int CAMERA_MSG_FOCUS_MOVE = 0x800; + /* ### QC ADD-ONS: START */ + private static final int CAMERA_MSG_STATS_DATA = 0x1000; + private static final int CAMERA_MSG_META_DATA = 0x2000; + /* ### QC ADD-ONS: END */ @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023) private long mNativeContext; // accessed by native methods @@ -202,6 +208,17 @@ public class Camera { private boolean mShutterSoundEnabledFromApp = true; private static final int NO_ERROR = 0; + private static final int EACCESS = -13; + private static final int ENODEV = -19; + private static final int EBUSY = -16; + private static final int EINVAL = -22; + private static final int ENOSYS = -38; + private static final int EUSERS = -87; + private static final int EOPNOTSUPP = -95; + /* ### QC ADD-ONS: START */ + private CameraDataCallback mCameraDataCallback; + private CameraMetaDataCallback mCameraMetaDataCallback; + /* ### QC ADD-ONS: END */ /** * Broadcast Action: A new picture is taken by the camera, and the entry of @@ -279,7 +296,35 @@ public class Camera { * @return total number of accessible camera devices, or 0 if there are no * cameras or an error was encountered enumerating them. */ - public native static int getNumberOfCameras(); + public static int getNumberOfCameras() { + boolean exposeAuxCamera = false; + String packageName = ActivityThread.currentOpPackageName(); + /* Force to expose only two cameras + * if the package name does not falls in this bucket + */ + String packageList = SystemProperties.get("vendor.camera.aux.packagelist"); + if (packageList.length() > 0) { + TextUtils.StringSplitter splitter = new TextUtils.SimpleStringSplitter(','); + splitter.setString(packageList); + for (String str : splitter) { + if (packageName.equals(str)) { + exposeAuxCamera = true; + break; + } + } + } + int numberOfCameras = _getNumberOfCameras(); + if (exposeAuxCamera == false && (numberOfCameras > 2)) { + numberOfCameras = 2; + } + return numberOfCameras; + } + + /** + * Returns the number of physical cameras available on this device. + */ + /** @hide */ + public native static int _getNumberOfCameras(); /** * Returns the information about a particular camera. @@ -290,6 +335,9 @@ public class Camera { * low-level failure). */ public static void getCameraInfo(int cameraId, CameraInfo cameraInfo) { + if(cameraId >= getNumberOfCameras()){ + throw new RuntimeException("Unknown camera ID"); + } _getCameraInfo(cameraId, cameraInfo); IBinder b = ServiceManager.getService(Context.AUDIO_SERVICE); IAudioService audioService = IAudioService.Stub.asInterface(b); @@ -323,6 +371,17 @@ public class Camera { */ public static final int CAMERA_FACING_FRONT = 1; + /* ### QC ADD-ONS: START TBD*/ + /** @hide + * camera is in ZSL mode. + */ + public static final int CAMERA_SUPPORT_MODE_ZSL = 2; + + /** @hide + * camera is in non-ZSL mode. + */ + public static final int CAMERA_SUPPORT_MODE_NONZSL = 3; + /* ### QC ADD-ONS: END */ /** * The direction that the camera faces. It should be * CAMERA_FACING_BACK or CAMERA_FACING_FRONT. @@ -474,6 +533,10 @@ public class Camera { mPostviewCallback = null; mUsingPreviewAllocation = false; mZoomListener = null; + /* ### QC ADD-ONS: START */ + mCameraDataCallback = null; + mCameraMetaDataCallback = null; + /* ### QC ADD-ONS: END */ Looper looper; if ((looper = Looper.myLooper()) != null) { @@ -490,6 +553,9 @@ public class Camera { /** used by Camera#open, Camera#open(int) */ Camera(int cameraId) { + if(cameraId >= getNumberOfCameras()){ + throw new RuntimeException("Unknown camera ID"); + } int err = cameraInit(cameraId); if (checkInitErrors(err)) { if (err == -EACCES) { @@ -814,6 +880,7 @@ public class Camera { * @see android.media.MediaActionSound */ public final void setPreviewCallback(PreviewCallback cb) { + android.util.SeempLog.record(66); mPreviewCallback = cb; mOneShot = false; mWithBuffer = false; @@ -842,6 +909,7 @@ public class Camera { * @see android.media.MediaActionSound */ public final void setOneShotPreviewCallback(PreviewCallback cb) { + android.util.SeempLog.record(68); mPreviewCallback = cb; mOneShot = true; mWithBuffer = false; @@ -882,6 +950,7 @@ public class Camera { * @see android.media.MediaActionSound */ public final void setPreviewCallbackWithBuffer(PreviewCallback cb) { + android.util.SeempLog.record(67); mPreviewCallback = cb; mOneShot = false; mWithBuffer = true; @@ -1213,7 +1282,23 @@ public class Camera { mAutoFocusMoveCallback.onAutoFocusMoving(msg.arg1 == 0 ? false : true, mCamera); } return; + /* ### QC ADD-ONS: START */ + case CAMERA_MSG_STATS_DATA: + int statsdata[] = new int[257]; + for(int i =0; i<257; i++ ) { + statsdata[i] = byteToInt( (byte[])msg.obj, i*4); + } + if (mCameraDataCallback != null) { + mCameraDataCallback.onCameraData(statsdata, mCamera); + } + return; + case CAMERA_MSG_META_DATA: + if (mCameraMetaDataCallback != null) { + mCameraMetaDataCallback.onCameraMetaData((byte[])msg.obj, mCamera); + } + return; + /* ### QC ADD-ONS: END */ default: Log.e(TAG, "Unknown message type " + msg.what); return; @@ -1447,6 +1532,7 @@ public class Camera { */ public final void takePicture(ShutterCallback shutter, PictureCallback raw, PictureCallback jpeg) { + android.util.SeempLog.record(65); takePicture(shutter, raw, null, jpeg); } private native final void native_takePicture(int msgType); @@ -1485,6 +1571,7 @@ public class Camera { */ public final void takePicture(ShutterCallback shutter, PictureCallback raw, PictureCallback postview, PictureCallback jpeg) { + android.util.SeempLog.record(65); mShutterCallback = shutter; mRawImageCallback = raw; mPostviewCallback = postview; @@ -1954,6 +2041,23 @@ public class Camera { * as a set. Either they are all valid, or none of them are. */ public Point mouth = null; + + /** + * {@hide} + */ + public int smileDegree = 0; + /** + * {@hide} + */ + public int smileScore = 0; + /** + * {@hide} + */ + public int blinkDetected = 0; + /** + * {@hide} + */ + public int faceRecognised = 0; } /** @@ -2078,6 +2182,27 @@ public class Camera { return p; } + /** @hide + * Returns the current cct value of white balance. + * + * If it's in AWB mode, cct is determined by stats/awb module. + * + * If it's in Manual WB mode, it actually returns cct value + * set by user via {@link #setParameters(Camera.Parameters)}. + */ + public int getWBCurrentCCT() { + Parameters p = new Parameters(); + String s = native_getParameters(); + p.unflatten(s); + + int cct = 0; + if (p.getWBCurrentCCT() != null) { + cct = Integer.parseInt(p.getWBCurrentCCT()); + } + + return cct; + } + /** * Returns an empty {@link Parameters} for testing purpose. * @@ -2091,6 +2216,157 @@ public class Camera { return camera.new Parameters(); } + /* ### QC ADD-ONS: START */ + private static int byteToInt(byte[] b, int offset) { + int value = 0; + for (int i = 0; i < 4; i++) { + int shift = (4 - 1 - i) * 8; + value += (b[(3-i) + offset] & 0x000000FF) << shift; + } + return value; + } + /** @hide + * Handles the callback for when Camera Data is available. + * data is read from the camera. + */ + public interface CameraDataCallback { + /** + * Callback for when camera data is available. + * + * @param data a int array of the camera data + * @param camera the Camera service object + */ + void onCameraData(int[] data, Camera camera); + }; + + /** @hide + * Set camera histogram mode and registers a callback function to run. + * Only valid after startPreview() has been called. + * + * @param cb the callback to run + */ + public final void setHistogramMode(CameraDataCallback cb) + { + mCameraDataCallback = cb; + native_setHistogramMode(cb!=null); + } + private native final void native_setHistogramMode(boolean mode); + + /** @hide + * Set camera histogram command to send data. + * + */ + public final void sendHistogramData() + { + native_sendHistogramData(); + } + private native final void native_sendHistogramData(); + + /** @hide + * Handles the callback for when Camera Meta Data is available. + * Meta data is read from the camera. + */ + public interface CameraMetaDataCallback { + /** + * Callback for when camera meta data is available. + * + * @param data a byte array of the camera meta data + * @param camera the Camera service object + */ + void onCameraMetaData(byte[] data, Camera camera); + }; + + /** @hide + * Set camera meta data and registers a callback function to run. + * Only valid after startPreview() has been called. + * + * @param cb the callback to run + */ + public final void setMetadataCb(CameraMetaDataCallback cb) + { + mCameraMetaDataCallback = cb; + native_setMetadataCb(cb!=null); + } + private native final void native_setMetadataCb(boolean mode); + + /** @hide + * Set camera face detection command to send meta data. + */ + public final void sendMetaData() + { + native_sendMetaData(); + } + private native final void native_sendMetaData(); + + /** @hide + * Configure longshot mode. Available only in ZSL. + * + * @param enable enable/disable this mode + */ + public final void setLongshot(boolean enable) + { + native_setLongshot(enable); + } + private native final void native_setLongshot(boolean enable); + + /** @hide + * Handles the Touch Co-ordinate. + */ + public class Coordinate { + /** + * Sets the x,y co-ordinates for a touch event + * + * @param x the x co-ordinate (pixels) + * @param y the y co-ordinate (pixels) + */ + public Coordinate(int x, int y) { + xCoordinate = x; + yCoordinate = y; + } + /** + * Compares {@code obj} to this co-ordinate. + * + * @param obj the object to compare this co-ordinate with. + * @return {@code true} if the xCoordinate and yCoordinate of {@code obj} is the + * same as those of this coordinate. {@code false} otherwise. + */ + @Override + public boolean equals(Object obj) { + if (!(obj instanceof Coordinate)) { + return false; + } + Coordinate c = (Coordinate) obj; + return xCoordinate == c.xCoordinate && yCoordinate == c.yCoordinate; + } + + /** x co-ordinate for the touch event*/ + public int xCoordinate; + + /** y co-ordinate for the touch event */ + public int yCoordinate; + }; + + /** @hide + * Returns the current focus position. + * + * If it's in AF mode, it's the lens position after af is done. + * + * If it's in Manual Focus mode, it actually returns the value + * set by user via {@link #setParameters(Camera.Parameters)}. + */ + public int getCurrentFocusPosition() { + Parameters p = new Parameters(); + String s = native_getParameters(); + p.unflatten(s); + + int focus_pos = -1; + if (p.getCurrentFocusPosition() != null) { + focus_pos = Integer.parseInt(p.getCurrentFocusPosition()); + } + return focus_pos; + } + + /* ### QC ADD-ONS: END */ /** * Returns a copied {@link Parameters}; for shim use only. * @@ -2352,6 +2628,10 @@ public class Camera { public static final String WHITE_BALANCE_CLOUDY_DAYLIGHT = "cloudy-daylight"; public static final String WHITE_BALANCE_TWILIGHT = "twilight"; public static final String WHITE_BALANCE_SHADE = "shade"; + /** @hide + * wb manual cct mode. + */ + public static final String WHITE_BALANCE_MANUAL_CCT = "manual-cct"; // Values for color effect settings. public static final String EFFECT_NONE = "none"; @@ -2399,6 +2679,11 @@ public class Camera { */ public static final String FLASH_MODE_TORCH = "torch"; + /** @hide + * Scene mode is off. + */ + public static final String SCENE_MODE_ASD = "asd"; + /** * Scene mode is off. */ @@ -2475,6 +2760,14 @@ public class Camera { * Capture the naturally warm color of scenes lit by candles. */ public static final String SCENE_MODE_CANDLELIGHT = "candlelight"; + /** @hide + * SCENE_MODE_BACKLIGHT + **/ + public static final String SCENE_MODE_BACKLIGHT = "backlight"; + /** @hide + * SCENE_MODE_FLOWERS + **/ + public static final String SCENE_MODE_FLOWERS = "flowers"; /** * Applications are looking for a barcode. Camera driver will be @@ -2517,6 +2810,13 @@ public class Camera { */ public static final String FOCUS_MODE_FIXED = "fixed"; + /** @hide + * Normal focus mode. Applications should call + * {@link #autoFocus(AutoFocusCallback)} to start the focus in this + * mode. + */ + public static final String FOCUS_MODE_NORMAL = "normal"; + /** * Extended depth of field (EDOF). Focusing is done digitally and * continuously. Applications should not call {@link @@ -2569,6 +2869,11 @@ public class Camera { */ public static final String FOCUS_MODE_CONTINUOUS_PICTURE = "continuous-picture"; + /** @hide + * manual focus mode + */ + public static final String FOCUS_MODE_MANUAL_POSITION = "manual"; + // Indices for focus distance array. /** * The array index of near focus distance for use with @@ -2605,11 +2910,15 @@ public class Camera { // Formats for setPreviewFormat and setPictureFormat. private static final String PIXEL_FORMAT_YUV422SP = "yuv422sp"; private static final String PIXEL_FORMAT_YUV420SP = "yuv420sp"; + private static final String PIXEL_FORMAT_YUV420SP_ADRENO = "yuv420sp-adreno"; private static final String PIXEL_FORMAT_YUV422I = "yuv422i-yuyv"; private static final String PIXEL_FORMAT_YUV420P = "yuv420p"; private static final String PIXEL_FORMAT_RGB565 = "rgb565"; private static final String PIXEL_FORMAT_JPEG = "jpeg"; private static final String PIXEL_FORMAT_BAYER_RGGB = "bayer-rggb"; + private static final String PIXEL_FORMAT_RAW = "raw"; + private static final String PIXEL_FORMAT_YV12 = "yv12"; + private static final String PIXEL_FORMAT_NV12 = "nv12"; /** * Order matters: Keys that are {@link #set(String, String) set} later @@ -3429,8 +3738,11 @@ public class Camera { * parameters. */ public void removeGpsData() { + remove(KEY_QC_GPS_LATITUDE_REF); remove(KEY_GPS_LATITUDE); + remove(KEY_QC_GPS_LONGITUDE_REF); remove(KEY_GPS_LONGITUDE); + remove(KEY_QC_GPS_ALTITUDE_REF); remove(KEY_GPS_ALTITUDE); remove(KEY_GPS_TIMESTAMP); remove(KEY_GPS_PROCESSING_METHOD); @@ -4454,5 +4766,1231 @@ public class Camera { if (s1 != null && s1.equals(s2)) return true; return false; } + /* ### QC ADD-ONS: START */ + + /* ### QC ADDED PARAMETER KEYS*/ + private static final String KEY_QC_HFR_SIZE = "hfr-size"; + private static final String KEY_QC_PREVIEW_FRAME_RATE_MODE = "preview-frame-rate-mode"; + private static final String KEY_QC_PREVIEW_FRAME_RATE_AUTO_MODE = "frame-rate-auto"; + private static final String KEY_QC_PREVIEW_FRAME_RATE_FIXED_MODE = "frame-rate-fixed"; + private static final String KEY_QC_GPS_LATITUDE_REF = "gps-latitude-ref"; + private static final String KEY_QC_GPS_LONGITUDE_REF = "gps-longitude-ref"; + private static final String KEY_QC_GPS_ALTITUDE_REF = "gps-altitude-ref"; + private static final String KEY_QC_GPS_STATUS = "gps-status"; + private static final String KEY_QC_EXIF_DATETIME = "exif-datetime"; + private static final String KEY_QC_TOUCH_AF_AEC = "touch-af-aec"; + private static final String KEY_QC_TOUCH_INDEX_AEC = "touch-index-aec"; + private static final String KEY_QC_TOUCH_INDEX_AF = "touch-index-af"; + private static final String KEY_QC_MANUAL_FOCUS_POSITION = "manual-focus-position"; + private static final String KEY_QC_MANUAL_FOCUS_POS_TYPE = "manual-focus-pos-type"; + private static final String KEY_QC_SCENE_DETECT = "scene-detect"; + private static final String KEY_QC_ISO_MODE = "iso"; + private static final String KEY_QC_EXPOSURE_TIME = "exposure-time"; + private static final String KEY_QC_MIN_EXPOSURE_TIME = "min-exposure-time"; + private static final String KEY_QC_MAX_EXPOSURE_TIME = "max-exposure-time"; + private static final String KEY_QC_LENSSHADE = "lensshade"; + private static final String KEY_QC_HISTOGRAM = "histogram"; + private static final String KEY_QC_SKIN_TONE_ENHANCEMENT = "skinToneEnhancement"; + private static final String KEY_QC_AUTO_EXPOSURE = "auto-exposure"; + private static final String KEY_QC_SHARPNESS = "sharpness"; + private static final String KEY_QC_MAX_SHARPNESS = "max-sharpness"; + private static final String KEY_QC_CONTRAST = "contrast"; + private static final String KEY_QC_MAX_CONTRAST = "max-contrast"; + private static final String KEY_QC_SATURATION = "saturation"; + private static final String KEY_QC_MAX_SATURATION = "max-saturation"; + private static final String KEY_QC_DENOISE = "denoise"; + private static final String KEY_QC_CONTINUOUS_AF = "continuous-af"; + private static final String KEY_QC_SELECTABLE_ZONE_AF = "selectable-zone-af"; + private static final String KEY_QC_FACE_DETECTION = "face-detection"; + private static final String KEY_QC_MEMORY_COLOR_ENHANCEMENT = "mce"; + private static final String KEY_QC_REDEYE_REDUCTION = "redeye-reduction"; + private static final String KEY_QC_ZSL = "zsl"; + private static final String KEY_QC_CAMERA_MODE = "camera-mode"; + private static final String KEY_QC_VIDEO_HIGH_FRAME_RATE = "video-hfr"; + private static final String KEY_QC_VIDEO_HDR = "video-hdr"; + private static final String KEY_QC_POWER_MODE = "power-mode"; + private static final String KEY_QC_POWER_MODE_SUPPORTED = "power-mode-supported"; + private static final String KEY_QC_WB_MANUAL_CCT = "wb-manual-cct"; + private static final String KEY_QC_MIN_WB_CCT = "min-wb-cct"; + private static final String KEY_QC_MAX_WB_CCT = "max-wb-cct"; + private static final String KEY_QC_AUTO_HDR_ENABLE = "auto-hdr-enable"; + private static final String KEY_QC_VIDEO_ROTATION = "video-rotation"; + + /** @hide + * KEY_QC_AE_BRACKET_HDR + **/ + public static final String KEY_QC_AE_BRACKET_HDR = "ae-bracket-hdr"; + + /* ### QC ADDED PARAMETER VALUES*/ + + // Values for touch af/aec settings. + /** @hide + * TOUCH_AF_AEC_OFF + **/ + public static final String TOUCH_AF_AEC_OFF = "touch-off"; + /** @hide + * TOUCH_AF_AEC_ON + **/ + public static final String TOUCH_AF_AEC_ON = "touch-on"; + + // Values for auto exposure settings. + /** @hide + * Auto exposure frame-avg + **/ + public static final String AUTO_EXPOSURE_FRAME_AVG = "frame-average"; + /** @hide + * Auto exposure center weighted + **/ + public static final String AUTO_EXPOSURE_CENTER_WEIGHTED = "center-weighted"; + /** @hide + * Auto exposure spot metering + **/ + public static final String AUTO_EXPOSURE_SPOT_METERING = "spot-metering"; + + //Values for ISO settings + /** @hide + * ISO_AUTO + **/ + public static final String ISO_AUTO = "auto"; + /** @hide + * ISO_HJR + **/ + public static final String ISO_HJR = "ISO_HJR"; + /** @hide + * ISO_100 + **/ + public static final String ISO_100 = "ISO100"; + /** @hide + * ISO_200 + **/ + public static final String ISO_200 = "ISO200"; + /** @hide + * ISO_400 + **/ + public static final String ISO_400 = "ISO400"; + /** @hide + * ISO_800 + **/ + public static final String ISO_800 = "ISO800"; + /** @hide + * ISO_1600 + **/ + public static final String ISO_1600 = "ISO1600"; + + /** @hide + * ISO_3200 + **/ + public static final String ISO_3200 = "ISO3200"; + + //Values for Lens Shading + /** @hide + * LENSSHADE_ENABLE + **/ + public static final String LENSSHADE_ENABLE = "enable"; + /** @hide + * LENSSHADE_DISABLE + **/ + public static final String LENSSHADE_DISABLE= "disable"; + + //Values for Histogram + /** @hide + * Histogram enable + **/ + public static final String HISTOGRAM_ENABLE = "enable"; + /** @hide + * Histogram disable + **/ + public static final String HISTOGRAM_DISABLE= "disable"; + + //Values for Skin Tone Enhancement + /** @hide + * SKIN_TONE_ENHANCEMENT_ENABLE + **/ + public static final String SKIN_TONE_ENHANCEMENT_ENABLE = "enable"; + /** @hide + * SKIN_TONE_ENHANCEMENT_DISABLE + **/ + public static final String SKIN_TONE_ENHANCEMENT_DISABLE= "disable"; + + // Values for MCE settings. + /** @hide + * MCE_ENaBLE + **/ + public static final String MCE_ENABLE = "enable"; + /** @hide + * MCE_DISABLE + **/ + public static final String MCE_DISABLE = "disable"; + + // Values for ZSL settings. + /** @hide + * ZSL_ON + **/ + public static final String ZSL_ON = "on"; + /** @hide + * ZSL_OFF + **/ + public static final String ZSL_OFF = "off"; + + // Values for HDR Bracketing settings. + + /** @hide + * AEC bracketing off + **/ + public static final String AE_BRACKET_HDR_OFF = "Off"; + /** @hide + * AEC bracketing hdr + **/ + public static final String AE_BRACKET_HDR = "HDR"; + /** @hide + * AEC bracketing aec-bracket + **/ + public static final String AE_BRACKET = "AE-Bracket"; + + // Values for Power mode. + /** @hide + * LOW_POWER + **/ + public static final String LOW_POWER = "Low_Power"; + /** @hide + * NORMAL_POWER + **/ + public static final String NORMAL_POWER = "Normal_Power"; + + // Values for HFR settings. + /** @hide + * VIDEO_HFR_OFF + **/ + public static final String VIDEO_HFR_OFF = "off"; + /** @hide + * VIDEO_HFR_2X + **/ + public static final String VIDEO_HFR_2X = "60"; + /** @hide + * VIDEO_HFR_3X + **/ + public static final String VIDEO_HFR_3X = "90"; + /** @hide + * VIDEO_HFR_4X + **/ + public static final String VIDEO_HFR_4X = "120"; + + // Values for auto scene detection settings. + /** @hide + * SCENE_DETECT_OFF + **/ + public static final String SCENE_DETECT_OFF = "off"; + /** @hide + * SCENE_DETECT_ON + **/ + public static final String SCENE_DETECT_ON = "on"; + + //Values for Continuous AF + + /** @hide + * CAF off + **/ + public static final String CONTINUOUS_AF_OFF = "caf-off"; + /** @hide + * CAF on + **/ + public static final String CONTINUOUS_AF_ON = "caf-on"; + /** @hide + * Denoise off + **/ + public static final String DENOISE_OFF = "denoise-off"; + /** @hide + * Denoise on + **/ + public static final String DENOISE_ON = "denoise-on"; + + // Values for Redeye Reduction settings. + /** @hide + * REDEYE_REDUCTION_ENABLE + **/ + public static final String REDEYE_REDUCTION_ENABLE = "enable"; + /** @hide + * REDEYE_REDUCTION_DISABLE + **/ + public static final String REDEYE_REDUCTION_DISABLE = "disable"; + + // Values for selectable zone af settings. + /** @hide + * SELECTABLE_ZONE_AF_AUTO + **/ + public static final String SELECTABLE_ZONE_AF_AUTO = "auto"; + /** @hide + * SELECTABLE_ZONE_AF_SPOTMETERING + **/ + public static final String SELECTABLE_ZONE_AF_SPOTMETERING = "spot-metering"; + /** @hide + * SELECTABLE_ZONE_AF_CENTER_WEIGHTED + **/ + public static final String SELECTABLE_ZONE_AF_CENTER_WEIGHTED = "center-weighted"; + /** @hide + * SELECTABLE_ZONE_AF_FRAME_AVERAGE + **/ + public static final String SELECTABLE_ZONE_AF_FRAME_AVERAGE = "frame-average"; + + // Values for Face Detection settings. + /** @hide + * Face Detection off + **/ + public static final String FACE_DETECTION_OFF = "off"; + /** @hide + * Face Detction on + **/ + public static final String FACE_DETECTION_ON = "on"; + + // Values for video rotation settings. + + /** @hide + * VIDEO_ROTATION_0 + **/ + public static final String VIDEO_ROTATION_0 = "0"; + /** @hide + * VIDEO_ROTATION_90 + **/ + public static final String VIDEO_ROTATION_90 = "90"; + /** @hide + * VIDEO_ROTATION_180 + **/ + public static final String VIDEO_ROTATION_180 = "180"; + /** @hide + * VIDEO_ROTATION_270 + **/ + public static final String VIDEO_ROTATION_270 = "270"; + + /* ### QC ADDED PARAMETER APIS*/ + /** @hide + * Gets the supported preview sizes in high frame rate recording mode. + * + * @return a list of Size object. This method will always return a list + * with at least one element. + */ + public List<Size> getSupportedHfrSizes() { + String str = get(KEY_QC_HFR_SIZE + SUPPORTED_VALUES_SUFFIX); + return splitSize(str); + } + + /** @hide + * Gets the supported Touch AF/AEC setting. + * + * @return a List of TOUCH_AF_AEC_XXX string constants. null if TOUCH AF/AEC + * setting is not supported. + * + */ + public List<String> getSupportedTouchAfAec() { + String str = get(KEY_QC_TOUCH_AF_AEC + SUPPORTED_VALUES_SUFFIX); + return split(str); + } + + /** + * Gets the supported Touch AF/AEC setting. + * + * @return a List of TOUCH_AF_AEC_XXX string constants. null if TOUCH AF/AEC + * setting is not supported. + * + */ + + /** @hide + * Gets the supported frame rate modes. + * + * @return a List of FRAME_RATE_XXX_MODE string constant. null if this + * setting is not supported. + */ + public List<String> getSupportedPreviewFrameRateModes() { + String str = get(KEY_QC_PREVIEW_FRAME_RATE_MODE + SUPPORTED_VALUES_SUFFIX); + return split(str); + } + + /** @hide + * Gets the supported auto scene detection modes. + * + * @return a List of SCENE_DETECT_XXX string constant. null if scene detection + * setting is not supported. + * + */ + public List<String> getSupportedSceneDetectModes() { + String str = get(KEY_QC_SCENE_DETECT + SUPPORTED_VALUES_SUFFIX); + return split(str); + } + + /** @hide + * Gets the supported ISO values. + * + * @return a List of FLASH_MODE_XXX string constants. null if flash mode + * setting is not supported. + */ + public List<String> getSupportedIsoValues() { + String str = get(KEY_QC_ISO_MODE + SUPPORTED_VALUES_SUFFIX); + return split(str); + } + + /** @hide + * Gets the supported Lensshade modes. + * + * @return a List of LENS_MODE_XXX string constants. null if lens mode + * setting is not supported. + */ + public List<String> getSupportedLensShadeModes() { + String str = get(KEY_QC_LENSSHADE + SUPPORTED_VALUES_SUFFIX); + return split(str); + } + + /** @hide + * Gets the supported Histogram modes. + * + * @return a List of HISTOGRAM_XXX string constants. null if histogram mode + * setting is not supported. + */ + public List<String> getSupportedHistogramModes() { + String str = get(KEY_QC_HISTOGRAM + SUPPORTED_VALUES_SUFFIX); + return split(str); + } + + /** @hide + * Gets the supported Skin Tone Enhancement modes. + * + * @return a List of SKIN_TONE_ENHANCEMENT_XXX string constants. null if skin tone enhancement + * setting is not supported. + */ + public List<String> getSupportedSkinToneEnhancementModes() { + String str = get(KEY_QC_SKIN_TONE_ENHANCEMENT + SUPPORTED_VALUES_SUFFIX); + return split(str); + } + + /** @hide + * Gets the supported auto exposure setting. + * + * @return a List of AUTO_EXPOSURE_XXX string constants. null if auto exposure + * setting is not supported. + */ + public List<String> getSupportedAutoexposure() { + String str = get(KEY_QC_AUTO_EXPOSURE + SUPPORTED_VALUES_SUFFIX); + return split(str); + } + + /** @hide + * Gets the supported MCE modes. + * + * @return a List of MCE_ENABLE/DISABLE string constants. null if MCE mode + * setting is not supported. + */ + public List<String> getSupportedMemColorEnhanceModes() { + String str = get(KEY_QC_MEMORY_COLOR_ENHANCEMENT + SUPPORTED_VALUES_SUFFIX); + return split(str); + } + + /** @hide + * Gets the supported ZSL modes. + * + * @return a List of ZSL_OFF/OFF string constants. null if ZSL mode + * setting is not supported. + */ + public List<String> getSupportedZSLModes() { + String str = get(KEY_QC_ZSL + SUPPORTED_VALUES_SUFFIX); + return split(str); + } + + /** @hide + * Gets the supported Video HDR modes. + * + * @return a List of Video HDR_OFF/OFF string constants. null if + * Video HDR mode setting is not supported. + */ + public List<String> getSupportedVideoHDRModes() { + String str = get(KEY_QC_VIDEO_HDR + SUPPORTED_VALUES_SUFFIX); + return split(str); + } + + /** @hide + * Gets the supported HFR modes. + * + * @return a List of VIDEO_HFR_XXX string constants. null if hfr mode + * setting is not supported. + */ + public List<String> getSupportedVideoHighFrameRateModes() { + String str = get(KEY_QC_VIDEO_HIGH_FRAME_RATE + SUPPORTED_VALUES_SUFFIX); + return split(str); + } + + /** @hide + * Gets the supported Continuous AF modes. + * + * @return a List of CONTINUOUS_AF_XXX string constant. null if continuous AF + * setting is not supported. + * + */ + public List<String> getSupportedContinuousAfModes() { + String str = get(KEY_QC_CONTINUOUS_AF + SUPPORTED_VALUES_SUFFIX); + return split(str); + } + + /** @hide + * Gets the supported DENOISE modes. + * + * @return a List of DENOISE_XXX string constant. null if DENOISE + * setting is not supported. + * + */ + public List<String> getSupportedDenoiseModes() { + String str = get(KEY_QC_DENOISE + SUPPORTED_VALUES_SUFFIX); + return split(str); + } + + /** @hide + * Gets the supported selectable zone af setting. + * + * @return a List of SELECTABLE_ZONE_AF_XXX string constants. null if selectable zone af + * setting is not supported. + */ + public List<String> getSupportedSelectableZoneAf() { + String str = get(KEY_QC_SELECTABLE_ZONE_AF + SUPPORTED_VALUES_SUFFIX); + return split(str); + } + + /** @hide + * Gets the supported face detection modes. + * + * @return a List of FACE_DETECTION_XXX string constant. null if face detection + * setting is not supported. + * + */ + public List<String> getSupportedFaceDetectionModes() { + String str = get(KEY_QC_FACE_DETECTION + SUPPORTED_VALUES_SUFFIX); + return split(str); + } + + /** @hide + * Gets the supported redeye reduction modes. + * + * @return a List of REDEYE_REDUCTION_XXX string constant. null if redeye reduction + * setting is not supported. + * + */ + public List<String> getSupportedRedeyeReductionModes() { + String str = get(KEY_QC_REDEYE_REDUCTION + SUPPORTED_VALUES_SUFFIX); + return split(str); + } + + /** @hide + * Sets GPS altitude reference. This will be stored in JPEG EXIF header. + * @param altRef reference GPS altitude in meters. + */ + public void setGpsAltitudeRef(double altRef) { + set(KEY_QC_GPS_ALTITUDE_REF, Double.toString(altRef)); + } + + /** @hide + * Sets GPS Status. This will be stored in JPEG EXIF header. + * + * @param status GPS status (UTC in seconds since January 1, + * 1970). + */ + public void setGpsStatus(double status) { + set(KEY_QC_GPS_STATUS, Double.toString(status)); + } + + /** @hide + * Sets the touch co-ordinate for Touch AEC. + * + * @param x the x co-ordinate of the touch event + * @param y the y co-ordinate of the touch event + * + */ + public void setTouchIndexAec(int x, int y) { + String v = Integer.toString(x) + "x" + Integer.toString(y); + set(KEY_QC_TOUCH_INDEX_AEC, v); + } + + /** @hide + * Returns the touch co-ordinates of the touch event. + * + * @return a Index object with the x and y co-ordinated + * for the touch event + * + */ + public Coordinate getTouchIndexAec() { + String pair = get(KEY_QC_TOUCH_INDEX_AEC); + return strToCoordinate(pair); + } + + /** @hide + * Sets the touch co-ordinate for Touch AF. + * + * @param x the x co-ordinate of the touch event + * @param y the y co-ordinate of the touch event + * + */ + public void setTouchIndexAf(int x, int y) { + String v = Integer.toString(x) + "x" + Integer.toString(y); + set(KEY_QC_TOUCH_INDEX_AF, v); + } + + /** @hide + * Returns the touch co-ordinates of the touch event. + * + * @return a Index object with the x and y co-ordinated + * for the touch event + * + */ + public Coordinate getTouchIndexAf() { + String pair = get(KEY_QC_TOUCH_INDEX_AF); + return strToCoordinate(pair); + } + /** @hide + * Set Sharpness Level + * + * @param sharpness level + */ + public void setSharpness(int sharpness){ + if((sharpness < 0) || (sharpness > getMaxSharpness()) ) + throw new IllegalArgumentException( + "Invalid Sharpness " + sharpness); + + set(KEY_QC_SHARPNESS, String.valueOf(sharpness)); + } + + /** @hide + * Set Contrast Level + * + * @param contrast level + */ + public void setContrast(int contrast){ + if((contrast < 0 ) || (contrast > getMaxContrast())) + throw new IllegalArgumentException( + "Invalid Contrast " + contrast); + + set(KEY_QC_CONTRAST, String.valueOf(contrast)); + } + + /** @hide + * Set Saturation Level + * + * @param saturation level + */ + public void setSaturation(int saturation){ + if((saturation < 0 ) || (saturation > getMaxSaturation())) + throw new IllegalArgumentException( + "Invalid Saturation " + saturation); + + set(KEY_QC_SATURATION, String.valueOf(saturation)); + } + + /** @hide + * @return true if full size video snapshot is supported. + */ + public boolean isPowerModeSupported() { + String str = get(KEY_QC_POWER_MODE_SUPPORTED); + return TRUE.equals(str); + } + + /** @hide + * Get Sharpness level + * + * @return sharpness level + */ + public int getSharpness(){ + return getInt(KEY_QC_SHARPNESS); + } + + /** @hide + * Get Max Sharpness Level + * + * @return max sharpness level + */ + public int getMaxSharpness(){ + return getInt(KEY_QC_MAX_SHARPNESS); + } + + /** @hide + * Get Contrast level + * + * @return contrast level + */ + public int getContrast(){ + return getInt(KEY_QC_CONTRAST); + } + + /** @hide + * Get Max Contrast Level + * + * @return max contrast level + */ + public int getMaxContrast(){ + return getInt(KEY_QC_MAX_CONTRAST); + } + + /** @hide + * Get Saturation level + * + * @return saturation level + */ + public int getSaturation(){ + return getInt(KEY_QC_SATURATION); + } + + /** @hide + * Get Max Saturation Level + * + * @return max contrast level + */ + public int getMaxSaturation(){ + return getInt(KEY_QC_MAX_SATURATION); + } + + /** @hide + * Sets GPS latitude reference coordinate. This will be stored in JPEG EXIF + * header. + * @param latRef GPS latitude reference coordinate. + */ + public void setGpsLatitudeRef(String latRef) { + set(KEY_QC_GPS_LATITUDE_REF, latRef); + } + + /** @hide + * Sets GPS longitude reference coordinate. This will be stored in JPEG EXIF + * header. + * @param lonRef GPS longitude reference coordinate. + */ + public void setGpsLongitudeRef(String lonRef) { + set(KEY_QC_GPS_LONGITUDE_REF, lonRef); + } + + /** @hide + * Sets system timestamp. This will be stored in JPEG EXIF header. + * + * @param dateTime current timestamp (UTC in seconds since January 1, + * 1970). + */ + public void setExifDateTime(String dateTime) { + set(KEY_QC_EXIF_DATETIME, dateTime); + } + + /** @hide + * Gets the current Touch AF/AEC setting. + * + * @return one of TOUCH_AF_AEC_XXX string constant. null if Touch AF/AEC + * setting is not supported. + * + */ + public String getTouchAfAec() { + return get(KEY_QC_TOUCH_AF_AEC); + } + + /** @hide + * Sets the current TOUCH AF/AEC setting. + * + * @param value TOUCH_AF_AEC_XXX string constants. + * + */ + public void setTouchAfAec(String value) { + set(KEY_QC_TOUCH_AF_AEC, value); + } + + /** @hide + * Gets the current redeye reduction setting. + * + * @return one of REDEYE_REDUCTION_XXX string constant. null if redeye reduction + * setting is not supported. + * + */ + public String getRedeyeReductionMode() { + return get(KEY_QC_REDEYE_REDUCTION); + } + + /** @hide + * Sets the redeye reduction. Other parameters may be changed after changing + * redeye reduction. After setting redeye reduction, + * applications should call getParameters to know if some parameters are + * changed. + * + * @param value REDEYE_REDUCTION_XXX string constants. + * + */ + public void setRedeyeReductionMode(String value) { + set(KEY_QC_REDEYE_REDUCTION, value); + } + + /** @hide + * Gets the frame rate mode setting. + * + * @return one of FRAME_RATE_XXX_MODE string constant. null if this + * setting is not supported. + */ + public String getPreviewFrameRateMode() { + return get(KEY_QC_PREVIEW_FRAME_RATE_MODE); + } + + /** @hide + * Sets the frame rate mode. + * + * @param value FRAME_RATE_XXX_MODE string constants. + */ + public void setPreviewFrameRateMode(String value) { + set(KEY_QC_PREVIEW_FRAME_RATE_MODE, value); + } + + /** @hide + * Gets the current auto scene detection setting. + * + * @return one of SCENE_DETECT_XXX string constant. null if auto scene detection + * setting is not supported. + * + */ + public String getSceneDetectMode() { + return get(KEY_QC_SCENE_DETECT); + } + + /** @hide + * Sets the auto scene detect. Other parameters may be changed after changing + * scene detect. After setting auto scene detection, + * applications should call getParameters to know if some parameters are + * changed. + * + * @param value SCENE_DETECT_XXX string constants. + * + */ + public void setSceneDetectMode(String value) { + set(KEY_QC_SCENE_DETECT, value); + } + + /** @hide + * Gets the current hdr bracketing mode setting. + * + * @return current hdr bracketing mode. + * @see #KEY_AE_BRACKET_OFF + * @see #KEY_AE_BRACKET_HDR + * @see #KEY_AE_BRACKET_BRACKATING + */ + public String getAEBracket() { + return get(KEY_QC_AE_BRACKET_HDR); + } + + /** @hide + * Sets the Power mode. + * + * @param value Power mode. + * @see #getPowerMode() + */ + public void setPowerMode(String value) { + set(KEY_QC_POWER_MODE, value); + } + + /** @hide + * Gets the current power mode setting. + * + * @return current power mode. null if power mode setting is not + * supported. + * @see #POWER_MODE_LOW + * @see #POWER_MODE_NORMAL + */ + public String getPowerMode() { + return get(KEY_QC_POWER_MODE); + } + + /** @hide + * Set HDR-Bracketing Level + * + * @param value HDR-Bracketing + */ + public void setAEBracket(String value){ + set(KEY_QC_AE_BRACKET_HDR, value); + } + + /** @hide + * Gets the current ISO setting. + * + * @return one of ISO_XXX string constant. null if ISO + * setting is not supported. + */ + public String getISOValue() { + return get(KEY_QC_ISO_MODE); + } + + /** @hide + * Sets the ISO. + * + * @param iso ISO_XXX string constant. + */ + public void setISOValue(String iso) { + set(KEY_QC_ISO_MODE, iso); + } + + /** @hide + * Sets the exposure time. + * + * @param value exposure time. + */ + public void setExposureTime(int value) { + set(KEY_QC_EXPOSURE_TIME, Integer.toString(value)); + } + + /** @hide + * Gets the current exposure time. + * + * @return exposure time. + */ + public String getExposureTime() { + return get(KEY_QC_EXPOSURE_TIME); + } + + /** @hide + * Gets the min supported exposure time. + * + * @return min supported exposure time. + */ + public String getMinExposureTime() { + return get(KEY_QC_MIN_EXPOSURE_TIME); + } + + /** @hide + * Gets the max supported exposure time. + * + * @return max supported exposure time. + */ + public String getMaxExposureTime() { + return get(KEY_QC_MAX_EXPOSURE_TIME); + } + + /** @hide + * Gets the current LensShade Mode. + * + * @return LensShade Mode + */ + public String getLensShade() { + return get(KEY_QC_LENSSHADE); + } + + /** @hide + * Sets the current LensShade Mode. + * + * @return LensShade Mode + */ + public void setLensShade(String lensshade) { + set(KEY_QC_LENSSHADE, lensshade); + } + + /** @hide + * Gets the current auto exposure setting. + * + * @return one of AUTO_EXPOSURE_XXX string constant. null if auto exposure + * setting is not supported. + */ + public String getAutoExposure() { + return get(KEY_QC_AUTO_EXPOSURE); + } + + /** @hide + * Sets the current auto exposure setting. + * + * @param value AUTO_EXPOSURE_XXX string constants. + */ + public void setAutoExposure(String value) { + set(KEY_QC_AUTO_EXPOSURE, value); + } + + /** @hide + * Gets the current MCE Mode. + * + * @return MCE value + */ + public String getMemColorEnhance() { + return get(KEY_QC_MEMORY_COLOR_ENHANCEMENT); + } + + /** @hide + * Sets the current MCE Mode. + * + * @return MCE Mode + */ + public void setMemColorEnhance(String mce) { + set(KEY_QC_MEMORY_COLOR_ENHANCEMENT, mce); + } + + /** @hide + * Set white balance manual cct value. + * + * @param cct user CCT setting. + */ + public void setWBManualCCT(int cct) { + set(KEY_QC_WB_MANUAL_CCT, Integer.toString(cct)); + } + + /** @hide + * Gets the WB min supported CCT. + * + * @return min cct value. + */ + public String getWBMinCCT() { + return get(KEY_QC_MIN_WB_CCT); + } + + /** @hide + * Gets the WB max supported CCT. + * + * @return max cct value. + */ + public String getMaxWBCCT() { + return get(KEY_QC_MAX_WB_CCT); + } + + /** @hide + * Gets the current WB CCT. + * + * @return CCT value + */ + public String getWBCurrentCCT() { + return get(KEY_QC_WB_MANUAL_CCT); + } + + /** @hide + * Gets the current ZSL Mode. + * + * @return ZSL mode value + */ + public String getZSLMode() { + return get(KEY_QC_ZSL); + } + + /** @hide + * Sets the current ZSL Mode. ZSL mode is set as a 0th bit in KEY_CAMERA_MODE. + * + * @return null + */ + public void setZSLMode(String zsl) { + set(KEY_QC_ZSL, zsl); + } + + /** @hide + * Sets the current Auto HDR Mode. + * @ auto_hdr auto hdr string for enable/disable + * @return null + */ + public void setAutoHDRMode(String auto_hdr){ + set(KEY_QC_AUTO_HDR_ENABLE,auto_hdr); + } + + /** @hide + * Gets the current Camera Mode Flag. Camera mode includes a + * flag(byte) which indicates different camera modes. + * For now support for ZSL added at bit0 + * + * @return Camera Mode. + */ + public String getCameraMode() { + return get(KEY_QC_CAMERA_MODE); + } + + /** @hide + * Sets the current Camera Mode. + * + * @return null + */ + public void setCameraMode(int cameraMode) { + set(KEY_QC_CAMERA_MODE, cameraMode); + } + + private static final int MANUAL_FOCUS_POS_TYPE_INDEX = 0; + private static final int MANUAL_FOCUS_POS_TYPE_DAC = 1; + /** @hide + * Set focus position. + * + * @param pos user setting of focus position. + */ + public void setFocusPosition(int type, int pos) { + set(KEY_QC_MANUAL_FOCUS_POS_TYPE, Integer.toString(type)); + set(KEY_QC_MANUAL_FOCUS_POSITION, Integer.toString(pos)); + } + + /** @hide + * Gets the current focus position. + * + * @return current focus position + */ + public String getCurrentFocusPosition() { + return get(KEY_QC_MANUAL_FOCUS_POSITION); + } + + + /** @hide + * Gets the current HFR Mode. + * + * @return VIDEO_HFR_XXX string constants + */ + public String getVideoHighFrameRate() { + return get(KEY_QC_VIDEO_HIGH_FRAME_RATE); + } + + /** @hide + * Sets the current HFR Mode. + * + * @param hfr VIDEO_HFR_XXX string constants + */ + public void setVideoHighFrameRate(String hfr) { + set(KEY_QC_VIDEO_HIGH_FRAME_RATE, hfr); + } + + /** @hide + * Gets the current Video HDR Mode. + * + * @return Video HDR mode value + */ + public String getVideoHDRMode() { + return get(KEY_QC_VIDEO_HDR); + } + + /** @hide + * Sets the current Video HDR Mode. + * + * @return null + */ + public void setVideoHDRMode(String videohdr) { + set(KEY_QC_VIDEO_HDR, videohdr); + } + + /** @hide + * Gets the current DENOISE setting. + * + * @return one of DENOISE_XXX string constant. null if Denoise + * setting is not supported. + * + */ + public String getDenoise() { + return get(KEY_QC_DENOISE); + } + + /** @hide + * Gets the current Continuous AF setting. + * + * @return one of CONTINUOUS_AF_XXX string constant. null if continuous AF + * setting is not supported. + * + */ + public String getContinuousAf() { + return get(KEY_QC_CONTINUOUS_AF); + } + + /** @hide + * Sets the current Denoise mode. + * @param value DENOISE_XXX string constants. + * + */ + + public void setDenoise(String value) { + set(KEY_QC_DENOISE, value); + } + + /** @hide + * Sets the current Continuous AF mode. + * @param value CONTINUOUS_AF_XXX string constants. + * + */ + public void setContinuousAf(String value) { + set(KEY_QC_CONTINUOUS_AF, value); + } + + /** @hide + * Gets the current selectable zone af setting. + * + * @return one of SELECTABLE_ZONE_AF_XXX string constant. null if selectable zone af + * setting is not supported. + */ + public String getSelectableZoneAf() { + return get(KEY_QC_SELECTABLE_ZONE_AF); + } + + /** @hide + * Sets the current selectable zone af setting. + * + * @param value SELECTABLE_ZONE_AF_XXX string constants. + */ + public void setSelectableZoneAf(String value) { + set(KEY_QC_SELECTABLE_ZONE_AF, value); + } + + /** @hide + * Gets the current face detection setting. + * + * @return one of FACE_DETECTION_XXX string constant. null if face detection + * setting is not supported. + * + */ + public String getFaceDetectionMode() { + return get(KEY_QC_FACE_DETECTION); + } + + /** @hide + * Sets the auto scene detect. Other settings like Touch AF/AEC might be + * changed after setting face detection. + * + * @param value FACE_DETECTION_XXX string constants. + * + */ + public void setFaceDetectionMode(String value) { + set(KEY_QC_FACE_DETECTION, value); + } + + /** @hide + * Gets the current video rotation setting. + * + * @return one of VIDEO_QC_ROTATION_XXX string constant. null if video rotation + * setting is not supported. + */ + public String getVideoRotation() { + return get(KEY_QC_VIDEO_ROTATION); + } + + /** @hide + * Sets the current video rotation setting. + * + * @param value VIDEO_QC_ROTATION_XXX string constants. + */ + public void setVideoRotation(String value) { + set(KEY_QC_VIDEO_ROTATION, value); + } + /** @hide + * Gets the supported video rotation modes. + * + * @return a List of VIDEO_QC_ROTATION_XXX string constant. null if this + * setting is not supported. + */ + public List<String> getSupportedVideoRotationValues() { + String str = get(KEY_QC_VIDEO_ROTATION + SUPPORTED_VALUES_SUFFIX); + return split(str); + } + + // Splits a comma delimited string to an ArrayList of Coordinate. + // Return null if the passing string is null or the Coordinate is 0. + private ArrayList<Coordinate> splitCoordinate(String str) { + if (str == null) return null; + TextUtils.StringSplitter splitter = new TextUtils.SimpleStringSplitter(','); + splitter.setString(str); + ArrayList<Coordinate> coordinateList = new ArrayList<Coordinate>(); + for (String s : splitter) { + Coordinate coordinate = strToCoordinate(s); + if (coordinate != null) coordinateList.add(coordinate); + } + if (coordinateList.size() == 0) return null; + return coordinateList; + } + + // Parses a string (ex: "500x500") to Coordinate object. + // Return null if the passing string is null. + private Coordinate strToCoordinate(String str) { + if (str == null) return null; + + int pos = str.indexOf('x'); + if (pos != -1) { + String x = str.substring(0, pos); + String y = str.substring(pos + 1); + return new Coordinate(Integer.parseInt(x), + Integer.parseInt(y)); + } + Log.e(TAG, "Invalid Coordinate parameter string=" + str); + return null; + } + /* ### QC ADD-ONS: END */ }; } diff --git a/core/java/android/hardware/SystemSensorManager.java b/core/java/android/hardware/SystemSensorManager.java index fe8dc46aff4d..0ae131a45537 100644 --- a/core/java/android/hardware/SystemSensorManager.java +++ b/core/java/android/hardware/SystemSensorManager.java @@ -174,6 +174,7 @@ public class SystemSensorManager extends SensorManager { @Override protected boolean registerListenerImpl(SensorEventListener listener, Sensor sensor, int delayUs, Handler handler, int maxBatchReportLatencyUs, int reservedFlags) { + android.util.SeempLog.record_sensor_rate(381, sensor, delayUs); if (listener == null || sensor == null) { Log.e(TAG, "sensor or listener is null"); return false; @@ -221,6 +222,7 @@ public class SystemSensorManager extends SensorManager { /** @hide */ @Override protected void unregisterListenerImpl(SensorEventListener listener, Sensor sensor) { + android.util.SeempLog.record_sensor(382, sensor); // Trigger Sensors should use the cancelTriggerSensor call. if (sensor != null && sensor.getReportingMode() == Sensor.REPORTING_MODE_ONE_SHOT) { return; diff --git a/core/java/android/hardware/camera2/CameraDevice.java b/core/java/android/hardware/camera2/CameraDevice.java index 3c1ec3e629a9..564c13ecdc8a 100644 --- a/core/java/android/hardware/camera2/CameraDevice.java +++ b/core/java/android/hardware/camera2/CameraDevice.java @@ -244,6 +244,10 @@ public abstract class CameraDevice implements AutoCloseable { @NonNull CameraCaptureSession.StateCallback callback, @Nullable Handler handler) throws CameraAccessException; + /** @hide */ + public abstract void setVendorStreamConfigMode(int index) + throws CameraAccessException; + /** * <p>Create a new camera capture session by providing the target output set of Surfaces and * its corresponding surface configuration to the camera device.</p> diff --git a/core/java/android/hardware/camera2/CameraManager.java b/core/java/android/hardware/camera2/CameraManager.java index b7c5644df107..0fca32196518 100644 --- a/core/java/android/hardware/camera2/CameraManager.java +++ b/core/java/android/hardware/camera2/CameraManager.java @@ -23,6 +23,7 @@ import android.annotation.RequiresPermission; import android.annotation.SystemApi; import android.annotation.SystemService; import android.annotation.TestApi; +import android.app.ActivityThread; import android.content.Context; import android.hardware.CameraStatus; import android.hardware.ICameraService; @@ -47,6 +48,8 @@ import android.os.RemoteException; import android.os.ServiceManager; import android.os.ServiceSpecificException; import android.os.SystemProperties; +import android.text.TextUtils; +import android.util.Log; import android.util.ArrayMap; import android.util.ArraySet; import android.util.Log; @@ -1520,8 +1523,22 @@ public final class CameraManager { private String[] extractCameraIdListLocked() { String[] cameraIds = null; + boolean exposeAuxCamera = false; + String packageName = ActivityThread.currentOpPackageName(); + String packageList = SystemProperties.get("vendor.camera.aux.packagelist"); + if (packageList.length() > 0) { + TextUtils.StringSplitter splitter = new TextUtils.SimpleStringSplitter(','); + splitter.setString(packageList); + for (String str : splitter) { + if (packageName.equals(str)) { + exposeAuxCamera = true; + break; + } + } + } int idCount = 0; for (int i = 0; i < mDeviceStatus.size(); i++) { + if(!exposeAuxCamera && (i == 2)) break; int status = mDeviceStatus.valueAt(i); if (status == ICameraServiceListener.STATUS_NOT_PRESENT || status == ICameraServiceListener.STATUS_ENUMERATING) continue; @@ -1530,6 +1547,7 @@ public final class CameraManager { cameraIds = new String[idCount]; idCount = 0; for (int i = 0; i < mDeviceStatus.size(); i++) { + if(!exposeAuxCamera && (i == 2)) break; int status = mDeviceStatus.valueAt(i); if (status == ICameraServiceListener.STATUS_NOT_PRESENT || status == ICameraServiceListener.STATUS_ENUMERATING) continue; @@ -1790,6 +1808,26 @@ public final class CameraManager { throw new IllegalArgumentException("cameraId was null"); } + /* Force to expose only two cameras + * if the package name does not falls in this bucket + */ + boolean exposeAuxCamera = false; + String packageName = ActivityThread.currentOpPackageName(); + String packageList = SystemProperties.get("vendor.camera.aux.packagelist"); + if (packageList.length() > 0) { + TextUtils.StringSplitter splitter = new TextUtils.SimpleStringSplitter(','); + splitter.setString(packageList); + for (String str : splitter) { + if (packageName.equals(str)) { + exposeAuxCamera = true; + break; + } + } + } + if (exposeAuxCamera == false && (Integer.parseInt(cameraId) >= 2)) { + throw new IllegalArgumentException("invalid cameraId"); + } + ICameraService cameraService = getCameraService(); if (cameraService == null) { throw new CameraAccessException(CameraAccessException.CAMERA_DISCONNECTED, @@ -1988,6 +2026,30 @@ public final class CameraManager { } private void onStatusChangedLocked(int status, String id) { + /* Force to ignore the last mono/aux camera status update + * if the package name does not falls in this bucket + */ + boolean exposeMonoCamera = false; + String packageName = ActivityThread.currentOpPackageName(); + String packageList = SystemProperties.get("vendor.camera.aux.packagelist"); + if (packageList.length() > 0) { + TextUtils.StringSplitter splitter = new TextUtils.SimpleStringSplitter(','); + splitter.setString(packageList); + for (String str : splitter) { + if (packageName.equals(str)) { + exposeMonoCamera = true; + break; + } + } + } + + if (exposeMonoCamera == false) { + if (Integer.parseInt(id) >= 2) { + Log.w(TAG, "[soar.cts] ignore the status update of camera: " + id); + return; + } + } + if (DEBUG) { Log.v(TAG, String.format("Camera id %s has status changed to 0x%x", id, status)); @@ -2119,6 +2181,31 @@ public final class CameraManager { String.format("Camera id %s has torch status changed to 0x%x", id, status)); } + /* Force to ignore the aux or composite camera torch status update + * if the package name does not falls in this bucket + */ + boolean exposeMonoCamera = false; + String packageName = ActivityThread.currentOpPackageName(); + String packageList = SystemProperties.get("vendor.camera.aux.packagelist"); + if (packageList.length() > 0) { + TextUtils.StringSplitter splitter = new TextUtils.SimpleStringSplitter(','); + splitter.setString(packageList); + for (String str : splitter) { + if (packageName.equals(str)) { + exposeMonoCamera = true; + break; + } + } + } + + if (exposeMonoCamera == false) { + if (Integer.parseInt(id) >= 2) { + Log.w(TAG, "ignore the torch status update of camera: " + id); + return; + } + } + + if (!validTorchStatus(status)) { Log.e(TAG, String.format("Ignoring invalid device %s torch status 0x%x", id, status)); diff --git a/core/java/android/hardware/camera2/impl/CameraCaptureSessionImpl.java b/core/java/android/hardware/camera2/impl/CameraCaptureSessionImpl.java index 9a9163c724ff..b2f118bce794 100644 --- a/core/java/android/hardware/camera2/impl/CameraCaptureSessionImpl.java +++ b/core/java/android/hardware/camera2/impl/CameraCaptureSessionImpl.java @@ -222,7 +222,8 @@ public class CameraCaptureSessionImpl extends CameraCaptureSession } else if (request.isReprocess() && !isReprocessable()) { throw new IllegalArgumentException("this capture session cannot handle reprocess " + "requests"); - } else if (request.isReprocess() && request.getReprocessableSessionId() != mId) { + } else if (!mDeviceImpl.isPrivilegedApp() && + request.isReprocess() && request.getReprocessableSessionId() != mId) { throw new IllegalArgumentException("capture request was created for another session"); } } diff --git a/core/java/android/hardware/camera2/impl/CameraConstrainedHighSpeedCaptureSessionImpl.java b/core/java/android/hardware/camera2/impl/CameraConstrainedHighSpeedCaptureSessionImpl.java index 2920e670f15b..9ac415b465ba 100644 --- a/core/java/android/hardware/camera2/impl/CameraConstrainedHighSpeedCaptureSessionImpl.java +++ b/core/java/android/hardware/camera2/impl/CameraConstrainedHighSpeedCaptureSessionImpl.java @@ -26,10 +26,12 @@ import android.hardware.camera2.CameraOfflineSession.CameraOfflineSessionCallbac import android.hardware.camera2.CaptureRequest; import android.hardware.camera2.params.OutputConfiguration; import android.hardware.camera2.params.StreamConfigurationMap; +import android.hardware.camera2.params.HighSpeedVideoConfiguration; import android.hardware.camera2.utils.SurfaceUtils; import android.os.Handler; import android.os.ConditionVariable; import android.util.Range; +import android.util.Size; import android.view.Surface; import java.util.ArrayList; @@ -95,10 +97,7 @@ public class CameraConstrainedHighSpeedCaptureSessionImpl StreamConfigurationMap config = mCharacteristics.get(ck); SurfaceUtils.checkConstrainedHighSpeedSurfaces(outputSurfaces, fpsRange, config); - // Request list size: to limit the preview to 30fps, need use maxFps/30; to maximize - // the preview frame rate, should use maxBatch size for that high speed stream - // configuration. We choose the former for now. - int requestListSize = fpsRange.getUpper() / 30; + int requestListSize = getHighSpeedRequestListSize(fpsRange, outputSurfaces); List<CaptureRequest> requestList = new ArrayList<CaptureRequest>(); // Prepare the Request builders: need carry over the request controls. @@ -177,6 +176,34 @@ public class CameraConstrainedHighSpeedCaptureSessionImpl return true; } + private int getHighSpeedRequestListSize(Range<Integer> fpsRange, Collection<Surface> surfaces) { + int requestListSize = 0; + + for (Surface surface : surfaces) { + + if (SurfaceUtils.isSurfaceForHwVideoEncoder(surface)) { + Size surfaceSize = SurfaceUtils.getSurfaceSize(surface); + HighSpeedVideoConfiguration[] highSpeedVideoConfigurations = + mCharacteristics.get(CameraCharacteristics.CONTROL_AVAILABLE_HIGH_SPEED_VIDEO_CONFIGURATIONS); + + // Get the batchsize for matching FPS & video size + for (HighSpeedVideoConfiguration config : highSpeedVideoConfigurations) { + if (config.getSize().equals(surfaceSize) && config.getFpsRange().equals(fpsRange)) { + requestListSize = config.getBatchSizeMax(); + break; + } + } + break; + } + } + + if (requestListSize == 0) { + // If cant' find the matching batch size, limit the preview to 30fps. + requestListSize = fpsRange.getUpper() / 30; + } + return requestListSize; + } + @Override public CameraDevice getDevice() { return mSessionImpl.getDevice(); diff --git a/core/java/android/hardware/camera2/impl/CameraDeviceImpl.java b/core/java/android/hardware/camera2/impl/CameraDeviceImpl.java index 9b19fc4d3ef2..cabb14122e00 100644 --- a/core/java/android/hardware/camera2/impl/CameraDeviceImpl.java +++ b/core/java/android/hardware/camera2/impl/CameraDeviceImpl.java @@ -16,12 +16,15 @@ package android.hardware.camera2.impl; +import static android.hardware.camera2.CameraAccessException.CAMERA_IN_USE; import static com.android.internal.util.function.pooled.PooledLambda.obtainRunnable; import android.annotation.NonNull; import android.content.Context; import android.graphics.ImageFormat; import android.hardware.ICameraService; +import android.app.ActivityThread; +import android.graphics.ImageFormat; import android.hardware.camera2.CameraAccessException; import android.hardware.camera2.CameraCaptureSession; import android.hardware.camera2.CameraCharacteristics; @@ -53,6 +56,8 @@ import android.os.Looper; import android.os.RemoteException; import android.os.ServiceSpecificException; import android.os.SystemClock; +import android.os.SystemProperties; +import android.text.TextUtils; import android.util.Log; import android.util.Range; import android.util.Size; @@ -84,7 +89,7 @@ public class CameraDeviceImpl extends CameraDevice private final boolean DEBUG = false; private static final int REQUEST_ID_NONE = -1; - + private int customOpMode = 0; // TODO: guard every function with if (!mRemoteDevice) check (if it was closed) private ICameraDeviceUserWrapper mRemoteDevice; @@ -151,6 +156,7 @@ public class CameraDeviceImpl extends CameraDevice private int mNextSessionId = 0; private final int mAppTargetSdkVersion; + private boolean mIsPrivilegedApp = false; private ExecutorService mOfflineSwitchService; private CameraOfflineSessionImpl mOfflineSessionImpl; @@ -301,6 +307,7 @@ public class CameraDeviceImpl extends CameraDevice } else { mTotalPartialCount = partialCount; } + mIsPrivilegedApp = checkPrivilegedAppList(); } public CameraDeviceCallbacks getCallbacks() { @@ -389,6 +396,10 @@ public class CameraDeviceImpl extends CameraDevice } } + public void setVendorStreamConfigMode(int fpsrange) { + customOpMode = fpsrange; + } + @Override public String getId() { return mCameraId; @@ -507,6 +518,7 @@ public class CameraDeviceImpl extends CameraDevice mConfiguredOutputs.put(streamId, outConfig); } } + operatingMode = (operatingMode | (customOpMode << 16)); int offlineStreamIds[]; if (sessionParams != null) { @@ -1503,6 +1515,27 @@ public class CameraDeviceImpl extends CameraDevice return false; } + private boolean checkPrivilegedAppList() { + String packageName = ActivityThread.currentOpPackageName(); + String packageList = SystemProperties.get("persist.vendor.camera.privapp.list"); + + if (packageList.length() > 0) { + TextUtils.StringSplitter splitter = new TextUtils.SimpleStringSplitter(','); + splitter.setString(packageList); + for (String str : splitter) { + if (packageName.equals(str)) { + return true; + } + } + } + + return false; + } + + public boolean isPrivilegedApp() { + return mIsPrivilegedApp; + } + private void checkInputConfiguration(InputConfiguration inputConfig) { if (inputConfig == null) { return; @@ -1540,6 +1573,14 @@ public class CameraDeviceImpl extends CameraDevice inputConfig.getWidth() + "x" + inputConfig.getHeight() + " is not valid"); } } else { + /* + * don't check input format and size, + * if the package name is in the white list + */ + if (isPrivilegedApp()) { + Log.w(TAG, "ignore input format/size check for white listed app"); + return; + } if (!checkInputConfigurationWithStreamConfigurations(inputConfig, /*maxRes*/false) && !checkInputConfigurationWithStreamConfigurations(inputConfig, /*maxRes*/true)) { throw new IllegalArgumentException("Input config with format " + diff --git a/core/java/android/hardware/camera2/utils/SurfaceUtils.java b/core/java/android/hardware/camera2/utils/SurfaceUtils.java index fd1a33161740..d2d33c2de63e 100644 --- a/core/java/android/hardware/camera2/utils/SurfaceUtils.java +++ b/core/java/android/hardware/camera2/utils/SurfaceUtils.java @@ -34,6 +34,11 @@ import java.util.Collection; import java.util.Iterator; import java.util.List; +import android.app.ActivityThread; +import android.os.SystemProperties; +import android.text.TextUtils; + + /** * Various Surface utilities. */ @@ -78,8 +83,8 @@ public class SurfaceUtils { public static boolean isSurfaceForHwVideoEncoder(Surface surface) { checkNotNull(surface); long usageFlags = nativeDetectSurfaceUsageFlags(surface); - long disallowedFlags = HardwareBuffer.USAGE_GPU_SAMPLED_IMAGE | USAGE_HW_COMPOSER - | USAGE_RENDERSCRIPT | HardwareBuffer.USAGE_CPU_READ_OFTEN; + long disallowedFlags = USAGE_HW_COMPOSER | USAGE_RENDERSCRIPT | + HardwareBuffer.USAGE_CPU_READ_OFTEN; long allowedFlags = HardwareBuffer.USAGE_VIDEO_ENCODE; boolean videoEncoderConsumer = ((usageFlags & disallowedFlags) == 0 && (usageFlags & allowedFlags) != 0); @@ -241,7 +246,13 @@ public class SurfaceUtils { + " the size must be 1 or 2"); } + if (isPrivilegedApp()) { + //skip checks for privileged apps + return; + } + List<Size> highSpeedSizes = null; + if (fpsRange == null) { highSpeedSizes = Arrays.asList(config.getHighSpeedVideoSizes()); } else { @@ -303,4 +314,21 @@ public class SurfaceUtils { /*out*/int[/*2*/] dimens); private static native long nativeGetSurfaceId(Surface surface); + + private static boolean isPrivilegedApp() { + String packageName = ActivityThread.currentOpPackageName(); + String packageList = SystemProperties.get("persist.camera.privapp.list"); + + if (packageList.length() > 0) { + TextUtils.StringSplitter splitter = new TextUtils.SimpleStringSplitter(','); + splitter.setString(packageList); + for (String str : splitter) { + if (packageName.equals(str)) { + return true; + } + } + } + + return false; + } } diff --git a/core/java/android/net/NetworkStats.java b/core/java/android/net/NetworkStats.java index 288b06ee52c8..6630463002cb 100644 --- a/core/java/android/net/NetworkStats.java +++ b/core/java/android/net/NetworkStats.java @@ -930,6 +930,7 @@ public final class NetworkStats implements Parcelable { entry.operations += operations[i]; } } + return entry; } diff --git a/core/java/android/net/NetworkStatsHistory.java b/core/java/android/net/NetworkStatsHistory.java index f41306301d42..865503502325 100644 --- a/core/java/android/net/NetworkStatsHistory.java +++ b/core/java/android/net/NetworkStatsHistory.java @@ -256,6 +256,34 @@ public class NetworkStatsHistory implements Parcelable { } /** + * Safely multiple a value by a rational. + * <p> + * Internally it uses integer-based math whenever possible, but switches + * over to double-based math if values would overflow. + */ + public static long multiplySafe(long value, long num, long den) { + if (den == 0) den = 1; + long x = value; + long y = num; + + // Logic shamelessly borrowed from Math.multiplyExact() + long r = x * y; + long ax = Math.abs(x); + long ay = Math.abs(y); + if (((ax | ay) >>> 31 != 0)) { + // Some bits greater than 2^31 that might cause overflow + // Check the result using the divide operator + // and check for the special case of Long.MIN_VALUE * -1 + if (((y != 0) && (r / y != x)) || + (x == Long.MIN_VALUE && y == -1)) { + // Use double math to avoid overflowing + return (long) (((double) num / den) * value); + } + } + return r / den; + } + + /** * Return index of bucket that contains or is immediately before the * requested time. */ diff --git a/core/java/android/nfc/INfcAdapter.aidl b/core/java/android/nfc/INfcAdapter.aidl index cb9a3e43db81..37ba09b381ea 100644 --- a/core/java/android/nfc/INfcAdapter.aidl +++ b/core/java/android/nfc/INfcAdapter.aidl @@ -1,4 +1,7 @@ /* + * Copyright (c) 2018, The Linux Foundation. All rights reserved. + * Not a Contribution. + * * Copyright (C) 2010 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -32,6 +35,7 @@ import android.nfc.INfcUnlockHandler; import android.nfc.ITagRemovedCallback; import android.nfc.INfcDta; import android.os.Bundle; +import android.os.IBinder; /** * @hide @@ -43,6 +47,8 @@ interface INfcAdapter INfcFCardEmulation getNfcFCardEmulationInterface(); INfcAdapterExtras getNfcAdapterExtrasInterface(in String pkg); INfcDta getNfcDtaInterface(in String pkg); + IBinder getNfcAdapterVendorInterface(in String vendor); + int getState(); boolean disable(boolean saveState); boolean enable(); diff --git a/core/java/android/nfc/cardemulation/AidGroup.java b/core/java/android/nfc/cardemulation/AidGroup.java index 2436e57b74bc..d4c966be04b8 100644 --- a/core/java/android/nfc/cardemulation/AidGroup.java +++ b/core/java/android/nfc/cardemulation/AidGroup.java @@ -1,4 +1,7 @@ /* + * Copyright (c) 2018, The Linux Foundation. All rights reserved. + * Not a Contribution. + * * Copyright (C) 2015 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -39,7 +42,7 @@ import java.util.List; * * @hide */ -public final class AidGroup implements Parcelable { +public class AidGroup implements Parcelable { /** * The maximum number of AIDs that can be present in any one group. */ @@ -48,11 +51,11 @@ public final class AidGroup implements Parcelable { static final String TAG = "AidGroup"; @UnsupportedAppUsage - final List<String> aids; + protected List<String> aids; @UnsupportedAppUsage - final String category; + protected String category; @UnsupportedAppUsage - final String description; + protected String description; /** * Creates a new AidGroup object. diff --git a/core/java/android/nfc/cardemulation/ApduServiceInfo.java b/core/java/android/nfc/cardemulation/ApduServiceInfo.java index 0af322e885b1..3de6f43bc7ea 100644 --- a/core/java/android/nfc/cardemulation/ApduServiceInfo.java +++ b/core/java/android/nfc/cardemulation/ApduServiceInfo.java @@ -1,4 +1,7 @@ /* + * Copyright (c) 2018, The Linux Foundation. All rights reserved. + * Not a Contribution. + * * Copyright (C) 2013 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -49,24 +52,24 @@ import java.util.Map; /** * @hide */ -public final class ApduServiceInfo implements Parcelable { +public class ApduServiceInfo implements Parcelable { static final String TAG = "ApduServiceInfo"; /** * The service that implements this */ @UnsupportedAppUsage - final ResolveInfo mService; + protected ResolveInfo mService; /** * Description of the service */ - final String mDescription; + protected String mDescription; /** * Whether this service represents AIDs running on the host CPU */ - final boolean mOnHost; + protected boolean mOnHost; /** * Offhost reader name. @@ -84,18 +87,18 @@ public final class ApduServiceInfo implements Parcelable { * Mapping from category to static AID group */ @UnsupportedAppUsage - final HashMap<String, AidGroup> mStaticAidGroups; + protected HashMap<String, AidGroup> mStaticAidGroups; /** * Mapping from category to dynamic AID group */ @UnsupportedAppUsage - final HashMap<String, AidGroup> mDynamicAidGroups; + protected HashMap<String, AidGroup> mDynamicAidGroups; /** * Whether this service should only be started when the device is unlocked. */ - final boolean mRequiresDeviceUnlock; + protected boolean mRequiresDeviceUnlock; /** * Whether this service should only be started when the device is screen on. @@ -105,17 +108,17 @@ public final class ApduServiceInfo implements Parcelable { /** * The id of the service banner specified in XML. */ - final int mBannerResourceId; + protected int mBannerResourceId; /** * The uid of the package the service belongs to */ - final int mUid; + protected int mUid; /** * Settings Activity for this service */ - final String mSettingsActivityName; + protected String mSettingsActivityName; /** * @hide diff --git a/core/java/android/nfc/tech/MifareClassic.java b/core/java/android/nfc/tech/MifareClassic.java index 080e058737b6..9cae043c4bdd 100644 --- a/core/java/android/nfc/tech/MifareClassic.java +++ b/core/java/android/nfc/tech/MifareClassic.java @@ -1,4 +1,6 @@ /* + * Copyright (C) 2018 NXP Semiconductors + * The original Work has been changed by NXP Semiconductors. * Copyright (C) 2010 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -173,6 +175,10 @@ public final class MifareClassic extends BasicTagTechnology { mType = TYPE_CLASSIC; mSize = SIZE_4K; break; + case 0x19: + mType = TYPE_CLASSIC; + mSize = SIZE_2K; + break; case 0x28: mType = TYPE_CLASSIC; mSize = SIZE_1K; diff --git a/core/java/android/nfc/tech/NfcA.java b/core/java/android/nfc/tech/NfcA.java index 88730f9af3df..819e9e31b6e6 100644 --- a/core/java/android/nfc/tech/NfcA.java +++ b/core/java/android/nfc/tech/NfcA.java @@ -1,4 +1,6 @@ /* + * Copyright (C) 2018 NXP Semiconductors + * The original Work has been changed by NXP Semiconductors. * Copyright (C) 2010 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -66,8 +68,15 @@ public final class NfcA extends BasicTagTechnology { /** @hide */ public NfcA(Tag tag) throws RemoteException { super(tag, TagTechnology.NFC_A); - Bundle extras = tag.getTechExtras(TagTechnology.NFC_A); - mSak = extras.getShort(EXTRA_SAK); + Bundle extras; + mSak = 0; + if(tag.hasTech(TagTechnology.MIFARE_CLASSIC)) + { + extras = tag.getTechExtras(TagTechnology.MIFARE_CLASSIC); + mSak = extras.getShort(EXTRA_SAK); + } + extras = tag.getTechExtras(TagTechnology.NFC_A); + mSak |= extras.getShort(EXTRA_SAK); mAtqa = extras.getByteArray(EXTRA_ATQA); } diff --git a/core/java/android/os/Process.java b/core/java/android/os/Process.java index 9f37c4877199..1945a54128b6 100644 --- a/core/java/android/os/Process.java +++ b/core/java/android/os/Process.java @@ -964,6 +964,31 @@ public class Process { throws IllegalArgumentException, SecurityException; /** + * Sets the scheduling group for processes in the same cgroup.procs of uid and pid + * @hide + * @param uid The user identifier of the process to change. + * @param pid The identifier of the process to change. + * @param group The target group for this process from THREAD_GROUP_*. + * @param dex2oat_only is the cgroup apply for all or for dex2oat only. + * + * @throws IllegalArgumentException Throws IllegalArgumentException if + * <var>tid</var> does not exist. + * @throws SecurityException Throws SecurityException if your process does + * not have permission to modify the given thread, or to use the given + * priority. + * + * group == THREAD_GROUP_DEFAULT means to move all non-background priority + * threads to the foreground scheduling group, but to leave background + * priority threads alone. group == THREAD_GROUP_BG_NONINTERACTIVE moves all + * threads, regardless of priority, to the background scheduling group. + * group == THREAD_GROUP_FOREGROUND is not allowed. + * + * Always sets cpusets. + */ + public static final native void setCgroupProcsProcessGroup(int uid, int pid, int group, boolean dex2oat_only) + throws IllegalArgumentException, SecurityException; + + /** * Freeze or unfreeze the specified process. * * @param pid Identifier of the process to freeze or unfreeze. diff --git a/core/java/android/os/storage/DiskInfo.java b/core/java/android/os/storage/DiskInfo.java index d32928cbeb38..b751e821c78d 100644 --- a/core/java/android/os/storage/DiskInfo.java +++ b/core/java/android/os/storage/DiskInfo.java @@ -50,6 +50,8 @@ public class DiskInfo implements Parcelable { public static final int FLAG_DEFAULT_PRIMARY = 1 << 1; public static final int FLAG_SD = 1 << 2; public static final int FLAG_USB = 1 << 3; + public static final int FLAG_EMMC = 1 << 4; + public static final int FLAG_UFS_CARD = 1 << 5; /** The FLAG_STUB_VISIBLE is set from vold, which gets the flag from outside (e.g., ChromeOS) */ public static final int FLAG_STUB_VISIBLE = 1 << 6; diff --git a/core/java/android/provider/Browser.java b/core/java/android/provider/Browser.java index afa7b80f58a0..472c0fb110f9 100644 --- a/core/java/android/provider/Browser.java +++ b/core/java/android/provider/Browser.java @@ -242,6 +242,7 @@ public class Browser { */ public static final Cursor getAllBookmarks(ContentResolver cr) throws IllegalStateException { + android.util.SeempLog.record(32); return new MatrixCursor(new String[]{Bookmarks.URL}, 0); } @@ -254,6 +255,7 @@ public class Browser { */ public static final Cursor getAllVisitedUrls(ContentResolver cr) throws IllegalStateException { + android.util.SeempLog.record(33); return new MatrixCursor(new String[]{Combined.URL}, 0); } @@ -262,6 +264,7 @@ public class Browser { } private static final Cursor getVisitedLike(ContentResolver cr, String url) { + android.util.SeempLog.record(34); boolean secure = false; String compareString = url; if (compareString.startsWith("http://")) { @@ -323,6 +326,7 @@ public class Browser { @Deprecated @UnsupportedAppUsage public static final String[] getVisitedHistory(ContentResolver cr) { + android.util.SeempLog.record(35); return new String[0]; } @@ -358,6 +362,7 @@ public class Browser { * @removed */ public static final void clearHistory(ContentResolver cr) { + android.util.SeempLog.record(37); } @@ -419,6 +424,7 @@ public class Browser { */ public static final void requestAllIcons(ContentResolver cr, String where, WebIconDatabase.IconListener listener) { + android.util.SeempLog.record(36); // Do nothing: this is no longer used. } diff --git a/core/java/android/provider/CalendarContract.java b/core/java/android/provider/CalendarContract.java index 92a18836653a..1b1e30c71374 100644 --- a/core/java/android/provider/CalendarContract.java +++ b/core/java/android/provider/CalendarContract.java @@ -984,6 +984,7 @@ public final class CalendarContract { * @return A Cursor containing all attendees for the event */ public static final Cursor query(ContentResolver cr, long eventId, String[] projection) { + android.util.SeempLog.record(54); String[] attArgs = {Long.toString(eventId)}; return cr.query(CONTENT_URI, projection, ATTENDEES_WHERE, attArgs /* selection args */, null /* sort order */); @@ -1916,6 +1917,7 @@ public final class CalendarContract { */ public static final Cursor query(ContentResolver cr, String[] projection, long begin, long end) { + android.util.SeempLog.record(54); Uri.Builder builder = CONTENT_URI.buildUpon(); ContentUris.appendId(builder, begin); ContentUris.appendId(builder, end); @@ -1945,6 +1947,7 @@ public final class CalendarContract { */ public static final Cursor query(ContentResolver cr, String[] projection, long begin, long end, String searchQuery) { + android.util.SeempLog.record(54); Uri.Builder builder = CONTENT_SEARCH_URI.buildUpon(); ContentUris.appendId(builder, begin); ContentUris.appendId(builder, end); @@ -2255,6 +2258,7 @@ public final class CalendarContract { */ public static final Cursor query(ContentResolver cr, int startDay, int numDays, String[] projection) { + android.util.SeempLog.record(54); if (numDays < 1) { return null; } @@ -2338,6 +2342,7 @@ public final class CalendarContract { * @return A Cursor containing all reminders for the event */ public static final Cursor query(ContentResolver cr, long eventId, String[] projection) { + android.util.SeempLog.record(54); String[] remArgs = {Long.toString(eventId)}; return cr.query(CONTENT_URI, projection, REMINDERS_WHERE, remArgs /*selection args*/, null /* sort order */); @@ -2488,6 +2493,7 @@ public final class CalendarContract { */ public static final Uri insert(ContentResolver cr, long eventId, long begin, long end, long alarmTime, int minutes) { + android.util.SeempLog.record(51); ContentValues values = new ContentValues(); values.put(CalendarAlerts.EVENT_ID, eventId); values.put(CalendarAlerts.BEGIN, begin); @@ -2516,6 +2522,7 @@ public final class CalendarContract { */ @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) public static final long findNextAlarmTime(ContentResolver cr, long millis) { + android.util.SeempLog.record(53); String selection = ALARM_TIME + ">=" + millis; // TODO: construct an explicit SQL query so that we can add // "LIMIT 1" to the end and get just one result. @@ -2647,6 +2654,7 @@ public final class CalendarContract { */ public static final boolean alarmExists(ContentResolver cr, long eventId, long begin, long alarmTime) { + android.util.SeempLog.record(52); // TODO: construct an explicit SQL query so that we can add // "LIMIT 1" to the end and get just one result. String[] projection = new String[] { ALARM_TIME }; diff --git a/core/java/android/provider/ContactsContract.java b/core/java/android/provider/ContactsContract.java index 376d9421e8d3..87bb32ce8afa 100644 --- a/core/java/android/provider/ContactsContract.java +++ b/core/java/android/provider/ContactsContract.java @@ -1638,6 +1638,7 @@ public final class ContactsContract { * {@link #CONTENT_LOOKUP_URI} to attempt refreshing. */ public static Uri getLookupUri(ContentResolver resolver, Uri contactUri) { + android.util.SeempLog.record(86); final Cursor c = resolver.query(contactUri, new String[] { Contacts.LOOKUP_KEY, Contacts._ID }, null, null, null); @@ -1665,6 +1666,7 @@ public final class ContactsContract { * provided parameters. */ public static Uri getLookupUri(long contactId, String lookupKey) { + android.util.SeempLog.record(86); if (TextUtils.isEmpty(lookupKey)) { return null; } @@ -1678,6 +1680,7 @@ public final class ContactsContract { * Returns null if the contact cannot be found. */ public static Uri lookupContact(ContentResolver resolver, Uri lookupUri) { + android.util.SeempLog.record(87); if (lookupUri == null) { return null; } @@ -2170,6 +2173,7 @@ public final class ContactsContract { */ public static InputStream openContactPhotoInputStream(ContentResolver cr, Uri contactUri, boolean preferHighres) { + android.util.SeempLog.record(88); if (preferHighres) { final Uri displayPhotoUri = Uri.withAppendedPath(contactUri, Contacts.Photo.DISPLAY_PHOTO); @@ -2218,6 +2222,7 @@ public final class ContactsContract { * of the thumbnail the high-res picture is preferred */ public static InputStream openContactPhotoInputStream(ContentResolver cr, Uri contactUri) { + android.util.SeempLog.record(88); return openContactPhotoInputStream(cr, contactUri, false); } @@ -2920,6 +2925,7 @@ public final class ContactsContract { * entry of the given {@link RawContacts} entry. */ public static Uri getContactLookupUri(ContentResolver resolver, Uri rawContactUri) { + android.util.SeempLog.record(89); // TODO: use a lighter query by joining rawcontacts with contacts in provider final Uri dataUri = Uri.withAppendedPath(rawContactUri, Data.CONTENT_DIRECTORY); final Cursor cursor = resolver.query(dataUri, new String[] { @@ -4978,6 +4984,7 @@ public final class ContactsContract { * </p> */ public static Uri getContactLookupUri(ContentResolver resolver, Uri dataUri) { + android.util.SeempLog.record(89); final Cursor cursor = resolver.query(dataUri, new String[] { RawContacts.CONTACT_ID, Contacts.LOOKUP_KEY }, null, null, null); diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java index 54952fc2dc39..042445b5011f 100644 --- a/core/java/android/provider/Settings.java +++ b/core/java/android/provider/Settings.java @@ -3504,6 +3504,7 @@ public final class Settings { @UnsupportedAppUsage public static String getStringForUser(ContentResolver resolver, String name, int userHandle) { + android.util.SeempLog.record(android.util.SeempLog.getSeempGetApiIdFromValue(name)); if (MOVED_TO_SECURE.contains(name)) { Log.w(TAG, "Setting " + name + " has moved from android.provider.Settings.System" + " to android.provider.Settings.Secure, returning read-only value."); @@ -3559,6 +3560,7 @@ public final class Settings { private static boolean putStringForUser(ContentResolver resolver, String name, String value, int userHandle, boolean overrideableByRestore) { + android.util.SeempLog.record(android.util.SeempLog.getSeempPutApiIdFromValue(name)); if (MOVED_TO_SECURE.contains(name)) { Log.w(TAG, "Setting " + name + " has moved from android.provider.Settings.System" + " to android.provider.Settings.Secure, value is unchanged."); @@ -4290,6 +4292,13 @@ public final class Settings { "display_color_mode_vendor_hint"; /** + * Whether to play tone while outgoing call is accepted. + * The value 1 - vibrate, 0 - not + * @hide + */ + public static final String CALL_CONNECTED_TONE_ENABLED = "call_connected_tone_enabled"; + + /** * The user selected min refresh rate in frames per second. * * If this isn't set, 0 will be used. @@ -5326,6 +5335,7 @@ public final class Settings { PRIVATE_SETTINGS.add(SHOW_BATTERY_PERCENT); PRIVATE_SETTINGS.add(DISPLAY_COLOR_MODE); PRIVATE_SETTINGS.add(DISPLAY_COLOR_MODE_VENDOR_HINT); + PRIVATE_SETTINGS.add(CALL_CONNECTED_TONE_ENABLED); } /** @@ -5731,6 +5741,7 @@ public final class Settings { MOVED_TO_GLOBAL.add(Settings.Global.NITZ_UPDATE_SPACING); MOVED_TO_GLOBAL.add(Settings.Global.NTP_SERVER); MOVED_TO_GLOBAL.add(Settings.Global.NTP_TIMEOUT); + MOVED_TO_GLOBAL.add(Settings.Global.NTP_SERVER_2); MOVED_TO_GLOBAL.add(Settings.Global.PDP_WATCHDOG_ERROR_POLL_COUNT); MOVED_TO_GLOBAL.add(Settings.Global.PDP_WATCHDOG_LONG_POLL_INTERVAL_MS); MOVED_TO_GLOBAL.add(Settings.Global.PDP_WATCHDOG_MAX_PDP_RESET_FAIL_COUNT); @@ -11233,6 +11244,15 @@ public final class Settings { public static final String MOBILE_DATA_ALWAYS_ON = "mobile_data_always_on"; /** + * Whether to allow modem to intelligently switch DDS without user direction + * + * (0 = disabled, 1 = enabled) + * @hide + */ + @Readable + public static final String SMART_DDS_SWITCH = "smart_dds_switch"; + + /** * Whether the wifi data connection should remain active even when higher * priority networks like Ethernet are active, to keep both networks. * In the case where higher priority networks are connected, wifi will be @@ -11385,12 +11405,15 @@ public final class Settings { @Readable public static final String NITZ_UPDATE_SPACING = "nitz_update_spacing"; - /** Preferred NTP server. {@hide} */ - @Readable - public static final String NTP_SERVER = "ntp_server"; - /** Timeout in milliseconds to wait for NTP server. {@hide} */ - @Readable - public static final String NTP_TIMEOUT = "ntp_timeout"; + /** Preferred NTP server. {@hide} */ + @Readable + public static final String NTP_SERVER = "ntp_server"; + /** Timeout in milliseconds to wait for NTP server. {@hide} */ + @Readable + public static final String NTP_TIMEOUT = "ntp_timeout"; + /** Secondary NTP server. {@hide} */ + @Readable + public static final String NTP_SERVER_2 = "ntp_server_2"; /** {@hide} */ @Readable @@ -15703,6 +15726,14 @@ public final class Settings { public static final String CELL_ON = "cell_on"; /** + * Whether to vibrate while outgoing call is accepted + * The value 1 - vibrate, 0 - not + * @hide + */ + public static final String VIBRATING_FOR_OUTGOING_CALL_ACCEPTED = + "vibrating_for_outgoing_call_accepted"; + + /** * Global settings which can be accessed by instant apps. * @hide */ diff --git a/core/java/android/provider/Telephony.java b/core/java/android/provider/Telephony.java index 9f3a847e12eb..3baecf0acc7f 100644 --- a/core/java/android/provider/Telephony.java +++ b/core/java/android/provider/Telephony.java @@ -282,6 +282,13 @@ public final class Telephony { * <p>Type: TEXT</p> */ public static final String CREATOR = "creator"; + + /** + * The priority of the message. + * <P>Type: INTEGER</P> + * @hide + */ + public static final String PRIORITY = "priority"; } /** @@ -390,6 +397,7 @@ public final class Telephony { * @hide */ public static Cursor query(ContentResolver cr, String[] projection) { + android.util.SeempLog.record(10); return cr.query(CONTENT_URI, projection, null, null, DEFAULT_SORT_ORDER); } @@ -400,6 +408,7 @@ public final class Telephony { @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023) public static Cursor query(ContentResolver cr, String[] projection, String where, String orderBy) { + android.util.SeempLog.record(10); return cr.query(CONTENT_URI, projection, where, null, orderBy == null ? DEFAULT_SORT_ORDER : orderBy); } @@ -503,6 +512,31 @@ public final class Telephony { public static Uri addMessageToUri(int subId, ContentResolver resolver, Uri uri, String address, String body, String subject, Long date, boolean read, boolean deliveryReport, long threadId) { + return addMessageToUri(subId, resolver, uri, address, body, subject, + date, read, deliveryReport, threadId, -1); + } + + /** + * Add an SMS to the given URI with thread_id specified. + * + * @param resolver the content resolver to use + * @param uri the URI to add the message to + * @param address the address of the sender + * @param body the body of the message + * @param subject the psuedo-subject of the message + * @param date the timestamp for the message + * @param read true if the message has been read, false if not + * @param deliveryReport true if a delivery report was requested, false if not + * @param threadId the thread_id of the message + * @param subId the subscription which the message belongs to + * @param priority the priority of the message + * @return the URI for the new message + * @hide + */ + public static Uri addMessageToUri(int subId, ContentResolver resolver, + Uri uri, String address, String body, String subject, + Long date, boolean read, boolean deliveryReport, + long threadId, int priority) { ContentValues values = new ContentValues(8); Rlog.v(TAG,"Telephony addMessageToUri sub id: " + subId); @@ -514,6 +548,7 @@ public final class Telephony { values.put(READ, read ? Integer.valueOf(1) : Integer.valueOf(0)); values.put(SUBJECT, subject); values.put(BODY, body); + values.put(PRIORITY, priority); if (deliveryReport) { values.put(STATUS, STATUS_PENDING); } @@ -2127,6 +2162,20 @@ public final class Telephony { * <P>Type: INTEGER (boolean)</P> */ public static final String ARCHIVED = "archived"; + + /** + * Indicates the last mms type in the thread. + * <P>Type: TEXT</P> + * @hide + */ + public static final String ATTACHMENT_INFO = "attachment_info"; + + /** + * Indicates whether this thread is a notification thread. + * <P>Type: INTEGER</P> + * @hide + */ + public static final String NOTIFICATION = "notification"; } /** @@ -2927,6 +2976,7 @@ public final class Telephony { */ public static Cursor query( ContentResolver cr, String[] projection) { + android.util.SeempLog.record(10); return cr.query(CONTENT_URI, projection, null, null, DEFAULT_SORT_ORDER); } @@ -2937,6 +2987,7 @@ public final class Telephony { public static Cursor query( ContentResolver cr, String[] projection, String where, String orderBy) { + android.util.SeempLog.record(10); return cr.query(CONTENT_URI, projection, where, null, orderBy == null ? DEFAULT_SORT_ORDER : orderBy); } diff --git a/core/java/android/service/wallpaper/WallpaperService.java b/core/java/android/service/wallpaper/WallpaperService.java index b68717a9b457..8a2b15de6757 100644 --- a/core/java/android/service/wallpaper/WallpaperService.java +++ b/core/java/android/service/wallpaper/WallpaperService.java @@ -2250,7 +2250,7 @@ public abstract class WallpaperService extends Service { return; } case MSG_UPDATE_SURFACE: - mEngine.updateSurface(true, false, false); + mEngine.updateSurface(true, false, true/*false*/); break; case MSG_ZOOM: mEngine.setZoom(Float.intBitsToFloat(message.arg1)); diff --git a/core/java/android/speech/SpeechRecognizer.java b/core/java/android/speech/SpeechRecognizer.java index 3cdd8b8d8436..b907596427d8 100644 --- a/core/java/android/speech/SpeechRecognizer.java +++ b/core/java/android/speech/SpeechRecognizer.java @@ -401,6 +401,7 @@ public class SpeechRecognizer { */ @MainThread public void startListening(final Intent recognizerIntent) { + android.util.SeempLog.record(72); if (recognizerIntent == null) { throw new IllegalArgumentException("intent must not be null"); } diff --git a/core/java/android/util/BoostFramework.java b/core/java/android/util/BoostFramework.java new file mode 100644 index 000000000000..ee29434f55ca --- /dev/null +++ b/core/java/android/util/BoostFramework.java @@ -0,0 +1,790 @@ +/* + * Copyright (c) 2017-2018, The Linux Foundation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of The Linux Foundation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +package android.util; + +import android.content.Context; +import android.graphics.BLASTBufferQueue; +import android.os.SystemProperties; +import android.util.Log; + +import dalvik.system.PathClassLoader; + +import java.lang.reflect.Constructor; +import java.lang.reflect.Method; + +/** @hide */ +public class BoostFramework { + + private static final String TAG = "BoostFramework"; + private static final String PERFORMANCE_JAR = "/system/framework/QPerformance.jar"; + private static final String PERFORMANCE_CLASS = "com.qualcomm.qti.Performance"; + + private static final String UXPERFORMANCE_JAR = "/system/framework/UxPerformance.jar"; + private static final String UXPERFORMANCE_CLASS = "com.qualcomm.qti.UxPerformance"; + public static final float PERF_HAL_V22 = 2.2f; + public static final float PERF_HAL_V23 = 2.3f; + +/** @hide */ + private static boolean sIsLoaded = false; + private static Class<?> sPerfClass = null; + private static Method sAcquireFunc = null; + private static Method sPerfHintFunc = null; + private static Method sReleaseFunc = null; + private static Method sReleaseHandlerFunc = null; + private static Method sFeedbackFunc = null; + private static Method sFeedbackFuncExtn = null; + private static Method sPerfGetPropFunc = null; + private static Method sAcqAndReleaseFunc = null; + private static Method sperfHintAcqRelFunc = null; + private static Method sperfHintRenewFunc = null; + private static Method sPerfEventFunc = null; + private static Method sPerfGetPerfHalVerFunc = null; + + private static Method sIOPStart = null; + private static Method sIOPStop = null; + private static Method sUXEngineEvents = null; + private static Method sUXEngineTrigger = null; + + private static boolean sUxIsLoaded = false; + private static Class<?> sUxPerfClass = null; + private static Method sUxIOPStart = null; + +/** @hide */ + private Object mPerf = null; + private Object mUxPerf = null; + + //perf hints + public static final int VENDOR_HINT_SCROLL_BOOST = 0x00001080; + public static final int VENDOR_HINT_FIRST_LAUNCH_BOOST = 0x00001081; + public static final int VENDOR_HINT_SUBSEQ_LAUNCH_BOOST = 0x00001082; + public static final int VENDOR_HINT_ANIM_BOOST = 0x00001083; + public static final int VENDOR_HINT_ACTIVITY_BOOST = 0x00001084; + public static final int VENDOR_HINT_TOUCH_BOOST = 0x00001085; + public static final int VENDOR_HINT_MTP_BOOST = 0x00001086; + public static final int VENDOR_HINT_DRAG_BOOST = 0x00001087; + public static final int VENDOR_HINT_PACKAGE_INSTALL_BOOST = 0x00001088; + public static final int VENDOR_HINT_ROTATION_LATENCY_BOOST = 0x00001089; + public static final int VENDOR_HINT_ROTATION_ANIM_BOOST = 0x00001090; + public static final int VENDOR_HINT_PERFORMANCE_MODE = 0x00001091; + public static final int VENDOR_HINT_APP_UPDATE = 0x00001092; + public static final int VENDOR_HINT_KILL = 0x00001093; + public static final int VENDOR_HINT_BOOST_RENDERTHREAD = 0x00001096; + //perf events + public static final int VENDOR_HINT_FIRST_DRAW = 0x00001042; + public static final int VENDOR_HINT_TAP_EVENT = 0x00001043; + public static final int VENDOR_HINT_DRAG_START = 0x00001051; + public static final int VENDOR_HINT_DRAG_END = 0x00001052; + //feedback hints + public static final int VENDOR_FEEDBACK_WORKLOAD_TYPE = 0x00001601; + public static final int VENDOR_FEEDBACK_LAUNCH_END_POINT = 0x00001602; + + //UXE Events and Triggers + public static final int UXE_TRIGGER = 1; + public static final int UXE_EVENT_BINDAPP = 2; + public static final int UXE_EVENT_DISPLAYED_ACT = 3; + public static final int UXE_EVENT_KILL = 4; + public static final int UXE_EVENT_GAME = 5; + public static final int UXE_EVENT_SUB_LAUNCH = 6; + public static final int UXE_EVENT_PKG_UNINSTALL = 7; + public static final int UXE_EVENT_PKG_INSTALL = 8; + + //perf opcodes + public static final int MPCTLV3_GPU_IS_APP_FG = 0X42820000; + public static final int MPCTLV3_GPU_IS_APP_BG = 0X42824000; + + public class Scroll { + public static final int VERTICAL = 1; + public static final int HORIZONTAL = 2; + public static final int PANEL_VIEW = 3; + public static final int PREFILING = 4; + }; + + public class Launch { + public static final int BOOST_V1 = 1; + public static final int BOOST_V2 = 2; + public static final int BOOST_V3 = 3; + public static final int BOOST_GAME = 4; + public static final int RESERVED_1 = 5; + public static final int RESERVED_2 = 6; + public static final int RESERVED_3 = 7; + public static final int RESERVED_4 = 8; + public static final int RESERVED_5 = 9; + public static final int TYPE_SERVICE_START = 100; + public static final int TYPE_START_PROC = 101; + public static final int TYPE_START_APP_FROM_BG = 102; + public static final int TYPE_ATTACH_APPLICATION = 103; + }; + + public class Draw { + public static final int EVENT_TYPE_V1 = 1; + }; + + public class WorkloadType { + public static final int NOT_KNOWN = 0; + public static final int APP = 1; + public static final int GAME = 2; + public static final int BROWSER = 3; + public static final int PREPROAPP = 4; + }; + +/** @hide */ + public BoostFramework() { + initFunctions(); + + try { + if (sPerfClass != null) { + mPerf = sPerfClass.newInstance(); + } + if (sUxPerfClass != null) { + mUxPerf = sUxPerfClass.newInstance(); + } + } + catch(Exception e) { + Log.e(TAG,"BoostFramework() : Exception_2 = " + e); + } + } + +/** @hide */ + public BoostFramework(Context context) { + this(context, false); + } + +/** @hide */ + public BoostFramework(Context context, boolean isTrusted) { + initFunctions(); + + try { + if (sPerfClass != null) { + Constructor cons = sPerfClass.getConstructor(Context.class); + if (cons != null) + mPerf = cons.newInstance(context); + } + if (sUxPerfClass != null) { + if (isTrusted) { + Constructor cons = sUxPerfClass.getConstructor(Context.class); + if (cons != null) + mUxPerf = cons.newInstance(context); + } else { + mUxPerf = sUxPerfClass.newInstance(); + } + } + } + catch(Exception e) { + Log.e(TAG,"BoostFramework() : Exception_3 = " + e); + } + } + +/** @hide */ + public BoostFramework(boolean isUntrustedDomain) { + initFunctions(); + + try { + if (sPerfClass != null) { + Constructor cons = sPerfClass.getConstructor(boolean.class); + if (cons != null) + mPerf = cons.newInstance(isUntrustedDomain); + } + if (sUxPerfClass != null) { + mUxPerf = sUxPerfClass.newInstance(); + } + } + catch(Exception e) { + Log.e(TAG,"BoostFramework() : Exception_5 = " + e); + } + } + + private void initFunctions () { + synchronized(BoostFramework.class) { + if (sIsLoaded == false) { + try { + sPerfClass = Class.forName(PERFORMANCE_CLASS); + + Class[] argClasses = new Class[] {int.class, int[].class}; + sAcquireFunc = sPerfClass.getMethod("perfLockAcquire", argClasses); + + argClasses = new Class[] {int.class, String.class, int.class, int.class}; + sPerfHintFunc = sPerfClass.getMethod("perfHint", argClasses); + + argClasses = new Class[] {}; + sReleaseFunc = sPerfClass.getMethod("perfLockRelease", argClasses); + + argClasses = new Class[] {int.class}; + sReleaseHandlerFunc = sPerfClass.getDeclaredMethod("perfLockReleaseHandler", argClasses); + + argClasses = new Class[] {int.class, String.class}; + sFeedbackFunc = sPerfClass.getMethod("perfGetFeedback", argClasses); + + argClasses = new Class[] {int.class, String.class, int.class, int[].class}; + sFeedbackFuncExtn = sPerfClass.getMethod("perfGetFeedbackExtn", argClasses); + + argClasses = new Class[] {int.class, String.class, String.class}; + sIOPStart = sPerfClass.getDeclaredMethod("perfIOPrefetchStart", argClasses); + + argClasses = new Class[] {}; + sIOPStop = sPerfClass.getDeclaredMethod("perfIOPrefetchStop", argClasses); + + argClasses = new Class[] {String.class, String.class}; + sPerfGetPropFunc = sPerfClass.getMethod("perfGetProp", argClasses); + + argClasses = new Class[] {int.class, int.class, int.class, int.class, int[].class}; + sAcqAndReleaseFunc = sPerfClass.getMethod("perfLockAcqAndRelease", argClasses); + + argClasses = new Class[] {int.class, String.class, int.class, int[].class}; + sPerfEventFunc = sPerfClass.getMethod("perfEvent", argClasses); + + argClasses = new Class[] {int.class, int.class, String.class, int.class, + int.class, int.class, int[].class}; + sperfHintAcqRelFunc = sPerfClass.getMethod("perfHintAcqRel", argClasses); + + argClasses = new Class[] {int.class, int.class, String.class, int.class, + int.class, int.class, int[].class}; + sperfHintRenewFunc = sPerfClass.getMethod("perfHintRenew", argClasses); + + try { + argClasses = new Class[] {}; + sPerfGetPerfHalVerFunc = sPerfClass.getMethod("perfGetHalVer", argClasses); + + } catch (Exception e) { + Log.i(TAG, "BoostFramework() : Exception_1 = perfGetHalVer not supported"); + sPerfGetPerfHalVerFunc = null; + } + + try { + argClasses = new Class[] {int.class, int.class, String.class, int.class, String.class}; + sUXEngineEvents = sPerfClass.getDeclaredMethod("perfUXEngine_events", + argClasses); + + argClasses = new Class[] {int.class}; + sUXEngineTrigger = sPerfClass.getDeclaredMethod("perfUXEngine_trigger", + argClasses); + } catch (Exception e) { + Log.i(TAG, "BoostFramework() : Exception_4 = PreferredApps not supported"); + } + + sIsLoaded = true; + } + catch(Exception e) { + Log.e(TAG,"BoostFramework() : Exception_1 = " + e); + } + // Load UXE Class now Adding new try/catch block to avoid + // any interference with Qperformance + try { + sUxPerfClass = Class.forName(UXPERFORMANCE_CLASS); + + Class[] argUxClasses = new Class[] {int.class, String.class, String.class}; + sUxIOPStart = sUxPerfClass.getDeclaredMethod("perfIOPrefetchStart", argUxClasses); + + sUxIsLoaded = true; + } + catch(Exception e) { + Log.e(TAG,"BoostFramework() Ux Perf: Exception = " + e); + } + } + } + } + +/** @hide */ + public int perfLockAcquire(int duration, int... list) { + int ret = -1; + try { + if (sAcquireFunc != null) { + Object retVal = sAcquireFunc.invoke(mPerf, duration, list); + ret = (int)retVal; + } + } catch(Exception e) { + Log.e(TAG,"Exception " + e); + } + return ret; + } + +/** @hide */ + public int perfLockRelease() { + int ret = -1; + try { + if (sReleaseFunc != null) { + Object retVal = sReleaseFunc.invoke(mPerf); + ret = (int)retVal; + } + } catch(Exception e) { + Log.e(TAG,"Exception " + e); + } + return ret; + } + +/** @hide */ + public int perfLockReleaseHandler(int handle) { + int ret = -1; + try { + if (sReleaseHandlerFunc != null) { + Object retVal = sReleaseHandlerFunc.invoke(mPerf, handle); + ret = (int)retVal; + } + } catch(Exception e) { + Log.e(TAG,"Exception " + e); + } + return ret; + } + +/** @hide */ + public int perfHint(int hint, String userDataStr) { + return perfHint(hint, userDataStr, -1, -1); + } + +/** @hide */ + public int perfHint(int hint, String userDataStr, int userData) { + return perfHint(hint, userDataStr, userData, -1); + } + +/** @hide */ + public int perfHint(int hint, String userDataStr, int userData1, int userData2) { + int ret = -1; + try { + if (sPerfHintFunc != null) { + Object retVal = sPerfHintFunc.invoke(mPerf, hint, userDataStr, userData1, userData2); + ret = (int)retVal; + } + } catch(Exception e) { + Log.e(TAG,"Exception " + e); + } + return ret; + } + +/** @hide */ + public double getPerfHalVersion() { + double retVal = PERF_HAL_V22; + try { + if (sPerfGetPerfHalVerFunc != null) { + Object ret = sPerfGetPerfHalVerFunc.invoke(mPerf); + retVal = (double)ret; + } + } catch(Exception e) { + Log.e(TAG,"Exception " + e); + } + return retVal; + } + +/** @hide */ + public int perfGetFeedback(int req, String pkg_name) { + int ret = -1; + try { + if (sFeedbackFunc != null) { + Object retVal = sFeedbackFunc.invoke(mPerf, req, pkg_name); + ret = (int)retVal; + } + } catch(Exception e) { + Log.e(TAG,"Exception " + e); + } + return ret; + } + +/** @hide */ + public int perfGetFeedbackExtn(int req, String pkg_name, int numArgs, int... list) { + int ret = -1; + try { + if (sFeedbackFuncExtn != null) { + Object retVal = sFeedbackFuncExtn.invoke(mPerf, req, pkg_name, numArgs, list); + ret = (int)retVal; + } + } catch(Exception e) { + Log.e(TAG,"Exception " + e); + } + return ret; + } + +/** @hide */ + public int perfIOPrefetchStart(int pid, String pkgName, String codePath) { + int ret = -1; + try { + Object retVal = sIOPStart.invoke(mPerf, pid, pkgName, codePath); + ret = (int) retVal; + } catch (Exception e) { + Log.e(TAG, "Exception " + e); + } + try { + Object retVal = sUxIOPStart.invoke(mUxPerf, pid, pkgName, codePath); + ret = (int) retVal; + } catch (Exception e) { + Log.e(TAG, "Ux Perf Exception " + e); + } + + return ret; + } + +/** @hide */ + public int perfIOPrefetchStop() { + int ret = -1; + try { + Object retVal = sIOPStop.invoke(mPerf); + ret = (int) retVal; + } catch (Exception e) { + Log.e(TAG, "Exception " + e); + } + return ret; + } + +/** @hide */ + public int perfUXEngine_events(int opcode, int pid, String pkgName, int lat) { + return perfUXEngine_events(opcode, pid, pkgName, lat, null); + } + +/** @hide */ + public int perfUXEngine_events(int opcode, int pid, String pkgName, int lat, String codePath) { + int ret = -1; + try { + if (sUXEngineEvents == null) { + return ret; + } + + Object retVal = sUXEngineEvents.invoke(mPerf, opcode, pid, pkgName, lat,codePath); + ret = (int) retVal; + } catch (Exception e) { + Log.e(TAG, "Exception " + e); + } + return ret; + } + + +/** @hide */ + public String perfUXEngine_trigger(int opcode) { + String ret = null; + try { + if (sUXEngineTrigger == null) { + return ret; + } + Object retVal = sUXEngineTrigger.invoke(mPerf, opcode); + ret = (String) retVal; + } catch (Exception e) { + Log.e(TAG, "Exception " + e); + } + return ret; + } + + +/** @hide */ + public String perfGetProp(String prop_name, String def_val) { + String ret = ""; + try { + if (sPerfGetPropFunc != null) { + Object retVal = sPerfGetPropFunc.invoke(mPerf, prop_name, def_val); + ret = (String)retVal; + }else { + ret = def_val; + } + } catch(Exception e) { + Log.e(TAG,"Exception " + e); + } + return ret; + } + +/** @hide */ + public int perfLockAcqAndRelease(int handle, int duration, int numArgs,int reserveNumArgs, int... list) { + int ret = -1; + try { + if (sAcqAndReleaseFunc != null) { + Object retVal = sAcqAndReleaseFunc.invoke(mPerf, handle, duration, numArgs, reserveNumArgs, list); + ret = (int)retVal; + } + } catch(Exception e) { + Log.e(TAG,"Exception " + e); + } + return ret; + } + +/** @hide */ + public void perfEvent(int eventId, String pkg_name) { + perfEvent(eventId, pkg_name, 0); + } + +/** @hide */ + public void perfEvent(int eventId, String pkg_name, int numArgs, int... list) { + try { + if (sPerfEventFunc != null) { + sPerfEventFunc.invoke(mPerf, eventId, pkg_name, numArgs, list); + } + } catch(Exception e) { + Log.e(TAG,"Exception " + e); + } + } + +/** @hide */ + public int perfHintAcqRel(int handle, int hint, String pkg_name) { + return perfHintAcqRel(handle, hint, pkg_name, -1, -1, 0); + } + +/** @hide */ + public int perfHintAcqRel(int handle, int hint, String pkg_name, int duration) { + return perfHintAcqRel(handle, hint, pkg_name, duration, -1, 0); + } + +/** @hide */ + public int perfHintAcqRel(int handle, int hint, String pkg_name, int duration, int hintType) { + return perfHintAcqRel(handle, hint, pkg_name, duration, hintType, 0); + } + +/** @hide */ + public int perfHintAcqRel(int handle, int hint, String pkg_name, int duration, + int hintType, int numArgs, int... list) { + int ret = -1; + try { + if (sperfHintAcqRelFunc != null) { + Object retVal = sperfHintAcqRelFunc.invoke(mPerf,handle, hint, pkg_name, + duration, hintType, numArgs, list); + ret = (int)retVal; + } + } catch(Exception e) { + Log.e(TAG,"Exception " + e); + } + return ret; + } + +/** @hide */ + public int perfHintRenew(int handle, int hint, String pkg_name) { + return perfHintRenew(handle, hint, pkg_name, -1, -1, 0); + } + +/** @hide */ + public int perfHintRenew(int handle, int hint, String pkg_name, int duration) { + return perfHintRenew(handle, hint, pkg_name, duration, -1, 0); + } + +/** @hide */ + public int perfHintRenew(int handle, int hint, String pkg_name, int duration, int hintType) { + return perfHintRenew(handle, hint, pkg_name, duration, hintType, 0); + } + +/** @hide */ + public int perfHintRenew(int handle, int hint, String pkg_name, int duration, + int hintType, int numArgs, int... list) { + int ret = -1; + try { + if (sperfHintRenewFunc != null) { + Object retVal = sperfHintRenewFunc.invoke(mPerf,handle, hint, pkg_name, + duration, hintType, numArgs, list); + ret = (int)retVal; + } + } catch(Exception e) { + Log.e(TAG,"Exception " + e); + } + return ret; + } + + /** @hide */ + public static class ScrollOptimizer { + /** @hide */ + public static final int FLING_START = 1; + /** @hide */ + public static final int FLING_END = 0; + private static final String SCROLL_OPT_PROP = "ro.vendor.perf.scroll_opt"; + private static final String QXPERFORMANCE_JAR = + "/system/framework/QXPerformance.jar"; + private static final String SCROLL_OPT_CLASS = + "com.qualcomm.qti.QXPerformance.ScrollOptimizer"; + private static boolean sScrollOptProp = false; + private static boolean sScrollOptEnable = false; + private static boolean sQXIsLoaded = false; + private static Class<?> sQXPerfClass = null; + private static Method sSetFrameInterval = null; + private static Method sSetBLASTBufferQueue = null; + private static Method sSetMotionType = null; + private static Method sSetVsyncTime = null; + private static Method sSetUITaskStatus = null; + private static Method sSetFlingFlag = null; + private static Method sShouldUseVsync = null; + private static Method sGetFrameDelay = null; + private static Method sGetAdjustedAnimationClock = null; + + private static void initQXPerfFuncs() { + if (sQXIsLoaded) return; + + try { + sScrollOptProp = SystemProperties.getBoolean(SCROLL_OPT_PROP, false); + if (!sScrollOptProp) { + sScrollOptEnable = false; + sQXIsLoaded = true; + return; + } + + PathClassLoader qXPerfClassLoader = new PathClassLoader( + QXPERFORMANCE_JAR, ClassLoader.getSystemClassLoader()); + sQXPerfClass = qXPerfClassLoader.loadClass(SCROLL_OPT_CLASS); + Class[] argClasses = new Class[]{long.class}; + sSetFrameInterval = sQXPerfClass.getMethod( + "setFrameInterval", argClasses); + + argClasses = new Class[]{BLASTBufferQueue.class}; + sSetBLASTBufferQueue = sQXPerfClass.getMethod("setBLASTBufferQueue", argClasses); + + argClasses = new Class[]{int.class}; + sSetMotionType = sQXPerfClass.getMethod("setMotionType", argClasses); + + argClasses = new Class[]{long.class}; + sSetVsyncTime = sQXPerfClass.getMethod("setVsyncTime", argClasses); + + argClasses = new Class[]{boolean.class}; + sSetUITaskStatus = sQXPerfClass.getMethod("setUITaskStatus", argClasses); + + argClasses = new Class[]{int.class}; + sSetFlingFlag = sQXPerfClass.getMethod("setFlingFlag", argClasses); + + sShouldUseVsync = sQXPerfClass.getMethod("shouldUseVsync"); + + argClasses = new Class[]{long.class}; + sGetFrameDelay = sQXPerfClass.getMethod("getFrameDelay", argClasses); + + argClasses = new Class[]{long.class}; + sGetAdjustedAnimationClock = sQXPerfClass.getMethod( + "getAdjustedAnimationClock", argClasses); + + sQXIsLoaded = true; + } catch (Exception e) { + Log.e(TAG, "initQXPerfFuncs failed"); + e.printStackTrace(); + } + } + + /** @hide */ + public static void setFrameInterval(long frameIntervalNanos) { + Thread initThread = new Thread(new Runnable() { + @Override + public void run() { + try { + initQXPerfFuncs(); + if (sScrollOptProp && sSetFrameInterval != null) { + sSetFrameInterval.invoke(null, frameIntervalNanos); + sScrollOptEnable = true; + } + } catch (Exception e) { + Log.e(TAG, "Failed to run initThread."); + e.printStackTrace(); + } + } + }); + initThread.start(); + } + + /** @hide */ + public static void setBLASTBufferQueue(BLASTBufferQueue blastBufferQueue) { + if (sScrollOptEnable && sSetBLASTBufferQueue != null) { + try { + sSetBLASTBufferQueue.invoke(null, blastBufferQueue); + } catch (Exception e) { + e.printStackTrace(); + } + } + } + + /** @hide */ + public static void setMotionType(int eventType) { + if (sScrollOptEnable && sSetMotionType != null) { + try { + sSetMotionType.invoke(null, eventType); + } catch (Exception e) { + e.printStackTrace(); + } + } + } + + /** @hide */ + public static void setVsyncTime(long vsyncTimeNanos) { + if (sScrollOptEnable && sSetVsyncTime != null) { + try { + sSetVsyncTime.invoke(null, vsyncTimeNanos); + } catch (Exception e) { + e.printStackTrace(); + } + } + } + + /** @hide */ + public static void setUITaskStatus(boolean running) { + if (sScrollOptEnable && sSetUITaskStatus != null) { + try { + sSetUITaskStatus.invoke(null, running); + } catch (Exception e) { + e.printStackTrace(); + } + } + } + + /** @hide */ + public static void setFlingFlag(int flag) { + if (sScrollOptEnable && sSetFlingFlag != null) { + try { + sSetFlingFlag.invoke(null, flag); + } catch (Exception e) { + e.printStackTrace(); + } + } + } + + /** @hide */ + public static boolean shouldUseVsync(boolean defaultVsyncFlag) { + boolean useVsync = defaultVsyncFlag; + if (sScrollOptEnable && sShouldUseVsync != null) { + try { + Object retVal = sShouldUseVsync.invoke(null); + useVsync = (boolean)retVal; + } catch (Exception e) { + e.printStackTrace(); + } + } + return useVsync; + } + + /** @hide */ + public static long getFrameDelay(long defaultDelay, long lastFrameTimeNanos) { + long frameDelay = defaultDelay; + if (sScrollOptEnable && sGetFrameDelay != null) { + try { + Object retVal = sGetFrameDelay.invoke(null, lastFrameTimeNanos); + frameDelay = (long)retVal; + } catch (Exception e) { + e.printStackTrace(); + } + } + return frameDelay; + } + + /** @hide */ + public static long getAdjustedAnimationClock(long frameTimeNanos) { + long newFrameTimeNanos = frameTimeNanos; + if (sScrollOptEnable && sGetAdjustedAnimationClock != null) { + try { + Object retVal = sGetAdjustedAnimationClock.invoke(null, + frameTimeNanos); + newFrameTimeNanos = (long)retVal; + } catch (Exception e) { + e.printStackTrace(); + } + } + return newFrameTimeNanos; + } + } +}; diff --git a/core/java/android/util/FeatureFlagUtils.java b/core/java/android/util/FeatureFlagUtils.java index e08b913fe248..871fd51b5968 100644 --- a/core/java/android/util/FeatureFlagUtils.java +++ b/core/java/android/util/FeatureFlagUtils.java @@ -76,7 +76,7 @@ public class FeatureFlagUtils { DEFAULT_FLAGS.put("settings_tether_all_in_one", "false"); DEFAULT_FLAGS.put("settings_contextual_home", "false"); - DEFAULT_FLAGS.put(SETTINGS_PROVIDER_MODEL, "true"); + DEFAULT_FLAGS.put(SETTINGS_PROVIDER_MODEL, "false"); DEFAULT_FLAGS.put(SETTINGS_USE_NEW_BACKUP_ELIGIBILITY_RULES, "true"); DEFAULT_FLAGS.put(SETTINGS_ENABLE_SECURITY_HUB, "true"); DEFAULT_FLAGS.put(SETTINGS_SUPPORT_LARGE_SCREEN, "true"); @@ -98,6 +98,11 @@ public class FeatureFlagUtils { * @return true if the flag is enabled (either by default in system, or override by user) */ public static boolean isEnabled(Context context, String feature) { + // Hide feature in SC Developer Preview + if (SETTINGS_PROVIDER_MODEL.equals(feature)) { + return false; + } + // Override precedence: // Settings.Global -> sys.fflag.override.* -> static list diff --git a/core/java/android/util/NtpTrustedTime.java b/core/java/android/util/NtpTrustedTime.java index 4ac3178ecb4c..519fd2b9a171 100644 --- a/core/java/android/util/NtpTrustedTime.java +++ b/core/java/android/util/NtpTrustedTime.java @@ -28,6 +28,7 @@ import android.net.NetworkInfo; import android.net.SntpClient; import android.os.Build; import android.os.SystemClock; +import android.os.SystemProperties; import android.provider.Settings; import android.text.TextUtils; @@ -126,6 +127,12 @@ public class NtpTrustedTime implements TrustedTime { // forceRefresh(). private volatile TimeResult mTimeResult; + private boolean mBackupmode = false; + private static String mBackupServer = ""; + private static int mNtpRetries = 0; + private static int mNtpRetriesMax = 0; + private static final String BACKUP_SERVER = "persist.backup.ntpServer"; + private NtpTrustedTime(Context context) { mContext = Objects.requireNonNull(context); } @@ -133,14 +140,39 @@ public class NtpTrustedTime implements TrustedTime { @UnsupportedAppUsage public static synchronized NtpTrustedTime getInstance(Context context) { if (sSingleton == null) { + final Resources res = context.getResources(); + final ContentResolver resolver = context.getContentResolver(); + Context appContext = context.getApplicationContext(); sSingleton = new NtpTrustedTime(appContext); + + final String sserver_prop = Settings.Global.getString( + resolver, Settings.Global.NTP_SERVER_2); + + final String secondServer_prop = ((null != sserver_prop) + && (0 < sserver_prop.length())) + ? sserver_prop : BACKUP_SERVER; + + final String backupServer = SystemProperties.get(secondServer_prop); + + if ((null != backupServer) && (0 < backupServer.length())) { + int retryMax = res.getInteger(com.android.internal.R.integer.config_ntpRetry); + if (0 < retryMax) { + sSingleton.mNtpRetriesMax = retryMax; + sSingleton.mBackupServer = (backupServer.trim()).replace("\"", ""); + } + } } return sSingleton; } @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) public boolean forceRefresh() { + return hasCache() ? forceSync() : false; + } + + @Override + public boolean forceSync() { synchronized (this) { NtpConnectionInfo connectionInfo = getNtpConnectionInfo(); if (connectionInfo == null) { @@ -163,14 +195,21 @@ public class NtpTrustedTime implements TrustedTime { if (LOGD) Log.d(TAG, "forceRefresh() from cache miss"); final SntpClient client = new SntpClient(); - final String serverName = connectionInfo.getServer(); + String serverName = connectionInfo.getServer(); final int timeoutMillis = connectionInfo.getTimeoutMillis(); + + if (getBackupmode()) { + setBackupmode(false); + serverName = mBackupServer; + } + if (LOGD) Log.d(TAG, "Ntp Server to access at:" + serverName); if (client.requestTime(serverName, timeoutMillis, network)) { long ntpCertainty = client.getRoundTripTime() / 2; mTimeResult = new TimeResult( client.getNtpTime(), client.getNtpTimeReference(), ntpCertainty); return true; } else { + countInBackupmode(); return false; } } @@ -294,4 +333,32 @@ public class NtpTrustedTime implements TrustedTime { final String server = secureServer != null ? secureServer : defaultServer; return TextUtils.isEmpty(server) ? null : new NtpConnectionInfo(server, timeoutMillis); } + + public void setBackupmode(boolean mode) { + if (isBackupSupported()) { + mBackupmode = mode; + } + if (LOGD) Log.d(TAG, "setBackupmode() set the backup mode to be:" + mBackupmode); + } + + private boolean getBackupmode() { + return mBackupmode; + } + + private boolean isBackupSupported() { + return ((0 < mNtpRetriesMax) && + (null != mBackupServer) && + (0 != mBackupServer.length())); + } + + private void countInBackupmode() { + if (isBackupSupported()) { + mNtpRetries++; + if (mNtpRetries >= mNtpRetriesMax) { + mNtpRetries = 0; + setBackupmode(true); + } + } + if (LOGD) Log.d(TAG, "countInBackupmode() func"); + } } diff --git a/core/java/android/util/SeempLog.java b/core/java/android/util/SeempLog.java new file mode 100644 index 000000000000..3764882644d8 --- /dev/null +++ b/core/java/android/util/SeempLog.java @@ -0,0 +1,754 @@ +/* + * Copyright (c) 2015, The Linux Foundation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of The Linux Foundation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +package android.util; + +import com.android.internal.os.RuntimeInit; + +import java.io.PrintWriter; +import java.io.StringWriter; +import java.net.UnknownHostException; +import java.util.Hashtable; +import java.util.Map; +import java.util.List; +import java.util.Iterator; +import android.util.Log; +import android.provider.Settings; + +/** + * SeempLog + * + * @hide + */ +public final class SeempLog { + private SeempLog() { + } + + /** + * Send a log message to the seemp log. + * @param api The api triggering this message. + */ + public static int record(int api) { + return seemp_println_native(api, ""); + } + + /** + * Send a log message to the seemp log. + * @param api The api triggering this message. + * @param msg The message you would like logged. + */ + public static int record_str(int api, String msg) { + if ( msg != null ) { + return seemp_println_native(api, msg); + } + else { + return seemp_println_native(api, ""); + } + } + + public static int record_sensor(int api, + android.hardware.Sensor sensor) { + if ( sensor != null ) { + return seemp_println_native(api, "sensor="+sensor.getType()); + } + else { + return seemp_println_native(api, "sensor=-1"); + } + } + + public static int record_sensor_rate(int api, + android.hardware.Sensor sensor, int rate) { + if ( sensor != null ) { + return seemp_println_native(api, + "sensor="+sensor.getType() + ",rate="+rate); + } + else { + return seemp_println_native(api, "sensor=-1,rate=" + rate); + } + } + + public static int record_uri(int api, android.net.Uri uri) { + if ( uri != null ) { + return seemp_println_native(api, "uri, " + uri.toString()); + } + else { + return seemp_println_native(api, "uri, null" ); + } + } + + public static int record_vg_layout(int api, + android.view.ViewGroup.LayoutParams params) { + try { + android.view.WindowManager.LayoutParams p = + (android.view.WindowManager.LayoutParams) params; + if ( p != null ) { + return seemp_println_native(api, + "window_type=" + p.type + ",window_flag=" + p.flags); + } + else { + return seemp_println_native(api, ""); + } + } catch (ClassCastException cce) { + return seemp_println_native(api, ""); + } + } + + /** @hide */ public static native int seemp_println_native(int api, String msg); + + public static final int SEEMP_API_android_provider_Settings__get_ANDROID_ID_ = 7; + public static final int SEEMP_API_android_provider_Settings__get_ACCELEROMETER_ROTATION_ = 96; + public static final int SEEMP_API_android_provider_Settings__get_USER_ROTATION_ = 97; + public static final int SEEMP_API_android_provider_Settings__get_ADB_ENABLED_ = 98; + public static final int SEEMP_API_android_provider_Settings__get_DEBUG_APP_ = 99; + public static final int SEEMP_API_android_provider_Settings__get_WAIT_FOR_DEBUGGER_ = 100; + public static final int SEEMP_API_android_provider_Settings__get_AIRPLANE_MODE_ON_ = 101; + public static final int SEEMP_API_android_provider_Settings__get_AIRPLANE_MODE_RADIOS_ = 102; + public static final int SEEMP_API_android_provider_Settings__get_ALARM_ALERT_ = 103; + public static final int SEEMP_API_android_provider_Settings__get_NEXT_ALARM_FORMATTED_ = 104; + public static final int SEEMP_API_android_provider_Settings__get_ALWAYS_FINISH_ACTIVITIES_ = 105; + public static final int SEEMP_API_android_provider_Settings__get_LOGGING_ID_ = 106; + public static final int SEEMP_API_android_provider_Settings__get_ANIMATOR_DURATION_SCALE_ = 107; + public static final int SEEMP_API_android_provider_Settings__get_WINDOW_ANIMATION_SCALE_ = 108; + public static final int SEEMP_API_android_provider_Settings__get_FONT_SCALE_ = 109; + public static final int SEEMP_API_android_provider_Settings__get_SCREEN_BRIGHTNESS_ = 110; + public static final int SEEMP_API_android_provider_Settings__get_SCREEN_BRIGHTNESS_MODE_ = 111; + public static final int SEEMP_API_android_provider_Settings__get_SCREEN_BRIGHTNESS_MODE_AUTOMATIC_ = 112; + public static final int SEEMP_API_android_provider_Settings__get_SCREEN_BRIGHTNESS_MODE_MANUAL_ = 113; + public static final int SEEMP_API_android_provider_Settings__get_SCREEN_OFF_TIMEOUT_ = 114; + public static final int SEEMP_API_android_provider_Settings__get_DIM_SCREEN_ = 115; + public static final int SEEMP_API_android_provider_Settings__get_TRANSITION_ANIMATION_SCALE_ = 116; + public static final int SEEMP_API_android_provider_Settings__get_STAY_ON_WHILE_PLUGGED_IN_ = 117; + public static final int SEEMP_API_android_provider_Settings__get_WALLPAPER_ACTIVITY_ = 118; + public static final int SEEMP_API_android_provider_Settings__get_SHOW_PROCESSES_ = 119; + public static final int SEEMP_API_android_provider_Settings__get_SHOW_WEB_SUGGESTIONS_ = 120; + public static final int SEEMP_API_android_provider_Settings__get_SHOW_GTALK_SERVICE_STATUS_ = 121; + public static final int SEEMP_API_android_provider_Settings__get_USE_GOOGLE_MAIL_ = 122; + public static final int SEEMP_API_android_provider_Settings__get_AUTO_TIME_ = 123; + public static final int SEEMP_API_android_provider_Settings__get_AUTO_TIME_ZONE_ = 124; + public static final int SEEMP_API_android_provider_Settings__get_DATE_FORMAT_ = 125; + public static final int SEEMP_API_android_provider_Settings__get_TIME_12_24_ = 126; + public static final int SEEMP_API_android_provider_Settings__get_BLUETOOTH_DISCOVERABILITY_ = 127; + public static final int SEEMP_API_android_provider_Settings__get_BLUETOOTH_DISCOVERABILITY_TIMEOUT_ = 128; + public static final int SEEMP_API_android_provider_Settings__get_BLUETOOTH_ON_ = 129; + public static final int SEEMP_API_android_provider_Settings__get_DEVICE_PROVISIONED_ = 130; + public static final int SEEMP_API_android_provider_Settings__get_SETUP_WIZARD_HAS_RUN_ = 131; + public static final int SEEMP_API_android_provider_Settings__get_DTMF_TONE_WHEN_DIALING_ = 132; + public static final int SEEMP_API_android_provider_Settings__get_END_BUTTON_BEHAVIOR_ = 133; + public static final int SEEMP_API_android_provider_Settings__get_RINGTONE_ = 134; + public static final int SEEMP_API_android_provider_Settings__get_MODE_RINGER_ = 135; + public static final int SEEMP_API_android_provider_Settings__get_INSTALL_NON_MARKET_APPS_ = 136; + public static final int SEEMP_API_android_provider_Settings__get_LOCATION_PROVIDERS_ALLOWED_ = 137; + public static final int SEEMP_API_android_provider_Settings__get_LOCK_PATTERN_ENABLED_ = 138; + public static final int SEEMP_API_android_provider_Settings__get_LOCK_PATTERN_TACTILE_FEEDBACK_ENABLED_ = 139; + public static final int SEEMP_API_android_provider_Settings__get_LOCK_PATTERN_VISIBLE_ = 140; + public static final int SEEMP_API_android_provider_Settings__get_NETWORK_PREFERENCE_ = 141; + public static final int SEEMP_API_android_provider_Settings__get_DATA_ROAMING_ = 142; + public static final int SEEMP_API_android_provider_Settings__get_HTTP_PROXY_ = 143; + public static final int SEEMP_API_android_provider_Settings__get_PARENTAL_CONTROL_ENABLED_ = 144; + public static final int SEEMP_API_android_provider_Settings__get_PARENTAL_CONTROL_LAST_UPDATE_ = 145; + public static final int SEEMP_API_android_provider_Settings__get_PARENTAL_CONTROL_REDIRECT_URL_ = 146; + public static final int SEEMP_API_android_provider_Settings__get_RADIO_BLUETOOTH_ = 147; + public static final int SEEMP_API_android_provider_Settings__get_RADIO_CELL_ = 148; + public static final int SEEMP_API_android_provider_Settings__get_RADIO_NFC_ = 149; + public static final int SEEMP_API_android_provider_Settings__get_RADIO_WIFI_ = 150; + public static final int SEEMP_API_android_provider_Settings__get_SYS_PROP_SETTING_VERSION_ = 151; + public static final int SEEMP_API_android_provider_Settings__get_SETTINGS_CLASSNAME_ = 152; + public static final int SEEMP_API_android_provider_Settings__get_TEXT_AUTO_CAPS_ = 153; + public static final int SEEMP_API_android_provider_Settings__get_TEXT_AUTO_PUNCTUATE_ = 154; + public static final int SEEMP_API_android_provider_Settings__get_TEXT_AUTO_REPLACE_ = 155; + public static final int SEEMP_API_android_provider_Settings__get_TEXT_SHOW_PASSWORD_ = 156; + public static final int SEEMP_API_android_provider_Settings__get_USB_MASS_STORAGE_ENABLED_ = 157; + public static final int SEEMP_API_android_provider_Settings__get_VIBRATE_ON_ = 158; + public static final int SEEMP_API_android_provider_Settings__get_HAPTIC_FEEDBACK_ENABLED_ = 159; + public static final int SEEMP_API_android_provider_Settings__get_VOLUME_ALARM_ = 160; + public static final int SEEMP_API_android_provider_Settings__get_VOLUME_BLUETOOTH_SCO_ = 161; + public static final int SEEMP_API_android_provider_Settings__get_VOLUME_MUSIC_ = 162; + public static final int SEEMP_API_android_provider_Settings__get_VOLUME_NOTIFICATION_ = 163; + public static final int SEEMP_API_android_provider_Settings__get_VOLUME_RING_ = 164; + public static final int SEEMP_API_android_provider_Settings__get_VOLUME_SYSTEM_ = 165; + public static final int SEEMP_API_android_provider_Settings__get_VOLUME_VOICE_ = 166; + public static final int SEEMP_API_android_provider_Settings__get_SOUND_EFFECTS_ENABLED_ = 167; + public static final int SEEMP_API_android_provider_Settings__get_MODE_RINGER_STREAMS_AFFECTED_ = 168; + public static final int SEEMP_API_android_provider_Settings__get_MUTE_STREAMS_AFFECTED_ = 169; + public static final int SEEMP_API_android_provider_Settings__get_NOTIFICATION_SOUND_ = 170; + public static final int SEEMP_API_android_provider_Settings__get_APPEND_FOR_LAST_AUDIBLE_ = 171; + public static final int SEEMP_API_android_provider_Settings__get_WIFI_MAX_DHCP_RETRY_COUNT_ = 172; + public static final int SEEMP_API_android_provider_Settings__get_WIFI_MOBILE_DATA_TRANSITION_WAKELOCK_TIMEOUT_MS_ = 173; + public static final int SEEMP_API_android_provider_Settings__get_WIFI_NETWORKS_AVAILABLE_NOTIFICATION_ON_ = 174; + public static final int SEEMP_API_android_provider_Settings__get_WIFI_NETWORKS_AVAILABLE_REPEAT_DELAY_ = 175; + public static final int SEEMP_API_android_provider_Settings__get_WIFI_NUM_OPEN_NETWORKS_KEPT_ = 176; + public static final int SEEMP_API_android_provider_Settings__get_WIFI_ON_ = 177; + public static final int SEEMP_API_android_provider_Settings__get_WIFI_SLEEP_POLICY_ = 178; + public static final int SEEMP_API_android_provider_Settings__get_WIFI_SLEEP_POLICY_DEFAULT_ = 179; + public static final int SEEMP_API_android_provider_Settings__get_WIFI_SLEEP_POLICY_NEVER_ = 180; + public static final int SEEMP_API_android_provider_Settings__get_WIFI_SLEEP_POLICY_NEVER_WHILE_PLUGGED_ = 181; + public static final int SEEMP_API_android_provider_Settings__get_WIFI_STATIC_DNS1_ = 182; + public static final int SEEMP_API_android_provider_Settings__get_WIFI_STATIC_DNS2_ = 183; + public static final int SEEMP_API_android_provider_Settings__get_WIFI_STATIC_GATEWAY_ = 184; + public static final int SEEMP_API_android_provider_Settings__get_WIFI_STATIC_IP_ = 185; + public static final int SEEMP_API_android_provider_Settings__get_WIFI_STATIC_NETMASK_ = 186; + public static final int SEEMP_API_android_provider_Settings__get_WIFI_USE_STATIC_IP_ = 187; + public static final int SEEMP_API_android_provider_Settings__get_WIFI_WATCHDOG_ACCEPTABLE_PACKET_LOSS_PERCENTAGE_ = 188; + public static final int SEEMP_API_android_provider_Settings__get_WIFI_WATCHDOG_AP_COUNT_ = 189; + public static final int SEEMP_API_android_provider_Settings__get_WIFI_WATCHDOG_BACKGROUND_CHECK_DELAY_MS_ = 190; + public static final int SEEMP_API_android_provider_Settings__get_WIFI_WATCHDOG_BACKGROUND_CHECK_ENABLED_ = 191; + public static final int SEEMP_API_android_provider_Settings__get_WIFI_WATCHDOG_BACKGROUND_CHECK_TIMEOUT_MS_ = 192; + public static final int SEEMP_API_android_provider_Settings__get_WIFI_WATCHDOG_INITIAL_IGNORED_PING_COUNT_ = 193; + public static final int SEEMP_API_android_provider_Settings__get_WIFI_WATCHDOG_MAX_AP_CHECKS_ = 194; + public static final int SEEMP_API_android_provider_Settings__get_WIFI_WATCHDOG_ON_ = 195; + public static final int SEEMP_API_android_provider_Settings__get_WIFI_WATCHDOG_PING_COUNT_ = 196; + public static final int SEEMP_API_android_provider_Settings__get_WIFI_WATCHDOG_PING_DELAY_MS_ = 197; + public static final int SEEMP_API_android_provider_Settings__get_WIFI_WATCHDOG_PING_TIMEOUT_MS_ = 198; + public static final int SEEMP_API_android_provider_Settings__put_ACCELEROMETER_ROTATION_ = 199; + public static final int SEEMP_API_android_provider_Settings__put_USER_ROTATION_ = 200; + public static final int SEEMP_API_android_provider_Settings__put_ADB_ENABLED_ = 201; + public static final int SEEMP_API_android_provider_Settings__put_DEBUG_APP_ = 202; + public static final int SEEMP_API_android_provider_Settings__put_WAIT_FOR_DEBUGGER_ = 203; + public static final int SEEMP_API_android_provider_Settings__put_AIRPLANE_MODE_ON_ = 204; + public static final int SEEMP_API_android_provider_Settings__put_AIRPLANE_MODE_RADIOS_ = 205; + public static final int SEEMP_API_android_provider_Settings__put_ALARM_ALERT_ = 206; + public static final int SEEMP_API_android_provider_Settings__put_NEXT_ALARM_FORMATTED_ = 207; + public static final int SEEMP_API_android_provider_Settings__put_ALWAYS_FINISH_ACTIVITIES_ = 208; + public static final int SEEMP_API_android_provider_Settings__put_ANDROID_ID_ = 209; + public static final int SEEMP_API_android_provider_Settings__put_LOGGING_ID_ = 210; + public static final int SEEMP_API_android_provider_Settings__put_ANIMATOR_DURATION_SCALE_ = 211; + public static final int SEEMP_API_android_provider_Settings__put_WINDOW_ANIMATION_SCALE_ = 212; + public static final int SEEMP_API_android_provider_Settings__put_FONT_SCALE_ = 213; + public static final int SEEMP_API_android_provider_Settings__put_SCREEN_BRIGHTNESS_ = 214; + public static final int SEEMP_API_android_provider_Settings__put_SCREEN_BRIGHTNESS_MODE_ = 215; + public static final int SEEMP_API_android_provider_Settings__put_SCREEN_BRIGHTNESS_MODE_AUTOMATIC_ = 216; + public static final int SEEMP_API_android_provider_Settings__put_SCREEN_BRIGHTNESS_MODE_MANUAL_ = 217; + public static final int SEEMP_API_android_provider_Settings__put_SCREEN_OFF_TIMEOUT_ = 218; + public static final int SEEMP_API_android_provider_Settings__put_DIM_SCREEN_ = 219; + public static final int SEEMP_API_android_provider_Settings__put_TRANSITION_ANIMATION_SCALE_ = 220; + public static final int SEEMP_API_android_provider_Settings__put_STAY_ON_WHILE_PLUGGED_IN_ = 221; + public static final int SEEMP_API_android_provider_Settings__put_WALLPAPER_ACTIVITY_ = 222; + public static final int SEEMP_API_android_provider_Settings__put_SHOW_PROCESSES_ = 223; + public static final int SEEMP_API_android_provider_Settings__put_SHOW_WEB_SUGGESTIONS_ = 224; + public static final int SEEMP_API_android_provider_Settings__put_SHOW_GTALK_SERVICE_STATUS_ = 225; + public static final int SEEMP_API_android_provider_Settings__put_USE_GOOGLE_MAIL_ = 226; + public static final int SEEMP_API_android_provider_Settings__put_AUTO_TIME_ = 227; + public static final int SEEMP_API_android_provider_Settings__put_AUTO_TIME_ZONE_ = 228; + public static final int SEEMP_API_android_provider_Settings__put_DATE_FORMAT_ = 229; + public static final int SEEMP_API_android_provider_Settings__put_TIME_12_24_ = 230; + public static final int SEEMP_API_android_provider_Settings__put_BLUETOOTH_DISCOVERABILITY_ = 231; + public static final int SEEMP_API_android_provider_Settings__put_BLUETOOTH_DISCOVERABILITY_TIMEOUT_ = 232; + public static final int SEEMP_API_android_provider_Settings__put_BLUETOOTH_ON_ = 233; + public static final int SEEMP_API_android_provider_Settings__put_DEVICE_PROVISIONED_ = 234; + public static final int SEEMP_API_android_provider_Settings__put_SETUP_WIZARD_HAS_RUN_ = 235; + public static final int SEEMP_API_android_provider_Settings__put_DTMF_TONE_WHEN_DIALING_ = 236; + public static final int SEEMP_API_android_provider_Settings__put_END_BUTTON_BEHAVIOR_ = 237; + public static final int SEEMP_API_android_provider_Settings__put_RINGTONE_ = 238; + public static final int SEEMP_API_android_provider_Settings__put_MODE_RINGER_ = 239; + public static final int SEEMP_API_android_provider_Settings__put_INSTALL_NON_MARKET_APPS_ = 240; + public static final int SEEMP_API_android_provider_Settings__put_LOCATION_PROVIDERS_ALLOWED_ = 241; + public static final int SEEMP_API_android_provider_Settings__put_LOCK_PATTERN_ENABLED_ = 242; + public static final int SEEMP_API_android_provider_Settings__put_LOCK_PATTERN_TACTILE_FEEDBACK_ENABLED_ = 243; + public static final int SEEMP_API_android_provider_Settings__put_LOCK_PATTERN_VISIBLE_ = 244; + public static final int SEEMP_API_android_provider_Settings__put_NETWORK_PREFERENCE_ = 245; + public static final int SEEMP_API_android_provider_Settings__put_DATA_ROAMING_ = 246; + public static final int SEEMP_API_android_provider_Settings__put_HTTP_PROXY_ = 247; + public static final int SEEMP_API_android_provider_Settings__put_PARENTAL_CONTROL_ENABLED_ = 248; + public static final int SEEMP_API_android_provider_Settings__put_PARENTAL_CONTROL_LAST_UPDATE_ = 249; + public static final int SEEMP_API_android_provider_Settings__put_PARENTAL_CONTROL_REDIRECT_URL_ = 250; + public static final int SEEMP_API_android_provider_Settings__put_RADIO_BLUETOOTH_ = 251; + public static final int SEEMP_API_android_provider_Settings__put_RADIO_CELL_ = 252; + public static final int SEEMP_API_android_provider_Settings__put_RADIO_NFC_ = 253; + public static final int SEEMP_API_android_provider_Settings__put_RADIO_WIFI_ = 254; + public static final int SEEMP_API_android_provider_Settings__put_SYS_PROP_SETTING_VERSION_ = 255; + public static final int SEEMP_API_android_provider_Settings__put_SETTINGS_CLASSNAME_ = 256; + public static final int SEEMP_API_android_provider_Settings__put_TEXT_AUTO_CAPS_ = 257; + public static final int SEEMP_API_android_provider_Settings__put_TEXT_AUTO_PUNCTUATE_ = 258; + public static final int SEEMP_API_android_provider_Settings__put_TEXT_AUTO_REPLACE_ = 259; + public static final int SEEMP_API_android_provider_Settings__put_TEXT_SHOW_PASSWORD_ = 260; + public static final int SEEMP_API_android_provider_Settings__put_USB_MASS_STORAGE_ENABLED_ = 261; + public static final int SEEMP_API_android_provider_Settings__put_VIBRATE_ON_ = 262; + public static final int SEEMP_API_android_provider_Settings__put_HAPTIC_FEEDBACK_ENABLED_ = 263; + public static final int SEEMP_API_android_provider_Settings__put_VOLUME_ALARM_ = 264; + public static final int SEEMP_API_android_provider_Settings__put_VOLUME_BLUETOOTH_SCO_ = 265; + public static final int SEEMP_API_android_provider_Settings__put_VOLUME_MUSIC_ = 266; + public static final int SEEMP_API_android_provider_Settings__put_VOLUME_NOTIFICATION_ = 267; + public static final int SEEMP_API_android_provider_Settings__put_VOLUME_RING_ = 268; + public static final int SEEMP_API_android_provider_Settings__put_VOLUME_SYSTEM_ = 269; + public static final int SEEMP_API_android_provider_Settings__put_VOLUME_VOICE_ = 270; + public static final int SEEMP_API_android_provider_Settings__put_SOUND_EFFECTS_ENABLED_ = 271; + public static final int SEEMP_API_android_provider_Settings__put_MODE_RINGER_STREAMS_AFFECTED_ = 272; + public static final int SEEMP_API_android_provider_Settings__put_MUTE_STREAMS_AFFECTED_ = 273; + public static final int SEEMP_API_android_provider_Settings__put_NOTIFICATION_SOUND_ = 274; + public static final int SEEMP_API_android_provider_Settings__put_APPEND_FOR_LAST_AUDIBLE_ = 275; + public static final int SEEMP_API_android_provider_Settings__put_WIFI_MAX_DHCP_RETRY_COUNT_ = 276; + public static final int SEEMP_API_android_provider_Settings__put_WIFI_MOBILE_DATA_TRANSITION_WAKELOCK_TIMEOUT_MS_ = 277; + public static final int SEEMP_API_android_provider_Settings__put_WIFI_NETWORKS_AVAILABLE_NOTIFICATION_ON_ = 278; + public static final int SEEMP_API_android_provider_Settings__put_WIFI_NETWORKS_AVAILABLE_REPEAT_DELAY_ = 279; + public static final int SEEMP_API_android_provider_Settings__put_WIFI_NUM_OPEN_NETWORKS_KEPT_ = 280; + public static final int SEEMP_API_android_provider_Settings__put_WIFI_ON_ = 281; + public static final int SEEMP_API_android_provider_Settings__put_WIFI_SLEEP_POLICY_ = 282; + public static final int SEEMP_API_android_provider_Settings__put_WIFI_SLEEP_POLICY_DEFAULT_ = 283; + public static final int SEEMP_API_android_provider_Settings__put_WIFI_SLEEP_POLICY_NEVER_ = 284; + public static final int SEEMP_API_android_provider_Settings__put_WIFI_SLEEP_POLICY_NEVER_WHILE_PLUGGED_ = 285; + public static final int SEEMP_API_android_provider_Settings__put_WIFI_STATIC_DNS1_ = 286; + public static final int SEEMP_API_android_provider_Settings__put_WIFI_STATIC_DNS2_ = 287; + public static final int SEEMP_API_android_provider_Settings__put_WIFI_STATIC_GATEWAY_ = 288; + public static final int SEEMP_API_android_provider_Settings__put_WIFI_STATIC_IP_ = 289; + public static final int SEEMP_API_android_provider_Settings__put_WIFI_STATIC_NETMASK_ = 290; + public static final int SEEMP_API_android_provider_Settings__put_WIFI_USE_STATIC_IP_ = 291; + public static final int SEEMP_API_android_provider_Settings__put_WIFI_WATCHDOG_ACCEPTABLE_PACKET_LOSS_PERCENTAGE_ = 292; + public static final int SEEMP_API_android_provider_Settings__put_WIFI_WATCHDOG_AP_COUNT_ = 293; + public static final int SEEMP_API_android_provider_Settings__put_WIFI_WATCHDOG_BACKGROUND_CHECK_DELAY_MS_ = 294; + public static final int SEEMP_API_android_provider_Settings__put_WIFI_WATCHDOG_BACKGROUND_CHECK_ENABLED_ = 295; + public static final int SEEMP_API_android_provider_Settings__put_WIFI_WATCHDOG_BACKGROUND_CHECK_TIMEOUT_MS_ = 296; + public static final int SEEMP_API_android_provider_Settings__put_WIFI_WATCHDOG_INITIAL_IGNORED_PING_COUNT_ = 297; + public static final int SEEMP_API_android_provider_Settings__put_WIFI_WATCHDOG_MAX_AP_CHECKS_ = 298; + public static final int SEEMP_API_android_provider_Settings__put_WIFI_WATCHDOG_ON_ = 299; + public static final int SEEMP_API_android_provider_Settings__put_WIFI_WATCHDOG_PING_COUNT_ = 300; + public static final int SEEMP_API_android_provider_Settings__put_WIFI_WATCHDOG_PING_DELAY_MS_ = 301; + public static final int SEEMP_API_android_provider_Settings__put_WIFI_WATCHDOG_PING_TIMEOUT_MS_ = 302; + + private final static java.util.Map<String,Integer> value_to_get_map; + static { + value_to_get_map = new java.util.HashMap<String,Integer>( 198 ); + value_to_get_map.put(Settings.System.NOTIFICATION_SOUND, + SEEMP_API_android_provider_Settings__get_NOTIFICATION_SOUND_); + value_to_get_map.put(Settings.System.DTMF_TONE_WHEN_DIALING, + SEEMP_API_android_provider_Settings__get_DTMF_TONE_WHEN_DIALING_); + value_to_get_map.put(Settings.System.LOCK_PATTERN_ENABLED, + SEEMP_API_android_provider_Settings__get_LOCK_PATTERN_ENABLED_); + value_to_get_map.put(Settings.System.WIFI_MAX_DHCP_RETRY_COUNT, + SEEMP_API_android_provider_Settings__get_WIFI_MAX_DHCP_RETRY_COUNT_); + value_to_get_map.put(Settings.System.AUTO_TIME, + SEEMP_API_android_provider_Settings__get_AUTO_TIME_); + value_to_get_map.put(Settings.System.SETUP_WIZARD_HAS_RUN, + SEEMP_API_android_provider_Settings__get_SETUP_WIZARD_HAS_RUN_); + value_to_get_map.put(Settings.System.WIFI_WATCHDOG_BACKGROUND_CHECK_TIMEOUT_MS, + SEEMP_API_android_provider_Settings__get_WIFI_WATCHDOG_BACKGROUND_CHECK_TIMEOUT_MS_); + value_to_get_map.put(Settings.System.LOCATION_PROVIDERS_ALLOWED, + SEEMP_API_android_provider_Settings__get_LOCATION_PROVIDERS_ALLOWED_); + value_to_get_map.put(Settings.System.ALARM_ALERT, + SEEMP_API_android_provider_Settings__get_ALARM_ALERT_); + value_to_get_map.put(Settings.System.VIBRATE_ON, + SEEMP_API_android_provider_Settings__get_VIBRATE_ON_); + value_to_get_map.put(Settings.System.USB_MASS_STORAGE_ENABLED, + SEEMP_API_android_provider_Settings__get_USB_MASS_STORAGE_ENABLED_); + value_to_get_map.put(Settings.System.WIFI_WATCHDOG_PING_DELAY_MS, + SEEMP_API_android_provider_Settings__get_WIFI_WATCHDOG_PING_DELAY_MS_); + value_to_get_map.put(Settings.System.FONT_SCALE, + SEEMP_API_android_provider_Settings__get_FONT_SCALE_); + value_to_get_map.put(Settings.System.WIFI_WATCHDOG_AP_COUNT, + SEEMP_API_android_provider_Settings__get_WIFI_WATCHDOG_AP_COUNT_); + value_to_get_map.put(Settings.System.ALWAYS_FINISH_ACTIVITIES, + SEEMP_API_android_provider_Settings__get_ALWAYS_FINISH_ACTIVITIES_); + value_to_get_map.put(Settings.System.ACCELEROMETER_ROTATION, + SEEMP_API_android_provider_Settings__get_ACCELEROMETER_ROTATION_); + value_to_get_map.put(Settings.System.WIFI_WATCHDOG_PING_TIMEOUT_MS, + SEEMP_API_android_provider_Settings__get_WIFI_WATCHDOG_PING_TIMEOUT_MS_); + value_to_get_map.put(Settings.System.VOLUME_NOTIFICATION, + SEEMP_API_android_provider_Settings__get_VOLUME_NOTIFICATION_); + value_to_get_map.put(Settings.System.AIRPLANE_MODE_ON, + SEEMP_API_android_provider_Settings__get_AIRPLANE_MODE_ON_); + value_to_get_map.put(Settings.System.WIFI_WATCHDOG_BACKGROUND_CHECK_DELAY_MS, + SEEMP_API_android_provider_Settings__get_WIFI_WATCHDOG_BACKGROUND_CHECK_DELAY_MS_); + value_to_get_map.put(Settings.System.WIFI_STATIC_IP, + SEEMP_API_android_provider_Settings__get_WIFI_STATIC_IP_); + value_to_get_map.put(Settings.System.RADIO_BLUETOOTH, + SEEMP_API_android_provider_Settings__get_RADIO_BLUETOOTH_); + value_to_get_map.put(Settings.System.BLUETOOTH_DISCOVERABILITY_TIMEOUT, + SEEMP_API_android_provider_Settings__get_BLUETOOTH_DISCOVERABILITY_TIMEOUT_); + value_to_get_map.put(Settings.System.VOLUME_RING, + SEEMP_API_android_provider_Settings__get_VOLUME_RING_); + value_to_get_map.put(Settings.System.MODE_RINGER_STREAMS_AFFECTED, + SEEMP_API_android_provider_Settings__get_MODE_RINGER_STREAMS_AFFECTED_); + value_to_get_map.put(Settings.System.VOLUME_SYSTEM, + SEEMP_API_android_provider_Settings__get_VOLUME_SYSTEM_); + value_to_get_map.put(Settings.System.SCREEN_OFF_TIMEOUT, + SEEMP_API_android_provider_Settings__get_SCREEN_OFF_TIMEOUT_); + value_to_get_map.put(Settings.System.RADIO_WIFI, + SEEMP_API_android_provider_Settings__get_RADIO_WIFI_); + value_to_get_map.put(Settings.System.AUTO_TIME_ZONE, + SEEMP_API_android_provider_Settings__get_AUTO_TIME_ZONE_); + value_to_get_map.put(Settings.System.TEXT_AUTO_CAPS, + SEEMP_API_android_provider_Settings__get_TEXT_AUTO_CAPS_); + value_to_get_map.put(Settings.System.WALLPAPER_ACTIVITY, + SEEMP_API_android_provider_Settings__get_WALLPAPER_ACTIVITY_); + value_to_get_map.put(Settings.System.ANIMATOR_DURATION_SCALE, + SEEMP_API_android_provider_Settings__get_ANIMATOR_DURATION_SCALE_); + value_to_get_map.put(Settings.System.WIFI_NUM_OPEN_NETWORKS_KEPT, + SEEMP_API_android_provider_Settings__get_WIFI_NUM_OPEN_NETWORKS_KEPT_); + value_to_get_map.put(Settings.System.LOCK_PATTERN_VISIBLE, + SEEMP_API_android_provider_Settings__get_LOCK_PATTERN_VISIBLE_); + value_to_get_map.put(Settings.System.VOLUME_VOICE, + SEEMP_API_android_provider_Settings__get_VOLUME_VOICE_); + value_to_get_map.put(Settings.System.DEBUG_APP, + SEEMP_API_android_provider_Settings__get_DEBUG_APP_); + value_to_get_map.put(Settings.System.WIFI_ON, + SEEMP_API_android_provider_Settings__get_WIFI_ON_); + value_to_get_map.put(Settings.System.TEXT_SHOW_PASSWORD, + SEEMP_API_android_provider_Settings__get_TEXT_SHOW_PASSWORD_); + value_to_get_map.put(Settings.System.WIFI_NETWORKS_AVAILABLE_REPEAT_DELAY, + SEEMP_API_android_provider_Settings__get_WIFI_NETWORKS_AVAILABLE_REPEAT_DELAY_); + value_to_get_map.put(Settings.System.WIFI_SLEEP_POLICY, + SEEMP_API_android_provider_Settings__get_WIFI_SLEEP_POLICY_); + value_to_get_map.put(Settings.System.VOLUME_MUSIC, + SEEMP_API_android_provider_Settings__get_VOLUME_MUSIC_); + value_to_get_map.put(Settings.System.PARENTAL_CONTROL_LAST_UPDATE, + SEEMP_API_android_provider_Settings__get_PARENTAL_CONTROL_LAST_UPDATE_); + value_to_get_map.put(Settings.System.DEVICE_PROVISIONED, + SEEMP_API_android_provider_Settings__get_DEVICE_PROVISIONED_); + value_to_get_map.put(Settings.System.HTTP_PROXY, + SEEMP_API_android_provider_Settings__get_HTTP_PROXY_); + value_to_get_map.put(Settings.System.ANDROID_ID, + SEEMP_API_android_provider_Settings__get_ANDROID_ID_); + value_to_get_map.put(Settings.System.WIFI_WATCHDOG_MAX_AP_CHECKS, + SEEMP_API_android_provider_Settings__get_WIFI_WATCHDOG_MAX_AP_CHECKS_); + value_to_get_map.put(Settings.System.END_BUTTON_BEHAVIOR, + SEEMP_API_android_provider_Settings__get_END_BUTTON_BEHAVIOR_); + value_to_get_map.put(Settings.System.NEXT_ALARM_FORMATTED, + SEEMP_API_android_provider_Settings__get_NEXT_ALARM_FORMATTED_); + value_to_get_map.put(Settings.System.RADIO_CELL, + SEEMP_API_android_provider_Settings__get_RADIO_CELL_); + value_to_get_map.put(Settings.System.PARENTAL_CONTROL_ENABLED, + SEEMP_API_android_provider_Settings__get_PARENTAL_CONTROL_ENABLED_); + value_to_get_map.put(Settings.System.BLUETOOTH_ON, + SEEMP_API_android_provider_Settings__get_BLUETOOTH_ON_); + value_to_get_map.put(Settings.System.WINDOW_ANIMATION_SCALE, + SEEMP_API_android_provider_Settings__get_WINDOW_ANIMATION_SCALE_); + value_to_get_map.put(Settings.System.WIFI_WATCHDOG_BACKGROUND_CHECK_ENABLED, + SEEMP_API_android_provider_Settings__get_WIFI_WATCHDOG_BACKGROUND_CHECK_ENABLED_); + value_to_get_map.put(Settings.System.BLUETOOTH_DISCOVERABILITY, + SEEMP_API_android_provider_Settings__get_BLUETOOTH_DISCOVERABILITY_); + value_to_get_map.put(Settings.System.WIFI_STATIC_DNS1, + SEEMP_API_android_provider_Settings__get_WIFI_STATIC_DNS1_); + value_to_get_map.put(Settings.System.WIFI_STATIC_DNS2, + SEEMP_API_android_provider_Settings__get_WIFI_STATIC_DNS2_); + value_to_get_map.put(Settings.System.HAPTIC_FEEDBACK_ENABLED, + SEEMP_API_android_provider_Settings__get_HAPTIC_FEEDBACK_ENABLED_); + value_to_get_map.put(Settings.System.SHOW_WEB_SUGGESTIONS, + SEEMP_API_android_provider_Settings__get_SHOW_WEB_SUGGESTIONS_); + value_to_get_map.put(Settings.System.PARENTAL_CONTROL_REDIRECT_URL, + SEEMP_API_android_provider_Settings__get_PARENTAL_CONTROL_REDIRECT_URL_); + value_to_get_map.put(Settings.System.DATE_FORMAT, + SEEMP_API_android_provider_Settings__get_DATE_FORMAT_); + value_to_get_map.put(Settings.System.RADIO_NFC, + SEEMP_API_android_provider_Settings__get_RADIO_NFC_); + value_to_get_map.put(Settings.System.AIRPLANE_MODE_RADIOS, + SEEMP_API_android_provider_Settings__get_AIRPLANE_MODE_RADIOS_); + value_to_get_map.put(Settings.System.LOCK_PATTERN_TACTILE_FEEDBACK_ENABLED, + SEEMP_API_android_provider_Settings__get_LOCK_PATTERN_TACTILE_FEEDBACK_ENABLED_); + value_to_get_map.put(Settings.System.TIME_12_24, + SEEMP_API_android_provider_Settings__get_TIME_12_24_); + value_to_get_map.put(Settings.System.WIFI_WATCHDOG_INITIAL_IGNORED_PING_COUNT, + SEEMP_API_android_provider_Settings__get_WIFI_WATCHDOG_INITIAL_IGNORED_PING_COUNT_); + value_to_get_map.put(Settings.System.VOLUME_BLUETOOTH_SCO, + SEEMP_API_android_provider_Settings__get_VOLUME_BLUETOOTH_SCO_); + value_to_get_map.put(Settings.System.USER_ROTATION, + SEEMP_API_android_provider_Settings__get_USER_ROTATION_); + value_to_get_map.put(Settings.System.WIFI_STATIC_GATEWAY, + SEEMP_API_android_provider_Settings__get_WIFI_STATIC_GATEWAY_); + value_to_get_map.put(Settings.System.STAY_ON_WHILE_PLUGGED_IN, + SEEMP_API_android_provider_Settings__get_STAY_ON_WHILE_PLUGGED_IN_); + value_to_get_map.put(Settings.System.SOUND_EFFECTS_ENABLED, + SEEMP_API_android_provider_Settings__get_SOUND_EFFECTS_ENABLED_); + value_to_get_map.put(Settings.System.WIFI_WATCHDOG_PING_COUNT, + SEEMP_API_android_provider_Settings__get_WIFI_WATCHDOG_PING_COUNT_); + value_to_get_map.put(Settings.System.DATA_ROAMING, + SEEMP_API_android_provider_Settings__get_DATA_ROAMING_); + value_to_get_map.put(Settings.System.SETTINGS_CLASSNAME, + SEEMP_API_android_provider_Settings__get_SETTINGS_CLASSNAME_); + value_to_get_map.put(Settings.System.TRANSITION_ANIMATION_SCALE, + SEEMP_API_android_provider_Settings__get_TRANSITION_ANIMATION_SCALE_); + value_to_get_map.put(Settings.System.WAIT_FOR_DEBUGGER, + SEEMP_API_android_provider_Settings__get_WAIT_FOR_DEBUGGER_); + value_to_get_map.put(Settings.System.INSTALL_NON_MARKET_APPS, + SEEMP_API_android_provider_Settings__get_INSTALL_NON_MARKET_APPS_); + value_to_get_map.put(Settings.System.ADB_ENABLED, + SEEMP_API_android_provider_Settings__get_ADB_ENABLED_); + value_to_get_map.put(Settings.System.WIFI_USE_STATIC_IP, + SEEMP_API_android_provider_Settings__get_WIFI_USE_STATIC_IP_); + value_to_get_map.put(Settings.System.DIM_SCREEN, + SEEMP_API_android_provider_Settings__get_DIM_SCREEN_); + value_to_get_map.put(Settings.System.VOLUME_ALARM, + SEEMP_API_android_provider_Settings__get_VOLUME_ALARM_); + value_to_get_map.put(Settings.System.WIFI_WATCHDOG_ON, + SEEMP_API_android_provider_Settings__get_WIFI_WATCHDOG_ON_); + value_to_get_map.put(Settings.System.WIFI_STATIC_NETMASK, + SEEMP_API_android_provider_Settings__get_WIFI_STATIC_NETMASK_); + value_to_get_map.put(Settings.System.NETWORK_PREFERENCE, + SEEMP_API_android_provider_Settings__get_NETWORK_PREFERENCE_); + value_to_get_map.put(Settings.System.SHOW_PROCESSES, + SEEMP_API_android_provider_Settings__get_SHOW_PROCESSES_); + value_to_get_map.put(Settings.System.TEXT_AUTO_REPLACE, + SEEMP_API_android_provider_Settings__get_TEXT_AUTO_REPLACE_); + value_to_get_map.put(Settings.System.WIFI_NETWORKS_AVAILABLE_NOTIFICATION_ON, + SEEMP_API_android_provider_Settings__get_WIFI_NETWORKS_AVAILABLE_NOTIFICATION_ON_); + value_to_get_map.put(Settings.System.APPEND_FOR_LAST_AUDIBLE, + SEEMP_API_android_provider_Settings__get_APPEND_FOR_LAST_AUDIBLE_); + value_to_get_map.put(Settings.System.SHOW_GTALK_SERVICE_STATUS, + SEEMP_API_android_provider_Settings__get_SHOW_GTALK_SERVICE_STATUS_); + value_to_get_map.put(Settings.System.SCREEN_BRIGHTNESS, + SEEMP_API_android_provider_Settings__get_SCREEN_BRIGHTNESS_); + value_to_get_map.put(Settings.System.USE_GOOGLE_MAIL, + SEEMP_API_android_provider_Settings__get_USE_GOOGLE_MAIL_); + value_to_get_map.put(Settings.System.RINGTONE, + SEEMP_API_android_provider_Settings__get_RINGTONE_); + value_to_get_map.put(Settings.System.LOGGING_ID, + SEEMP_API_android_provider_Settings__get_LOGGING_ID_); + value_to_get_map.put(Settings.System.MODE_RINGER, + SEEMP_API_android_provider_Settings__get_MODE_RINGER_); + value_to_get_map.put(Settings.System.MUTE_STREAMS_AFFECTED, + SEEMP_API_android_provider_Settings__get_MUTE_STREAMS_AFFECTED_); + value_to_get_map.put(Settings.System.WIFI_WATCHDOG_ACCEPTABLE_PACKET_LOSS_PERCENTAGE, + SEEMP_API_android_provider_Settings__get_WIFI_WATCHDOG_ACCEPTABLE_PACKET_LOSS_PERCENTAGE_); + value_to_get_map.put(Settings.System.TEXT_AUTO_PUNCTUATE, + SEEMP_API_android_provider_Settings__get_TEXT_AUTO_PUNCTUATE_); + value_to_get_map.put(Settings.System.WIFI_MOBILE_DATA_TRANSITION_WAKELOCK_TIMEOUT_MS, + SEEMP_API_android_provider_Settings__get_WIFI_MOBILE_DATA_TRANSITION_WAKELOCK_TIMEOUT_MS_); + value_to_get_map.put(Settings.System.SCREEN_BRIGHTNESS_MODE, + SEEMP_API_android_provider_Settings__get_SCREEN_BRIGHTNESS_MODE_); + } + + public static int getSeempGetApiIdFromValue( String v ) + { + Integer result = value_to_get_map.get( v ); + if (result == null) + { + result = -1; + } + return result; + } + + private final static java.util.Map<String,Integer> value_to_put_map; + static { + value_to_put_map = new java.util.HashMap<String,Integer>( 198 ); + value_to_put_map.put(Settings.System.NOTIFICATION_SOUND, + SEEMP_API_android_provider_Settings__put_NOTIFICATION_SOUND_); + value_to_put_map.put(Settings.System.DTMF_TONE_WHEN_DIALING, + SEEMP_API_android_provider_Settings__put_DTMF_TONE_WHEN_DIALING_); + value_to_put_map.put(Settings.System.LOCK_PATTERN_ENABLED, + SEEMP_API_android_provider_Settings__put_LOCK_PATTERN_ENABLED_); + value_to_put_map.put(Settings.System.WIFI_MAX_DHCP_RETRY_COUNT, + SEEMP_API_android_provider_Settings__put_WIFI_MAX_DHCP_RETRY_COUNT_); + value_to_put_map.put(Settings.System.AUTO_TIME, + SEEMP_API_android_provider_Settings__put_AUTO_TIME_); + value_to_put_map.put(Settings.System.SETUP_WIZARD_HAS_RUN, + SEEMP_API_android_provider_Settings__put_SETUP_WIZARD_HAS_RUN_); + value_to_put_map.put(Settings.System.WIFI_WATCHDOG_BACKGROUND_CHECK_TIMEOUT_MS, + SEEMP_API_android_provider_Settings__put_WIFI_WATCHDOG_BACKGROUND_CHECK_TIMEOUT_MS_); + value_to_put_map.put(Settings.System.LOCATION_PROVIDERS_ALLOWED, + SEEMP_API_android_provider_Settings__put_LOCATION_PROVIDERS_ALLOWED_); + value_to_put_map.put(Settings.System.ALARM_ALERT, + SEEMP_API_android_provider_Settings__put_ALARM_ALERT_); + value_to_put_map.put(Settings.System.VIBRATE_ON, + SEEMP_API_android_provider_Settings__put_VIBRATE_ON_); + value_to_put_map.put(Settings.System.USB_MASS_STORAGE_ENABLED, + SEEMP_API_android_provider_Settings__put_USB_MASS_STORAGE_ENABLED_); + value_to_put_map.put(Settings.System.WIFI_WATCHDOG_PING_DELAY_MS, + SEEMP_API_android_provider_Settings__put_WIFI_WATCHDOG_PING_DELAY_MS_); + value_to_put_map.put(Settings.System.FONT_SCALE, + SEEMP_API_android_provider_Settings__put_FONT_SCALE_); + value_to_put_map.put(Settings.System.WIFI_WATCHDOG_AP_COUNT, + SEEMP_API_android_provider_Settings__put_WIFI_WATCHDOG_AP_COUNT_); + value_to_put_map.put(Settings.System.ALWAYS_FINISH_ACTIVITIES, + SEEMP_API_android_provider_Settings__put_ALWAYS_FINISH_ACTIVITIES_); + value_to_put_map.put(Settings.System.ACCELEROMETER_ROTATION, + SEEMP_API_android_provider_Settings__put_ACCELEROMETER_ROTATION_); + value_to_put_map.put(Settings.System.WIFI_WATCHDOG_PING_TIMEOUT_MS, + SEEMP_API_android_provider_Settings__put_WIFI_WATCHDOG_PING_TIMEOUT_MS_); + value_to_put_map.put(Settings.System.VOLUME_NOTIFICATION, + SEEMP_API_android_provider_Settings__put_VOLUME_NOTIFICATION_); + value_to_put_map.put(Settings.System.AIRPLANE_MODE_ON, + SEEMP_API_android_provider_Settings__put_AIRPLANE_MODE_ON_); + value_to_put_map.put(Settings.System.WIFI_WATCHDOG_BACKGROUND_CHECK_DELAY_MS, + SEEMP_API_android_provider_Settings__put_WIFI_WATCHDOG_BACKGROUND_CHECK_DELAY_MS_); + value_to_put_map.put(Settings.System.WIFI_STATIC_IP, + SEEMP_API_android_provider_Settings__put_WIFI_STATIC_IP_); + value_to_put_map.put(Settings.System.RADIO_BLUETOOTH, + SEEMP_API_android_provider_Settings__put_RADIO_BLUETOOTH_); + value_to_put_map.put(Settings.System.BLUETOOTH_DISCOVERABILITY_TIMEOUT, + SEEMP_API_android_provider_Settings__put_BLUETOOTH_DISCOVERABILITY_TIMEOUT_); + value_to_put_map.put(Settings.System.VOLUME_RING, + SEEMP_API_android_provider_Settings__put_VOLUME_RING_); + value_to_put_map.put(Settings.System.MODE_RINGER_STREAMS_AFFECTED, + SEEMP_API_android_provider_Settings__put_MODE_RINGER_STREAMS_AFFECTED_); + value_to_put_map.put(Settings.System.VOLUME_SYSTEM, + SEEMP_API_android_provider_Settings__put_VOLUME_SYSTEM_); + value_to_put_map.put(Settings.System.SCREEN_OFF_TIMEOUT, + SEEMP_API_android_provider_Settings__put_SCREEN_OFF_TIMEOUT_); + value_to_put_map.put(Settings.System.RADIO_WIFI, + SEEMP_API_android_provider_Settings__put_RADIO_WIFI_); + value_to_put_map.put(Settings.System.AUTO_TIME_ZONE, + SEEMP_API_android_provider_Settings__put_AUTO_TIME_ZONE_); + value_to_put_map.put(Settings.System.TEXT_AUTO_CAPS, + SEEMP_API_android_provider_Settings__put_TEXT_AUTO_CAPS_); + value_to_put_map.put(Settings.System.WALLPAPER_ACTIVITY, + SEEMP_API_android_provider_Settings__put_WALLPAPER_ACTIVITY_); + value_to_put_map.put(Settings.System.ANIMATOR_DURATION_SCALE, + SEEMP_API_android_provider_Settings__put_ANIMATOR_DURATION_SCALE_); + value_to_put_map.put(Settings.System.WIFI_NUM_OPEN_NETWORKS_KEPT, + SEEMP_API_android_provider_Settings__put_WIFI_NUM_OPEN_NETWORKS_KEPT_); + value_to_put_map.put(Settings.System.LOCK_PATTERN_VISIBLE, + SEEMP_API_android_provider_Settings__put_LOCK_PATTERN_VISIBLE_); + value_to_put_map.put(Settings.System.VOLUME_VOICE, + SEEMP_API_android_provider_Settings__put_VOLUME_VOICE_); + value_to_put_map.put(Settings.System.DEBUG_APP, + SEEMP_API_android_provider_Settings__put_DEBUG_APP_); + value_to_put_map.put(Settings.System.WIFI_ON, + SEEMP_API_android_provider_Settings__put_WIFI_ON_); + value_to_put_map.put(Settings.System.TEXT_SHOW_PASSWORD, + SEEMP_API_android_provider_Settings__put_TEXT_SHOW_PASSWORD_); + value_to_put_map.put(Settings.System.WIFI_NETWORKS_AVAILABLE_REPEAT_DELAY, + SEEMP_API_android_provider_Settings__put_WIFI_NETWORKS_AVAILABLE_REPEAT_DELAY_); + value_to_put_map.put(Settings.System.WIFI_SLEEP_POLICY, + SEEMP_API_android_provider_Settings__put_WIFI_SLEEP_POLICY_); + value_to_put_map.put(Settings.System.VOLUME_MUSIC, + SEEMP_API_android_provider_Settings__put_VOLUME_MUSIC_); + value_to_put_map.put(Settings.System.PARENTAL_CONTROL_LAST_UPDATE, + SEEMP_API_android_provider_Settings__put_PARENTAL_CONTROL_LAST_UPDATE_); + value_to_put_map.put(Settings.System.DEVICE_PROVISIONED, + SEEMP_API_android_provider_Settings__put_DEVICE_PROVISIONED_); + value_to_put_map.put(Settings.System.HTTP_PROXY, + SEEMP_API_android_provider_Settings__put_HTTP_PROXY_); + value_to_put_map.put(Settings.System.ANDROID_ID, + SEEMP_API_android_provider_Settings__put_ANDROID_ID_); + value_to_put_map.put(Settings.System.WIFI_WATCHDOG_MAX_AP_CHECKS, + SEEMP_API_android_provider_Settings__put_WIFI_WATCHDOG_MAX_AP_CHECKS_); + value_to_put_map.put(Settings.System.END_BUTTON_BEHAVIOR, + SEEMP_API_android_provider_Settings__put_END_BUTTON_BEHAVIOR_); + value_to_put_map.put(Settings.System.NEXT_ALARM_FORMATTED, + SEEMP_API_android_provider_Settings__put_NEXT_ALARM_FORMATTED_); + value_to_put_map.put(Settings.System.RADIO_CELL, + SEEMP_API_android_provider_Settings__put_RADIO_CELL_); + value_to_put_map.put(Settings.System.PARENTAL_CONTROL_ENABLED, + SEEMP_API_android_provider_Settings__put_PARENTAL_CONTROL_ENABLED_); + value_to_put_map.put(Settings.System.BLUETOOTH_ON, + SEEMP_API_android_provider_Settings__put_BLUETOOTH_ON_); + value_to_put_map.put(Settings.System.WINDOW_ANIMATION_SCALE, + SEEMP_API_android_provider_Settings__put_WINDOW_ANIMATION_SCALE_); + value_to_put_map.put(Settings.System.WIFI_WATCHDOG_BACKGROUND_CHECK_ENABLED, + SEEMP_API_android_provider_Settings__put_WIFI_WATCHDOG_BACKGROUND_CHECK_ENABLED_); + value_to_put_map.put(Settings.System.BLUETOOTH_DISCOVERABILITY, + SEEMP_API_android_provider_Settings__put_BLUETOOTH_DISCOVERABILITY_); + value_to_put_map.put(Settings.System.WIFI_STATIC_DNS1, + SEEMP_API_android_provider_Settings__put_WIFI_STATIC_DNS1_); + value_to_put_map.put(Settings.System.WIFI_STATIC_DNS2, + SEEMP_API_android_provider_Settings__put_WIFI_STATIC_DNS2_); + value_to_put_map.put(Settings.System.HAPTIC_FEEDBACK_ENABLED, + SEEMP_API_android_provider_Settings__put_HAPTIC_FEEDBACK_ENABLED_); + value_to_put_map.put(Settings.System.SHOW_WEB_SUGGESTIONS, + SEEMP_API_android_provider_Settings__put_SHOW_WEB_SUGGESTIONS_); + value_to_put_map.put(Settings.System.PARENTAL_CONTROL_REDIRECT_URL, + SEEMP_API_android_provider_Settings__put_PARENTAL_CONTROL_REDIRECT_URL_); + value_to_put_map.put(Settings.System.DATE_FORMAT, + SEEMP_API_android_provider_Settings__put_DATE_FORMAT_); + value_to_put_map.put(Settings.System.RADIO_NFC, + SEEMP_API_android_provider_Settings__put_RADIO_NFC_); + value_to_put_map.put(Settings.System.AIRPLANE_MODE_RADIOS, + SEEMP_API_android_provider_Settings__put_AIRPLANE_MODE_RADIOS_); + value_to_put_map.put(Settings.System.LOCK_PATTERN_TACTILE_FEEDBACK_ENABLED, + SEEMP_API_android_provider_Settings__put_LOCK_PATTERN_TACTILE_FEEDBACK_ENABLED_); + value_to_put_map.put(Settings.System.TIME_12_24, + SEEMP_API_android_provider_Settings__put_TIME_12_24_); + value_to_put_map.put(Settings.System.WIFI_WATCHDOG_INITIAL_IGNORED_PING_COUNT, + SEEMP_API_android_provider_Settings__put_WIFI_WATCHDOG_INITIAL_IGNORED_PING_COUNT_); + value_to_put_map.put(Settings.System.VOLUME_BLUETOOTH_SCO, + SEEMP_API_android_provider_Settings__put_VOLUME_BLUETOOTH_SCO_); + value_to_put_map.put(Settings.System.USER_ROTATION, + SEEMP_API_android_provider_Settings__put_USER_ROTATION_); + value_to_put_map.put(Settings.System.WIFI_STATIC_GATEWAY, + SEEMP_API_android_provider_Settings__put_WIFI_STATIC_GATEWAY_); + value_to_put_map.put(Settings.System.STAY_ON_WHILE_PLUGGED_IN, + SEEMP_API_android_provider_Settings__put_STAY_ON_WHILE_PLUGGED_IN_); + value_to_put_map.put(Settings.System.SOUND_EFFECTS_ENABLED, + SEEMP_API_android_provider_Settings__put_SOUND_EFFECTS_ENABLED_); + value_to_put_map.put(Settings.System.WIFI_WATCHDOG_PING_COUNT, + SEEMP_API_android_provider_Settings__put_WIFI_WATCHDOG_PING_COUNT_); + value_to_put_map.put(Settings.System.DATA_ROAMING, + SEEMP_API_android_provider_Settings__put_DATA_ROAMING_); + value_to_put_map.put(Settings.System.SETTINGS_CLASSNAME, + SEEMP_API_android_provider_Settings__put_SETTINGS_CLASSNAME_); + value_to_put_map.put(Settings.System.TRANSITION_ANIMATION_SCALE, + SEEMP_API_android_provider_Settings__put_TRANSITION_ANIMATION_SCALE_); + value_to_put_map.put(Settings.System.WAIT_FOR_DEBUGGER, + SEEMP_API_android_provider_Settings__put_WAIT_FOR_DEBUGGER_); + value_to_put_map.put(Settings.System.INSTALL_NON_MARKET_APPS, + SEEMP_API_android_provider_Settings__put_INSTALL_NON_MARKET_APPS_); + value_to_put_map.put(Settings.System.ADB_ENABLED, + SEEMP_API_android_provider_Settings__put_ADB_ENABLED_); + value_to_put_map.put(Settings.System.WIFI_USE_STATIC_IP, + SEEMP_API_android_provider_Settings__put_WIFI_USE_STATIC_IP_); + value_to_put_map.put(Settings.System.DIM_SCREEN, + SEEMP_API_android_provider_Settings__put_DIM_SCREEN_); + value_to_put_map.put(Settings.System.VOLUME_ALARM, + SEEMP_API_android_provider_Settings__put_VOLUME_ALARM_); + value_to_put_map.put(Settings.System.WIFI_WATCHDOG_ON, + SEEMP_API_android_provider_Settings__put_WIFI_WATCHDOG_ON_); + value_to_put_map.put(Settings.System.WIFI_STATIC_NETMASK, + SEEMP_API_android_provider_Settings__put_WIFI_STATIC_NETMASK_); + value_to_put_map.put(Settings.System.NETWORK_PREFERENCE, + SEEMP_API_android_provider_Settings__put_NETWORK_PREFERENCE_); + value_to_put_map.put(Settings.System.SHOW_PROCESSES, + SEEMP_API_android_provider_Settings__put_SHOW_PROCESSES_); + value_to_put_map.put(Settings.System.TEXT_AUTO_REPLACE, + SEEMP_API_android_provider_Settings__put_TEXT_AUTO_REPLACE_); + value_to_put_map.put(Settings.System.WIFI_NETWORKS_AVAILABLE_NOTIFICATION_ON, + SEEMP_API_android_provider_Settings__put_WIFI_NETWORKS_AVAILABLE_NOTIFICATION_ON_); + value_to_put_map.put(Settings.System.APPEND_FOR_LAST_AUDIBLE, + SEEMP_API_android_provider_Settings__put_APPEND_FOR_LAST_AUDIBLE_); + value_to_put_map.put(Settings.System.SHOW_GTALK_SERVICE_STATUS, + SEEMP_API_android_provider_Settings__put_SHOW_GTALK_SERVICE_STATUS_); + value_to_put_map.put(Settings.System.SCREEN_BRIGHTNESS, + SEEMP_API_android_provider_Settings__put_SCREEN_BRIGHTNESS_); + value_to_put_map.put(Settings.System.USE_GOOGLE_MAIL, + SEEMP_API_android_provider_Settings__put_USE_GOOGLE_MAIL_); + value_to_put_map.put(Settings.System.RINGTONE, + SEEMP_API_android_provider_Settings__put_RINGTONE_); + value_to_put_map.put(Settings.System.LOGGING_ID, + SEEMP_API_android_provider_Settings__put_LOGGING_ID_); + value_to_put_map.put(Settings.System.MODE_RINGER, + SEEMP_API_android_provider_Settings__put_MODE_RINGER_); + value_to_put_map.put(Settings.System.MUTE_STREAMS_AFFECTED, + SEEMP_API_android_provider_Settings__put_MUTE_STREAMS_AFFECTED_); + value_to_put_map.put(Settings.System.WIFI_WATCHDOG_ACCEPTABLE_PACKET_LOSS_PERCENTAGE, + SEEMP_API_android_provider_Settings__put_WIFI_WATCHDOG_ACCEPTABLE_PACKET_LOSS_PERCENTAGE_); + value_to_put_map.put(Settings.System.TEXT_AUTO_PUNCTUATE, + SEEMP_API_android_provider_Settings__put_TEXT_AUTO_PUNCTUATE_); + value_to_put_map.put(Settings.System.WIFI_MOBILE_DATA_TRANSITION_WAKELOCK_TIMEOUT_MS, + SEEMP_API_android_provider_Settings__put_WIFI_MOBILE_DATA_TRANSITION_WAKELOCK_TIMEOUT_MS_); + value_to_put_map.put(Settings.System.SCREEN_BRIGHTNESS_MODE, + SEEMP_API_android_provider_Settings__put_SCREEN_BRIGHTNESS_MODE_); + } + + public static int getSeempPutApiIdFromValue( String v ) + { + Integer result = value_to_put_map.get( v ); + if (result == null) + { + result = -1; + } + return result; + } +} diff --git a/core/java/android/util/SparseArrayMap.java b/core/java/android/util/SparseArrayMap.java index 3287c279c87f..17a4c3aa865c 100644 --- a/core/java/android/util/SparseArrayMap.java +++ b/core/java/android/util/SparseArrayMap.java @@ -18,6 +18,7 @@ package android.util; import android.annotation.NonNull; import android.annotation.Nullable; +import android.annotation.SuppressLint; import android.annotation.TestApi; import java.util.function.Consumer; @@ -78,6 +79,7 @@ public class SparseArrayMap<K, V> { /** * Get the value associated with the int-K pair. */ + @SuppressLint("KotlinOperator") @Nullable public V get(int key, @NonNull K mapKey) { ArrayMap<K, V> data = mData.get(key); diff --git a/core/java/android/util/TrustedTime.java b/core/java/android/util/TrustedTime.java index f279bdb79420..ca236ed7e42f 100644 --- a/core/java/android/util/TrustedTime.java +++ b/core/java/android/util/TrustedTime.java @@ -30,6 +30,12 @@ public interface TrustedTime { /** * Force update with an external trusted time source, returning {@code true} * when successful. + */ + public boolean forceSync(); + + /** + * Force update the cached time with an external trusted time source, + * returning {@code true} when successful. * * @deprecated Only kept for UnsupportedAppUsage. Do not use. See {@link NtpTrustedTime} */ diff --git a/core/java/android/util/apk/ApkSignatureVerifier.java b/core/java/android/util/apk/ApkSignatureVerifier.java index 73f7543ba819..36d97af6fb0d 100644 --- a/core/java/android/util/apk/ApkSignatureVerifier.java +++ b/core/java/android/util/apk/ApkSignatureVerifier.java @@ -30,7 +30,10 @@ import android.content.pm.Signature; import android.content.pm.parsing.ParsingPackageUtils; import android.os.Build; import android.os.Trace; +import android.util.ArrayMap; +import android.util.Slog; import android.util.jar.StrictJarFile; +import android.util.BoostFramework; import com.android.internal.util.ArrayUtils; @@ -49,6 +52,9 @@ import java.util.List; import java.util.Map; import java.util.concurrent.atomic.AtomicReference; import java.util.zip.ZipEntry; +import java.util.concurrent.ThreadPoolExecutor; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.LinkedBlockingQueue; /** * Facade class that takes care of the details of APK verification on @@ -60,6 +66,12 @@ public class ApkSignatureVerifier { private static final AtomicReference<byte[]> sBuffer = new AtomicReference<>(); + private static final String TAG = "ApkSignatureVerifier"; + // multithread verification + private static final int NUMBER_OF_CORES = + Runtime.getRuntime().availableProcessors() >= 4 ? 4 : Runtime.getRuntime().availableProcessors() ; + private static BoostFramework sPerfBoost = null; + private static boolean sIsPerfLockAcquired = false; /** * Verifies the provided APK and returns the certificates associated with each signer. * @@ -354,31 +366,44 @@ public class ApkSignatureVerifier { */ private static SigningDetailsWithDigests verifyV1Signature(String apkPath, boolean verifyFull) throws PackageParserException { - StrictJarFile jarFile = null; - + int objectNumber = verifyFull ? NUMBER_OF_CORES : 1; + StrictJarFile[] jarFile = new StrictJarFile[objectNumber]; + final ArrayMap<String, StrictJarFile> strictJarFiles = new ArrayMap<String, StrictJarFile>(); try { final Certificate[][] lastCerts; final Signature[] lastSigs; Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "strictJarFileCtor"); + if (sPerfBoost == null) { + sPerfBoost = new BoostFramework(); + } + if (sPerfBoost != null && !sIsPerfLockAcquired && verifyFull) { + //Use big enough number here to hold the perflock for entire PackageInstall session + sPerfBoost.perfHint(BoostFramework.VENDOR_HINT_PACKAGE_INSTALL_BOOST, + null, Integer.MAX_VALUE, -1); + Slog.d(TAG, "Perflock acquired for PackageInstall "); + sIsPerfLockAcquired = true; + } // we still pass verify = true to ctor to collect certs, even though we're not checking // the whole jar. - jarFile = new StrictJarFile( - apkPath, - true, // collect certs - verifyFull); // whether to reject APK with stripped v2 signatures (b/27887819) + for (int i = 0; i < objectNumber; i++) { + jarFile[i] = new StrictJarFile( + apkPath, + true, // collect certs + verifyFull); // whether to reject APK with stripped v2 signatures (b/27887819) + } final List<ZipEntry> toVerify = new ArrayList<>(); // Gather certs from AndroidManifest.xml, which every APK must have, as an optimization // to not need to verify the whole APK when verifyFUll == false. - final ZipEntry manifestEntry = jarFile.findEntry( + final ZipEntry manifestEntry = jarFile[0].findEntry( ParsingPackageUtils.ANDROID_MANIFEST_FILENAME); if (manifestEntry == null) { throw new PackageParserException(INSTALL_PARSE_FAILED_BAD_MANIFEST, "Package " + apkPath + " has no manifest"); } - lastCerts = loadCertificates(jarFile, manifestEntry); + lastCerts = loadCertificates(jarFile[0], manifestEntry); if (ArrayUtils.isEmpty(lastCerts)) { throw new PackageParserException(INSTALL_PARSE_FAILED_NO_CERTIFICATES, "Package " + apkPath + " has no certificates at entry " @@ -388,7 +413,7 @@ public class ApkSignatureVerifier { // fully verify all contents, except for AndroidManifest.xml and the META-INF/ files. if (verifyFull) { - final Iterator<ZipEntry> i = jarFile.iterator(); + final Iterator<ZipEntry> i = jarFile[0].iterator(); while (i.hasNext()) { final ZipEntry entry = i.next(); if (entry.isDirectory()) continue; @@ -399,24 +424,93 @@ public class ApkSignatureVerifier { toVerify.add(entry); } - + class VerificationData { + public Exception exception; + public int exceptionFlag; + public boolean wait; + public int index; + public Object objWaitAll; + public boolean shutDown; + } + VerificationData vData = new VerificationData(); + vData.objWaitAll = new Object(); + final ThreadPoolExecutor verificationExecutor = new ThreadPoolExecutor( + NUMBER_OF_CORES, + NUMBER_OF_CORES, + 1,/*keep alive time*/ + TimeUnit.SECONDS, + new LinkedBlockingQueue<Runnable>()); for (ZipEntry entry : toVerify) { - final Certificate[][] entryCerts = loadCertificates(jarFile, entry); - if (ArrayUtils.isEmpty(entryCerts)) { - throw new PackageParserException(INSTALL_PARSE_FAILED_NO_CERTIFICATES, - "Package " + apkPath + " has no certificates at entry " - + entry.getName()); + Runnable verifyTask = new Runnable(){ + public void run() { + try { + if (vData.exceptionFlag != 0 ) { + Slog.w(TAG, "VerifyV1 exit with exception " + vData.exceptionFlag); + return; + } + String tid = Long.toString(Thread.currentThread().getId()); + StrictJarFile tempJarFile; + synchronized (strictJarFiles) { + tempJarFile = strictJarFiles.get(tid); + if (tempJarFile == null) { + if (vData.index >= NUMBER_OF_CORES) { + vData.index = 0; + } + tempJarFile = jarFile[vData.index++]; + strictJarFiles.put(tid, tempJarFile); + } + } + final Certificate[][] entryCerts = loadCertificates(tempJarFile, entry); + if (ArrayUtils.isEmpty(entryCerts)) { + throw new PackageParserException(INSTALL_PARSE_FAILED_NO_CERTIFICATES, + "Package " + apkPath + " has no certificates at entry " + + entry.getName()); + } + + // make sure all entries use the same signing certs + final Signature[] entrySigs = convertToSignatures(entryCerts); + if (!Signature.areExactMatch(lastSigs, entrySigs)) { + throw new PackageParserException( + INSTALL_PARSE_FAILED_INCONSISTENT_CERTIFICATES, + "Package " + apkPath + " has mismatched certificates at entry " + + entry.getName()); + } + } catch (GeneralSecurityException e) { + synchronized (vData.objWaitAll) { + vData.exceptionFlag = INSTALL_PARSE_FAILED_CERTIFICATE_ENCODING; + vData.exception = e; + } + } catch (PackageParserException e) { + synchronized (vData.objWaitAll) { + vData.exceptionFlag = INSTALL_PARSE_FAILED_UNEXPECTED_EXCEPTION; + vData.exception = e; + } + } + }}; + synchronized (vData.objWaitAll) { + if (vData.exceptionFlag == 0) { + verificationExecutor.execute(verifyTask); + } } - - // make sure all entries use the same signing certs - final Signature[] entrySigs = convertToSignatures(entryCerts); - if (!Signature.areExactMatch(lastSigs, entrySigs)) { - throw new PackageParserException( - INSTALL_PARSE_FAILED_INCONSISTENT_CERTIFICATES, - "Package " + apkPath + " has mismatched certificates at entry " - + entry.getName()); + } + vData.wait = true; + verificationExecutor.shutdown(); + while (vData.wait) { + try { + if (vData.exceptionFlag != 0 && !vData.shutDown) { + Slog.w(TAG, "verifyV1 Exception " + vData.exceptionFlag); + verificationExecutor.shutdownNow(); + vData.shutDown = true; + } + vData.wait = !verificationExecutor.awaitTermination(50, + TimeUnit.MILLISECONDS); + } catch (InterruptedException e) { + Slog.w(TAG,"VerifyV1 interrupted while awaiting all threads done..."); } } + if (vData.exceptionFlag != 0) + throw new PackageParserException(vData.exceptionFlag, + "Failed to collect certificates from " + apkPath, vData.exception); } return new SigningDetailsWithDigests( new PackageParser.SigningDetails(lastSigs, SignatureSchemeVersion.JAR), null); @@ -427,8 +521,16 @@ public class ApkSignatureVerifier { throw new PackageParserException(INSTALL_PARSE_FAILED_NO_CERTIFICATES, "Failed to collect certificates from " + apkPath, e); } finally { + if (sIsPerfLockAcquired && sPerfBoost != null) { + sPerfBoost.perfLockRelease(); + sIsPerfLockAcquired = false; + Slog.d(TAG, "Perflock released for PackageInstall "); + } + strictJarFiles.clear(); Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER); - closeQuietly(jarFile); + for (int i = 0; i < objectNumber ; i++) { + closeQuietly(jarFile[i]); + } } } diff --git a/core/java/android/view/Choreographer.java b/core/java/android/view/Choreographer.java index be172f748b55..39beeeae11de 100644 --- a/core/java/android/view/Choreographer.java +++ b/core/java/android/view/Choreographer.java @@ -31,6 +31,7 @@ import android.os.Message; import android.os.SystemClock; import android.os.SystemProperties; import android.os.Trace; +import android.util.BoostFramework.ScrollOptimizer; import android.util.Log; import android.util.TimeUtils; import android.view.animation.AnimationUtils; @@ -84,6 +85,7 @@ public final class Choreographer { // Prints debug messages about jank which was detected (low volume). private static final boolean DEBUG_JANK = false; + private static final boolean OPTS_INPUT = true; // Prints debug messages about every frame and callback registered (high volume). private static final boolean DEBUG_FRAMES = false; @@ -151,6 +153,11 @@ public final class Choreographer { private static final int MSG_DO_SCHEDULE_VSYNC = 1; private static final int MSG_DO_SCHEDULE_CALLBACK = 2; + private static final int MOTION_EVENT_ACTION_DOWN = 0; + private static final int MOTION_EVENT_ACTION_UP = 1; + private static final int MOTION_EVENT_ACTION_MOVE = 2; + private static final int MOTION_EVENT_ACTION_CANCEL = 3; + // All frame callbacks posted by applications have this token. private static final Object FRAME_CALLBACK_TOKEN = new Object() { public String toString() { return "FRAME_CALLBACK_TOKEN"; } @@ -189,6 +196,13 @@ public final class Choreographer { private int mFPSDivisor = 1; private DisplayEventReceiver.VsyncEventData mLastVsyncEventData = new DisplayEventReceiver.VsyncEventData(); + private int mTouchMoveNum = -1; + private int mMotionEventType = -1; + private boolean mConsumedMove = false; + private boolean mConsumedDown = false; + private boolean mIsVsyncScheduled = false; + private long mLastTouchOptTimeNanos = 0; + private boolean mIsDoFrameProcessing = false; /** * Contains information about the current frame for jank-tracking, @@ -270,6 +284,7 @@ public final class Choreographer { mLastFrameTimeNanos = Long.MIN_VALUE; mFrameIntervalNanos = (long)(1000000000 / getRefreshRate()); + ScrollOptimizer.setFrameInterval(mFrameIntervalNanos); mCallbackQueues = new CallbackQueue[CALLBACK_LAST + 1]; for (int i = 0; i <= CALLBACK_LAST; i++) { @@ -305,6 +320,17 @@ public final class Choreographer { } /** + * {@hide} + */ + public void setMotionEventInfo(int motionEventType, int touchMoveNum) { + synchronized(this) { + mTouchMoveNum = touchMoveNum; + mMotionEventType = motionEventType; + ScrollOptimizer.setMotionType(mMotionEventType); + } + } + + /** * @return The Choreographer of the main thread, if it exists, or {@code null} otherwise. * @hide */ @@ -636,7 +662,55 @@ public final class Choreographer { private void scheduleFrameLocked(long now) { if (!mFrameScheduled) { mFrameScheduled = true; - if (USE_VSYNC) { + if (OPTS_INPUT) { + if (!mIsVsyncScheduled) { + long curr = System.nanoTime(); + boolean skipFlag = curr - mLastTouchOptTimeNanos < mFrameIntervalNanos; + Trace.traceBegin(Trace.TRACE_TAG_VIEW, "scheduleFrameLocked-mMotionEventType:" + + mMotionEventType + " mTouchMoveNum:"+ mTouchMoveNum + + " mConsumedDown:" + mConsumedDown + + " mConsumedMove:" + mConsumedMove + + " mIsDoFrameProcessing:" + mIsDoFrameProcessing + + " skip:" + skipFlag + + " diff:" + (curr - mLastTouchOptTimeNanos)); + Trace.traceEnd(Trace.TRACE_TAG_VIEW); + synchronized(this) { + switch(mMotionEventType) { + case MOTION_EVENT_ACTION_DOWN: + mConsumedMove = false; + if (!mConsumedDown && !skipFlag && !mIsDoFrameProcessing) { + Message msg = mHandler.obtainMessage(MSG_DO_FRAME); + msg.setAsynchronous(true); + mHandler.sendMessageAtFrontOfQueue(msg); + mLastTouchOptTimeNanos = System.nanoTime(); + mConsumedDown = true; + return; + } + break; + case MOTION_EVENT_ACTION_MOVE: + mConsumedDown = false; + //if ((mTouchMoveNum == 1) && !mConsumedMove && !skipFlag) { + if (!mConsumedMove && !skipFlag && !mIsDoFrameProcessing) { + Message msg = mHandler.obtainMessage(MSG_DO_FRAME); + msg.setAsynchronous(true); + mHandler.sendMessageAtFrontOfQueue(msg); + mLastTouchOptTimeNanos = System.nanoTime(); + mConsumedMove = true; + return; + } + break; + case MOTION_EVENT_ACTION_UP: + case MOTION_EVENT_ACTION_CANCEL: + mConsumedMove = false; + mConsumedDown = false; + break; + default: + break; + } + } + } + } + if (ScrollOptimizer.shouldUseVsync(USE_VSYNC)) { if (DEBUG_FRAMES) { Log.d(TAG, "Scheduling next frame on vsync."); } @@ -652,6 +726,8 @@ public final class Choreographer { mHandler.sendMessageAtFrontOfQueue(msg); } } else { + sFrameDelay = ScrollOptimizer.getFrameDelay(sFrameDelay, + mLastFrameTimeNanos); final long nextFrameTime = Math.max( mLastFrameTimeNanos / TimeUtils.NANOS_PER_MS + sFrameDelay, now); if (DEBUG_FRAMES) { @@ -703,11 +779,13 @@ public final class Choreographer { final long startNanos; final long frameIntervalNanos = vsyncEventData.frameInterval; try { + mIsDoFrameProcessing = true; if (Trace.isTagEnabled(Trace.TRACE_TAG_VIEW)) { Trace.traceBegin(Trace.TRACE_TAG_VIEW, "Choreographer#doFrame " + vsyncEventData.id); } synchronized (mLock) { + mIsVsyncScheduled = false; if (!mFrameScheduled) { traceMessage("Frame not scheduled"); return; // no work to do @@ -766,6 +844,7 @@ public final class Choreographer { mLastVsyncEventData = vsyncEventData; } + ScrollOptimizer.setUITaskStatus(true); AnimationUtils.lockAnimationClock(frameTimeNanos / TimeUtils.NANOS_PER_MS); mFrameInfo.markInputHandlingStart(); @@ -780,6 +859,7 @@ public final class Choreographer { doCallbacks(Choreographer.CALLBACK_TRAVERSAL, frameTimeNanos, frameIntervalNanos); doCallbacks(Choreographer.CALLBACK_COMMIT, frameTimeNanos, frameIntervalNanos); + ScrollOptimizer.setUITaskStatus(false); } finally { AnimationUtils.unlockAnimationClock(); Trace.traceEnd(Trace.TRACE_TAG_VIEW); @@ -791,6 +871,7 @@ public final class Choreographer { + (endNanos - startNanos) * 0.000001f + " ms, latency " + (startNanos - frameTimeNanos) * 0.000001f + " ms."); } + mIsDoFrameProcessing = false; } void doCallbacks(int callbackType, long frameTimeNanos, long frameIntervalNanos) { @@ -881,6 +962,7 @@ public final class Choreographer { try { Trace.traceBegin(Trace.TRACE_TAG_VIEW, "Choreographer#scheduleVsyncLocked"); mDisplayEventReceiver.scheduleVsync(); + mIsVsyncScheduled = true; } finally { Trace.traceEnd(Trace.TRACE_TAG_VIEW); } @@ -1008,6 +1090,7 @@ public final class Choreographer { mTimestampNanos = timestampNanos; mFrame = frame; mLastVsyncEventData = vsyncEventData; + ScrollOptimizer.setVsyncTime(mTimestampNanos); Message msg = Message.obtain(mHandler, this); msg.setAsynchronous(true); mHandler.sendMessageAtTime(msg, timestampNanos / TimeUtils.NANOS_PER_MS); diff --git a/core/java/android/view/DisplayCutout.java b/core/java/android/view/DisplayCutout.java index c1a5636b7b34..0632dbc6b691 100644 --- a/core/java/android/view/DisplayCutout.java +++ b/core/java/android/view/DisplayCutout.java @@ -38,6 +38,7 @@ import android.graphics.Path; import android.graphics.Rect; import android.os.Parcel; import android.os.Parcelable; +import android.os.SystemProperties; import android.text.TextUtils; import android.util.DisplayUtils; import android.util.Pair; @@ -1038,7 +1039,11 @@ public final class DisplayCutout { if (TextUtils.isEmpty(spec) && waterfallInsets.equals(Insets.NONE)) { return NULL_PAIR; } - + int disableRoundedCorner = + SystemProperties.getInt("vendor.display.disable_rounded_corner", 0); + if (disableRoundedCorner == 1) { + return NULL_PAIR; + } synchronized (CACHE_LOCK) { if (spec.equals(sCachedSpec) && sCachedDisplayWidth == displayWidth && sCachedDisplayHeight == displayHeight diff --git a/core/java/android/view/InputEventReceiver.java b/core/java/android/view/InputEventReceiver.java index 25dda5b2e0bb..f28242aa8215 100644 --- a/core/java/android/view/InputEventReceiver.java +++ b/core/java/android/view/InputEventReceiver.java @@ -49,6 +49,7 @@ public abstract class InputEventReceiver { // Map from InputEvent sequence numbers to dispatcher sequence numbers. private final SparseIntArray mSeqMap = new SparseIntArray(); + Choreographer mChoreographer; private static native long nativeInit(WeakReference<InputEventReceiver> receiver, InputChannel inputChannel, MessageQueue messageQueue); @@ -259,6 +260,19 @@ public abstract class InputEventReceiver { onInputEvent(event); } + // Called from native code. + @SuppressWarnings("unused") + private void dispatchMotionEventInfo(int motionEventType, int touchMoveNum) { + try { + if (mChoreographer == null) + mChoreographer = Choreographer.getInstance(); + + if (mChoreographer != null) + mChoreographer.setMotionEventInfo(motionEventType, touchMoveNum); + } catch (Exception e) { + Log.e(TAG, "cannot invoke setMotionEventInfo."); + } + } /** * Dump the state of this InputEventReceiver to the writer. * @param prefix the prefix (typically whitespace padding) to append in front of each line diff --git a/core/java/android/view/SurfaceView.java b/core/java/android/view/SurfaceView.java index 0e49cc967656..49a55a43b7ab 100644 --- a/core/java/android/view/SurfaceView.java +++ b/core/java/android/view/SurfaceView.java @@ -859,6 +859,26 @@ public class SurfaceView extends View implements ViewRootImpl.SurfaceChangedCall } } + /** + * Control whether the surface view's content should flow through + * protected hardware path to display disallowing access from non-secure + * execution environments. + * + * <p>Note that this must be set before the surface view's containing + * window is attached to the window manager. + * + * @param isProtected True if the surface view is protected. + * + * @hide + */ + public void setProtected(boolean isProtected) { + if (isProtected) { + mSurfaceFlags |= SurfaceControl.PROTECTED_APP; + } else { + mSurfaceFlags &= ~SurfaceControl.PROTECTED_APP; + } + } + private void updateOpaqueFlag() { if (!PixelFormat.formatHasAlpha(mRequestedFormat)) { mSurfaceFlags |= SurfaceControl.OPAQUE; diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java index f4386099a550..79e52995ade3 100644 --- a/core/java/android/view/View.java +++ b/core/java/android/view/View.java @@ -14580,6 +14580,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback, final int actionMasked = event.getActionMasked(); if (actionMasked == MotionEvent.ACTION_DOWN) { + android.util.SeempLog.record(3); // Defensive cleanup for new gesture stopNestedScroll(); } @@ -15260,6 +15261,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback, * @param event the KeyEvent object that defines the button action */ public boolean onKeyDown(int keyCode, KeyEvent event) { + android.util.SeempLog.record(4); if (KeyEvent.isConfirmKey(keyCode)) { if ((mViewFlags & ENABLED_MASK) == DISABLED) { return true; @@ -15317,6 +15319,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback, * @param event The KeyEvent object that defines the button action. */ public boolean onKeyUp(int keyCode, KeyEvent event) { + android.util.SeempLog.record(5); if (KeyEvent.isConfirmKey(keyCode)) { if ((mViewFlags & ENABLED_MASK) == DISABLED) { return true; @@ -15961,6 +15964,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback, * @return True if the event was handled, false otherwise. */ public boolean onTouchEvent(MotionEvent event) { + android.util.SeempLog.record(3); final float x = event.getX(); final float y = event.getY(); final int viewFlags = mViewFlags; diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java index f1eb783726db..6aa85a6cc1d4 100644 --- a/core/java/android/view/ViewRootImpl.java +++ b/core/java/android/view/ViewRootImpl.java @@ -141,6 +141,7 @@ import android.os.UserHandle; import android.sysprop.DisplayProperties; import android.util.AndroidRuntimeException; import android.util.ArraySet; +import android.util.BoostFramework.ScrollOptimizer; import android.util.DisplayMetrics; import android.util.EventLog; import android.util.IndentingPrintWriter; @@ -791,6 +792,7 @@ public final class ViewRootImpl implements ViewParent, private int mSurfaceSequenceId = 0; private String mTag = TAG; + boolean mHaveMoveEvent = false; public ViewRootImpl(Context context, Display display) { this(context, display, WindowManagerGlobal.getWindowSession(), @@ -2026,6 +2028,7 @@ public final class ViewRootImpl implements ViewParent, mSurfaceSize.x, mSurfaceSize.y, mWindowAttributes.format); } + ScrollOptimizer.setBLASTBufferQueue(mBlastBufferQueue); return ret; } @@ -6444,6 +6447,12 @@ public final class ViewRootImpl implements ViewParent, mAttachInfo.mUnbufferedDispatchRequested = false; mAttachInfo.mHandlingPointerEvent = true; boolean handled = mView.dispatchPointerEvent(event); + int action = event.getActionMasked(); + if (action == MotionEvent.ACTION_MOVE) { + mHaveMoveEvent = true; + } else if (action == MotionEvent.ACTION_UP) { + mHaveMoveEvent = false; + } maybeUpdatePointerIcon(event); maybeUpdateTooltip(event); mAttachInfo.mHandlingPointerEvent = false; @@ -8629,6 +8638,7 @@ public final class ViewRootImpl implements ViewParent, } void doProcessInputEvents() { + ScrollOptimizer.setBLASTBufferQueue(mBlastBufferQueue); // Deliver all pending input events in the queue. while (mPendingInputEventHead != null) { QueuedInputEvent q = mPendingInputEventHead; diff --git a/core/java/android/view/WindowManagerImpl.java b/core/java/android/view/WindowManagerImpl.java index a2d3e3447354..3ad4e353f0cb 100644 --- a/core/java/android/view/WindowManagerImpl.java +++ b/core/java/android/view/WindowManagerImpl.java @@ -134,6 +134,7 @@ public final class WindowManagerImpl implements WindowManager { @Override public void addView(@NonNull View view, @NonNull ViewGroup.LayoutParams params) { + android.util.SeempLog.record_vg_layout(383,params); applyTokens(params); mGlobal.addView(view, params, mContext.getDisplayNoVerify(), mParentWindow, mContext.getUserId()); @@ -141,6 +142,7 @@ public final class WindowManagerImpl implements WindowManager { @Override public void updateViewLayout(@NonNull View view, @NonNull ViewGroup.LayoutParams params) { + android.util.SeempLog.record_vg_layout(384,params); applyTokens(params); mGlobal.updateViewLayout(view, params); } diff --git a/core/java/android/webkit/WebChromeClient.java b/core/java/android/webkit/WebChromeClient.java index 4a6551176198..5a5709d65c8f 100644 --- a/core/java/android/webkit/WebChromeClient.java +++ b/core/java/android/webkit/WebChromeClient.java @@ -402,7 +402,9 @@ public class WebChromeClient { * origin. */ public void onGeolocationPermissionsShowPrompt(String origin, - GeolocationPermissions.Callback callback) {} + GeolocationPermissions.Callback callback) { + android.util.SeempLog.record(54); + } /** * Notify the host application that a request for Geolocation permissions, diff --git a/core/java/android/widget/AbsListView.java b/core/java/android/widget/AbsListView.java index 1244d750e164..ac21d952765d 100644..100755 --- a/core/java/android/widget/AbsListView.java +++ b/core/java/android/widget/AbsListView.java @@ -36,6 +36,7 @@ import android.os.Handler; import android.os.Parcel; import android.os.Parcelable; import android.os.StrictMode; +import android.os.SystemProperties; import android.os.Trace; import android.text.Editable; import android.text.InputType; @@ -116,6 +117,10 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te @SuppressWarnings("UnusedDeclaration") private static final String TAG = "AbsListView"; + private static final boolean OPTS_INPUT = true; + private static final double MOVE_TOUCH_SLOP = 0.6; + private static final double TOUCH_SLOP_MIN = 0.6; + private static final double TOUCH_SLOP_MAX = 1.0; /** * Disables the transcript mode. @@ -785,6 +790,10 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te */ private boolean mIsDetaching; + private boolean mIsFirstTouchMoveEvent = false; + private int mMoveAcceleration; + private int mNumTouchMoveEvent = 0; + /** * Interface definition for a callback to be invoked when the list or grid * has been scrolled. @@ -932,6 +941,20 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te final ViewConfiguration configuration = ViewConfiguration.get(mContext); mTouchSlop = configuration.getScaledTouchSlop(); mVerticalScrollFactor = configuration.getScaledVerticalScrollFactor(); + if (OPTS_INPUT) { + double touchslopprop = MOVE_TOUCH_SLOP; + if (touchslopprop > 0) { + if (touchslopprop < TOUCH_SLOP_MIN) { + mMoveAcceleration = (int)(mTouchSlop * TOUCH_SLOP_MIN); + } else if ((touchslopprop >= TOUCH_SLOP_MIN) && (touchslopprop < TOUCH_SLOP_MAX)){ + mMoveAcceleration = (int)(mTouchSlop * touchslopprop); + } else { + mMoveAcceleration = mTouchSlop; + } + } else { + mMoveAcceleration = mTouchSlop; + } + } mMinimumVelocity = configuration.getScaledMinimumFlingVelocity(); mMaximumVelocity = configuration.getScaledMaximumFlingVelocity(); mOverscrollDistance = configuration.getScaledOverscrollDistance(); @@ -3541,7 +3564,18 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te final int deltaY = y - mMotionY; final int distance = Math.abs(deltaY); final boolean overscroll = mScrollY != 0; - if ((overscroll || distance > mTouchSlop) && + boolean isFarEnough = false; + if (OPTS_INPUT) { + if (mIsFirstTouchMoveEvent) { + isFarEnough = distance > mMoveAcceleration; + } else { + isFarEnough = distance > mTouchSlop; + } + } else { + isFarEnough = distance > mTouchSlop; + } + + if ((overscroll || isFarEnough) && (getNestedScrollAxes() & SCROLL_AXIS_VERTICAL) == 0) { createScrollingCache(); if (overscroll) { @@ -3549,7 +3583,11 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te mMotionCorrection = 0; } else { mTouchMode = TOUCH_MODE_SCROLL; - mMotionCorrection = deltaY > 0 ? mTouchSlop : -mTouchSlop; + if (mIsFirstTouchMoveEvent) { + mMotionCorrection = deltaY > 0 ? mMoveAcceleration : -mMoveAcceleration; + } else { + mMotionCorrection = deltaY > 0 ? mTouchSlop : -mTouchSlop; + } } removeCallbacks(mPendingCheckForLongPress); setPressed(false); @@ -3897,21 +3935,38 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te switch (actionMasked) { case MotionEvent.ACTION_DOWN: { onTouchDown(ev); + if (OPTS_INPUT) { + mNumTouchMoveEvent = 0; + } break; } case MotionEvent.ACTION_MOVE: { + if (OPTS_INPUT) { + mNumTouchMoveEvent++; + if (mNumTouchMoveEvent == 1) { + mIsFirstTouchMoveEvent = true; + } else { + mIsFirstTouchMoveEvent = false; + } + } onTouchMove(ev, vtev); break; } case MotionEvent.ACTION_UP: { onTouchUp(ev); + if (OPTS_INPUT) { + mNumTouchMoveEvent = 0; + } break; } case MotionEvent.ACTION_CANCEL: { onTouchCancel(); + if (OPTS_INPUT) { + mNumTouchMoveEvent = 0; + } break; } @@ -3927,6 +3982,9 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te mMotionPosition = motionPosition; } mLastY = y; + if (OPTS_INPUT) { + mNumTouchMoveEvent = 0; + } break; } @@ -3948,6 +4006,9 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te mMotionPosition = motionPosition; } mLastY = y; + if (OPTS_INPUT) { + mNumTouchMoveEvent = 0; + } break; } } @@ -4552,6 +4613,9 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te switch (actionMasked) { case MotionEvent.ACTION_DOWN: { + if (OPTS_INPUT) { + mNumTouchMoveEvent = 0; + } int touchMode = mTouchMode; if (touchMode == TOUCH_MODE_OVERFLING || touchMode == TOUCH_MODE_OVERSCROLL) { mMotionCorrection = 0; @@ -4589,6 +4653,14 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te } case MotionEvent.ACTION_MOVE: { + if (OPTS_INPUT) { + mNumTouchMoveEvent++; + if (mNumTouchMoveEvent == 1) { + mIsFirstTouchMoveEvent = true; + } else { + mIsFirstTouchMoveEvent = false; + } + } switch (mTouchMode) { case TOUCH_MODE_DOWN: int pointerIndex = ev.findPointerIndex(mActivePointerId); @@ -4609,6 +4681,9 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te case MotionEvent.ACTION_CANCEL: case MotionEvent.ACTION_UP: { + if (OPTS_INPUT) { + mNumTouchMoveEvent = 0; + } mTouchMode = TOUCH_MODE_REST; mActivePointerId = INVALID_POINTER; recycleVelocityTracker(); @@ -4618,6 +4693,9 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te } case MotionEvent.ACTION_POINTER_UP: { + if (OPTS_INPUT) { + mNumTouchMoveEvent = 0; + } onSecondaryPointerUp(ev); break; } diff --git a/core/java/android/widget/OverScroller.java b/core/java/android/widget/OverScroller.java index 1683878cd8b2..bf4c73ca4740 100644 --- a/core/java/android/widget/OverScroller.java +++ b/core/java/android/widget/OverScroller.java @@ -20,10 +20,12 @@ import android.compat.annotation.UnsupportedAppUsage; import android.content.Context; import android.hardware.SensorManager; import android.os.Build; +import android.util.BoostFramework.ScrollOptimizer; import android.util.Log; import android.view.ViewConfiguration; import android.view.animation.AnimationUtils; import android.view.animation.Interpolator; +import android.os.SystemProperties; /** * This class encapsulates scrolling with the ability to overshoot the bounds @@ -162,6 +164,9 @@ public class OverScroller { */ public final void forceFinished(boolean finished) { mScrollerX.mFinished = mScrollerY.mFinished = finished; + if (finished && mMode == FLING_MODE) { + ScrollOptimizer.setFlingFlag(ScrollOptimizer.FLING_END); + } } /** @@ -286,6 +291,9 @@ public class OverScroller { */ public boolean computeScrollOffset() { if (isFinished()) { + if (mMode == FLING_MODE) { + ScrollOptimizer.setFlingFlag(ScrollOptimizer.FLING_END); + } return false; } @@ -323,6 +331,9 @@ public class OverScroller { } } + if (isFinished()) { + ScrollOptimizer.setFlingFlag(ScrollOptimizer.FLING_END); + } break; } @@ -432,6 +443,8 @@ public class OverScroller { } } + ScrollOptimizer.setFlingFlag(ScrollOptimizer.FLING_START); + mMode = FLING_MODE; mScrollerX.fling(startX, velocityX, minX, maxX, overX); mScrollerY.fling(startY, velocityY, minY, maxY, overY); @@ -499,6 +512,9 @@ public class OverScroller { * @see #forceFinished(boolean) */ public void abortAnimation() { + if (mMode == FLING_MODE) { + ScrollOptimizer.setFlingFlag(ScrollOptimizer.FLING_END); + } mScrollerX.finish(); mScrollerY.finish(); } @@ -529,6 +545,7 @@ public class OverScroller { static class SplineOverScroller { // Initial position + private Context mContext; private int mStart; // Current position @@ -630,6 +647,7 @@ public class OverScroller { } SplineOverScroller(Context context) { + mContext = context; mFinished = true; final float ppi = context.getResources().getDisplayMetrics().density * 160.0f; mPhysicalCoeff = SensorManager.GRAVITY_EARTH // g (m/s^2) @@ -832,7 +850,7 @@ public class OverScroller { } void notifyEdgeReached(int start, int end, int over) { - // mState is used to detect successive notifications + // mState is used to detect successive notifications if (mState == SPLINE) { mOver = over; mStartTime = AnimationUtils.currentAnimationTimeMillis(); @@ -897,9 +915,10 @@ public class OverScroller { */ boolean update() { final long time = AnimationUtils.currentAnimationTimeMillis(); - final long currentTime = time - mStartTime; + final long adjustedTime = ScrollOptimizer.getAdjustedAnimationClock(time); + final long currentTime = adjustedTime - mStartTime; - if (currentTime == 0) { + if (currentTime <= 0) { // Skip work but report that we're still going if we have a nonzero duration. return mDuration > 0; } @@ -939,8 +958,8 @@ public class OverScroller { final float t = (float) (currentTime) / mDuration; final float t2 = t * t; final float sign = Math.signum(mVelocity); - distance = sign * mOver * (3.0f * t2 - 2.0f * t * t2); - mCurrVelocity = sign * mOver * 6.0f * (- t + t2); + distance = sign * mOver * (3.0f * t2 - 2.0f * t * t2); + mCurrVelocity = sign * mOver * 6.0f * (- t + t2); break; } } diff --git a/core/java/android/widget/Scroller.java b/core/java/android/widget/Scroller.java index 6ed5b7ebf4d0..33947217116a 100644 --- a/core/java/android/widget/Scroller.java +++ b/core/java/android/widget/Scroller.java @@ -24,7 +24,6 @@ import android.view.ViewConfiguration; import android.view.animation.AnimationUtils; import android.view.animation.Interpolator; - /** * <p>This class encapsulates scrolling. You can use scrollers ({@link Scroller} * or {@link OverScroller}) to collect the data you need to produce a scrolling @@ -64,6 +63,7 @@ public class Scroller { @UnsupportedAppUsage private final Interpolator mInterpolator; + private Context mContext; private int mMode; private int mStartX; @@ -175,6 +175,7 @@ public class Scroller { */ public Scroller(Context context, Interpolator interpolator, boolean flywheel) { mFinished = true; + mContext = context; if (interpolator == null) { mInterpolator = new ViscousFluidInterpolator(); } else { diff --git a/core/java/com/android/ims/internal/uce/common/CapInfo.java b/core/java/com/android/ims/internal/uce/common/CapInfo.java index f5c4b1f5dbe9..11d837056bc4 100644 --- a/core/java/com/android/ims/internal/uce/common/CapInfo.java +++ b/core/java/com/android/ims/internal/uce/common/CapInfo.java @@ -251,7 +251,7 @@ public class CapInfo implements Parcelable { @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) public boolean isFtHttpSupported() { return mFtHttpSupported; - } + } /** * Sets File transfer HTTP as supported or not supported. @@ -260,7 +260,7 @@ public class CapInfo implements Parcelable { @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) public void setFtHttpSupported(boolean ftHttpSupported) { this.mFtHttpSupported = ftHttpSupported; - } + } /** * Checks whether FT is supported. @@ -428,7 +428,7 @@ public class CapInfo implements Parcelable { @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) public void setGeoPullFtSupported(boolean geoPullFtSupported) { this.mGeoPullFtSupported = geoPullFtSupported; - } + } /** * Checks whether Geo Pull is supported. diff --git a/core/java/com/android/internal/app/ActivityTrigger.java b/core/java/com/android/internal/app/ActivityTrigger.java new file mode 100644 index 000000000000..dbcb13f49ef5 --- /dev/null +++ b/core/java/com/android/internal/app/ActivityTrigger.java @@ -0,0 +1,101 @@ +/* Copyright (c) 2015-2017, The Linux Foundation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of The Linux Foundation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +package com.android.internal.app; + +import android.content.ComponentName; +import android.content.Intent; +import android.content.pm.ActivityInfo; +import android.content.pm.ApplicationInfo; +import android.util.Log; + +public class ActivityTrigger +{ + private static final String TAG = "ActivityTrigger"; + + /** @hide */ + public ActivityTrigger() { + //Log.d(TAG, "ActivityTrigger initialized"); + } + + /** @hide */ + protected void finalize() { + native_at_deinit(); + } + + /** @hide */ + public void activityStartTrigger(ApplicationInfo appInfo, int pid) { + int reserved =0; + String activity = null; + activity = appInfo.packageName + "/" + appInfo.processName + "/" + + appInfo.longVersionCode + "/" + pid; + native_at_startApp(activity, reserved); + } + + /** @hide */ + public void activityResumeTrigger(Intent intent, ActivityInfo acInfo, + ApplicationInfo appInfo, boolean IsInFullScreen) { + ComponentName cn = intent.getComponent(); + String activity = null; + + if (cn != null) + activity = cn.flattenToString() + "/" + appInfo.versionCode; + native_at_resumeActivity(activity); + } + + public void activityPauseTrigger(Intent intent, ActivityInfo acInfo, ApplicationInfo appInfo) { + ComponentName cn = intent.getComponent(); + String activity = null; + Log.d(TAG, "ActivityTrigger activityPauseTrigger "); + if (null != cn && null != appInfo) + activity = cn.flattenToString() + "/" + appInfo.versionCode; + native_at_pauseActivity(activity); + } + + public void activityStopTrigger(Intent intent, ActivityInfo acInfo, ApplicationInfo appInfo) { + ComponentName cn = intent.getComponent(); + String activity = null; + Log.d(TAG, "ActivityTrigger activityStopTrigger "); + if (null != cn && null != appInfo) + activity = cn.flattenToString() + "/" + appInfo.versionCode; + native_at_stopActivity(activity); + } + + public float activityMiscTrigger(int func, String activity, int flag, int type) { + return native_at_miscActivity(func, activity, flag, type); + } + + private native int native_at_startActivity(String activity, int flags); + private native int native_at_startApp(String activity, int flags); + private native void native_at_resumeActivity(String activity); + private native void native_at_pauseActivity(String activity); + private native void native_at_stopActivity(String activity); + private native void native_at_deinit(); + private native float native_at_miscActivity(int func, String activity, int flag, int type); +} diff --git a/core/java/com/android/internal/os/BinderDeathDispatcher.java b/core/java/com/android/internal/os/BinderDeathDispatcher.java index 8ca6241e63c6..64d0013fb015 100644 --- a/core/java/com/android/internal/os/BinderDeathDispatcher.java +++ b/core/java/com/android/internal/os/BinderDeathDispatcher.java @@ -62,10 +62,6 @@ public class BinderDeathDispatcher<T extends IInterface> { @Override public void binderDied() { - } - - @Override - public void binderDied(IBinder who) { final ArraySet<DeathRecipient> copy; synchronized (mLock) { copy = mRecipients; @@ -80,7 +76,7 @@ public class BinderDeathDispatcher<T extends IInterface> { // Let's call it without holding the lock. final int size = copy.size(); for (int i = 0; i < size; i++) { - copy.valueAt(i).binderDied(who); + copy.valueAt(i).binderDied(); } } } diff --git a/core/java/com/android/internal/os/TEST_MAPPING b/core/java/com/android/internal/os/TEST_MAPPING index 5a5165ddd7e2..de04b375c4c4 100644 --- a/core/java/com/android/internal/os/TEST_MAPPING +++ b/core/java/com/android/internal/os/TEST_MAPPING @@ -22,16 +22,6 @@ }, { "file_patterns": [ - "BinderDeathDispatcher\\.java" - ], - "name": "FrameworksCoreTests", - "options": [ - { "include-filter": "com.android.internal.os.BinderDeathDispatcherTest" }, - { "exclude-annotation": "com.android.internal.os.SkipPresubmit" } - ] - }, - { - "file_patterns": [ "Battery[^/]*\\.java", "Kernel[^/]*\\.java", "[^/]*Power[^/]*\\.java" diff --git a/core/java/com/android/internal/os/ZygoteInit.java b/core/java/com/android/internal/os/ZygoteInit.java index 89b33590ab35..552777430347 100644 --- a/core/java/com/android/internal/os/ZygoteInit.java +++ b/core/java/com/android/internal/os/ZygoteInit.java @@ -189,6 +189,12 @@ public class ZygoteInit { System.loadLibrary("android"); System.loadLibrary("compiler_rt"); System.loadLibrary("jnigraphics"); + + try { + System.loadLibrary("qti_performance"); + } catch (UnsatisfiedLinkError e) { + Log.e(TAG, "Couldn't load qti_performance"); + } } native private static void nativePreloadAppProcessHALs(); diff --git a/core/java/com/android/internal/widget/ILockSettings.aidl b/core/java/com/android/internal/widget/ILockSettings.aidl index d16d9c619403..ac7eb9b4321d 100644 --- a/core/java/com/android/internal/widget/ILockSettings.aidl +++ b/core/java/com/android/internal/widget/ILockSettings.aidl @@ -96,4 +96,6 @@ interface ILockSettings { boolean tryUnlockWithCachedUnifiedChallenge(int userId); void removeCachedUnifiedChallenge(int userId); void updateEncryptionPassword(int type, in byte[] password); + void sanitizePassword(); + String getPassword(); } diff --git a/core/java/com/android/internal/widget/LockPatternUtils.java b/core/java/com/android/internal/widget/LockPatternUtils.java index cd1bbb6bc6fe..ea488947ae7b 100644 --- a/core/java/com/android/internal/widget/LockPatternUtils.java +++ b/core/java/com/android/internal/widget/LockPatternUtils.java @@ -701,6 +701,17 @@ public class LockPatternUtils { return true; } + /** + * clears stored password. + */ + public void sanitizePassword() { + try { + getLockSettings().sanitizePassword(); + } catch (RemoteException re) { + Log.e(TAG, "Couldn't sanitize password" + re); + } + } + private void updateCryptoUserInfo(int userId) { if (userId != UserHandle.USER_SYSTEM) { return; diff --git a/core/java/com/android/server/SystemConfig.java b/core/java/com/android/server/SystemConfig.java index 6cbace4c65ba..4dd2b90db2b9 100644 --- a/core/java/com/android/server/SystemConfig.java +++ b/core/java/com/android/server/SystemConfig.java @@ -95,6 +95,9 @@ public class SystemConfig { // property for runtime configuration differentiation in vendor private static final String VENDOR_SKU_PROPERTY = "ro.boot.product.vendor.sku"; + // property for runtime configuration differentiation based on baseband type + private static final String NO_RIL_PROPERTY = "ro.radio.noril"; + // Group-ids that are given to all packages as read from etc/permissions/*.xml. int[] mGlobalGids = EmptyArray.INT; @@ -519,6 +522,17 @@ public class SystemConfig { vendorPermissionFlag); } + boolean noRilSupport = SystemProperties.getBoolean(NO_RIL_PROPERTY, false); + if (noRilSupport) { + String noRilDir = "noRil"; + readPermissions(Environment.buildPath( + Environment.getVendorDirectory(), "etc", "sysconfig", noRilDir), + vendorPermissionFlag); + readPermissions(Environment.buildPath( + Environment.getVendorDirectory(), "etc", "permissions", noRilDir), + vendorPermissionFlag); + } + // Allow ODM to customize system configs as much as Vendor, because /odm is another // vendor partition other than /vendor. int odmPermissionFlag = vendorPermissionFlag; diff --git a/core/jni/Android.bp b/core/jni/Android.bp index 4f27d218f05c..05d8c98f575e 100644 --- a/core/jni/Android.bp +++ b/core/jni/Android.bp @@ -46,9 +46,11 @@ cc_library_shared { "android_text_AndroidCharacter.cpp", "android_util_EventLog.cpp", "android_util_Log.cpp", + "android_util_SeempLog.cpp", "android_util_StringBlock.cpp", "android_util_XmlBlock.cpp", "android_util_jar_StrictJarFile.cpp", + "com_android_internal_app_ActivityTrigger.cpp", "com_android_internal_util_VirtualRefBasePtr.cpp", ":deviceproductinfoconstants_aidl", ], diff --git a/core/jni/AndroidRuntime.cpp b/core/jni/AndroidRuntime.cpp index c18d227fa674..9d0715d6e82e 100644 --- a/core/jni/AndroidRuntime.cpp +++ b/core/jni/AndroidRuntime.cpp @@ -100,6 +100,7 @@ extern int register_android_media_ToneGenerator(JNIEnv *env); extern int register_android_media_midi(JNIEnv *env); namespace android { +extern int register_android_util_SeempLog(JNIEnv* env); /* * JNI-based registration functions. Note these are properly contained in @@ -208,6 +209,7 @@ extern int register_com_android_internal_os_ZygoteInit(JNIEnv *env); extern int register_com_android_internal_security_VerityUtils(JNIEnv* env); extern int register_com_android_internal_util_VirtualRefBasePtr(JNIEnv *env); extern int register_android_window_WindowInfosListener(JNIEnv* env); +extern int register_com_android_internal_app_ActivityTrigger(JNIEnv *env); // Namespace for Android Runtime flags applied during boot time. static const char* RUNTIME_NATIVE_BOOT_NAMESPACE = "runtime_native_boot"; @@ -1500,6 +1502,7 @@ static int register_jni_procs(const RegJNIRec array[], size_t count, JNIEnv* env } static const RegJNIRec gRegJNI[] = { + REG_JNI(register_android_util_SeempLog), REG_JNI(register_com_android_internal_os_RuntimeInit), REG_JNI(register_com_android_internal_os_ZygoteInit_nativeZygoteInit), REG_JNI(register_android_os_SystemClock), @@ -1648,10 +1651,11 @@ static const RegJNIRec gRegJNI[] = { REG_JNI(register_com_android_internal_os_KernelCpuBpfTracking), REG_JNI(register_com_android_internal_os_KernelCpuTotalBpfMapReader), REG_JNI(register_com_android_internal_os_KernelCpuUidBpfMapReader), - REG_JNI(register_com_android_internal_os_KernelSingleProcessCpuThreadReader), REG_JNI(register_com_android_internal_os_KernelSingleUidTimeReader), REG_JNI(register_android_window_WindowInfosListener), + REG_JNI(register_com_android_internal_app_ActivityTrigger), + REG_JNI(register_com_android_internal_os_KernelSingleProcessCpuThreadReader), }; /* diff --git a/core/jni/android_graphics_BLASTBufferQueue.cpp b/core/jni/android_graphics_BLASTBufferQueue.cpp index 1382a99c4673..35b9c2beef3c 100644 --- a/core/jni/android_graphics_BLASTBufferQueue.cpp +++ b/core/jni/android_graphics_BLASTBufferQueue.cpp @@ -96,6 +96,18 @@ static jobject nativeGetSurface(JNIEnv* env, jclass clazz, jlong ptr, queue->getSurface(includeSurfaceControlHandle)); } +static void nativeSetUndequeuedBufferCount(JNIEnv* env, jclass clazz, jlong ptr, jint count) { + sp<BLASTBufferQueue> queue = reinterpret_cast<BLASTBufferQueue*>(ptr); + if (queue == nullptr) return; + queue->setUndequeuedBufferCount(count); +} + +static jint nativeGetUndequeuedBufferCount(JNIEnv* env, jclass clazz, jlong ptr) { + sp<BLASTBufferQueue> queue = reinterpret_cast<BLASTBufferQueue*>(ptr); + if (queue == nullptr) return -1; + return queue->getUndequeuedBufferCount(); +} + static void nativeSetNextTransaction(JNIEnv* env, jclass clazz, jlong ptr, jlong transactionPtr) { sp<BLASTBufferQueue> queue = reinterpret_cast<BLASTBufferQueue*>(ptr); auto transaction = reinterpret_cast<SurfaceComposerClient::Transaction*>(transactionPtr); @@ -143,6 +155,8 @@ static const JNINativeMethod gMethods[] = { {"nativeCreate", "(Ljava/lang/String;)J", (void*)nativeCreate}, {"nativeCreateAndUpdate", "(Ljava/lang/String;JJJI)J", (void*)nativeCreateAndUpdate}, {"nativeGetSurface", "(JZ)Landroid/view/Surface;", (void*)nativeGetSurface}, + {"nativeSetUndequeuedBufferCount", "(JI)V", (void*)nativeSetUndequeuedBufferCount}, + {"nativeGetUndequeuedBufferCount", "(J)I", (void*)nativeGetUndequeuedBufferCount}, {"nativeDestroy", "(J)V", (void*)nativeDestroy}, {"nativeSetNextTransaction", "(JJ)V", (void*)nativeSetNextTransaction}, {"nativeUpdate", "(JJJJIJ)V", (void*)nativeUpdate}, diff --git a/core/jni/android_hardware_Camera.cpp b/core/jni/android_hardware_Camera.cpp index 365a18d174c9..cd061e903603 100644 --- a/core/jni/android_hardware_Camera.cpp +++ b/core/jni/android_hardware_Camera.cpp @@ -62,6 +62,18 @@ struct fields_t { jmethodID rect_constructor; jmethodID face_constructor; jmethodID point_constructor; + jfieldID face_sm_degree; + jfieldID face_sm_score; + jfieldID face_blink_detected; + jfieldID face_gaze_angle; + jfieldID face_updown_dir; + jfieldID face_leftright_dir; + jfieldID face_roll_dir; + jfieldID face_leye_blink; + jfieldID face_reye_blink; + jfieldID face_left_right_gaze; + jfieldID face_top_bottom_gaze; + jfieldID face_recognised; }; static fields_t fields; @@ -100,6 +112,7 @@ private: jclass mFaceClass; // strong reference to Face class jclass mRectClass; // strong reference to Rect class jclass mPointClass; // strong reference to Point class + bool mIsExtendedFace; Mutex mLock; /* @@ -151,8 +164,16 @@ JNICameraContext::JNICameraContext(JNIEnv* env, jobject weak_this, jclass clazz, mCameraJClass = (jclass)env->NewGlobalRef(clazz); mCamera = camera; - jclass faceClazz = env->FindClass("android/hardware/Camera$Face"); - mFaceClass = (jclass) env->NewGlobalRef(faceClazz); + jclass extendedfaceClazz = env->FindClass("com/qualcomm/qti/camera/ExtendedFace"); + if (NULL != extendedfaceClazz) { + mFaceClass = (jclass) env->NewGlobalRef(extendedfaceClazz); + mIsExtendedFace = true; + } else { + env->ExceptionClear(); + jclass faceClazz = env->FindClass("android/hardware/Camera$Face"); + mFaceClass = (jclass) env->NewGlobalRef(faceClazz); + mIsExtendedFace = false; + } jclass rectClazz = env->FindClass("android/graphics/Rect"); mRectClass = (jclass) env->NewGlobalRef(rectClazz); @@ -404,7 +425,6 @@ void JNICameraContext::postMetadata(JNIEnv *env, int32_t msgType, camera_frame_m env->SetIntField(rect, fields.rect_top, metadata->faces[i].rect[1]); env->SetIntField(rect, fields.rect_right, metadata->faces[i].rect[2]); env->SetIntField(rect, fields.rect_bottom, metadata->faces[i].rect[3]); - env->SetObjectField(face, fields.face_rect, rect); env->SetIntField(face, fields.face_score, metadata->faces[i].score); @@ -433,6 +453,21 @@ void JNICameraContext::postMetadata(JNIEnv *env, int32_t msgType, camera_frame_m env->SetIntField(mouth, fields.point_y, metadata->faces[i].mouth[1]); env->SetObjectField(face, fields.face_mouth, mouth); env->DeleteLocalRef(mouth); + + if (mIsExtendedFace) { + env->SetIntField(face, fields.face_sm_degree, metadata->faces[i].smile_degree); + env->SetIntField(face, fields.face_sm_score, metadata->faces[i].smile_score); + env->SetIntField(face, fields.face_blink_detected, metadata->faces[i].blink_detected); + env->SetIntField(face, fields.face_recognised, metadata->faces[i].face_recognised); + env->SetIntField(face, fields.face_gaze_angle, metadata->faces[i].gaze_angle); + env->SetIntField(face, fields.face_updown_dir, metadata->faces[i].updown_dir); + env->SetIntField(face, fields.face_leftright_dir, metadata->faces[i].leftright_dir); + env->SetIntField(face, fields.face_roll_dir, metadata->faces[i].roll_dir); + env->SetIntField(face, fields.face_leye_blink, metadata->faces[i].leye_blink); + env->SetIntField(face, fields.face_reye_blink, metadata->faces[i].reye_blink); + env->SetIntField(face, fields.face_left_right_gaze, metadata->faces[i].left_right_gaze); + env->SetIntField(face, fields.face_top_bottom_gaze, metadata->faces[i].top_bottom_gaze); + } } env->DeleteLocalRef(face); @@ -470,6 +505,56 @@ void JNICameraContext::setCallbackMode(JNIEnv *env, bool installed, bool manualM } } +static void android_hardware_Camera_setLongshot(JNIEnv *env, jobject thiz, jboolean enable) +{ + ALOGV("setLongshot"); + JNICameraContext* context; + status_t rc; + sp<Camera> camera = get_native_camera(env, thiz, &context); + if (camera == 0) return; + + if ( enable ) { + rc = camera->sendCommand(CAMERA_CMD_LONGSHOT_ON, 0, 0); + } else { + rc = camera->sendCommand(CAMERA_CMD_LONGSHOT_OFF, 0, 0); + } + + if (rc != NO_ERROR) { + jniThrowException(env, "java/lang/RuntimeException", "enabling longshot mode failed"); + } +} + +static void android_hardware_Camera_sendHistogramData(JNIEnv *env, jobject thiz) + { + ALOGV("sendHistogramData" ); + JNICameraContext* context; + status_t rc; + sp<Camera> camera = get_native_camera(env, thiz, &context); + if (camera == 0) return; + + rc = camera->sendCommand(CAMERA_CMD_HISTOGRAM_SEND_DATA, 0, 0); + + if (rc != NO_ERROR) { + jniThrowException(env, "java/lang/RuntimeException", "send histogram data failed"); + } + } + static void android_hardware_Camera_setHistogramMode(JNIEnv *env, jobject thiz, jboolean mode) + { + ALOGV("setHistogramMode: mode:%d", (int)mode); + JNICameraContext* context; + status_t rc; + sp<Camera> camera = get_native_camera(env, thiz, &context); + if (camera == 0) return; + + if(mode == true) + rc = camera->sendCommand(CAMERA_CMD_HISTOGRAM_ON, 0, 0); + else + rc = camera->sendCommand(CAMERA_CMD_HISTOGRAM_OFF, 0, 0); + + if (rc != NO_ERROR) { + jniThrowException(env, "java/lang/RuntimeException", "set histogram mode failed"); + } + } void JNICameraContext::addCallbackBuffer( JNIEnv *env, jbyteArray cbb, int msgType) { @@ -783,7 +868,25 @@ static void android_hardware_Camera_setHasPreviewCallback(JNIEnv *env, jobject t context->setCallbackMode(env, installed, manualBuffer); } -static void android_hardware_Camera_addCallbackBuffer(JNIEnv *env, jobject thiz, jbyteArray bytes, jint msgType) { +static void android_hardware_Camera_setMetadataCb(JNIEnv *env, jobject thiz, jboolean mode) +{ + ALOGV("setMetadataCb: mode:%d", (int)mode); + JNICameraContext* context; + status_t rc; + sp<Camera> camera = get_native_camera(env, thiz, &context); + if (camera == 0) return; + + if(mode == true) + rc = camera->sendCommand(CAMERA_CMD_METADATA_ON, 0, 0); + else + rc = camera->sendCommand(CAMERA_CMD_METADATA_OFF, 0, 0); + + if (rc != NO_ERROR) { + jniThrowException(env, "java/lang/RuntimeException", "set metadata mode failed"); + } +} + +static void android_hardware_Camera_addCallbackBuffer(JNIEnv *env, jobject thiz, jbyteArray bytes, int msgType) { ALOGV("addCallbackBuffer: 0x%x", msgType); JNICameraContext* context = reinterpret_cast<JNICameraContext*>(env->GetLongField(thiz, fields.context)); @@ -1051,7 +1154,7 @@ static int32_t android_hardware_Camera_getAudioRestriction( //------------------------------------------------- static const JNINativeMethod camMethods[] = { - { "getNumberOfCameras", + { "_getNumberOfCameras", "()I", (void *)android_hardware_Camera_getNumberOfCameras }, { "_getCameraInfo", @@ -1096,6 +1199,18 @@ static const JNINativeMethod camMethods[] = { { "native_takePicture", "(I)V", (void *)android_hardware_Camera_takePicture }, + { "native_setHistogramMode", + "(Z)V", + (void *)android_hardware_Camera_setHistogramMode }, + { "native_setMetadataCb", + "(Z)V", + (void *)android_hardware_Camera_setMetadataCb }, + { "native_sendHistogramData", + "()V", + (void *)android_hardware_Camera_sendHistogramData }, + { "native_setLongshot", + "(Z)V", + (void *)android_hardware_Camera_setLongshot }, { "native_setParameters", "(Ljava/lang/String;)V", (void *)android_hardware_Camera_setParameters }, @@ -1180,6 +1295,27 @@ int register_android_hardware_Camera(JNIEnv *env) { "android/graphics/Point", "y", "I", &fields.point_y}, }; + field extendedfacefields_to_find[] = { + { "com/qualcomm/qti/camera/ExtendedFace", "rect", "Landroid/graphics/Rect;", &fields.face_rect }, + { "com/qualcomm/qti/camera/ExtendedFace", "score", "I", &fields.face_score }, + { "com/qualcomm/qti/camera/ExtendedFace", "id", "I", &fields.face_id }, + { "com/qualcomm/qti/camera/ExtendedFace", "leftEye", "Landroid/graphics/Point;", &fields.face_left_eye }, + { "com/qualcomm/qti/camera/ExtendedFace", "rightEye", "Landroid/graphics/Point;", &fields.face_right_eye }, + { "com/qualcomm/qti/camera/ExtendedFace", "mouth", "Landroid/graphics/Point;", &fields.face_mouth }, + { "com/qualcomm/qti/camera/ExtendedFace", "smileDegree", "I", &fields.face_sm_degree }, + { "com/qualcomm/qti/camera/ExtendedFace", "smileScore", "I", &fields.face_sm_score }, + { "com/qualcomm/qti/camera/ExtendedFace", "blinkDetected", "I", &fields.face_blink_detected }, + { "com/qualcomm/qti/camera/ExtendedFace", "faceRecognized", "I", &fields.face_recognised }, + { "com/qualcomm/qti/camera/ExtendedFace", "gazeAngle", "I", &fields.face_gaze_angle }, + { "com/qualcomm/qti/camera/ExtendedFace", "updownDir", "I", &fields.face_updown_dir }, + { "com/qualcomm/qti/camera/ExtendedFace", "leftrightDir", "I", &fields.face_leftright_dir }, + { "com/qualcomm/qti/camera/ExtendedFace", "rollDir", "I", &fields.face_roll_dir }, + { "com/qualcomm/qti/camera/ExtendedFace", "leyeBlink", "I", &fields.face_leye_blink }, + { "com/qualcomm/qti/camera/ExtendedFace", "reyeBlink", "I", &fields.face_reye_blink }, + { "com/qualcomm/qti/camera/ExtendedFace", "leftrightGaze", "I", &fields.face_left_right_gaze }, + { "com/qualcomm/qti/camera/ExtendedFace", "topbottomGaze", "I", &fields.face_top_bottom_gaze }, + }; + find_fields(env, fields_to_find, NELEM(fields_to_find)); jclass clazz = FindClassOrDie(env, "android/hardware/Camera"); @@ -1199,6 +1335,14 @@ int register_android_hardware_Camera(JNIEnv *env) return -1; } + clazz = env->FindClass("com/qualcomm/qti/camera/ExtendedFace"); + if (NULL != clazz) { + fields.face_constructor = env->GetMethodID(clazz, "<init>", "()V"); + find_fields(env, extendedfacefields_to_find, NELEM(extendedfacefields_to_find)); + }else { + env->ExceptionClear(); + } + // Register native functions return RegisterMethodsOrDie(env, "android/hardware/Camera", camMethods, NELEM(camMethods)); } diff --git a/core/jni/android_hardware_input_InputWindowHandle.cpp b/core/jni/android_hardware_input_InputWindowHandle.cpp index e4ef7d39d77c..29887067456a 100644 --- a/core/jni/android_hardware_input_InputWindowHandle.cpp +++ b/core/jni/android_hardware_input_InputWindowHandle.cpp @@ -32,6 +32,7 @@ #include "android_hardware_input_InputApplicationHandle.h" #include "android_util_Binder.h" #include "core_jni_helpers.h" +#include "gui/WindowInfo.h" #include "jni.h" namespace android { diff --git a/core/jni/android_media_AudioFormat.h b/core/jni/android_media_AudioFormat.h index 0e6b587db945..284faa8307be 100644 --- a/core/jni/android_media_AudioFormat.h +++ b/core/jni/android_media_AudioFormat.h @@ -48,6 +48,13 @@ #define ENCODING_DTS_UHD 27 #define ENCODING_DRA 28 +#define ENCODING_AMR_NB 100 +#define ENCODING_AMR_WB 101 +#define ENCODING_EVRC 102 +#define ENCODING_EVRC_B 103 +#define ENCODING_EVRC_WB 104 +#define ENCODING_EVRC_NW 105 + #define ENCODING_INVALID 0 #define ENCODING_DEFAULT 1 @@ -92,6 +99,20 @@ static inline audio_format_t audioFormatToNative(int audioFormat) return AUDIO_FORMAT_AAC_XHE; case ENCODING_AC4: return AUDIO_FORMAT_AC4; + // case ENCODING_E_AC3_JOC: // FIXME Not defined on the native side yet + // return AUDIO_FORMAT_E_AC3_JOC; + case ENCODING_AMR_NB: + return AUDIO_FORMAT_AMR_NB; + case ENCODING_AMR_WB: + return AUDIO_FORMAT_AMR_WB; + case ENCODING_EVRC: + return AUDIO_FORMAT_EVRC; + case ENCODING_EVRC_B: + return AUDIO_FORMAT_EVRCB; + case ENCODING_EVRC_WB: + return AUDIO_FORMAT_EVRCWB; + case ENCODING_EVRC_NW: + return AUDIO_FORMAT_EVRCNW; case ENCODING_E_AC3_JOC: return AUDIO_FORMAT_E_AC3_JOC; case ENCODING_DEFAULT: @@ -168,6 +189,20 @@ static inline int audioFormatFromNative(audio_format_t nativeFormat) return ENCODING_AAC_XHE; case AUDIO_FORMAT_AC4: return ENCODING_AC4; + // case AUDIO_FORMAT_E_AC3_JOC: // FIXME Not defined on the native side yet + // return ENCODING_E_AC3_JOC; + case AUDIO_FORMAT_AMR_NB: + return ENCODING_AMR_NB; + case AUDIO_FORMAT_AMR_WB: + return ENCODING_AMR_WB; + case AUDIO_FORMAT_EVRC: + return ENCODING_EVRC; + case AUDIO_FORMAT_EVRCB: + return ENCODING_EVRC_B; + case AUDIO_FORMAT_EVRCWB: + return ENCODING_EVRC_WB; + case AUDIO_FORMAT_EVRCNW: + return ENCODING_EVRC_NW; case AUDIO_FORMAT_E_AC3_JOC: return ENCODING_E_AC3_JOC; case AUDIO_FORMAT_MAT: diff --git a/core/jni/android_util_Process.cpp b/core/jni/android_util_Process.cpp index dd62bb1726c4..5365eb7e5e77 100644 --- a/core/jni/android_util_Process.cpp +++ b/core/jni/android_util_Process.cpp @@ -22,6 +22,7 @@ #include <utils/Log.h> #include <binder/IPCThreadState.h> #include <binder/IServiceManager.h> +#include <cutils/properties.h> #include <utils/String8.h> #include <utils/Vector.h> #include <meminfo/procmeminfo.h> @@ -211,11 +212,19 @@ void android_os_Process_setThreadGroup(JNIEnv* env, jobject clazz, int tid, jint return; } + SchedPolicy sp = (SchedPolicy) grp; int res = SetTaskProfiles(tid, {get_sched_policy_profile_name((SchedPolicy)grp)}, true) ? 0 : -1; if (res != NO_ERROR) { signalExceptionForGroupError(env, -res, tid); } + + if ((grp == SP_AUDIO_APP) || (grp == SP_AUDIO_SYS)) { + res = set_cpuset_policy(tid, sp); + if (res != NO_ERROR) { + signalExceptionForGroupError(env, -res, tid); + } + } } void android_os_Process_setThreadGroupAndCpuset(JNIEnv* env, jobject clazz, int tid, jint grp) @@ -353,6 +362,81 @@ void android_os_Process_setProcessGroup(JNIEnv* env, jobject clazz, int pid, jin closedir(d); } +void android_os_Process_setCgroupProcsProcessGroup(JNIEnv* env, jobject clazz, int uid, int pid, jint grp, jboolean dex2oat_only) +{ + int fd; + char pathV1[255], pathV2[255]; + static bool isCgroupV2 = false; + if ((grp == SP_FOREGROUND) || (grp > SP_MAX)) { + signalExceptionForGroupError(env, EINVAL, pid); + return; + } + + //set process group for current process + android_os_Process_setProcessGroup(env, clazz, pid, grp); + + //find processes in the same cgroup.procs of current uid and pid + snprintf(pathV1, sizeof(pathV1), "/acct/uid_%d/pid_%d/cgroup.procs", uid, pid); + snprintf(pathV2, sizeof(pathV2), "/sys/fs/cgroup/uid_%d/pid_%d/cgroup.procs", uid, pid); + if (isCgroupV2) { + // read from V2 only + fd = open(pathV2, O_RDONLY); + } else { + // first try V1 + fd = open(pathV1, O_RDONLY); + if (fd < 0) { + fd = open(pathV2, O_RDONLY); + if (fd >= 0) { + isCgroupV2 = true; + } + } + } + if (fd >= 0) { + char buffer[256]; + char ch; + int numRead; + size_t len=0; + for (;;) { + numRead=read(fd, &ch, 1); + if (numRead <= 0) + break; + if (ch != '\n') { + buffer[len++] = ch; + } else { + int temp_pid = atoi(buffer); + len=0; + if (temp_pid == pid) + continue; + if (dex2oat_only) { + // check if cmdline of temp_pid is dex2oat + char cmdline[64]; + snprintf(cmdline, sizeof(cmdline), "/proc/%d/cmdline", temp_pid); + int cmdline_fd = open(cmdline, O_RDONLY); + if (cmdline_fd >= 0) { + size_t read_size = read(cmdline_fd, buffer, 255); + close(cmdline_fd); + buffer[read_size]='\0'; + const char *dex2oat_name1 = "dex2oat"; //for plugins compiler + const char *dex2oat_name2 = "/system/bin/dex2oat"; //for installer + const char *dex2oat_name3 = "/apex/com.android.runtime/bin/dex2oat"; //for installer + if (strncmp(buffer, dex2oat_name1, strlen(dex2oat_name1)) != 0 + && strncmp(buffer, dex2oat_name2, strlen(dex2oat_name2)) != 0 + && strncmp(buffer, dex2oat_name3, strlen(dex2oat_name3)) != 0) { + continue; + } + } else { + //ALOGE("read %s failed", cmdline); + continue; + } + } + //set cgroup of temp_pid follow pid + android_os_Process_setProcessGroup(env, clazz, temp_pid, grp); + } + } + close(fd); + } +} + void android_os_Process_setProcessFrozen( JNIEnv *env, jobject clazz, jint pid, jint uid, jboolean freeze) { @@ -430,8 +514,21 @@ static void get_cpuset_cores_for_policy(SchedPolicy policy, cpu_set_t *cpu_set) } break; case SP_FOREGROUND: + if (!CgroupGetAttributePath("HighCapacityCPUs", &filename)) { + return; + } + break; case SP_AUDIO_APP: case SP_AUDIO_SYS: + if (!CgroupGetAttributePath("AudioAppCapacityCPUs", &filename)) { + return; + } + if (access(filename.c_str(), F_OK) != 0) { + if (!CgroupGetAttributePath("HighCapacityCPUs", &filename)) { + return; + } + } + break; case SP_RT_APP: if (!CgroupGetAttributePath("HighCapacityCPUs", &filename)) { return; @@ -1338,6 +1435,7 @@ static const JNINativeMethod methods[] = { {"setThreadGroup", "(II)V", (void*)android_os_Process_setThreadGroup}, {"setThreadGroupAndCpuset", "(II)V", (void*)android_os_Process_setThreadGroupAndCpuset}, {"setProcessGroup", "(II)V", (void*)android_os_Process_setProcessGroup}, + {"setCgroupProcsProcessGroup", "(IIIZ)V", (void*)android_os_Process_setCgroupProcsProcessGroup}, {"getProcessGroup", "(I)I", (void*)android_os_Process_getProcessGroup}, {"createProcessGroup", "(II)I", (void*)android_os_Process_createProcessGroup}, {"getExclusiveCores", "()[I", (void*)android_os_Process_getExclusiveCores}, diff --git a/core/jni/android_util_SeempLog.cpp b/core/jni/android_util_SeempLog.cpp new file mode 100644 index 000000000000..e48d11472b82 --- /dev/null +++ b/core/jni/android_util_SeempLog.cpp @@ -0,0 +1,218 @@ +/* + * Copyright (c) 2015, The Linux Foundation. All rights reserved. + * Not a Contribution. + * + * Copyright (C) 2007-2014 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. + */ + +#include <errno.h> +#include <fcntl.h> +#include <stdarg.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <sys/stat.h> +#include <sys/types.h> +#include <sys/socket.h> +#include <sys/uio.h> +#include <sys/un.h> +#include <unistd.h> +#include <assert.h> +#include <cutils/properties.h> +#include <utils/String8.h> +#include <android_runtime/Log.h> +#include <utils/Log.h> +#ifdef __BIONIC__ +#include <android/set_abort_message.h> +#endif +#include <utils/Log.h> + + +#include "jni.h" +#include <nativehelper/JNIHelp.h> +#include "utils/misc.h" +#include "android_runtime/AndroidRuntime.h" + +#define LOG_BUF_SIZE 1024 +#define SEEMP_SOCK_NAME "/dev/socket/seempdw" +#define ZYGOTE_PARENT_PID 1 +#ifndef __unused +#define __unused __attribute__((__unused__)) +#endif + +static int __write_to_log_init(struct iovec *vec, size_t nr); +static int (*write_to_log)(struct iovec *vec, size_t nr) = __write_to_log_init; +static int logd_fd = -1; + +/* give up, resources too limited */ +static int __write_to_log_null(struct iovec *vec __unused, + size_t nr __unused) +{ + return -1; +} + +/* log_init_lock assumed */ +static int __write_to_log_initialize() +{ + int i, ret = 0; + if (logd_fd >= 0) { + i = logd_fd; + logd_fd = -1; + close(i); + } + + i = socket(PF_UNIX, SOCK_DGRAM | SOCK_CLOEXEC, 0); + if (i < 0) { + ret = -errno; + write_to_log = __write_to_log_null; + } else if (fcntl(i, F_SETFL, O_NONBLOCK) < 0) { + ret = -errno; + close(i); + i = -1; + write_to_log = __write_to_log_null; + } else { + struct sockaddr_un un; + memset(&un, 0, sizeof(struct sockaddr_un)); + un.sun_family = AF_UNIX; + strlcpy(un.sun_path, SEEMP_SOCK_NAME, sizeof(un.sun_path)); + if (connect(i, (struct sockaddr *)&un, sizeof(struct sockaddr_un)) < 0) { + ret = -errno; + close(i); + i = -1; + } + } + logd_fd = i; + return ret; +} + +static int __write_to_log_socket(struct iovec *vec, size_t nr) +{ + ssize_t ret; + if (logd_fd < 0) { + return -EBADF; + } + + /* + * The write below could be lost, but will never block. + * + * ENOTCONN occurs if logd dies. + * EAGAIN occurs if logd is overloaded. + */ + ret = writev(logd_fd, vec, nr); + if (ret < 0) { + ret = -errno; + if (ret == -ENOTCONN) { + ret = __write_to_log_initialize(); + if (ret < 0) { + return ret; + } + + ret = writev(logd_fd, vec, nr); + if (ret < 0) { + ret = -errno; + } + } + } + + return ret; +} + +static int __write_to_log_init(struct iovec *vec, size_t nr) +{ + if (write_to_log == __write_to_log_init) { + + if (getppid() == ZYGOTE_PARENT_PID) { + return 0; + } + + int ret; + + ret = __write_to_log_initialize(); + if (ret < 0) { + return ret; + } + + write_to_log = __write_to_log_socket; + } + return write_to_log(vec, nr); +} + +int __android_seemp_socket_write(int len, const char *msg) +{ + struct iovec vec; + vec.iov_base = (void *) msg; + vec.iov_len = len; + + return write_to_log(&vec, 1); +} + +namespace android { + +/* + * In class android.util.Log: + * public static native int println_native(int buffer, int priority, String tag, String msg) + */ +static jint android_util_SeempLog_println_native(JNIEnv* env, jobject clazz, + jint api, jstring msgObj) +{ + if (msgObj == NULL) { + jniThrowNullPointerException(env, "seemp_println needs a message"); + return -1; + } + + int apiId = (int)api; + int apiIdLen = sizeof(apiId); + int utf8MsgLen = env->GetStringUTFLength(msgObj); + int len = apiIdLen + 1 + utf8MsgLen + 1; + char *msg = (char*)malloc(len); + if ( NULL == msg ) + { + return -1; + } + char *params = msg + apiIdLen + 1; // api_id + encoding byte + params + + *((int*)msg) = apiId; // copy api id + // // skip encoding byte + env->GetStringUTFRegion(msgObj, 0, env->GetStringLength(msgObj), params); // copy message + msg[len - 1] = 0; // copy terminating zero + + int res = __android_seemp_socket_write(len, msg); // send message + + free(msg); + + return res; +} + +/* + * JNI registration. + */ +static JNINativeMethod gMethods[] = { + /* name, signature, funcPtr */ + { "seemp_println_native", "(ILjava/lang/String;)I", + (void*) android_util_SeempLog_println_native }, +}; + +int register_android_util_SeempLog(JNIEnv* env) +{ + jclass clazz = env->FindClass("android/util/SeempLog"); + if (clazz == NULL) { + return -1; + } + + return AndroidRuntime::registerNativeMethods(env, "android/util/SeempLog", gMethods, + NELEM(gMethods)); +} + +}; // namespace android diff --git a/core/jni/android_view_InputEventReceiver.cpp b/core/jni/android_view_InputEventReceiver.cpp index a699f912806d..ce419b104c57 100644 --- a/core/jni/android_view_InputEventReceiver.cpp +++ b/core/jni/android_view_InputEventReceiver.cpp @@ -54,6 +54,7 @@ static struct { jmethodID onPointerCaptureEvent; jmethodID onDragEvent; jmethodID onBatchedInputEventPending; + jmethodID dispatchMotionEventInfo; } gInputEventReceiverClassInfo; // Add prefix to the beginning of each line in 'str' @@ -108,6 +109,8 @@ private: bool mBatchedInputEventPending; int mFdEvents; std::vector<OutboundEvent> mOutboundQueue; + int mLastMotionEventType = -1; + int mLastTouchMoveNum = -1; void setFdEvents(int events); @@ -314,10 +317,34 @@ status_t NativeInputEventReceiver::consumeEvents(JNIEnv* env, bool skipCallbacks = false; for (;;) { uint32_t seq; + int motionEventType = -1; + int touchMoveNum = -1; + bool flag = false; + InputEvent* inputEvent; status_t status = mInputConsumer.consume(&mInputEventFactory, - consumeBatches, frameTime, &seq, &inputEvent); + consumeBatches, frameTime, &seq, &inputEvent, + &motionEventType, &touchMoveNum, &flag); + + if (!receiverObj.get()) { + receiverObj.reset(jniGetReferent(env, mReceiverWeakGlobal)); + if (!receiverObj.get()) { + ALOGW("channel '%s' ~ Receiver object was finalized " + "without being disposed.", getInputChannelName().c_str()); + return DEAD_OBJECT; + } + } + + if (flag && ((mLastMotionEventType != motionEventType) || + (mLastTouchMoveNum != touchMoveNum))) { + env->CallVoidMethod(receiverObj.get(), + gInputEventReceiverClassInfo.dispatchMotionEventInfo, motionEventType, touchMoveNum); + mLastMotionEventType = motionEventType; + mLastTouchMoveNum = touchMoveNum; + flag = false; + } + if (status != OK && status != WOULD_BLOCK) { ALOGE("channel '%s' ~ Failed to consume input event. status=%s(%d)", getInputChannelName().c_str(), statusToString(status).c_str(), status); @@ -611,6 +638,8 @@ int register_android_view_InputEventReceiver(JNIEnv* env) { gInputEventReceiverClassInfo.onBatchedInputEventPending = GetMethodIDOrDie(env, gInputEventReceiverClassInfo.clazz, "onBatchedInputEventPending", "(I)V"); + gInputEventReceiverClassInfo.dispatchMotionEventInfo = GetMethodIDOrDie(env, + gInputEventReceiverClassInfo.clazz, "dispatchMotionEventInfo", "(II)V"); return res; } diff --git a/core/jni/com_android_internal_app_ActivityTrigger.cpp b/core/jni/com_android_internal_app_ActivityTrigger.cpp new file mode 100644 index 000000000000..9d22f69d91ea --- /dev/null +++ b/core/jni/com_android_internal_app_ActivityTrigger.cpp @@ -0,0 +1,256 @@ +/* Copyright (c) 2015-2017, The Linux Foundation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of The Linux Foundation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#define LOG_TAG "ActTriggerJNI" + +#include "jni.h" +#include <nativehelper/JNIHelp.h> +#include <android_runtime/AndroidRuntime.h> + +#include <dlfcn.h> +#include <limits.h> +#include <string.h> + +#include <cutils/properties.h> +#include <utils/Log.h> + +namespace android +{ + +// ---------------------------------------------------------------------------- +/* + * Stuct containing handle to dynamically loaded lib as well as function + * pointers to key interfaces. + */ +typedef struct dlLibHandler { + void *dlhandle; + void (*startActivity)(const char *, int *); + void (*startApp)(const char *, int *); + void (*resumeActivity)(const char *); + void (*pauseActivity)(const char *); + void (*stopActivity)(const char *); + void (*init)(void); + void (*deinit)(void); + void (*miscActivity)(int, const char *, int, int, float *); + const char *dlname; +}dlLibHandler; + +/* + * Init for activity trigger library + */ +static dlLibHandler mDlLibHandler = { + NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, "libqti-at.so" +}; + +// ---------------------------------------------------------------------------- + +static void +com_android_internal_app_ActivityTrigger_native_at_init() +{ + bool errored = false; + + mDlLibHandler.dlhandle = dlopen(mDlLibHandler.dlname, RTLD_NOW | RTLD_LOCAL); + if (mDlLibHandler.dlhandle == NULL) { + return; + } + + *(void **) (&mDlLibHandler.startActivity) = dlsym(mDlLibHandler.dlhandle, "activity_trigger_start"); + if (mDlLibHandler.startActivity == NULL) { + errored = true; + } + + *(void **) (&mDlLibHandler.startApp) = dlsym(mDlLibHandler.dlhandle, "activity_trigger_qspm_start"); + + if (!errored) { + *(void **) (&mDlLibHandler.resumeActivity) = dlsym(mDlLibHandler.dlhandle, "activity_trigger_resume"); + if (mDlLibHandler.resumeActivity == NULL) { + errored = true; + } + } + if (!errored) { + *(void **) (&mDlLibHandler.pauseActivity) = dlsym(mDlLibHandler.dlhandle, "activity_trigger_pause"); + if (mDlLibHandler.pauseActivity == NULL) { + errored = true; + } + } + if (!errored) { + *(void **) (&mDlLibHandler.stopActivity) = dlsym(mDlLibHandler.dlhandle, "activity_trigger_stop"); + if (mDlLibHandler.stopActivity == NULL) { + errored = true; + } + } + if (!errored) { + *(void **) (&mDlLibHandler.init) = dlsym(mDlLibHandler.dlhandle, "activity_trigger_init"); + if (mDlLibHandler.init == NULL) { + errored = true; + } + } + if (!errored) { + *(void **) (&mDlLibHandler.miscActivity) = dlsym(mDlLibHandler.dlhandle, "activity_trigger_misc"); + if (mDlLibHandler.miscActivity == NULL) { + errored = true; + } + } + if (errored) { + mDlLibHandler.startActivity = NULL; + mDlLibHandler.startApp = NULL; + mDlLibHandler.resumeActivity = NULL; + mDlLibHandler.pauseActivity = NULL; + mDlLibHandler.stopActivity = NULL; + mDlLibHandler.miscActivity = NULL; + if (mDlLibHandler.dlhandle) { + dlclose(mDlLibHandler.dlhandle); + mDlLibHandler.dlhandle = NULL; + } + } else { + (*mDlLibHandler.init)(); + } +} + +static void +com_android_internal_app_ActivityTrigger_native_at_deinit(JNIEnv *env, jobject clazz) +{ + if (mDlLibHandler.dlhandle) { + mDlLibHandler.startActivity = NULL; + mDlLibHandler.startApp = NULL; + mDlLibHandler.resumeActivity = NULL; + mDlLibHandler.pauseActivity = NULL; + mDlLibHandler.stopActivity = NULL; + mDlLibHandler.miscActivity = NULL; + + *(void **) (&mDlLibHandler.deinit) = dlsym(mDlLibHandler.dlhandle, "activity_trigger_deinit"); + if (mDlLibHandler.deinit) { + (*mDlLibHandler.deinit)(); + } + + dlclose(mDlLibHandler.dlhandle); + mDlLibHandler.dlhandle = NULL; + } +} + +static jint +com_android_internal_app_ActivityTrigger_native_at_startActivity(JNIEnv *env, jobject clazz, jstring activity, jint flags) +{ + int activiyFlags = flags; + if(mDlLibHandler.startActivity && activity) { + const char *actStr = env->GetStringUTFChars(activity, NULL); + if (actStr) { + (*mDlLibHandler.startActivity)(actStr, &activiyFlags); + env->ReleaseStringUTFChars(activity, actStr); + } + } + return activiyFlags; +} + +static jint +com_android_internal_app_ActivityTrigger_native_at_startApp(JNIEnv *env, jobject clazz, jstring activity, jint flags) +{ + int activiyFlags = flags; + if(mDlLibHandler.startApp && activity) { + const char *actStr = env->GetStringUTFChars(activity, NULL); + if (actStr) { + (*mDlLibHandler.startApp)(actStr, &activiyFlags); + env->ReleaseStringUTFChars(activity, actStr); + } + } + return activiyFlags; +} + +static void +com_android_internal_app_ActivityTrigger_native_at_resumeActivity(JNIEnv *env, jobject clazz, jstring activity) +{ + if(mDlLibHandler.resumeActivity && activity) { + const char *actStr = env->GetStringUTFChars(activity, NULL); + if (actStr) { + (*mDlLibHandler.resumeActivity)(actStr); + env->ReleaseStringUTFChars(activity, actStr); + } + } +} + +static void +com_android_internal_app_ActivityTrigger_native_at_pauseActivity(JNIEnv *env, jobject clazz, jstring activity) +{ + if(mDlLibHandler.pauseActivity && activity) { + const char *actStr = env->GetStringUTFChars(activity, NULL); + if (NULL != actStr) { + (*mDlLibHandler.pauseActivity)(actStr); + env->ReleaseStringUTFChars(activity, actStr); + } + } +} + +static void +com_android_internal_app_ActivityTrigger_native_at_stopActivity(JNIEnv *env, jobject clazz, jstring activity) +{ + if(mDlLibHandler.stopActivity && activity) { + const char *actStr = env->GetStringUTFChars(activity, NULL); + if (NULL != actStr) { + (*mDlLibHandler.stopActivity)(actStr); + env->ReleaseStringUTFChars(activity, actStr); + } + } +} + +static jfloat +com_android_internal_app_ActivityTrigger_native_at_miscActivity(JNIEnv *env, jobject clazz, jint func, jstring activity, jint type, jint flag) +{ + float scaleValue = -1.0f; + if (mDlLibHandler.miscActivity && activity && func) { + const char *actStr = env->GetStringUTFChars(activity, NULL); + if (actStr) { + (*mDlLibHandler.miscActivity)(func, actStr, type, flag, &scaleValue); + env->ReleaseStringUTFChars(activity, actStr); + } + } + return scaleValue; +} + +// ---------------------------------------------------------------------------- + +static JNINativeMethod gMethods[] = { + {"native_at_startActivity", "(Ljava/lang/String;I)I", (void *)com_android_internal_app_ActivityTrigger_native_at_startActivity}, + {"native_at_startApp", "(Ljava/lang/String;I)I", (void *)com_android_internal_app_ActivityTrigger_native_at_startApp}, + {"native_at_resumeActivity", "(Ljava/lang/String;)V", (void *)com_android_internal_app_ActivityTrigger_native_at_resumeActivity}, + {"native_at_pauseActivity", "(Ljava/lang/String;)V", (void *)com_android_internal_app_ActivityTrigger_native_at_pauseActivity}, + {"native_at_stopActivity", "(Ljava/lang/String;)V", (void *)com_android_internal_app_ActivityTrigger_native_at_stopActivity}, + {"native_at_deinit", "()V", (void *)com_android_internal_app_ActivityTrigger_native_at_deinit}, + {"native_at_miscActivity", "(ILjava/lang/String;II)F", (void *)com_android_internal_app_ActivityTrigger_native_at_miscActivity}, +}; + +int register_com_android_internal_app_ActivityTrigger(JNIEnv *env) +{ + com_android_internal_app_ActivityTrigger_native_at_init(); + + return AndroidRuntime::registerNativeMethods(env, + "com/android/internal/app/ActivityTrigger", gMethods, NELEM(gMethods)); +} + +} // namespace android diff --git a/core/jni/com_android_internal_os_Zygote.cpp b/core/jni/com_android_internal_os_Zygote.cpp index bed0aae074a4..e28cbd8cf1a1 100644 --- a/core/jni/com_android_internal_os_Zygote.cpp +++ b/core/jni/com_android_internal_os_Zygote.cpp @@ -75,6 +75,8 @@ #include <bionic/mte.h> #include <cutils/fs.h> #include <cutils/multiuser.h> +#include <cutils/properties.h> +#include <cutils/sched_policy.h> #include <cutils/sockets.h> #include <private/android_filesystem_config.h> #include <processgroup/processgroup.h> @@ -84,6 +86,7 @@ #include <stats_socket.h> #include <utils/String8.h> #include <utils/Trace.h> +#include <dlfcn.h> #include <nativehelper/JNIHelp.h> #include <nativehelper/ScopedLocalRef.h> @@ -613,7 +616,14 @@ static void EnableDebugger() { if (getrlimit(RLIMIT_CORE, &rl) == -1) { ALOGE("getrlimit(RLIMIT_CORE) failed"); } else { - rl.rlim_cur = 0; + char prop_value[PROPERTY_VALUE_MAX]; + property_get("persist.debug.trace", prop_value, "0"); + if (prop_value[0] == '1') { + ALOGI("setting RLIM to infinity"); + rl.rlim_cur = RLIM_INFINITY; + } else { + rl.rlim_cur = 0; + } if (setrlimit(RLIMIT_CORE, &rl) == -1) { ALOGE("setrlimit(RLIMIT_CORE) failed"); } @@ -627,6 +637,19 @@ static void PreApplicationInit() { // Set the jemalloc decay time to 1. mallopt(M_DECAY_TIME, 1); + + void *mBelugaHandle = nullptr; + void (*mBeluga)() = nullptr; + mBelugaHandle = dlopen("libbeluga.so", RTLD_NOW); + if (!mBelugaHandle) { + ALOGW("Unable to open libbeluga.so: %s.", dlerror()); + } + else { + mBeluga = (void (*) ())dlsym(mBelugaHandle, "beluga"); + if (mBeluga) + mBeluga(); + dlclose(mBelugaHandle); + } } static void SetUpSeccompFilter(uid_t uid, bool is_child_zygote) { @@ -1836,6 +1859,7 @@ static jlong CalculateCapabilities(JNIEnv* env, jint uid, jint gid, jintArray gi capabilities |= (1LL << CAP_NET_RAW); capabilities |= (1LL << CAP_NET_BIND_SERVICE); capabilities |= (1LL << CAP_SYS_NICE); + capabilities |= (1LL << CAP_NET_ADMIN); } if (multiuser_get_app_id(uid) == AID_NETWORK_STACK) { diff --git a/core/proto/android/providers/settings/global.proto b/core/proto/android/providers/settings/global.proto index 83e26f66fd62..2a27b0998d4a 100644 --- a/core/proto/android/providers/settings/global.proto +++ b/core/proto/android/providers/settings/global.proto @@ -712,6 +712,8 @@ message GlobalSettingsProto { optional SettingProto server = 1; // Timeout in milliseconds to wait for NTP server. optional SettingProto timeout_ms = 2 [ (android.privacy).dest = DEST_AUTOMATIC ]; + // Secondary NTP server. + optional SettingProto server_2 = 3; } optional Ntp ntp = 84; diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml index f525315dd5fa..03fa20ecde2b 100644 --- a/core/res/AndroidManifest.xml +++ b/core/res/AndroidManifest.xml @@ -52,6 +52,7 @@ <protected-broadcast android:name="android.intent.action.PACKAGE_FIRST_LAUNCH" /> <protected-broadcast android:name="android.intent.action.PACKAGE_NEEDS_INTEGRITY_VERIFICATION" /> <protected-broadcast android:name="android.intent.action.PACKAGE_NEEDS_VERIFICATION" /> + <protected-broadcast android:name="com.qualcomm.qti.intent.action.PACKAGE_NEEDS_OPTIONAL_VERIFICATION" /> <protected-broadcast android:name="android.intent.action.PACKAGE_VERIFIED" /> <protected-broadcast android:name="android.intent.action.PACKAGES_SUSPENDED" /> <protected-broadcast android:name="android.intent.action.PACKAGES_UNSUSPENDED" /> @@ -172,8 +173,10 @@ <protected-broadcast android:name="android.bluetooth.device.action.CONNECTION_ACCESS_REQUEST" /> <protected-broadcast android:name="android.bluetooth.device.action.SDP_RECORD" /> <protected-broadcast android:name="android.bluetooth.device.action.BATTERY_LEVEL_CHANGED" /> + <protected-broadcast android:name="android.bluetooth.device.action.TWS_PLUS_DEVICE_PAIR" /> <protected-broadcast android:name="android.bluetooth.devicepicker.action.LAUNCH" /> <protected-broadcast android:name="android.bluetooth.devicepicker.action.DEVICE_SELECTED" /> + <protected-broadcast android:name="org.codeaurora.intent.bluetooth.action.REMOTE_ISSUE_OCCURRED" /> <protected-broadcast android:name="android.bluetooth.headset.profile.action.CONNECTION_STATE_CHANGED" /> <protected-broadcast @@ -185,6 +188,8 @@ <protected-broadcast android:name="android.bluetooth.headset.profile.action.ACTIVE_DEVICE_CHANGED" /> <protected-broadcast + android:name="android.bluetooth.headset.action.HF_TWSP_BATTERY_STATE_CHANGED" /> + <protected-broadcast android:name="android.bluetooth.headsetclient.profile.action.CONNECTION_STATE_CHANGED" /> <protected-broadcast android:name="android.bluetooth.headsetclient.profile.action.AUDIO_STATE_CHANGED" /> @@ -384,7 +389,28 @@ <protected-broadcast android:name="com.android.server.wifi.wakeup.OPEN_WIFI_PREFERENCES" /> <protected-broadcast android:name="com.android.server.wifi.wakeup.OPEN_WIFI_SETTINGS" /> <protected-broadcast android:name="com.android.server.wifi.wakeup.TURN_OFF_WIFI_WAKE" /> + + <protected-broadcast android:name="com.qualcomm.qti.wigig.WIGIG_CREDENTIAL_CHANGED" /> + <protected-broadcast android:name="com.qualcomm.qti.wigig.WIGIG_STATE_CHANGED" /> + <protected-broadcast android:name="com.qualcomm.qti.wigig.WIGIG_AP_STATE_CHANGED" /> + <protected-broadcast android:name="com.qualcomm.qti.wigig.supplicant.CONNECTION_CHANGE" /> + <protected-broadcast android:name="com.qualcomm.qti.wigig.STATE_CHANGE" /> + <protected-broadcast android:name="com.qualcomm.qti.wigig.CONFIGURED_NETWORKS_CHANGE" /> + <protected-broadcast android:name="com.qualcomm.qti.wigig.SCAN_RESULTS" /> + <protected-broadcast android:name="com.qualcomm.qti.wigig.LINK_CONFIGURATION_CHANGED" /> + <protected-broadcast android:name="com.qualcomm.qti.wigig.WIGIG_RATE_UPGRADE_STATE_CHANGED" /> + <protected-broadcast android:name="com.qualcomm.qti.wigig.RSSI_CHANGED" /> + <protected-broadcast android:name="wigig_scan_available" /> + <protected-broadcast android:name="android.net.wigig.p2p.STATE_CHANGED" /> + <protected-broadcast android:name="android.net.wigig.p2p.CONNECTION_STATE_CHANGE" /> + <protected-broadcast android:name="android.net.wigig.p2p.PEERS_CHANGED" /> + <protected-broadcast android:name="android.net.wigig.p2p.DISCOVERY_STATE_CHANGE" /> + <protected-broadcast android:name="android.net.wigig.p2p.THIS_DEVICE_CHANGED" /> + <protected-broadcast android:name="android.net.wigig.p2p.PERSISTENT_GROUPS_CHANGED" /> + <protected-broadcast android:name="android.net.wifi.WIFI_STATE_CHANGED" /> + <protected-broadcast android:name="com.qualcomm.qti.net.wifi.WIFI_ALERT" /> + <protected-broadcast android:name="com.qualcomm.qti.net.wifi.WIFI_NETWORK_DISCONNECTION" /> <protected-broadcast android:name="android.net.wifi.WIFI_AP_STATE_CHANGED" /> <protected-broadcast android:name="android.net.wifi.WIFI_CREDENTIAL_CHANGED" /> <protected-broadcast android:name="android.net.wifi.aware.action.WIFI_AWARE_STATE_CHANGED" /> @@ -411,6 +437,9 @@ <protected-broadcast android:name="android.net.wifi.p2p.PEERS_CHANGED" /> <protected-broadcast android:name="android.net.wifi.p2p.CONNECTION_STATE_CHANGE" /> <protected-broadcast android:name="android.net.wifi.p2p.action.WIFI_P2P_PERSISTENT_GROUPS_CHANGED" /> + <protected-broadcast android:name="com.qualcomm.qti.net.wifi.DPP_EVENT" /> + <protected-broadcast android:name="com.qualcomm.qti.net.wifi.PARTIAL_SCAN_RESULTS" /> + <protected-broadcast android:name="android.net.wifi.COUNTRY_CODE_CHANGED" /> <protected-broadcast android:name="android.net.conn.TETHER_STATE_CHANGED" /> <protected-broadcast android:name="android.net.conn.INET_CONDITION_ACTION" /> <!-- This broadcast is no longer sent in S but it should stay protected to avoid third party @@ -617,6 +646,11 @@ <protected-broadcast android:name="android.bluetooth.input.profile.action.HANDSHAKE" /> <protected-broadcast android:name="android.bluetooth.input.profile.action.REPORT" /> + <protected-broadcast android:name="android.bluetooth.bat.profile.action.BA_STATE_CHANGED" /> + <protected-broadcast android:name="android.bluetooth.bat.profile.action.BA_ENC_KEY_CHANGED" /> + <protected-broadcast android:name="android.bluetooth.bat.profile.action.BA_DIV_CHANGED" /> + <protected-broadcast android:name="android.bluetooth.bat.profile.action.BA_STR_ID_CHANGED" /> + <protected-broadcast android:name="android.intent.action.TWILIGHT_CHANGED" /> <protected-broadcast android:name="com.android.server.fingerprint.ACTION_LOCKOUT_RESET" /> @@ -1615,6 +1649,11 @@ <permission android:name="android.permission.MODIFY_CELL_BROADCASTS" android:protectionLevel="signature|privileged" /> + <!-- Allows an application to authorize outgoing SMS messages. + @hide --> + <permission android:name="com.qti.permission.AUTHORIZE_OUTGOING_SMS" + android:protectionLevel="signature" /> + <!-- =============================================================== --> <!-- Permissions for setting the device alarm --> <!-- =============================================================== --> diff --git a/core/res/res/drawable/ic_wifi_4_signal_0.xml b/core/res/res/drawable/ic_wifi_4_signal_0.xml new file mode 100644 index 000000000000..bf077124f065 --- /dev/null +++ b/core/res/res/drawable/ic_wifi_4_signal_0.xml @@ -0,0 +1,41 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + Copyright (c) 2019, The Linux Foundation. All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are + met: + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following + disclaimer in the documentation and/or other materials provided + with the distribution. + * Neither the name of The Linux Foundation nor the names of its + contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED + WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS + BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +--> +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="26dp" + android:height="24dp" + android:viewportWidth="26" + android:viewportHeight="24"> + <path + android:fillColor="@android:color/white" + android:pathData="M 12,2.001359 C 7.2499999,2.001359 2.9699999,4.079946 -1.25e-7,7.389946 L 12,21.998641 15.048913,18.289401 A 6.2033902,6.4067802 0 0 1 14.192935,16.186142 L 12,18.851901 2.6983696,7.528533 C 5.2683695,5.268533 8.5799999,3.998641 12,3.998641 c 3.42,0 6.73163,1.269892 9.30163,3.529892 l -0.709239,0.86413 a 6.2033902,6.4067802 0 0 1 2.148097,0.529891 L 24,7.389946 c -2.97,-3.31 -7.25,-5.388587 -12,-5.388587 z"/> + <path + android:fillColor="@android:color/white" + android:pathData="m 24.401344,17.117563 h -1.056598 v 1.849791 h -1.506209 v -1.849791 h -3.602534 v -1.359946 l 3.344006,-5.8716006 h 1.764737 v 5.8844916 h 1.056598 z M 21.838537,15.770508 V 12.79926 q 0,-0.348044 0.01967,-0.754093 0.01968,-0.406048 0.03092,-0.522067 v 0 q -0.146131,0.360936 -0.528296,1.044134 v 0 l -1.83781,3.203274 z"/> +</vector> diff --git a/core/res/res/drawable/ic_wifi_4_signal_1.xml b/core/res/res/drawable/ic_wifi_4_signal_1.xml new file mode 100644 index 000000000000..619614f90a53 --- /dev/null +++ b/core/res/res/drawable/ic_wifi_4_signal_1.xml @@ -0,0 +1,44 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + Copyright (c) 2019, The Linux Foundation. All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are + met: + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following + disclaimer in the documentation and/or other materials provided + with the distribution. + * Neither the name of The Linux Foundation nor the names of its + contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED + WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS + BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +--> +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="26dp" + android:height="24dp" + android:viewportWidth="26" + android:viewportHeight="24"> + <path + android:fillColor="@android:color/white" + android:pathData="m 24.401344,17.117563 h -1.056598 v 1.849791 h -1.506209 v -1.849791 h -3.602534 v -1.359946 l 3.344006,-5.8716006 h 1.764737 v 5.8844916 h 1.056598 z M 21.838537,15.770508 V 12.79926 q 0,-0.348044 0.01967,-0.754093 0.01968,-0.406048 0.03092,-0.522067 v 0 q -0.146131,0.360936 -0.528296,1.044134 v 0 l -1.83781,3.203274 z"/> + <path + android:fillColor="@android:color/white" + android:pathData="m 13.100543,2.0095112 c -4.75,0 -9.029999,2.078587 -12,5.388587 l 12,14.6005438 3.827446,-4.654892 a 7.7288136,8.3389834 0 0 1 -0.04484,-0.835598 7.7288136,8.3389834 0 0 1 0.460598,-2.816576 L 13.10054,18.860054 3.79891,7.5366842 c 2.57,-2.259999 5.88163,-3.529891 9.30163,-3.529891 3.42,0 6.731631,1.269892 9.301631,3.529891 l -1.247282,1.516305 a 7.7288136,8.3389834 0 0 1 3.305705,-0.876359 l 0.639947,-0.778532 c -2.97,-3.31 -7.250001,-5.388587 -12.000001,-5.388587 z"/> + <path + android:fillColor="@android:color/white" + android:pathData="m 13.100543,13.300272 c -3.2,0 -5.2986406,1.799456 -5.4986408,1.899456 l 5.4986408,6.798914 4.043479,-4.997283 a 7.7288137,8.3389834 0 0 1 -0.06114,-0.933424 7.7288137,8.3389834 0 0 1 0.171196,-1.732337 c -0.961558,-0.505425 -2.35688,-1.035326 -4.153535,-1.035326 z"/> +</vector> diff --git a/core/res/res/drawable/ic_wifi_4_signal_2.xml b/core/res/res/drawable/ic_wifi_4_signal_2.xml new file mode 100644 index 000000000000..e6fd9e862349 --- /dev/null +++ b/core/res/res/drawable/ic_wifi_4_signal_2.xml @@ -0,0 +1,44 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + Copyright (c) 2019, The Linux Foundation. All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are + met: + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following + disclaimer in the documentation and/or other materials provided + with the distribution. + * Neither the name of The Linux Foundation nor the names of its + contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED + WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS + BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +--> +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="26dp" + android:height="24dp" + android:viewportWidth="26" + android:viewportHeight="24"> + <path + android:fillColor="@android:color/white" + android:pathData="m 24.401344,17.117563 h -1.056598 v 1.849791 h -1.506209 v -1.849791 h -3.602534 v -1.359946 l 3.344006,-5.8716006 h 1.764737 v 5.8844916 h 1.056598 z M 21.838537,15.770508 V 12.79926 q 0,-0.348044 0.01967,-0.754093 0.01968,-0.406048 0.03092,-0.522067 v 0 q -0.146131,0.360936 -0.528296,1.044134 v 0 l -1.83781,3.203274 z"/> + <path + android:fillColor="@android:color/white" + android:pathData="m 12.998641,2.0095112 c -4.75,0 -9.029999,2.078587 -12,5.388587 l 12,14.6005438 3.827446,-4.654892 a 7.7288136,8.3389834 0 0 1 -0.04484,-0.835598 7.7288136,8.3389834 0 0 1 0.460598,-2.816576 L 12.998638,18.860054 3.697008,7.5366842 c 2.57,-2.259999 5.88163,-3.529891 9.30163,-3.529891 3.42,0 6.731631,1.269892 9.301631,3.529891 l -1.247282,1.516305 a 7.7288136,8.3389834 0 0 1 3.305705,-0.876359 l 0.639947,-0.778532 c -2.97,-3.31 -7.250001,-5.388587 -12.000001,-5.388587 z"/> + <path + android:fillColor="@android:color/white" + android:pathData="m 12.998641,9.998641 c -4.3999993,0 -7.297826,2.402446 -7.597826,2.702446 l 7.597826,9.297555 4.133152,-5.111414 a 7.7288137,8.3389834 0 0 1 -0.04891,-0.847826 7.7288137,8.3389834 0 0 1 1.377718,-4.744565 C 17.138647,10.644289 15.284639,9.998641 12.998644,9.998641 Z"/> +</vector> diff --git a/core/res/res/drawable/ic_wifi_4_signal_3.xml b/core/res/res/drawable/ic_wifi_4_signal_3.xml new file mode 100644 index 000000000000..1b2eb8efee0a --- /dev/null +++ b/core/res/res/drawable/ic_wifi_4_signal_3.xml @@ -0,0 +1,44 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + Copyright (c) 2019, The Linux Foundation. All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are + met: + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following + disclaimer in the documentation and/or other materials provided + with the distribution. + * Neither the name of The Linux Foundation nor the names of its + contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED + WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS + BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +--> +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="26dp" + android:height="24dp" + android:viewportWidth="26" + android:viewportHeight="24"> + <path + android:fillColor="@android:color/white" + android:pathData="m 24.401344,17.117563 h -1.056598 v 1.849791 h -1.506209 v -1.849791 h -3.602534 v -1.359946 l 3.344006,-5.8716006 h 1.764737 v 5.8844916 h 1.056598 z M 21.838537,15.770508 V 12.79926 q 0,-0.348044 0.01967,-0.754093 0.01968,-0.406048 0.03092,-0.522067 v 0 q -0.146131,0.360936 -0.528296,1.044134 v 0 l -1.83781,3.203274 z"/> + <path + android:fillColor="@android:color/white" + android:pathData="m 12.998641,7.398098 c -5.3000001,0 -8.8997284,3.003804 -9.1997284,3.203804 l 9.1997284,11.39674 4.03125,-4.997283 A 7.7288137,8.3389834 0 0 1 16.968751,16.039402 7.7288137,8.3389834 0 0 1 20.164403,9.30163 C 18.559413,8.406307 16.154773,7.398098 12.998641,7.398098 Z"/> + <path + android:fillColor="@android:color/white" + android:pathData="m 12.998641,2.0095112 c -4.75,0 -9.029999,2.078587 -12,5.388587 l 12,14.6005438 3.827446,-4.654892 a 7.7288136,8.3389834 0 0 1 -0.04484,-0.835598 7.7288136,8.3389834 0 0 1 0.460598,-2.816576 L 12.998638,18.860054 3.697008,7.5366842 c 2.57,-2.259999 5.88163,-3.529891 9.30163,-3.529891 3.42,0 6.731631,1.269892 9.301631,3.529891 l -1.247282,1.516305 a 7.7288136,8.3389834 0 0 1 3.305705,-0.876359 l 0.639947,-0.778532 c -2.97,-3.31 -7.250001,-5.388587 -12.000001,-5.388587 z"/> +</vector> diff --git a/core/res/res/drawable/ic_wifi_4_signal_4.xml b/core/res/res/drawable/ic_wifi_4_signal_4.xml new file mode 100644 index 000000000000..d264adbd140d --- /dev/null +++ b/core/res/res/drawable/ic_wifi_4_signal_4.xml @@ -0,0 +1,41 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + Copyright (c) 2019, The Linux Foundation. All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are + met: + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following + disclaimer in the documentation and/or other materials provided + with the distribution. + * Neither the name of The Linux Foundation nor the names of its + contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED + WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS + BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +--> +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="26dp" + android:height="24dp" + android:viewportWidth="26" + android:viewportHeight="24"> + <path + android:fillColor="@android:color/white" + android:pathData="m 24.401344,17.117563 h -1.056598 v 1.849791 h -1.506209 v -1.849791 h -3.602534 v -1.359946 l 3.344006,-5.8716006 h 1.764737 v 5.8844916 h 1.056598 z M 21.838537,15.770508 V 12.79926 q 0,-0.348044 0.01967,-0.754093 0.01968,-0.406048 0.03092,-0.522067 v 0 q -0.146131,0.360936 -0.528296,1.044134 v 0 l -1.83781,3.203274 z"/> + <path + android:fillColor="@android:color/white" + android:pathData="m 12.998641,2.099185 c -7.3000003,0 -12.0991851,4.002174 -12.59918509,4.402174 L 12.998641,21.998642 16.944293,17.148098 a 7.7288137,8.3389834 0 0 1 -0.06114,-0.978261 7.7288137,8.3389834 0 0 1 7.634511,-8.335597 l 1.084238,-1.332881 c -0.499999,-0.4 -5.303261,-4.402174 -12.603261,-4.402174 z"/> +</vector> diff --git a/core/res/res/drawable/ic_wifi_5_signal_0.xml b/core/res/res/drawable/ic_wifi_5_signal_0.xml new file mode 100644 index 000000000000..dde3ec85d286 --- /dev/null +++ b/core/res/res/drawable/ic_wifi_5_signal_0.xml @@ -0,0 +1,41 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + Copyright (c) 2019, The Linux Foundation. All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are + met: + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following + disclaimer in the documentation and/or other materials provided + with the distribution. + * Neither the name of The Linux Foundation nor the names of its + contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED + WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS + BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +--> +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="26dp" + android:height="24dp" + android:viewportWidth="26" + android:viewportHeight="24"> + <path + android:fillColor="@android:color/white" + android:pathData="M 12,2.001359 C 7.2499999,2.001359 2.9699999,4.079946 -1.25e-7,7.389946 L 12,21.998641 15.048913,18.289401 A 6.2033902,6.4067802 0 0 1 14.192935,16.186142 L 12,18.851901 2.6983696,7.528533 C 5.2683695,5.268533 8.5799999,3.998641 12,3.998641 c 3.42,0 6.73163,1.269892 9.30163,3.529892 l -0.709239,0.86413 a 6.2033902,6.4067802 0 0 1 2.148097,0.529891 L 24,7.389946 c -2.97,-3.31 -7.25,-5.388587 -12,-5.388587 z"/> + <path + android:fillColor="@android:color/white" + android:pathData="m 25.626571,16.969114 v 0 q 0,1.36304 -0.84885,2.1693 -0.84886,0.80626 -2.32751,0.80626 v 0 q -1.29001,0 -2.06585,-0.58112 -0.77583,-0.58112 -0.95838,-1.6825 v 0 l 1.70988,-0.13995 q 0.13387,0.54765 0.47462,0.79713 0.34076,0.24949 0.85799,0.24949 v 0 q 0.63892,0 1.01923,-0.4077 0.38031,-0.40769 0.38031,-1.1744 v 0 q 0,-0.67543 -0.35901,-1.08008 -0.35902,-0.40465 -1.00402,-0.40465 v 0 q -0.71195,0 -1.16223,0.55373 v 0 h -1.66729 l 0.29817,-4.825391 h 5.15397 v 1.27176 h -3.6023 l -0.13996,2.166251 q 0.62067,-0.54764 1.55167,-0.54764 v 0 q 1.22308,0 1.95632,0.76062 0.73324,0.76062 0.73324,2.06889 z"/> +</vector> diff --git a/core/res/res/drawable/ic_wifi_5_signal_1.xml b/core/res/res/drawable/ic_wifi_5_signal_1.xml new file mode 100644 index 000000000000..5ab3be132f45 --- /dev/null +++ b/core/res/res/drawable/ic_wifi_5_signal_1.xml @@ -0,0 +1,44 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + Copyright (c) 2019, The Linux Foundation. All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are + met: + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following + disclaimer in the documentation and/or other materials provided + with the distribution. + * Neither the name of The Linux Foundation nor the names of its + contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED + WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS + BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +--> +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="26dp" + android:height="24dp" + android:viewportWidth="26" + android:viewportHeight="24"> + <path + android:fillColor="@android:color/white" + android:pathData="m 25.626571,16.969114 v 0 q 0,1.36304 -0.84885,2.1693 -0.84886,0.80626 -2.32751,0.80626 v 0 q -1.29001,0 -2.06585,-0.58112 -0.77583,-0.58112 -0.95838,-1.6825 v 0 l 1.70988,-0.13995 q 0.13387,0.54765 0.47462,0.79713 0.34076,0.24949 0.85799,0.24949 v 0 q 0.63892,0 1.01923,-0.4077 0.38031,-0.40769 0.38031,-1.1744 v 0 q 0,-0.67543 -0.35901,-1.08008 -0.35902,-0.40465 -1.00402,-0.40465 v 0 q -0.71195,0 -1.16223,0.55373 v 0 h -1.66729 l 0.29817,-4.825391 h 5.15397 v 1.27176 h -3.6023 l -0.13996,2.166251 q 0.62067,-0.54764 1.55167,-0.54764 v 0 q 1.22308,0 1.95632,0.76062 0.73324,0.76062 0.73324,2.06889 z"/> + <path + android:fillColor="@android:color/white" + android:pathData="m 13.100543,2.0095112 c -4.75,0 -9.029999,2.078587 -12,5.388587 l 12,14.6005438 3.827446,-4.654892 a 7.7288136,8.3389834 0 0 1 -0.04484,-0.835598 7.7288136,8.3389834 0 0 1 0.460598,-2.816576 L 13.10054,18.860054 3.79891,7.5366842 c 2.57,-2.259999 5.88163,-3.529891 9.30163,-3.529891 3.42,0 6.731631,1.269892 9.301631,3.529891 l -1.247282,1.516305 a 7.7288136,8.3389834 0 0 1 3.305705,-0.876359 l 0.639947,-0.778532 c -2.97,-3.31 -7.250001,-5.388587 -12.000001,-5.388587 z"/> + <path + android:fillColor="@android:color/white" + android:pathData="m 13.100543,13.300272 c -3.2,0 -5.2986406,1.799456 -5.4986408,1.899456 l 5.4986408,6.798914 4.043479,-4.997283 a 7.7288137,8.3389834 0 0 1 -0.06114,-0.933424 7.7288137,8.3389834 0 0 1 0.171196,-1.732337 c -0.961558,-0.505425 -2.35688,-1.035326 -4.153535,-1.035326 z"/> +</vector> diff --git a/core/res/res/drawable/ic_wifi_5_signal_2.xml b/core/res/res/drawable/ic_wifi_5_signal_2.xml new file mode 100644 index 000000000000..31f09222d13a --- /dev/null +++ b/core/res/res/drawable/ic_wifi_5_signal_2.xml @@ -0,0 +1,44 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + Copyright (c) 2019, The Linux Foundation. All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are + met: + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following + disclaimer in the documentation and/or other materials provided + with the distribution. + * Neither the name of The Linux Foundation nor the names of its + contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED + WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS + BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +--> +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="26dp" + android:height="24dp" + android:viewportWidth="26" + android:viewportHeight="24"> + <path + android:fillColor="@android:color/white" + android:pathData="m 25.626571,16.969114 v 0 q 0,1.36304 -0.84885,2.1693 -0.84886,0.80626 -2.32751,0.80626 v 0 q -1.29001,0 -2.06585,-0.58112 -0.77583,-0.58112 -0.95838,-1.6825 v 0 l 1.70988,-0.13995 q 0.13387,0.54765 0.47462,0.79713 0.34076,0.24949 0.85799,0.24949 v 0 q 0.63892,0 1.01923,-0.4077 0.38031,-0.40769 0.38031,-1.1744 v 0 q 0,-0.67543 -0.35901,-1.08008 -0.35902,-0.40465 -1.00402,-0.40465 v 0 q -0.71195,0 -1.16223,0.55373 v 0 h -1.66729 l 0.29817,-4.825391 h 5.15397 v 1.27176 h -3.6023 l -0.13996,2.166251 q 0.62067,-0.54764 1.55167,-0.54764 v 0 q 1.22308,0 1.95632,0.76062 0.73324,0.76062 0.73324,2.06889 z"/> + <path + android:fillColor="@android:color/white" + android:pathData="m 12.998641,2.0095112 c -4.75,0 -9.029999,2.078587 -12,5.388587 l 12,14.6005438 3.827446,-4.654892 a 7.7288136,8.3389834 0 0 1 -0.04484,-0.835598 7.7288136,8.3389834 0 0 1 0.460598,-2.816576 L 12.998638,18.860054 3.697008,7.5366842 c 2.57,-2.259999 5.88163,-3.529891 9.30163,-3.529891 3.42,0 6.731631,1.269892 9.301631,3.529891 l -1.247282,1.516305 a 7.7288136,8.3389834 0 0 1 3.305705,-0.876359 l 0.639947,-0.778532 c -2.97,-3.31 -7.250001,-5.388587 -12.000001,-5.388587 z"/> + <path + android:fillColor="@android:color/white" + android:pathData="m 12.998641,9.998641 c -4.3999993,0 -7.297826,2.402446 -7.597826,2.702446 l 7.597826,9.297555 4.133152,-5.111414 a 7.7288137,8.3389834 0 0 1 -0.04891,-0.847826 7.7288137,8.3389834 0 0 1 1.377718,-4.744565 C 17.138647,10.644289 15.284639,9.998641 12.998644,9.998641 Z"/> +</vector> diff --git a/core/res/res/drawable/ic_wifi_5_signal_3.xml b/core/res/res/drawable/ic_wifi_5_signal_3.xml new file mode 100644 index 000000000000..706af960fc2b --- /dev/null +++ b/core/res/res/drawable/ic_wifi_5_signal_3.xml @@ -0,0 +1,44 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + Copyright (c) 2019, The Linux Foundation. All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are + met: + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following + disclaimer in the documentation and/or other materials provided + with the distribution. + * Neither the name of The Linux Foundation nor the names of its + contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED + WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS + BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +--> +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="26dp" + android:height="24dp" + android:viewportWidth="26" + android:viewportHeight="24"> + <path + android:fillColor="@android:color/white" + android:pathData="m 25.626571,16.969114 v 0 q 0,1.36304 -0.84885,2.1693 -0.84886,0.80626 -2.32751,0.80626 v 0 q -1.29001,0 -2.06585,-0.58112 -0.77583,-0.58112 -0.95838,-1.6825 v 0 l 1.70988,-0.13995 q 0.13387,0.54765 0.47462,0.79713 0.34076,0.24949 0.85799,0.24949 v 0 q 0.63892,0 1.01923,-0.4077 0.38031,-0.40769 0.38031,-1.1744 v 0 q 0,-0.67543 -0.35901,-1.08008 -0.35902,-0.40465 -1.00402,-0.40465 v 0 q -0.71195,0 -1.16223,0.55373 v 0 h -1.66729 l 0.29817,-4.825391 h 5.15397 v 1.27176 h -3.6023 l -0.13996,2.166251 q 0.62067,-0.54764 1.55167,-0.54764 v 0 q 1.22308,0 1.95632,0.76062 0.73324,0.76062 0.73324,2.06889 z"/> + <path + android:fillColor="@android:color/white" + android:pathData="m 12.998641,7.398098 c -5.3000001,0 -8.8997284,3.003804 -9.1997284,3.203804 l 9.1997284,11.39674 4.03125,-4.997283 A 7.7288137,8.3389834 0 0 1 16.968751,16.039402 7.7288137,8.3389834 0 0 1 20.164403,9.30163 C 18.559413,8.406307 16.154773,7.398098 12.998641,7.398098 Z"/> + <path + android:fillColor="@android:color/white" + android:pathData="m 12.998641,2.0095112 c -4.75,0 -9.029999,2.078587 -12,5.388587 l 12,14.6005438 3.827446,-4.654892 a 7.7288136,8.3389834 0 0 1 -0.04484,-0.835598 7.7288136,8.3389834 0 0 1 0.460598,-2.816576 L 12.998638,18.860054 3.697008,7.5366842 c 2.57,-2.259999 5.88163,-3.529891 9.30163,-3.529891 3.42,0 6.731631,1.269892 9.301631,3.529891 l -1.247282,1.516305 a 7.7288136,8.3389834 0 0 1 3.305705,-0.876359 l 0.639947,-0.778532 c -2.97,-3.31 -7.250001,-5.388587 -12.000001,-5.388587 z"/> +</vector> diff --git a/core/res/res/drawable/ic_wifi_5_signal_4.xml b/core/res/res/drawable/ic_wifi_5_signal_4.xml new file mode 100644 index 000000000000..6997bbe202b4 --- /dev/null +++ b/core/res/res/drawable/ic_wifi_5_signal_4.xml @@ -0,0 +1,41 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + Copyright (c) 2019, The Linux Foundation. All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are + met: + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following + disclaimer in the documentation and/or other materials provided + with the distribution. + * Neither the name of The Linux Foundation nor the names of its + contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED + WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS + BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +--> +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="26dp" + android:height="24dp" + android:viewportWidth="26" + android:viewportHeight="24"> + <path + android:fillColor="@android:color/white" + android:pathData="m 25.626571,16.969114 v 0 q 0,1.36304 -0.84885,2.1693 -0.84886,0.80626 -2.32751,0.80626 v 0 q -1.29001,0 -2.06585,-0.58112 -0.77583,-0.58112 -0.95838,-1.6825 v 0 l 1.70988,-0.13995 q 0.13387,0.54765 0.47462,0.79713 0.34076,0.24949 0.85799,0.24949 v 0 q 0.63892,0 1.01923,-0.4077 0.38031,-0.40769 0.38031,-1.1744 v 0 q 0,-0.67543 -0.35901,-1.08008 -0.35902,-0.40465 -1.00402,-0.40465 v 0 q -0.71195,0 -1.16223,0.55373 v 0 h -1.66729 l 0.29817,-4.825391 h 5.15397 v 1.27176 h -3.6023 l -0.13996,2.166251 q 0.62067,-0.54764 1.55167,-0.54764 v 0 q 1.22308,0 1.95632,0.76062 0.73324,0.76062 0.73324,2.06889 z"/> + <path + android:fillColor="@android:color/white" + android:pathData="m 12.998641,2.099185 c -7.3000003,0 -12.0991851,4.002174 -12.59918509,4.402174 L 12.998641,21.998642 16.944293,17.148098 a 7.7288137,8.3389834 0 0 1 -0.06114,-0.978261 7.7288137,8.3389834 0 0 1 7.634511,-8.335597 l 1.084238,-1.332881 c -0.499999,-0.4 -5.303261,-4.402174 -12.603261,-4.402174 z"/> +</vector> diff --git a/core/res/res/drawable/ic_wifi_6_signal_0.xml b/core/res/res/drawable/ic_wifi_6_signal_0.xml new file mode 100644 index 000000000000..0d24f5b5251a --- /dev/null +++ b/core/res/res/drawable/ic_wifi_6_signal_0.xml @@ -0,0 +1,41 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + Copyright (c) 2019, The Linux Foundation. All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are + met: + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following + disclaimer in the documentation and/or other materials provided + with the distribution. + * Neither the name of The Linux Foundation nor the names of its + contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED + WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS + BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +--> +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="26dp" + android:height="24dp" + android:viewportWidth="26" + android:viewportHeight="24"> + <path + android:fillColor="@android:color/white" + android:pathData="M 12,2.001359 C 7.2499999,2.001359 2.9699999,4.079946 -1.25e-7,7.389946 L 12,21.998641 15.048913,18.289401 A 6.2033902,6.4067802 0 0 1 14.192935,16.186142 L 12,18.851901 2.6983696,7.528533 C 5.2683695,5.268533 8.5799999,3.998641 12,3.998641 c 3.42,0 6.73163,1.269892 9.30163,3.529892 l -0.709239,0.86413 a 6.2033902,6.4067802 0 0 1 2.148097,0.529891 L 24,7.389946 c -2.97,-3.31 -7.25,-5.388587 -12,-5.388587 z"/> + <path + android:fillColor="@android:color/white" + android:pathData="m 25.217756,16.274066 v 0 q 0,1.31751 -0.814213,2.067022 -0.814212,0.749513 -2.248777,0.749513 v 0 q -1.609039,0 -2.471717,-1.0218 Q 18.820372,17.047 18.820372,15.038537 v 0 q 0,-2.207557 0.875601,-3.323047 Q 20.571575,10.6 22.2,10.6 v 0 q 1.156698,0 1.825516,0.462592 0.668817,0.462591 0.946684,1.434619 v 0 l -1.712431,0.216656 Q 23.014213,11.89994 22.161228,11.89994 v 0 q -0.730207,0 -1.147005,0.661682 -0.4168,0.661682 -0.4168,2.008467 v 0 q 0.29079,-0.439168 0.807751,-0.673393 0.51696,-0.234223 1.169623,-0.234223 v 0 q 1.221318,0 1.932139,0.702671 0.71082,0.702671 0.71082,1.908922 z m -1.822285,0.04685 v 0 q 0,-0.70267 -0.358641,-1.0745 -0.358642,-0.37183 -0.985456,-0.37183 v 0 q -0.600966,0 -0.962838,0.348408 -0.361873,0.348407 -0.361873,0.922255 v 0 q 0,0.720242 0.378028,1.191617 0.378026,0.471375 0.991917,0.471375 v 0 q 0.61389,0 0.956377,-0.395255 0.342486,-0.395254 0.342486,-1.09207 z"/> +</vector> diff --git a/core/res/res/drawable/ic_wifi_6_signal_1.xml b/core/res/res/drawable/ic_wifi_6_signal_1.xml new file mode 100644 index 000000000000..6c580ee4574f --- /dev/null +++ b/core/res/res/drawable/ic_wifi_6_signal_1.xml @@ -0,0 +1,44 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + Copyright (c) 2019, The Linux Foundation. All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are + met: + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following + disclaimer in the documentation and/or other materials provided + with the distribution. + * Neither the name of The Linux Foundation nor the names of its + contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED + WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS + BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +--> +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="26dp" + android:height="24dp" + android:viewportWidth="26" + android:viewportHeight="24"> + <path + android:fillColor="@android:color/white" + android:pathData="m 25.217756,16.274066 v 0 q 0,1.31751 -0.814213,2.067022 -0.814212,0.749513 -2.248777,0.749513 v 0 q -1.609039,0 -2.471717,-1.0218 Q 18.820372,17.047 18.820372,15.038537 v 0 q 0,-2.207557 0.875601,-3.323047 Q 20.571575,10.6 22.2,10.6 v 0 q 1.156698,0 1.825516,0.462592 0.668817,0.462591 0.946684,1.434619 v 0 l -1.712431,0.216656 Q 23.014213,11.89994 22.161228,11.89994 v 0 q -0.730207,0 -1.147005,0.661682 -0.4168,0.661682 -0.4168,2.008467 v 0 q 0.29079,-0.439168 0.807751,-0.673393 0.51696,-0.234223 1.169623,-0.234223 v 0 q 1.221318,0 1.932139,0.702671 0.71082,0.702671 0.71082,1.908922 z m -1.822285,0.04685 v 0 q 0,-0.70267 -0.358641,-1.0745 -0.358642,-0.37183 -0.985456,-0.37183 v 0 q -0.600966,0 -0.962838,0.348408 -0.361873,0.348407 -0.361873,0.922255 v 0 q 0,0.720242 0.378028,1.191617 0.378026,0.471375 0.991917,0.471375 v 0 q 0.61389,0 0.956377,-0.395255 0.342486,-0.395254 0.342486,-1.09207 z"/> + <path + android:fillColor="@android:color/white" + android:pathData="m 13.100543,2.0095112 c -4.75,0 -9.029999,2.078587 -12,5.388587 l 12,14.6005438 3.827446,-4.654892 a 7.7288136,8.3389834 0 0 1 -0.04484,-0.835598 7.7288136,8.3389834 0 0 1 0.460598,-2.816576 L 13.10054,18.860054 3.79891,7.5366842 c 2.57,-2.259999 5.88163,-3.529891 9.30163,-3.529891 3.42,0 6.731631,1.269892 9.301631,3.529891 l -1.247282,1.516305 a 7.7288136,8.3389834 0 0 1 3.305705,-0.876359 l 0.639947,-0.778532 c -2.97,-3.31 -7.250001,-5.388587 -12.000001,-5.388587 z"/> + <path + android:fillColor="@android:color/white" + android:pathData="m 13.100543,13.300272 c -3.2,0 -5.2986406,1.799456 -5.4986408,1.899456 l 5.4986408,6.798914 4.043479,-4.997283 a 7.7288137,8.3389834 0 0 1 -0.06114,-0.933424 7.7288137,8.3389834 0 0 1 0.171196,-1.732337 c -0.961558,-0.505425 -2.35688,-1.035326 -4.153535,-1.035326 z"/> +</vector> diff --git a/core/res/res/drawable/ic_wifi_6_signal_2.xml b/core/res/res/drawable/ic_wifi_6_signal_2.xml new file mode 100644 index 000000000000..345b89824d84 --- /dev/null +++ b/core/res/res/drawable/ic_wifi_6_signal_2.xml @@ -0,0 +1,44 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + Copyright (c) 2019, The Linux Foundation. All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are + met: + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following + disclaimer in the documentation and/or other materials provided + with the distribution. + * Neither the name of The Linux Foundation nor the names of its + contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED + WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS + BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +--> +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="26dp" + android:height="24dp" + android:viewportWidth="26" + android:viewportHeight="24"> + <path + android:fillColor="@android:color/white" + android:pathData="m 25.217756,16.274066 v 0 q 0,1.31751 -0.814213,2.067022 -0.814212,0.749513 -2.248777,0.749513 v 0 q -1.609039,0 -2.471717,-1.0218 Q 18.820372,17.047 18.820372,15.038537 v 0 q 0,-2.207557 0.875601,-3.323047 Q 20.571575,10.6 22.2,10.6 v 0 q 1.156698,0 1.825516,0.462592 0.668817,0.462591 0.946684,1.434619 v 0 l -1.712431,0.216656 Q 23.014213,11.89994 22.161228,11.89994 v 0 q -0.730207,0 -1.147005,0.661682 -0.4168,0.661682 -0.4168,2.008467 v 0 q 0.29079,-0.439168 0.807751,-0.673393 0.51696,-0.234223 1.169623,-0.234223 v 0 q 1.221318,0 1.932139,0.702671 0.71082,0.702671 0.71082,1.908922 z m -1.822285,0.04685 v 0 q 0,-0.70267 -0.358641,-1.0745 -0.358642,-0.37183 -0.985456,-0.37183 v 0 q -0.600966,0 -0.962838,0.348408 -0.361873,0.348407 -0.361873,0.922255 v 0 q 0,0.720242 0.378028,1.191617 0.378026,0.471375 0.991917,0.471375 v 0 q 0.61389,0 0.956377,-0.395255 0.342486,-0.395254 0.342486,-1.09207 z"/> + <path + android:fillColor="@android:color/white" + android:pathData="m 12.998641,2.0095112 c -4.75,0 -9.029999,2.078587 -12,5.388587 l 12,14.6005438 3.827446,-4.654892 a 7.7288136,8.3389834 0 0 1 -0.04484,-0.835598 7.7288136,8.3389834 0 0 1 0.460598,-2.816576 L 12.998638,18.860054 3.697008,7.5366842 c 2.57,-2.259999 5.88163,-3.529891 9.30163,-3.529891 3.42,0 6.731631,1.269892 9.301631,3.529891 l -1.247282,1.516305 a 7.7288136,8.3389834 0 0 1 3.305705,-0.876359 l 0.639947,-0.778532 c -2.97,-3.31 -7.250001,-5.388587 -12.000001,-5.388587 z"/> + <path + android:fillColor="@android:color/white" + android:pathData="m 12.998641,9.998641 c -4.3999993,0 -7.297826,2.402446 -7.597826,2.702446 l 7.597826,9.297555 4.133152,-5.111414 a 7.7288137,8.3389834 0 0 1 -0.04891,-0.847826 7.7288137,8.3389834 0 0 1 1.377718,-4.744565 C 17.138647,10.644289 15.284639,9.998641 12.998644,9.998641 Z"/> +</vector> diff --git a/core/res/res/drawable/ic_wifi_6_signal_3.xml b/core/res/res/drawable/ic_wifi_6_signal_3.xml new file mode 100644 index 000000000000..3eda6ff9407e --- /dev/null +++ b/core/res/res/drawable/ic_wifi_6_signal_3.xml @@ -0,0 +1,44 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + Copyright (c) 2019, The Linux Foundation. All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are + met: + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following + disclaimer in the documentation and/or other materials provided + with the distribution. + * Neither the name of The Linux Foundation nor the names of its + contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED + WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS + BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +--> +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="26dp" + android:height="24dp" + android:viewportWidth="26" + android:viewportHeight="24"> + <path + android:fillColor="@android:color/white" + android:pathData="m 25.217756,16.274066 v 0 q 0,1.31751 -0.814213,2.067022 -0.814212,0.749513 -2.248777,0.749513 v 0 q -1.609039,0 -2.471717,-1.0218 Q 18.820372,17.047 18.820372,15.038537 v 0 q 0,-2.207557 0.875601,-3.323047 Q 20.571575,10.6 22.2,10.6 v 0 q 1.156698,0 1.825516,0.462592 0.668817,0.462591 0.946684,1.434619 v 0 l -1.712431,0.216656 Q 23.014213,11.89994 22.161228,11.89994 v 0 q -0.730207,0 -1.147005,0.661682 -0.4168,0.661682 -0.4168,2.008467 v 0 q 0.29079,-0.439168 0.807751,-0.673393 0.51696,-0.234223 1.169623,-0.234223 v 0 q 1.221318,0 1.932139,0.702671 0.71082,0.702671 0.71082,1.908922 z m -1.822285,0.04685 v 0 q 0,-0.70267 -0.358641,-1.0745 -0.358642,-0.37183 -0.985456,-0.37183 v 0 q -0.600966,0 -0.962838,0.348408 -0.361873,0.348407 -0.361873,0.922255 v 0 q 0,0.720242 0.378028,1.191617 0.378026,0.471375 0.991917,0.471375 v 0 q 0.61389,0 0.956377,-0.395255 0.342486,-0.395254 0.342486,-1.09207 z"/> + <path + android:fillColor="@android:color/white" + android:pathData="m 12.998641,7.398098 c -5.3000001,0 -8.8997284,3.003804 -9.1997284,3.203804 l 9.1997284,11.39674 4.03125,-4.997283 A 7.7288137,8.3389834 0 0 1 16.968751,16.039402 7.7288137,8.3389834 0 0 1 20.164403,9.30163 C 18.559413,8.406307 16.154773,7.398098 12.998641,7.398098 Z"/> + <path + android:fillColor="@android:color/white" + android:pathData="m 12.998641,2.0095112 c -4.75,0 -9.029999,2.078587 -12,5.388587 l 12,14.6005438 3.827446,-4.654892 a 7.7288136,8.3389834 0 0 1 -0.04484,-0.835598 7.7288136,8.3389834 0 0 1 0.460598,-2.816576 L 12.998638,18.860054 3.697008,7.5366842 c 2.57,-2.259999 5.88163,-3.529891 9.30163,-3.529891 3.42,0 6.731631,1.269892 9.301631,3.529891 l -1.247282,1.516305 a 7.7288136,8.3389834 0 0 1 3.305705,-0.876359 l 0.639947,-0.778532 c -2.97,-3.31 -7.250001,-5.388587 -12.000001,-5.388587 z"/> +</vector> diff --git a/core/res/res/drawable/ic_wifi_6_signal_4.xml b/core/res/res/drawable/ic_wifi_6_signal_4.xml new file mode 100644 index 000000000000..dc9ff4eb70b6 --- /dev/null +++ b/core/res/res/drawable/ic_wifi_6_signal_4.xml @@ -0,0 +1,41 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + Copyright (c) 2019, The Linux Foundation. All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are + met: + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following + disclaimer in the documentation and/or other materials provided + with the distribution. + * Neither the name of The Linux Foundation nor the names of its + contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED + WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS + BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +--> +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="26dp" + android:height="24dp" + android:viewportWidth="26" + android:viewportHeight="24"> + <path + android:fillColor="@android:color/white" + android:pathData="m 25.217756,16.274066 v 0 q 0,1.31751 -0.814213,2.067022 -0.814212,0.749513 -2.248777,0.749513 v 0 q -1.609039,0 -2.471717,-1.0218 Q 18.820372,17.047 18.820372,15.038537 v 0 q 0,-2.207557 0.875601,-3.323047 Q 20.571575,10.6 22.2,10.6 v 0 q 1.156698,0 1.825516,0.462592 0.668817,0.462591 0.946684,1.434619 v 0 l -1.712431,0.216656 Q 23.014213,11.89994 22.161228,11.89994 v 0 q -0.730207,0 -1.147005,0.661682 -0.4168,0.661682 -0.4168,2.008467 v 0 q 0.29079,-0.439168 0.807751,-0.673393 0.51696,-0.234223 1.169623,-0.234223 v 0 q 1.221318,0 1.932139,0.702671 0.71082,0.702671 0.71082,1.908922 z m -1.822285,0.04685 v 0 q 0,-0.70267 -0.358641,-1.0745 -0.358642,-0.37183 -0.985456,-0.37183 v 0 q -0.600966,0 -0.962838,0.348408 -0.361873,0.348407 -0.361873,0.922255 v 0 q 0,0.720242 0.378028,1.191617 0.378026,0.471375 0.991917,0.471375 v 0 q 0.61389,0 0.956377,-0.395255 0.342486,-0.395254 0.342486,-1.09207 z"/> + <path + android:fillColor="@android:color/white" + android:pathData="m 12.998641,2.099185 c -7.3000003,0 -12.0991851,4.002174 -12.59918509,4.402174 L 12.998641,21.998642 16.944293,17.148098 a 7.7288137,8.3389834 0 0 1 -0.06114,-0.978261 7.7288137,8.3389834 0 0 1 7.634511,-8.335597 l 1.084238,-1.332881 c -0.499999,-0.4 -5.303261,-4.402174 -12.603261,-4.402174 z"/> +</vector> diff --git a/core/res/res/values/bools.xml b/core/res/res/values/bools.xml index fe296c704095..303b326e0153 100644 --- a/core/res/res/values/bools.xml +++ b/core/res/res/values/bools.xml @@ -30,4 +30,5 @@ lockscreen, setting this to true should come with customized drawables. --> <bool name="use_lock_pattern_drawable">false</bool> <bool name="resolver_landscape_phone">true</bool> + <bool name="config_wifi_dual_sap_mode_enabled">false</bool> </resources> diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml index d9007e50c7c6..2533199978e5 100644 --- a/core/res/res/values/config.xml +++ b/core/res/res/values/config.xml @@ -1848,6 +1848,9 @@ <!-- Integer to set a max latency the accelerometer will batch sensor requests with. --> <integer name="config_flipToScreenOffMaxLatencyMicros">2000000</integer> + <!-- Component name of the combo network location provider. --> + <string name="config_comboNetworkLocationProvider" translatable="false">com.qualcomm.location</string> + <!-- Boolean indicating if current platform supports bluetooth SCO for off call use cases --> <bool name="config_bluetooth_sco_off_call">true</bool> @@ -3099,6 +3102,9 @@ <!-- Flag indicating which package name can access DeviceConfig table --> <string name="config_deviceConfiguratorPackageName" translatable="false"></string> + <!-- Define optional package verifier name --> + <string name="config_optionalPackageVerifierName" translatable="false"></string> + <!-- Flag indicating apps will skip sending hold request before merge. In this case IMS service implementation will do both.i.e.hold followed by merge. --> <bool name="skipHoldBeforeMerge">true</bool> @@ -3247,6 +3253,10 @@ phone object irrespective of this config --> <bool name="config_switch_phone_on_voice_reg_state_change">true</bool> + <!-- Config determines whether to add 3 seconds delay for ims deregistration + before sending RADIO POWER OFF in APM ON and shutdown scenarios --> + <bool name="config_wait_for_ims_deregistration_before_radio_poweroff">false</bool> + <bool name="config_sms_force_7bit_encoding">false</bool> <!-- Number of physical SIM slots on the device. This includes both eSIM and pSIM slots, and @@ -4227,6 +4237,15 @@ <!-- Package name for ManagedProvisioning which is responsible for provisioning work profiles. --> <string name="config_managed_provisioning_package" translatable="false">com.android.managedprovisioning</string> + <!-- The duration (in milliseconds) for the outgoing sms authorization request to timeout.--> + <integer name="config_sms_authorization_timeout_ms">0</integer> + + <!-- Enable sms authorization framework--> + <bool name="config_sms_authorization_enabled">false</bool> + + <!-- whether to enable primarycard --> + <bool name="config_primarycard">false</bool> + <!-- Whether or not swipe up gesture's opt-in setting is available on this device --> <bool name="config_swipe_up_gesture_setting_available">true</bool> @@ -4262,6 +4281,10 @@ <!-- Whether or not the "SMS app service" feature is enabled --> <bool name="config_useSmsAppService">true</bool> + <!-- List of names that represent dual SoftAp interfaces. --> + <string-array translatable="false" name="config_wifi_dual_sap_interfaces"> + </string-array> + <!-- Class name for the InputEvent compatibility processor override. Empty string means use the default compatibility processor (android.view.InputEventCompatProcessor). --> @@ -5160,6 +5183,10 @@ <!-- the number of the max cached processes in the system. --> <integer name="config_customizedMaxCachedProcesses">32</integer> + <!-- Maximum time in millisecs for telephony should wait to deactivate data call + when user turned off mobile data or data roaming during CIWLAN --> + <integer name="config_maximumDelayTimeToDeactivateDataCall">7000</integer> + <!-- The display cutout configs for secondary built-in display. --> <string name="config_secondaryBuiltInDisplayCutout" translatable="false"></string> <string name="config_secondaryBuiltInDisplayCutoutRectApproximation" translatable="false"> diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml index 166d6abd1809..d497593ad5ec 100644 --- a/core/res/res/values/strings.xml +++ b/core/res/res/values/strings.xml @@ -291,6 +291,8 @@ <string name="wfc_mode_cellular_preferred_summary">Call over mobile network</string> <!-- WFC, summary for Wi-Fi Only --> <string name="wfc_mode_wifi_only_summary">Wi-Fi only</string> + <!-- WFC, summary for Ims Preferred --> + <string name="wfc_mode_ims_preferred_summary">Ims Preferred</string> <!-- Template for showing mobile network operator name while Cross SIM calling is active --> <string-array name="crossSimSpnFormats" translatable="false"> diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml index f68c26d76610..3ea2cc0cb544 100644 --- a/core/res/res/values/symbols.xml +++ b/core/res/res/values/symbols.xml @@ -896,6 +896,7 @@ <java-symbol type="string" name="wifi_calling_off_summary" /> <java-symbol type="string" name="wfc_mode_wifi_preferred_summary" /> <java-symbol type="string" name="wfc_mode_cellular_preferred_summary" /> + <java-symbol type="string" name="wfc_mode_ims_preferred_summary" /> <java-symbol type="string" name="wfc_mode_wifi_only_summary" /> <java-symbol type="array" name="crossSimSpnFormats" /> <java-symbol type="string" name="policydesc_disableCamera" /> @@ -1384,6 +1385,21 @@ <java-symbol type="drawable" name="ic_wifi_signal_2" /> <java-symbol type="drawable" name="ic_wifi_signal_3" /> <java-symbol type="drawable" name="ic_wifi_signal_4" /> + <java-symbol type="drawable" name="ic_wifi_4_signal_0" /> + <java-symbol type="drawable" name="ic_wifi_4_signal_1" /> + <java-symbol type="drawable" name="ic_wifi_4_signal_2" /> + <java-symbol type="drawable" name="ic_wifi_4_signal_3" /> + <java-symbol type="drawable" name="ic_wifi_4_signal_4" /> + <java-symbol type="drawable" name="ic_wifi_5_signal_0" /> + <java-symbol type="drawable" name="ic_wifi_5_signal_1" /> + <java-symbol type="drawable" name="ic_wifi_5_signal_2" /> + <java-symbol type="drawable" name="ic_wifi_5_signal_3" /> + <java-symbol type="drawable" name="ic_wifi_5_signal_4" /> + <java-symbol type="drawable" name="ic_wifi_6_signal_0" /> + <java-symbol type="drawable" name="ic_wifi_6_signal_1" /> + <java-symbol type="drawable" name="ic_wifi_6_signal_2" /> + <java-symbol type="drawable" name="ic_wifi_6_signal_3" /> + <java-symbol type="drawable" name="ic_wifi_6_signal_4" /> <java-symbol type="drawable" name="ic_signal_wifi_transient_animation" /> <java-symbol type="drawable" name="ic_hotspot_transient_animation" /> <java-symbol type="drawable" name="ic_bluetooth_transient_animation" /> @@ -2101,6 +2117,7 @@ <java-symbol type="string" name="config_geocoderProviderPackageName" /> <java-symbol type="string" name="config_geofenceProviderPackageName" /> <java-symbol type="string" name="config_networkLocationProviderPackageName" /> + <java-symbol type="string" name="config_comboNetworkLocationProvider" /> <java-symbol type="string" name="config_wimaxManagerClassname" /> <java-symbol type="string" name="config_wimaxNativeLibLocation" /> <java-symbol type="string" name="config_wimaxServiceClassname" /> @@ -2230,6 +2247,7 @@ <java-symbol type="string" name="config_primaryLocationTimeZoneProviderPackageName" /> <java-symbol type="bool" name="config_enableSecondaryLocationTimeZoneProvider" /> <java-symbol type="string" name="config_secondaryLocationTimeZoneProviderPackageName" /> + <java-symbol type="string" name="config_optionalPackageVerifierName" /> <java-symbol type="bool" name="config_autoResetAirplaneMode" /> <java-symbol type="string" name="config_notificationAccessConfirmationActivity" /> @@ -2721,6 +2739,7 @@ <java-symbol type="bool" name="config_restart_radio_on_pdp_fail_regular_deactivation" /> <java-symbol type="array" name="networks_not_clear_data" /> <java-symbol type="bool" name="config_switch_phone_on_voice_reg_state_change" /> + <java-symbol type="bool" name="config_wait_for_ims_deregistration_before_radio_poweroff" /> <java-symbol type="string" name="whichHomeApplicationNamed" /> <java-symbol type="string" name="whichHomeApplicationLabel" /> <java-symbol type="bool" name="config_sms_force_7bit_encoding" /> @@ -3836,7 +3855,11 @@ <java-symbol type="dimen" name="car_padding_4" /> <java-symbol type="style" name="Theme.DeviceDefault.Light.Dialog.Alert.UserSwitchingDialog" /> + <java-symbol type="integer" name="config_sms_authorization_timeout_ms" /> + <java-symbol type="bool" name="config_sms_authorization_enabled" /> + <java-symbol type="string" name="battery_saver_description_with_learn_more" /> + <java-symbol type="bool" name="config_primarycard" /> <java-symbol type="string" name="confirm_battery_saver" /> <java-symbol type="attr" name="opticalInsetLeft" /> @@ -3848,6 +3871,10 @@ <java-symbol type="drawable" name="ic_arrow_forward" /> <java-symbol type="drawable" name="ic_permission" /> + <!-- For Dual SoftaAp --> + <java-symbol type="array" name="config_wifi_dual_sap_interfaces" /> + <java-symbol type="bool" name="config_wifi_dual_sap_mode_enabled" /> + <java-symbol type="integer" name="config_defaultHapticFeedbackIntensity" /> <java-symbol type="integer" name="config_defaultNotificationVibrationIntensity" /> <java-symbol type="integer" name="config_defaultRingVibrationIntensity" /> @@ -4460,6 +4487,8 @@ <java-symbol type="color" name="overview_background"/> + <java-symbol type="integer" name="config_maximumDelayTimeToDeactivateDataCall" /> + <java-symbol type="string" name="config_secondaryBuiltInDisplayCutout" /> <java-symbol type="string" name="config_secondaryBuiltInDisplayCutoutRectApproximation" /> <java-symbol type="bool" name="config_fillSecondaryBuiltInDisplayCutout" /> diff --git a/core/tests/ConnectivityManagerTest/AndroidManifest.xml b/core/tests/ConnectivityManagerTest/AndroidManifest.xml index 796d7e8ff407..b647191c2aec 100644 --- a/core/tests/ConnectivityManagerTest/AndroidManifest.xml +++ b/core/tests/ConnectivityManagerTest/AndroidManifest.xml @@ -83,5 +83,6 @@ <uses-permission android:name="android.permission.INTERACT_ACROSS_USERS" /> <uses-permission android:name="android.permission.INJECT_EVENTS" /> <uses-permission android:name="android.permission.DEVICE_POWER" /> + <uses-permission android:name="android.permission.MANAGE_TEST_NETWORKS" /> </manifest> diff --git a/core/tests/coretests/src/com/android/internal/os/BinderDeathDispatcherTest.java b/core/tests/coretests/src/com/android/internal/os/BinderDeathDispatcherTest.java index 83103333f68b..942045c8bf35 100644 --- a/core/tests/coretests/src/com/android/internal/os/BinderDeathDispatcherTest.java +++ b/core/tests/coretests/src/com/android/internal/os/BinderDeathDispatcherTest.java @@ -17,7 +17,6 @@ package com.android.internal.os; import static com.google.common.truth.Truth.assertThat; -import static org.mockito.ArgumentMatchers.any; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.reset; import static org.mockito.Mockito.times; @@ -32,14 +31,14 @@ import android.os.RemoteException; import android.os.ResultReceiver; import android.os.ShellCallback; -import androidx.test.filters.SmallTest; -import androidx.test.runner.AndroidJUnit4; - import org.junit.Test; import org.junit.runner.RunWith; import java.io.FileDescriptor; +import androidx.test.filters.SmallTest; +import androidx.test.runner.AndroidJUnit4; + @SmallTest @RunWith(AndroidJUnit4.class) public class BinderDeathDispatcherTest { @@ -121,7 +120,7 @@ public class BinderDeathDispatcherTest { public void die() { isAlive = false; if (mRecipient != null) { - mRecipient.binderDied(this); + mRecipient.binderDied(); } mRecipient = null; } @@ -228,33 +227,33 @@ public class BinderDeathDispatcherTest { // Kill the targets. t1.die(); - verify(r1, times(1)).binderDied(t1); - verify(r2, times(1)).binderDied(t1); - verify(r3, times(1)).binderDied(t1); - verify(r4, times(0)).binderDied(any()); - verify(r5, times(0)).binderDied(any()); + verify(r1, times(1)).binderDied(); + verify(r2, times(1)).binderDied(); + verify(r3, times(1)).binderDied(); + verify(r4, times(0)).binderDied(); + verify(r5, times(0)).binderDied(); assertThat(d.getTargetsForTest().size()).isEqualTo(2); reset(r1, r2, r3, r4, r5); t2.die(); - verify(r1, times(1)).binderDied(t2); - verify(r2, times(0)).binderDied(any()); - verify(r3, times(0)).binderDied(any()); - verify(r4, times(0)).binderDied(any()); - verify(r5, times(0)).binderDied(any()); + verify(r1, times(1)).binderDied(); + verify(r2, times(0)).binderDied(); + verify(r3, times(0)).binderDied(); + verify(r4, times(0)).binderDied(); + verify(r5, times(0)).binderDied(); assertThat(d.getTargetsForTest().size()).isEqualTo(1); reset(r1, r2, r3, r4, r5); t3.die(); - verify(r1, times(0)).binderDied(any()); - verify(r2, times(0)).binderDied(any()); - verify(r3, times(1)).binderDied(t3); - verify(r4, times(0)).binderDied(any()); - verify(r5, times(1)).binderDied(t3); + verify(r1, times(0)).binderDied(); + verify(r2, times(0)).binderDied(); + verify(r3, times(1)).binderDied(); + verify(r4, times(0)).binderDied(); + verify(r5, times(1)).binderDied(); assertThat(d.getTargetsForTest().size()).isEqualTo(0); @@ -263,27 +262,4 @@ public class BinderDeathDispatcherTest { assertThat(d.getTargetsForTest().size()).isEqualTo(0); } - - @Test - public void duplicateRegistrations() { - BinderDeathDispatcher<MyTarget> d = new BinderDeathDispatcher<>(); - - MyTarget t1 = new MyTarget(); - - DeathRecipient r1 = mock(DeathRecipient.class); - DeathRecipient r2 = mock(DeathRecipient.class); - - for (int i = 0; i < 5; i++) { - assertThat(d.linkToDeath(t1, r1)).isEqualTo(1); - } - assertThat(d.linkToDeath(t1, r2)).isEqualTo(2); - - t1.die(); - verify(r1, times(1)).binderDied(t1); - verify(r2, times(1)).binderDied(t1); - - d.unlinkToDeath(t1, r1); - d.unlinkToDeath(t1, r2); - assertThat(d.getTargetsForTest()).isEmpty(); - } } |