Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,10 @@ import androidx.core.os.bundleOf
import com.google.android.gms.ads.identifier.internal.IAdvertisingIdService
import org.microg.gms.common.GooglePackagePermission
import org.microg.gms.common.PackageUtils
import org.microg.gms.settings.SettingsContract
import org.microg.gms.settings.SettingsContract.Ads
import org.microg.gms.settings.SettingsContract.getSettings
import org.microg.gms.settings.SettingsContract.setSettings
import java.util.UUID

const val TAG = "AdvertisingId"
Expand All @@ -39,6 +43,18 @@ class MemoryAdvertisingIdConfiguration(context: Context) : AdvertisingIdConfigur
}
}

class PersistentAdvertisingIdConfiguration(private val context: Context) : AdvertisingIdConfiguration(context) {
override val adTrackingLimitedPerApp: MutableMap<Int, Boolean> = hashMapOf()
override var adTrackingLimitedGlobally: Boolean
get() = getSettings(context, Ads.getContentUri(context), arrayOf(Ads.AD_LIMIT_TRACKING)) { it.getInt(0) != 0 }
set(value) = setSettings(context, Ads.getContentUri(context)) { put(Ads.AD_LIMIT_TRACKING, value) }
override var debugLogging: Boolean = false
override var adId: String
get() = getSettings(context, Ads.getContentUri(context), arrayOf(Ads.AD_ID)) { it.getString(0) ?: "" }.let { if (it.isEmpty()) resetAdvertisingId() else it }
set(value) = setSettings(context, Ads.getContentUri(context)) { put(Ads.AD_ID, value) }
override var debugAdId: String = EMPTY_AD_ID
}

abstract class AdvertisingIdConfiguration(private val context: Context) {
abstract val adTrackingLimitedPerApp: MutableMap<Int, Boolean>
abstract var adTrackingLimitedGlobally: Boolean
Expand Down Expand Up @@ -79,7 +95,7 @@ abstract class AdvertisingIdConfiguration(private val context: Context) {
}

class AdvertisingIdServiceImpl(private val context: Context) : IAdvertisingIdService.Stub() {
private val configuration = MemoryAdvertisingIdConfiguration(context)
private val configuration = PersistentAdvertisingIdConfiguration(context)

override fun getAdvertisingId(): String {
return configuration.getAdvertisingIdForApp(Binder.getCallingUid())
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -294,6 +294,20 @@ object SettingsContract {
)
}

object Ads {
const val ID = "ads"
fun getContentUri(context: Context) = Uri.withAppendedPath(getAuthorityUri(context), ID)
fun getContentType(context: Context) = "vnd.android.cursor.item/vnd.${getAuthority(context)}.$ID"

const val AD_ID = "ad_id"
const val AD_LIMIT_TRACKING = "ad_limit_tracking"

val PROJECTION = arrayOf(
AD_ID,
AD_LIMIT_TRACKING
)
}

object WorkProfile {
const val ID = "workprofile"
fun getContentUri(context: Context) = Uri.withAppendedPath(getCrossProfileSharedAuthorityUri(context), ID)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import android.net.Uri
import android.os.Build.VERSION.SDK_INT
import android.preference.PreferenceManager
import org.microg.gms.common.PackageUtils.warnIfNotMainProcess
import org.microg.gms.settings.SettingsContract.Ads
import org.microg.gms.settings.SettingsContract.Auth
import org.microg.gms.settings.SettingsContract.CheckIn
import org.microg.gms.settings.SettingsContract.DroidGuard
Expand Down Expand Up @@ -85,6 +86,7 @@ class SettingsProvider : ContentProvider() {
Vending.ID -> queryVending(projection ?: Vending.PROJECTION)
WorkProfile.ID -> queryWorkProfile(projection ?: WorkProfile.PROJECTION)
GameProfile.ID -> queryGameProfile(projection ?: GameProfile.PROJECTION)
Ads.ID -> queryAds(projection ?: Ads.PROJECTION)
else -> null
}

Expand All @@ -108,6 +110,7 @@ class SettingsProvider : ContentProvider() {
Vending.ID -> updateVending(values)
WorkProfile.ID -> updateWorkProfile(values)
GameProfile.ID -> updateGameProfile(values)
Ads.ID -> updateAds(values)
else -> return 0
}
return 1
Expand Down Expand Up @@ -434,6 +437,27 @@ class SettingsProvider : ContentProvider() {
editor.apply()
}

private fun queryAds(p: Array<out String>): Cursor = MatrixCursor(p).addRow(p) { key ->
when (key) {
Ads.AD_ID -> getSettingsString(key, "")
Ads.AD_LIMIT_TRACKING -> getSettingsBoolean(key, true)
else -> throw IllegalArgumentException("Unknown key: $key")
}
}

private fun updateAds(values: ContentValues) {
if (values.size() == 0) return
val editor = preferences.edit()
values.valueSet().forEach { (key, value) ->
when (key) {
Ads.AD_ID -> editor.putString(key, value as String)
Ads.AD_LIMIT_TRACKING -> editor.putBoolean(key, value as Boolean)
else -> throw IllegalArgumentException("Unknown key: $key")
}
}
editor.apply()
}

private fun MatrixCursor.addRow(
p: Array<out String>,
valueGetter: (String) -> Any?
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,6 @@ public IBinder onBind(Intent intent) {
return (new AbstractThreadedSyncAdapter(this, true) {
@Override
public void onPerformSync(Account account, Bundle extras, String authority, ContentProviderClient provider, SyncResult syncResult) {
Log.d(TAG, "unimplemented Method: onPerformSync");
}
}).getSyncAdapterBinder();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,8 +30,7 @@ public class ConfigurationProvider extends ContentProvider {
private static final String TAG = "GmsPhenotypeCfgProvider";
@Override
public boolean onCreate() {
Log.d(TAG, "unimplemented Method: onCreate");
return false;
return true;
}

@Nullable
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ class TermsOfServiceActivity : AppCompatActivity() {

override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setResult(RESULT_CANCELED)
setResult(RESULT_OK)
finish()
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -126,7 +126,6 @@ class AuthorizationServiceImpl(val context: Context, val packageName: String, ov
}

override fun verifyWithGoogle(callback: IVerifyWithGoogleCallback?, request: VerifyWithGoogleRequest?) {
Log.d(TAG, "unimplemented Method: verifyWithGoogle: request:$request")
lifecycleScope.launchWhenStarted {
val account = AccountUtils.get(context).getSelectedAccount(packageName) ?: SignInConfigurationService.getDefaultAccount(context, packageName)
if (account == null) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -273,14 +273,15 @@ class LocationRequestManager(private val context: Context, override val lifecycl
}
if (grantedPermissions.any { it != PackageManager.PERMISSION_GRANTED }) {
val grantedPermissions = locationPermissions.map { ContextCompat.checkSelfPermission(context, it) }
if (grantedPermissions == this.grantedPermissions) {
if (grantedPermissions != this.grantedPermissions) {
this.grantedPermissions = grantedPermissions
permissionChanged = true
}
}
if (pendingIntentsToRemove.isNotEmpty() || bindersToRemove.isNotEmpty() || permissionChanged) {
recalculateRequests()
}
requestDetailsUpdated = true
}
notifyRequestDetailsUpdated()
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,19 @@ public CapabilityManager(Context context, WearableImpl wearable, String packageN
this.context = context;
this.wearable = wearable;
this.packageName = packageName;
loadCapabilities();
}

private void loadCapabilities() {
DataHolder dataHolder = wearable.getDataItemsByUriAsHolder(ROOT, packageName);
for (int i = 0; i < dataHolder.getCount(); i++) {
if (wearable.getLocalNodeId().equals(dataHolder.getString("host", i, 0))) {
String path = dataHolder.getString("path", i, 0);
String capability = path.substring(path.lastIndexOf('/') + 1);
this.capabilities.add(Uri.decode(capability));
}
}
dataHolder.close();
}

private Uri buildCapabilityUri(String capability, boolean withAuthority) {
Expand Down Expand Up @@ -82,4 +95,26 @@ public int remove(String capability) {
capabilities.remove(capability);
return CommonStatusCodes.SUCCESS;
}
public List<CapabilityInfoParcelable> getAllCapabilities() {
DataHolder dataHolder = wearable.getDataItemsByUriAsHolder(ROOT, packageName);
List<CapabilityInfoParcelable> result = new ArrayList<>();
Set<String> capabilityNames = new HashSet<>();
for (int i = 0; i < dataHolder.getCount(); i++) {
String path = dataHolder.getString("path", i, 0);
capabilityNames.add(Uri.decode(path.substring(path.lastIndexOf('/') + 1)));
}
for (String capabilityName : capabilityNames) {
List<NodeParcelable> nodes = new ArrayList<>();
for (int i = 0; i < dataHolder.getCount(); i++) {
String path = dataHolder.getString("path", i, 0);
if (capabilityName.equals(Uri.decode(path.substring(path.lastIndexOf('/') + 1)))) {
String host = dataHolder.getString("host", i, 0);
nodes.add(new NodeParcelable(host, host));
}
}
result.add(new CapabilityInfoParcelable(capabilityName, nodes));
}
dataHolder.close();
return result;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -351,6 +351,13 @@ public void onConnectReceived(WearableConnection connection, String nodeId, Conn
Log.d(TAG, "Adding connection to list of open connections: " + connection + " with connect " + connect);
activeConnections.put(connect.id, connection);
onPeerConnected(new NodeParcelable(connect.id, connect.name));

// Sync all local data items (including capabilities) to the new peer
// This ensures the watch receives our capabilities immediately after connection
networkHandler.post(() -> {
syncToPeer(connect.id, getLocalNodeId(), 0);
});

// Fetch missing assets
Cursor cursor = nodeDatabase.listMissingAssets();
if (cursor != null) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,9 +31,11 @@
import com.google.android.gms.wearable.internal.*;

import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
import java.util.UUID;

public class WearableServiceImpl extends IWearableService.Stub {
private static final String TAG = "GmsWearSvcImpl";
Expand Down Expand Up @@ -234,12 +236,16 @@ public void optInCloudSync(IWearableCallbacks callbacks, boolean enable) throws
@Override
@Deprecated
public void getCloudSyncOptInDone(IWearableCallbacks callbacks) throws RemoteException {
Log.d(TAG, "unimplemented Method: getCloudSyncOptInDone");
postMain(callbacks, () -> {
callbacks.onGetCloudSyncOptInOutDoneResponse(new GetCloudSyncOptInOutDoneResponse(0, false));
});
}

@Override
public void setCloudSyncSetting(IWearableCallbacks callbacks, boolean enable) throws RemoteException {
Log.d(TAG, "unimplemented Method: setCloudSyncSetting");
postMain(callbacks, () -> {
callbacks.onStatus(Status.SUCCESS);
});
}

@Override
Expand All @@ -249,12 +255,14 @@ public void getCloudSyncSetting(IWearableCallbacks callbacks) throws RemoteExcep

@Override
public void getCloudSyncOptInStatus(IWearableCallbacks callbacks) throws RemoteException {
Log.d(TAG, "unimplemented Method: getCloudSyncOptInStatus");
postMain(callbacks, () -> {
callbacks.onGetCloudSyncOptInStatusResponse(new GetCloudSyncOptInStatusResponse(0, 0, false, false));
});
}

@Override
public void sendRemoteCommand(IWearableCallbacks callbacks, byte b) throws RemoteException {
Log.d(TAG, "unimplemented Method: sendRemoteCommand: " + b);
callbacks.onStatus(Status.SUCCESS);
}

@Override
Expand All @@ -281,7 +289,6 @@ public void getConnectedNodes(IWearableCallbacks callbacks) throws RemoteExcepti

@Override
public void getConnectedCapability(IWearableCallbacks callbacks, String capability, int nodeFilter) throws RemoteException {
Log.d(TAG, "unimplemented Method: getConnectedCapability " + capability + ", " + nodeFilter);
postMain(callbacks, () -> {
List<NodeParcelable> nodes = new ArrayList<>();
for (String host : capabilities.getNodesForCapability(capability)) {
Expand All @@ -294,13 +301,13 @@ public void getConnectedCapability(IWearableCallbacks callbacks, String capabili

@Override
public void getAllCapabilities(IWearableCallbacks callbacks, int nodeFilter) throws RemoteException {
Log.d(TAG, "unimplemented Method: getConnectedCapaibilties: " + nodeFilter);
callbacks.onGetAllCapabilitiesResponse(new GetAllCapabilitiesResponse());
postMain(callbacks, () -> {
callbacks.onGetAllCapabilitiesResponse(new GetAllCapabilitiesResponse(0, capabilities.getAllCapabilities()));
});
}

@Override
public void addLocalCapability(IWearableCallbacks callbacks, String capability) throws RemoteException {
Log.d(TAG, "unimplemented Method: addLocalCapability: " + capability);
this.wearable.networkHandler.post(new CallbackRunnable(callbacks) {
@Override
public void run(IWearableCallbacks callbacks) throws RemoteException {
Expand All @@ -311,7 +318,6 @@ public void run(IWearableCallbacks callbacks) throws RemoteException {

@Override
public void removeLocalCapability(IWearableCallbacks callbacks, String capability) throws RemoteException {
Log.d(TAG, "unimplemented Method: removeLocalCapability: " + capability);
this.wearable.networkHandler.post(new CallbackRunnable(callbacks) {
@Override
public void run(IWearableCallbacks callbacks) throws RemoteException {
Expand Down Expand Up @@ -379,48 +385,62 @@ public void doAncsNegativeAction(IWearableCallbacks callbacks, int i) throws Rem
}

@Override
public void openChannel(IWearableCallbacks callbacks, String s1, String s2) throws RemoteException {
Log.d(TAG, "unimplemented Method: openChannel; " + s1 + ", " + s2);
public void openChannel(IWearableCallbacks callbacks, String nodeId, String path) throws RemoteException {
postMain(callbacks, () -> {
String token = UUID.randomUUID().toString();
callbacks.onOpenChannelResponse(new OpenChannelResponse(0, new ChannelParcelable(token, nodeId, path)));
});
}

/*
* Channels
*/

@Override
public void closeChannel(IWearableCallbacks callbacks, String s) throws RemoteException {
Log.d(TAG, "unimplemented Method: closeChannel: " + s);
public void closeChannel(IWearableCallbacks callbacks, String token) throws RemoteException {
postMain(callbacks, () -> {
callbacks.onCloseChannelResponse(new CloseChannelResponse(0));
});
}

@Override
public void closeChannelWithError(IWearableCallbacks callbacks, String s, int errorCode) throws RemoteException {
Log.d(TAG, "unimplemented Method: closeChannelWithError:" + s + ", " + errorCode);

public void closeChannelWithError(IWearableCallbacks callbacks, String token, int errorCode) throws RemoteException {
postMain(callbacks, () -> {
callbacks.onCloseChannelResponse(new CloseChannelResponse(0));
});
}

@Override
public void getChannelInputStream(IWearableCallbacks callbacks, IChannelStreamCallbacks channelCallbacks, String s) throws RemoteException {
Log.d(TAG, "unimplemented Method: getChannelInputStream: " + s);
public void getChannelInputStream(IWearableCallbacks callbacks, IChannelStreamCallbacks channelCallbacks, String token) throws RemoteException {
postMain(callbacks, () -> {
callbacks.onGetChannelInputStreamResponse(new GetChannelInputStreamResponse(0, null));
});
}

@Override
public void getChannelOutputStream(IWearableCallbacks callbacks, IChannelStreamCallbacks channelCallbacks, String s) throws RemoteException {
Log.d(TAG, "unimplemented Method: getChannelOutputStream: " + s);
public void getChannelOutputStream(IWearableCallbacks callbacks, IChannelStreamCallbacks channelCallbacks, String token) throws RemoteException {
postMain(callbacks, () -> {
callbacks.onGetChannelOutputStreamResponse(new GetChannelOutputStreamResponse(0, null));
});
}

@Override
public void writeChannelInputToFd(IWearableCallbacks callbacks, String s, ParcelFileDescriptor fd) throws RemoteException {
Log.d(TAG, "unimplemented Method: writeChannelInputToFd: " + s);
public void writeChannelInputToFd(IWearableCallbacks callbacks, String token, ParcelFileDescriptor fd) throws RemoteException {
postMain(callbacks, () -> {
callbacks.onChannelSendFileResponse(new ChannelSendFileResponse(0));
});
}

@Override
public void readChannelOutputFromFd(IWearableCallbacks callbacks, String s, ParcelFileDescriptor fd, long l1, long l2) throws RemoteException {
Log.d(TAG, "unimplemented Method: readChannelOutputFromFd: " + s + ", " + l1 + ", " + l2);
public void readChannelOutputFromFd(IWearableCallbacks callbacks, String token, ParcelFileDescriptor fd, long startOffset, long length) throws RemoteException {
postMain(callbacks, () -> {
callbacks.onChannelReceiveFileResponse(new ChannelReceiveFileResponse(0));
});
}

@Override
public void syncWifiCredentials(IWearableCallbacks callbacks) throws RemoteException {
Log.d(TAG, "unimplemented Method: syncWifiCredentials");
callbacks.onStatus(Status.SUCCESS);
}

/*
Expand Down
Loading